2011-06-06 Emil A Eklund <eae@chromium.org>
[WebKit-https.git] / Source / WebCore / rendering / RenderLayer.cpp
index e493f3c..e2d9fb7 100644 (file)
@@ -56,6 +56,7 @@
 #include "FloatRect.h"
 #include "FocusController.h"
 #include "Frame.h"
+#include "FrameSelection.h"
 #include "FrameTree.h"
 #include "FrameView.h"
 #include "Gradient.h"
@@ -80,7 +81,6 @@
 #include "ScaleTransformOperation.h"
 #include "Scrollbar.h"
 #include "ScrollbarTheme.h"
-#include "SelectionController.h"
 #include "TextStream.h"
 #include "TransformState.h"
 #include "TransformationMatrix.h"
@@ -135,18 +135,6 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
     , m_next(0)
     , m_first(0)
     , m_last(0)
-    , m_relX(0)
-    , m_relY(0)
-    , m_x(0)
-    , m_y(0)
-    , m_width(0)
-    , m_height(0)
-    , m_scrollX(0)
-    , m_scrollY(0)
-    , m_scrollLeftOverflow(0)
-    , m_scrollTopOverflow(0)
-    , m_scrollWidth(0)
-    , m_scrollHeight(0)
     , m_inResizeMode(false)
     , m_posZOrderList(0)
     , m_negZOrderList(0)
@@ -182,6 +170,7 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
     , m_reflection(0)
     , m_scrollCorner(0)
     , m_resizer(0)
+    , m_scrollableAreaPage(0)
 {
     ScrollableArea::setConstrainsScrollingToContentEdge(false);
 
@@ -189,13 +178,6 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
         m_visibleContentStatusDirty = false;
         m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
     }
-
-    if (Frame* frame = renderer->frame()) {
-        if (Page* page = frame->page()) {
-            m_page = page;
-            m_page->addScrollableArea(this);
-        }
-    }
 }
 
 RenderLayer::~RenderLayer()
@@ -205,12 +187,15 @@ RenderLayer::~RenderLayer()
             frame->eventHandler()->resizeLayerDestroyed();
     }
 
-    if (m_page)
-        m_page->removeScrollableArea(this);
+    if (m_scrollableAreaPage)
+        m_scrollableAreaPage->removeScrollableArea(this);
 
     destroyScrollbar(HorizontalScrollbar);
     destroyScrollbar(VerticalScrollbar);
 
+    if (m_reflection)
+        removeReflection();
+
     // Child layers will be deleted by their corresponding render objects, so
     // we don't need to delete them ourselves.
 
@@ -226,9 +211,6 @@ RenderLayer::~RenderLayer()
     // Make sure we have no lingering clip rects.
     ASSERT(!m_clipRects);
     
-    if (m_reflection)
-        removeReflection();
-    
     if (m_scrollCorner)
         m_scrollCorner->destroy();
     if (m_resizer)
@@ -288,34 +270,29 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint
         else {
             oldCachedOffset = *cachedOffset;
             // Frequently our parent layer's renderer will be the same as our renderer's containing block.  In that case,
-            // we just update the cache using our offset to our parent (which is m_x / m_y).  Otherwise, regenerated cached
+            // we just update the cache using our offset to our parent (which is m_topLeft). Otherwise, regenerated cached
             // offsets to the root from the render tree.
             if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
-                cachedOffset->move(m_x, m_y); // Fast case
+                cachedOffset->move(m_topLeft.x(), m_topLeft.y()); // Fast case
             else {
-                int x = 0;
-                int y = 0;
-                convertToLayerCoords(root(), x, y);
-                *cachedOffset = IntPoint(x, y);
+                IntPoint offset;
+                convertToLayerCoords(root(), offset);
+                *cachedOffset = offset;
             }
         }
     }
 
-    int x = 0;
-    int y = 0;
+    IntPoint offset;
     if (cachedOffset) {
-        x += cachedOffset->x();
-        y += cachedOffset->y();
+        offset = *cachedOffset;
 #ifndef NDEBUG
-        int nonCachedX = 0;
-        int nonCachedY = 0;
-        convertToLayerCoords(root(), nonCachedX, nonCachedY);
-        ASSERT(x == nonCachedX);
-        ASSERT(y == nonCachedY);
+        IntPoint nonCachedOffset;
+        convertToLayerCoords(root(), nonCachedOffset);
+        ASSERT(offset == nonCachedOffset);
 #endif
     } else
-        convertToLayerCoords(root(), x, y);
-    positionOverflowControls(x, y);
+        convertToLayerCoords(root(), offset);
+    positionOverflowControls(toSize(offset));
 
     updateVisibilityStatus();
 
@@ -327,7 +304,7 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint
     if (m_hasVisibleContent) {
         RenderView* view = renderer()->view();
         ASSERT(view);
-        // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
+        // FIXME: Optimize using LayoutState and remove LayoutStateDisabler instantiation
         // from updateScrollInfoAfterLayout().
         ASSERT(!view->layoutStateEnabled());
 
@@ -426,7 +403,7 @@ void RenderLayer::updateTransform()
     bool hadTransform = m_transform;
     if (hasTransform != hadTransform) {
         if (hasTransform)
-            m_transform.set(new TransformationMatrix);
+            m_transform = adoptPtr(new TransformationMatrix);
         else
             m_transform.clear();
     }
@@ -669,13 +646,11 @@ void RenderLayer::updateLayerPosition()
     if (renderer()->isRenderInline()) {
         RenderInline* inlineFlow = toRenderInline(renderer());
         IntRect lineBox = inlineFlow->linesBoundingBox();
-        setWidth(lineBox.width());
-        setHeight(lineBox.height());
-        inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y());
+        setSize(lineBox.size());
+        inlineBoundingBoxOffset = toSize(lineBox.location());
         localPoint += inlineBoundingBoxOffset;
     } else if (RenderBox* box = renderBox()) {
-        setWidth(box->width());
-        setHeight(box->height());
+        setSize(box->size());
         localPoint += box->locationOffsetIncludingFlipping();
     }
 
@@ -725,11 +700,11 @@ void RenderLayer::updateLayerPosition()
         localPoint -= scrollOffset;
     }
         
-    m_relX = m_relY = 0;
     if (renderer()->isRelPositioned()) {
-        m_relX = renderer()->relativePositionOffsetX();
-        m_relY = renderer()->relativePositionOffsetY();
-        localPoint.move(m_relX, m_relY);
+        m_relativeOffset = renderer()->relativePositionOffset();
+        localPoint.move(m_relativeOffset);
+    } else {
+        m_relativeOffset = IntSize();
     }
 
     // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
@@ -921,12 +896,11 @@ static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const R
     // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
     // size into the parent layer.
     if (l->renderer()->hasReflection()) {
-        int deltaX = 0;
-        int deltaY = 0;
-        l->convertToLayerCoords(rootLayer, deltaX, deltaY);
-        clipRect.move(-deltaX, -deltaY);
+        IntPoint delta;
+        l->convertToLayerCoords(rootLayer, delta);
+        clipRect.move(-delta.x(), -delta.y());
         clipRect.unite(l->renderBox()->reflectedRect(clipRect));
-        clipRect.move(deltaX, deltaY);
+        clipRect.moveBy(delta);
     }
 }
 
@@ -939,12 +913,11 @@ static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* root
     if (rootLayer != l && l->paintsWithTransform(paintBehavior)) {
         // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
         // the transformed layer and all of its children.
-        int x = 0;
-        int y = 0;
-        l->convertToLayerCoords(rootLayer, x, y);
+        IntPoint delta;
+        l->convertToLayerCoords(rootLayer, delta);
 
         TransformationMatrix transform;
-        transform.translate(x, y);
+        transform.translate(delta.x(), delta.y());
         transform = transform * *l->transform();
 
         IntRect clipRect = l->boundingBox(l);
@@ -1132,7 +1105,7 @@ void RenderLayer::insertOnlyThisLayer()
 }
 
 void 
-RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const
 {
     if (ancestorLayer == this)
         return;
@@ -1142,8 +1115,7 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
         // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
         // localToAbsolute() on the RenderView.
         FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
-        xPos += absPos.x();
-        yPos += absPos.y();
+        location += flooredIntSize(absPos);
         return;
     }
  
@@ -1159,7 +1131,7 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
 
             if (isFixedPositionedContainer(currLayer)) {
                 fixedPositionContainerLayer = currLayer;
-                ASSERT(foundAncestor);
+                ASSERT_UNUSED(foundAncestor, foundAncestor);
                 break;
             }
         }
@@ -1167,16 +1139,13 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
         ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
 
         if (fixedPositionContainerLayer != ancestorLayer) {
-            int fixedContainerX = 0;
-            int fixedContainerY = 0;
-            convertToLayerCoords(fixedPositionContainerLayer, fixedContainerX, fixedContainerY);
-            
-            int ancestorX = 0;
-            int ancestorY = 0;
-            ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorX, ancestorY);
-        
-            xPos += (fixedContainerX - ancestorX);
-            yPos += (fixedContainerY - ancestorY);
+            IntPoint fixedContainerCoords;
+            convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
+
+            IntPoint ancestorCoords;
+            ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
+
+            location += (fixedContainerCoords - ancestorCoords);
             return;
         }
     }
@@ -1203,16 +1172,13 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
             // to enclosingPositionedAncestor and subtract.
             RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
 
-            int thisX = 0;
-            int thisY = 0;
-            convertToLayerCoords(positionedAncestor, thisX, thisY);
+            IntPoint thisCoords;
+            convertToLayerCoords(positionedAncestor, thisCoords);
             
-            int ancestorX = 0;
-            int ancestorY = 0;
-            ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY);
-        
-            xPos += (thisX - ancestorX);
-            yPos += (thisY - ancestorY);
+            IntPoint ancestorCoords;
+            ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
+
+            location += (thisCoords - ancestorCoords);
             return;
         }
     } else
@@ -1220,11 +1186,18 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
     
     if (!parentLayer)
         return;
-    
-    parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
-    
-    xPos += x();
-    yPos += y();
+
+    parentLayer->convertToLayerCoords(ancestorLayer, location);
+
+    location += toSize(m_topLeft);
+}
+
+void
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, IntRect& rect) const
+{
+    IntPoint delta;
+    convertToLayerCoords(ancestorLayer, delta);
+    rect.move(-delta.x(), -delta.y());
 }
 
 static inline int adjustedScrollDelta(int beginningDelta) {
@@ -1344,12 +1317,10 @@ void RenderLayer::scrollTo(int x, int y)
     // complicated (since it will involve testing whether our layer
     // is either occluded by another layer or clipped by an enclosing
     // layer or contains fixed backgrounds, etc.).
-    int newScrollX = x - m_scrollOrigin.x();
-    int newScrollY = y - m_scrollOrigin.y();
-    if (m_scrollY == newScrollY && m_scrollX == newScrollX)
+    IntSize newScrollOffset = IntSize(x - m_scrollOrigin.x(), y - m_scrollOrigin.y());
+    if (m_scrollOffset == newScrollOffset)
         return;
-    m_scrollX = newScrollX;
-    m_scrollY = newScrollY;
+    m_scrollOffset = newScrollOffset;
 
     // Update the positions of our child layers. Don't have updateLayerPositions() update
     // compositing layers, because we need to do a deep update from the compositing ancestor.
@@ -1407,11 +1378,10 @@ void RenderLayer::scrollTo(int x, int y)
     renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
 }
 
-void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+void RenderLayer::scrollRectToVisible(const IntRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
 {
     RenderLayer* parentLayer = 0;
     IntRect newRect = rect;
-    int xOffset = 0, yOffset = 0;
 
     // We may end up propagating a scroll event. It is important that we suspend events until 
     // the end of the function since they could delete the layer or the layer's renderer().
@@ -1437,8 +1407,8 @@ void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor,
         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
         
-        xOffset = r.x() - absPos.x();
-        yOffset = r.y() - absPos.y();
+        int xOffset = r.x() - absPos.x();
+        int yOffset = r.y() - absPos.y();
         // Adjust offsets if they're outside of the allowable range.
         xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
         yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
@@ -1452,14 +1422,14 @@ void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor,
             newRect.setX(rect.x() - diffX);
             newRect.setY(rect.y() - diffY);
         }
-    } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {
+    } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled()) {
         if (frameView) {
             if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
                 IntRect viewRect = frameView->visibleContentRect();
                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
                 
-                xOffset = r.x();
-                yOffset = r.y();
+                int xOffset = r.x();
+                int yOffset = r.y();
                 // Adjust offsets if they're outside of the allowable range.
                 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
                 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
@@ -1488,7 +1458,7 @@ void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor,
     }
     
     if (parentLayer)
-        parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
+        parentLayer->scrollRectToVisible(newRect, alignX, alignY);
 
     if (frameView)
         frameView->resumeScheduledEvents();
@@ -1582,7 +1552,7 @@ void RenderLayer::autoscroll()
 #endif
 
     IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
-    scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+    scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 }
 
 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
@@ -1670,6 +1640,45 @@ int RenderLayer::scrollPosition(Scrollbar* scrollbar) const
     return 0;
 }
 
+IntPoint RenderLayer::scrollPosition() const
+{
+    return m_scrollOrigin + m_scrollOffset;
+}
+
+IntPoint RenderLayer::minimumScrollPosition() const
+{
+    return m_scrollOrigin;
+}
+
+IntPoint RenderLayer::maximumScrollPosition() const
+{
+    // FIXME: m_scrollSize may not be up-to-date if m_scrollDimensionsDirty is true.
+    return m_scrollOrigin + m_scrollSize;
+}
+
+IntRect RenderLayer::visibleContentRect(bool includeScrollbars) const
+{
+    int verticalScrollbarWidth = 0;
+    int horizontalScrollbarHeight = 0;
+    if (includeScrollbars) {
+        verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar()) ? verticalScrollbar()->width() : 0;
+        horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0;
+    }
+    
+    return IntRect(IntPoint(scrollXOffset(), scrollYOffset()),
+                   IntSize(max(0, m_layerSize.width() - verticalScrollbarWidth), 
+                           max(0, m_layerSize.height() - horizontalScrollbarHeight)));
+}
+
+IntSize RenderLayer::overhangAmount() const
+{
+    return IntSize();
+}
+
+void RenderLayer::didCompleteRubberBand(const IntSize&) const
+{
+}
+
 bool RenderLayer::isActive() const
 {
     Page* page = renderer()->frame()->page();
@@ -1792,12 +1801,12 @@ IntSize RenderLayer::contentsSize() const
 
 int RenderLayer::visibleHeight() const
 {
-    return m_height;
+    return m_layerSize.height();
 }
 
 int RenderLayer::visibleWidth() const
 {
-    return m_width;
+    return m_layerSize.width();
 }
 
 bool RenderLayer::shouldSuspendScrollAnimations() const
@@ -1903,6 +1912,27 @@ void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
     }
 }
 
+bool RenderLayer::scrollsOverflow() const
+{
+    if (!renderer()->isBox())
+        return false;
+    
+    return toRenderBox(renderer())->scrollsOverflow();
+}
+
+void RenderLayer::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    m_renderer->document()->didAddWheelEventHandler();
+    ScrollableArea::didAddHorizontalScrollbar(scrollbar);
+}
+
+void RenderLayer::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    ScrollableArea::willRemoveHorizontalScrollbar(scrollbar);
+    // FIXME: maybe need a separate ScrollableArea::didRemoveHorizontalScrollbar callback?
+    m_renderer->document()->didRemoveWheelEventHandler();
+}
+
 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
 {
     if (hasScrollbar == (m_hBar != 0))
@@ -1966,7 +1996,8 @@ int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevan
 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
 {
     // Currently the resize corner is always the bottom right corner
-    IntPoint bottomRight(width(), height());
+    // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be the case?
+    IntPoint bottomRight = toPoint(size());
     IntPoint localPoint = absoluteToContents(absolutePoint);
     return localPoint - bottomRight;
 }
@@ -1976,7 +2007,7 @@ bool RenderLayer::hasOverflowControls() const
     return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
 }
 
-void RenderLayer::positionOverflowControls(int tx, int ty)
+void RenderLayer::positionOverflowControls(const IntSize& offsetFromLayer)
 {
     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
         return;
@@ -1987,7 +2018,7 @@ void RenderLayer::positionOverflowControls(int tx, int ty)
 
     const IntRect& borderBox = box->borderBoxRect();
     const IntRect& scrollCorner = scrollCornerRect();
-    IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
+    IntRect absBounds(borderBox.location() + offsetFromLayer, borderBox.size());
     if (m_vBar)
         m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(),
                                      absBounds.y() + box->borderTop(),
@@ -2003,14 +2034,14 @@ void RenderLayer::positionOverflowControls(int tx, int ty)
 #if USE(ACCELERATED_COMPOSITING)
     if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
         if (m_hBar) {
-            layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty));
+            layer->setPosition(m_hBar->frameRect().location() - offsetFromLayer);
             layer->setSize(m_hBar->frameRect().size());
         }
         layer->setDrawsContent(m_hBar);
     }
     if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
         if (m_vBar) {
-            layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty));
+            layer->setPosition(m_vBar->frameRect().location() - offsetFromLayer);
             layer->setSize(m_vBar->frameRect().size());
         }
         layer->setDrawsContent(m_vBar);
@@ -2034,14 +2065,14 @@ int RenderLayer::scrollWidth()
 {
     if (m_scrollDimensionsDirty)
         computeScrollDimensions();
-    return m_scrollWidth;
+    return m_scrollSize.width();
 }
 
 int RenderLayer::scrollHeight()
 {
     if (m_scrollDimensionsDirty)
         computeScrollDimensions();
-    return m_scrollHeight;
+    return m_scrollSize.height();
 }
 
 int RenderLayer::overflowTop() const
@@ -2083,18 +2114,18 @@ void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
     
     m_scrollDimensionsDirty = false;
 
-    m_scrollLeftOverflow = overflowLeft() - box->borderLeft();
-    m_scrollTopOverflow = overflowTop() - box->borderTop();
+    m_scrollOverflow.setWidth(overflowLeft() - box->borderLeft());
+    m_scrollOverflow.setHeight(overflowTop() - box->borderTop());
 
-    m_scrollWidth = overflowRight() - overflowLeft();
-    m_scrollHeight = overflowBottom() - overflowTop();
+    m_scrollSize.setWidth(overflowRight() - overflowLeft());
+    m_scrollSize.setHeight(overflowBottom() - overflowTop());
     
-    m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow);
+    m_scrollOrigin = IntPoint(-m_scrollOverflow.width(), -m_scrollOverflow.height());
 
     if (needHBar)
-        *needHBar = m_scrollWidth > box->clientWidth();
+        *needHBar = m_scrollSize.width() > box->clientWidth();
     if (needVBar)
-        *needVBar = m_scrollHeight > box->clientHeight();
+        *needVBar = m_scrollSize.height() > box->clientHeight();
 }
 
 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
@@ -2141,12 +2172,9 @@ void RenderLayer::updateScrollInfoAfterLayout()
             ASSERT(view);
             // scrollToOffset() may call updateLayerPositions(), which doesn't work
             // with LayoutState.
-            // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
-            if (view)
-                view->disableLayoutState();
+            // FIXME: Remove the LayoutStateDisabler instantiation if the above changes.
+            LayoutStateDisabler layoutStateDisabler(view);
             scrollToOffset(newX, newY);
-            if (view)
-                view->enableLayoutState();
         }
     }
 
@@ -2211,25 +2239,26 @@ void RenderLayer::updateScrollInfoAfterLayout()
         int clientWidth = box->clientWidth();
         int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
         m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
-        m_hBar->setProportion(clientWidth, m_scrollWidth);
+        m_hBar->setProportion(clientWidth, m_scrollSize.width());
     }
     if (m_vBar) {
         int clientHeight = box->clientHeight();
         int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
         m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
-        m_vBar->setProportion(clientHeight, m_scrollHeight);
+        m_vBar->setProportion(clientHeight, m_scrollSize.height());
     }
  
     RenderView* view = renderer()->view();
-    view->disableLayoutState();
-    scrollToOffset(scrollXOffset(), scrollYOffset());
-    view->enableLayoutState();
+    {
+        LayoutStateDisabler layoutStateDisabler(view);
+        scrollToOffset(scrollXOffset(), scrollYOffset());
+    }
+
     if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
         updateOverflowStatus(horizontalOverflow, verticalOverflow);
 }
 
-void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect, bool paintingOverlayControls)
+void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
 {
     // Don't do anything if we have no overflow.
     if (!renderer()->hasOverflowClip())
@@ -2244,22 +2273,23 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty
     if (hasOverlayScrollbars() && !paintingOverlayControls) {
         RenderView* renderView = renderer()->view();
         renderView->layer()->setContainsDirtyOverlayScrollbars(true);
-        m_cachedOverlayScrollbarOffset = IntPoint(tx, ty);
+        m_cachedOverlayScrollbarOffset = paintOffset;
         renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
         return;
     }
 
-    int offsetX = tx;
-    int offsetY = ty;
-    if (paintingOverlayControls) {
-        offsetX = m_cachedOverlayScrollbarOffset.x();
-        offsetY = m_cachedOverlayScrollbarOffset.y();
-    }
+    // This check is required to avoid painting custom CSS scrollbars twice.
+    if (paintingOverlayControls && !hasOverlayScrollbars())
+        return;
+
+    IntPoint adjustedPaintOffset = paintOffset;
+    if (paintingOverlayControls)
+        adjustedPaintOffset = m_cachedOverlayScrollbarOffset;
 
     // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
     // widgets can move without layout occurring (most notably when you scroll a document that
     // contains fixed positioned elements).
-    positionOverflowControls(offsetX, offsetY);
+    positionOverflowControls(toSize(adjustedPaintOffset));
 
     // Now that we're sure the scrollbars are in the right place, paint them.
     if (m_hBar
@@ -2282,19 +2312,19 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty
 
     // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
     // edge of the box.
-    paintScrollCorner(context, offsetX, offsetY, damageRect);
+    paintScrollCorner(context, adjustedPaintOffset, damageRect);
     
     // Paint our resizer last, since it sits on top of the scroll corner.
-    paintResizer(context, offsetX, offsetY, damageRect);
+    paintResizer(context, adjustedPaintOffset, damageRect);
 }
 
-void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
+void RenderLayer::paintScrollCorner(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
 {
     RenderBox* box = renderBox();
     ASSERT(box);
 
-    IntRect cornerRect = scrollCornerRect();
-    IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
+    IntRect absRect = scrollCornerRect();
+    absRect.moveBy(paintOffset);
     if (!absRect.intersects(damageRect))
         return;
 
@@ -2304,7 +2334,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co
     }
 
     if (m_scrollCorner) {
-        m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
+        m_scrollCorner->paintIntoRect(context, paintOffset.x(), paintOffset.y(), absRect);
         return;
     }
 
@@ -2314,7 +2344,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co
         context->fillRect(absRect, Color::white, box->style()->colorSpace());
 }
 
-void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
+void RenderLayer::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
 {
     if (renderer()->style()->resize() == RESIZE_NONE)
         return;
@@ -2322,8 +2352,8 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
     RenderBox* box = renderBox();
     ASSERT(box);
 
-    IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect());
-    IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
+    IntRect absRect = resizerCornerRect(this, box->borderBoxRect());
+    absRect.moveBy(paintOffset);
     if (!absRect.intersects(damageRect))
         return;
 
@@ -2333,7 +2363,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
     }
     
     if (m_resizer) {
-        m_resizer->paintIntoRect(context, tx, ty, absRect);
+        m_resizer->paintIntoRect(context, paintOffset.x(), paintOffset.y(), absRect);
         return;
     }
 
@@ -2533,11 +2563,10 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
 
         // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
         // This involves subtracting out the position of the layer in our current coordinate space.
-        int x = 0;
-        int y = 0;
-        convertToLayerCoords(rootLayer, x, y);
+        IntPoint delta;
+        convertToLayerCoords(rootLayer, delta);
         TransformationMatrix transform(layerTransform);
-        transform.translateRight(x, y);
+        transform.translateRight(delta.x(), delta.y());
         
         // Apply the transform.
         {
@@ -2667,7 +2696,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
 
     if (paintingOverlayScrollbars) {
         setClip(p, paintDirtyRect, damageRect);
-        paintOverflowControls(p, tx, ty, damageRect, true);
+        paintOverflowControls(p, IntPoint(tx, ty), damageRect, true);
         restoreClip(p, paintDirtyRect, damageRect);
     }
 
@@ -2727,9 +2756,8 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
     if (!columnBlock || !columnBlock->hasColumns())
         return;
     
-    int layerX = 0;
-    int layerY = 0;
-    columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
+    IntPoint layerOffset;
+    columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
     
     bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
 
@@ -2743,7 +2771,7 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
         int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
         IntSize offset = isHorizontal ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset);
 
-        colRect.move(layerX, layerY);
+        colRect.moveBy(layerOffset);
 
         IntRect localDirtyRect(paintDirtyRect);
         localDirtyRect.intersect(colRect);
@@ -2764,20 +2792,19 @@ void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLaye
                 TransformationMatrix newTransform(oldTransform);
                 newTransform.translateRight(offset.width(), offset.height());
                 
-                childLayer->m_transform.set(new TransformationMatrix(newTransform));
+                childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
                 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
                 if (oldHasTransform)
-                    childLayer->m_transform.set(new TransformationMatrix(oldTransform));
+                    childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
                 else
                     childLayer->m_transform.clear();
             } else {
                 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
                 // This involves subtracting out the position of the layer in our current coordinate space.
-                int childX = 0;
-                int childY = 0;
-                columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY);
+                IntPoint childOffset;
+                columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childOffset);
                 TransformationMatrix transform;
-                transform.translateRight(childX + offset.width(), childY + offset.height());
+                transform.translateRight(childOffset.x() + offset.width(), childOffset.y() + offset.height());
                 
                 // Apply the transform.
                 context->concatCTM(transform.toAffineTransform());
@@ -2871,26 +2898,25 @@ PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(Rend
                                         const HitTestingTransformState* containerTransformState) const
 {
     RefPtr<HitTestingTransformState> transformState;
-    int offsetX = 0;
-    int offsetY = 0;
+    IntPoint offset;
     if (containerTransformState) {
         // If we're already computing transform state, then it's relative to the container (which we know is non-null).
         transformState = HitTestingTransformState::create(*containerTransformState);
-        convertToLayerCoords(containerLayer, offsetX, offsetY);
+        convertToLayerCoords(containerLayer, offset);
     } else {
         // If this is the first time we need to make transform state, then base it off of hitTestPoint,
         // which is relative to rootLayer.
         transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect));
-        convertToLayerCoords(rootLayer, offsetX, offsetY);
+        convertToLayerCoords(rootLayer, offset);
     }
     
     RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
     if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
         TransformationMatrix containerTransform;
-        renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform);
+        renderer()->getTransformFromContainer(containerRenderer, toSize(offset), containerTransform);
         transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
     } else {
-        transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform);
+        transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
     }
     
     return transformState;
@@ -3199,10 +3225,9 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
     ASSERT(columnBlock && columnBlock->hasColumns());
     if (!columnBlock || !columnBlock->hasColumns())
         return 0;
-    
-    int layerX = 0;
-    int layerY = 0;
-    columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
+
+    IntPoint layerOffset;
+    columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
     
     ColumnInfo* colInfo = columnBlock->columnInfo();
     int colCount = columnBlock->columnCount(colInfo);
@@ -3230,7 +3255,7 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
             currLogicalTopOffset -= blockDelta;
         else
             currLogicalTopOffset += blockDelta;
-        colRect.move(layerX, layerY);
+        colRect.moveBy(layerOffset);
 
         IntRect localClipRect(hitTestRect);
         localClipRect.intersect(colRect);
@@ -3248,10 +3273,10 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
                 TransformationMatrix newTransform(oldTransform);
                 newTransform.translateRight(offset.width(), offset.height());
                 
-                childLayer->m_transform.set(new TransformationMatrix(newTransform));
+                childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
                 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
                 if (oldHasTransform)
-                    childLayer->m_transform.set(new TransformationMatrix(oldTransform));
+                    childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
                 else
                     childLayer->m_transform.clear();
             } else {
@@ -3339,24 +3364,22 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
     // Update the clip rects that will be passed to child layers.
     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
         // This layer establishes a clip of some kind.
-        int x = 0;
-        int y = 0;
-        convertToLayerCoords(rootLayer, x, y);
+        IntPoint offset;
+        convertToLayerCoords(rootLayer, offset);
         RenderView* view = renderer()->view();
         ASSERT(view);
         if (view && clipRects.fixed() && rootLayer->renderer() == view) {
-            x -= view->frameView()->scrollXForFixedPosition();
-            y -= view->frameView()->scrollYForFixedPosition();
+            offset -= view->frameView()->scrollOffsetForFixedPosition();
         }
         
         if (renderer()->hasOverflowClip()) {
-            IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
+            IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(offset, relevancy);
             clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
             if (renderer()->isPositioned() || renderer()->isRelPositioned())
                 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
         }
         if (renderer()->hasClip()) {
-            IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
+            IntRect newPosClip = toRenderBox(renderer())->clipRect(offset);
             clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
             clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
             clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
@@ -3406,19 +3429,18 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
     foregroundRect = backgroundRect;
     outlineRect = backgroundRect;
     
-    int x = 0;
-    int y = 0;
-    convertToLayerCoords(rootLayer, x, y);
-    layerBounds = IntRect(x, y, width(), height());
+    IntPoint offset;
+    convertToLayerCoords(rootLayer, offset);
+    layerBounds = IntRect(offset, size());
     
     // Update the clip rects that will be passed to child layers.
     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
         // This layer establishes a clip of some kind.
         if (renderer()->hasOverflowClip())
-            foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy));
+            foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, relevancy));
         if (renderer()->hasClip()) {
             // Clip applies to *us* as well, so go ahead and update the damageRect.
-            IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
+            IntRect newPosClip = toRenderBox(renderer())->clipRect(offset);
             backgroundRect.intersect(newPosClip);
             foregroundRect.intersect(newPosClip);
             outlineRect.intersect(newPosClip);
@@ -3487,9 +3509,9 @@ void RenderLayer::repaintBlockSelectionGaps()
     IntRect rect = m_blockSelectionGapsBounds;
     rect.move(-scrolledContentOffset());
     if (renderer()->hasOverflowClip())
-        rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0));
+        rect.intersect(toRenderBox(renderer())->overflowClipRect(IntPoint()));
     if (renderer()->hasClip())
-        rect.intersect(toRenderBox(renderer())->clipRect(0, 0));
+        rect.intersect(toRenderBox(renderer())->clipRect(IntPoint()));
     if (!rect.isEmpty())
         renderer()->repaintRectangle(rect);
 }
@@ -3572,9 +3594,9 @@ IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
         renderBox()->flipForWritingMode(result);
     else
         renderer()->containingBlock()->flipForWritingMode(result);
-    int deltaX = 0, deltaY = 0;
-    convertToLayerCoords(ancestorLayer, deltaX, deltaY);
-    result.move(deltaX, deltaY);
+    IntPoint delta;
+    convertToLayerCoords(ancestorLayer, delta);
+    result.moveBy(delta);
     return result;
 }
 
@@ -3609,7 +3631,7 @@ void RenderLayer::clearClipRects()
 RenderLayerBacking* RenderLayer::ensureBacking()
 {
     if (!m_backing)
-        m_backing.set(new RenderLayerBacking(this));
+        m_backing = adoptPtr(new RenderLayerBacking(this));
     return m_backing.get();
 }
 
@@ -3909,10 +3931,9 @@ void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
         // If we're trying to repaint the placeholder document layer, propagate the
         // repaint to the native view system.
         IntRect absRect(r);
-        int x = 0;
-        int y = 0;
-        convertToLayerCoords(root(), x, y);
-        absRect.move(x, y);
+        IntPoint delta;
+        convertToLayerCoords(root(), delta);
+        absRect.moveBy(delta);
 
         RenderView* view = renderer()->view();
         if (view)
@@ -3990,6 +4011,20 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle
         updateReflectionStyle();
     }
     
+    if (scrollsOverflow()) {
+        if (!m_scrollableAreaPage) {
+            if (Frame* frame = renderer()->frame()) {
+                if (Page* page = frame->page()) {
+                    m_scrollableAreaPage = page;
+                    m_scrollableAreaPage->addScrollableArea(this);
+                }
+            }
+        }
+    } else if (m_scrollableAreaPage) {
+        m_scrollableAreaPage->removeScrollableArea(this);
+        m_scrollableAreaPage = 0;
+    }
+    
     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
     if (m_hBar)
         m_hBar->styleChanged();
@@ -4021,7 +4056,7 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle
 void RenderLayer::updateScrollCornerStyle()
 {
     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
-    RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0;
+    RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
     if (corner) {
         if (!m_scrollCorner) {
             m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
@@ -4037,7 +4072,7 @@ void RenderLayer::updateScrollCornerStyle()
 void RenderLayer::updateResizerStyle()
 {
     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
-    RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0;
+    RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
     if (resizer) {
         if (!m_resizer) {
             m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());