diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp | 508 |
1 files changed, 292 insertions, 216 deletions
diff --git a/chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp index 51ecb5d055d..5dbf9982555 100644 --- a/chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp +++ b/chromium/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp @@ -27,15 +27,21 @@ #include "core/page/scrolling/ScrollingCoordinator.h" -#include "RuntimeEnabledFeatures.h" #include "core/dom/Document.h" +#include "core/dom/FullscreenElementStack.h" #include "core/dom/Node.h" -#include "core/dom/WheelController.h" -#include "core/html/HTMLElement.h" -#include "core/frame/Frame.h" +#include "core/frame/EventHandlerRegistry.h" #include "core/frame/FrameView.h" -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/html/HTMLElement.h" +#include "core/page/Page.h" +#include "core/plugins/PluginView.h" +#include "core/rendering/RenderGeometryMap.h" +#include "core/rendering/RenderView.h" +#include "core/rendering/compositing/CompositedLayerMapping.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" #include "platform/exported/WebScrollbarImpl.h" #include "platform/exported/WebScrollbarThemeGeometryNative.h" @@ -47,11 +53,6 @@ #endif #include "platform/scroll/ScrollAnimator.h" #include "platform/scroll/ScrollbarTheme.h" -#include "core/plugins/PluginView.h" -#include "core/rendering/CompositedLayerMapping.h" -#include "core/rendering/RenderGeometryMap.h" -#include "core/rendering/RenderLayerCompositor.h" -#include "core/rendering/RenderView.h" #include "public/platform/Platform.h" #include "public/platform/WebCompositorSupport.h" #include "public/platform/WebLayerPositionConstraint.h" @@ -66,29 +67,27 @@ using blink::WebRect; using blink::WebScrollbarLayer; using blink::WebVector; +namespace { -namespace WebCore { - -static WebLayer* scrollingWebLayerForGraphicsLayer(GraphicsLayer* layer) +WebLayer* toWebLayer(WebCore::GraphicsLayer* layer) { - return layer->platformLayer(); + return layer ? layer->platformLayer() : 0; } -WebLayer* ScrollingCoordinator::scrollingWebLayerForScrollableArea(ScrollableArea* scrollableArea) -{ - GraphicsLayer* graphicsLayer = scrollLayerForScrollableArea(scrollableArea); - return graphicsLayer ? scrollingWebLayerForGraphicsLayer(graphicsLayer) : 0; -} +} // namespace + +namespace WebCore { -PassRefPtr<ScrollingCoordinator> ScrollingCoordinator::create(Page* page) +PassOwnPtr<ScrollingCoordinator> ScrollingCoordinator::create(Page* page) { - return adoptRef(new ScrollingCoordinator(page)); + return adoptPtr(new ScrollingCoordinator(page)); } ScrollingCoordinator::ScrollingCoordinator(Page* page) : m_page(page) , m_scrollGestureRegionIsDirty(false) , m_touchEventTargetRectsAreDirty(false) + , m_shouldScrollOnMainThreadDirty(false) , m_wasFrameScrollable(false) , m_lastMainThreadScrollingReasons(0) { @@ -96,24 +95,22 @@ ScrollingCoordinator::ScrollingCoordinator(Page* page) ScrollingCoordinator::~ScrollingCoordinator() { - ASSERT(!m_page); - for (ScrollbarMap::iterator it = m_horizontalScrollbars.begin(); it != m_horizontalScrollbars.end(); ++it) - GraphicsLayer::unregisterContentsLayer(it->value->layer()); - for (ScrollbarMap::iterator it = m_verticalScrollbars.begin(); it != m_verticalScrollbars.end(); ++it) - GraphicsLayer::unregisterContentsLayer(it->value->layer()); - } bool ScrollingCoordinator::touchHitTestingEnabled() const { - RenderView* contentRenderer = m_page->mainFrame()->contentRenderer(); - Settings* settings = m_page->mainFrame()->document()->settings(); + if (!m_page->mainFrame()->isLocalFrame()) + return false; + RenderView* contentRenderer = m_page->deprecatedLocalMainFrame()->contentRenderer(); + Settings* settings = m_page->mainFrame()->settings(); return RuntimeEnabledFeatures::touchEnabled() && settings->compositorTouchHitTesting() && contentRenderer && contentRenderer->usesCompositing(); } void ScrollingCoordinator::setShouldHandleScrollGestureOnMainThreadRegion(const Region& region) { - if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainFrame()->view())) { + if (!m_page->mainFrame()->isLocalFrame()) + return; + if (WebLayer* scrollLayer = toWebLayer(m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) { Vector<IntRect> rects = region.rects(); WebVector<WebRect> webRects(rects.size()); for (size_t i = 0; i < rects.size(); ++i) @@ -124,14 +121,20 @@ void ScrollingCoordinator::setShouldHandleScrollGestureOnMainThreadRegion(const void ScrollingCoordinator::notifyLayoutUpdated() { - // These computations need to happen after compositing is updated. m_scrollGestureRegionIsDirty = true; m_touchEventTargetRectsAreDirty = true; + m_shouldScrollOnMainThreadDirty = true; } -void ScrollingCoordinator::updateAfterCompositingChange() +void ScrollingCoordinator::updateAfterCompositingChangeIfNeeded() { - TRACE_EVENT0("input", "ScrollingCoordinator::updateAfterCompositingChange"); + if (!m_page->mainFrame()->isLocalFrame()) + return; + + if (!shouldUpdateAfterCompositingChange()) + return; + + TRACE_EVENT0("input", "ScrollingCoordinator::updateAfterCompositingChangeIfNeeded"); if (m_scrollGestureRegionIsDirty) { // Compute the region of the page where we can't handle scroll gestures and mousewheel events @@ -142,7 +145,7 @@ void ScrollingCoordinator::updateAfterCompositingChange() // 2. Resize control areas, e.g. the small rect at the right bottom of div/textarea/iframe when // CSS property "resize" is enabled. // 3. Plugin areas. - Region shouldHandleScrollGestureOnMainThreadRegion = computeShouldHandleScrollGestureOnMainThreadRegion(m_page->mainFrame(), IntPoint()); + Region shouldHandleScrollGestureOnMainThreadRegion = computeShouldHandleScrollGestureOnMainThreadRegion(m_page->deprecatedLocalMainFrame(), IntPoint()); setShouldHandleScrollGestureOnMainThreadRegion(shouldHandleScrollGestureOnMainThreadRegion); m_scrollGestureRegionIsDirty = false; } @@ -152,29 +155,46 @@ void ScrollingCoordinator::updateAfterCompositingChange() m_touchEventTargetRectsAreDirty = false; } - FrameView* frameView = m_page->mainFrame()->view(); + FrameView* frameView = m_page->deprecatedLocalMainFrame()->view(); bool frameIsScrollable = frameView && frameView->isScrollable(); - if (m_wasFrameScrollable != frameIsScrollable) - updateShouldUpdateScrollLayerPositionOnMainThread(); + if (m_shouldScrollOnMainThreadDirty || m_wasFrameScrollable != frameIsScrollable) { + setShouldUpdateScrollLayerPositionOnMainThread(mainThreadScrollingReasons()); + m_shouldScrollOnMainThreadDirty = false; + } m_wasFrameScrollable = frameIsScrollable; + // The mainFrame view doesn't get included in the FrameTree below, so we + // update its size separately. + if (WebLayer* scrollingWebLayer = frameView ? toWebLayer(frameView->layerForScrolling()) : 0) { + scrollingWebLayer->setBounds(frameView->contentsSize()); + // If there is a fullscreen element, set the scroll clip layer to 0 so main frame won't scroll. + Document* mainFrameDocument = m_page->deprecatedLocalMainFrame()->document(); + Element* fullscreenElement = FullscreenElementStack::fullscreenElementFrom(*mainFrameDocument); + if (fullscreenElement && fullscreenElement != mainFrameDocument->documentElement()) + scrollingWebLayer->setScrollClipLayer(0); + else + scrollingWebLayer->setScrollClipLayer(toWebLayer(frameView->layerForContainer())); + } + const FrameTree& tree = m_page->mainFrame()->tree(); for (const Frame* child = tree.firstChild(); child; child = child->tree().nextSibling()) { - if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(child->view())) - scrollLayer->setBounds(child->view()->contentsSize()); + if (!child->isLocalFrame()) + continue; + if (WebLayer* scrollLayer = toWebLayer(toLocalFrame(child)->view()->layerForScrolling())) + scrollLayer->setBounds(toLocalFrame(child)->view()->contentsSize()); } } void ScrollingCoordinator::setLayerIsContainerForFixedPositionLayers(GraphicsLayer* layer, bool enable) { - if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(layer)) + if (WebLayer* scrollableLayer = toWebLayer(layer)) scrollableLayer->setIsContainerForFixedPositionLayers(enable); } static void clearPositionConstraintExceptForLayer(GraphicsLayer* layer, GraphicsLayer* except) { - if (layer && layer != except && scrollingWebLayerForGraphicsLayer(layer)) - scrollingWebLayerForGraphicsLayer(layer)->setPositionConstraint(WebLayerPositionConstraint()); + if (layer && layer != except && toWebLayer(layer)) + toWebLayer(layer)->setPositionConstraint(WebLayerPositionConstraint()); } static WebLayerPositionConstraint computePositionConstraint(const RenderLayer* layer) @@ -200,13 +220,13 @@ void ScrollingCoordinator::updateLayerPositionConstraint(RenderLayer* layer) { ASSERT(layer->hasCompositedLayerMapping()); CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping(); - GraphicsLayer* mainLayer = compositedLayerMapping->childForSuperlayers(); + GraphicsLayer* mainLayer = compositedLayerMapping->localRootForOwningLayer(); // Avoid unnecessary commits clearPositionConstraintExceptForLayer(compositedLayerMapping->ancestorClippingLayer(), mainLayer); clearPositionConstraintExceptForLayer(compositedLayerMapping->mainGraphicsLayer(), mainLayer); - if (WebLayer* scrollableLayer = scrollingWebLayerForGraphicsLayer(mainLayer)) + if (WebLayer* scrollableLayer = toWebLayer(mainLayer)) scrollableLayer->setPositionConstraint(computePositionConstraint(layer)); } @@ -234,10 +254,10 @@ static PassOwnPtr<WebScrollbarLayer> createScrollbarLayer(Scrollbar* scrollbar) return scrollbarLayer.release(); } -PassOwnPtr<WebScrollbarLayer> ScrollingCoordinator::createSolidColorScrollbarLayer(ScrollbarOrientation orientation, int thumbThickness, bool isLeftSideVerticalScrollbar) +PassOwnPtr<WebScrollbarLayer> ScrollingCoordinator::createSolidColorScrollbarLayer(ScrollbarOrientation orientation, int thumbThickness, int trackStart, bool isLeftSideVerticalScrollbar) { blink::WebScrollbar::Orientation webOrientation = (orientation == HorizontalScrollbar) ? blink::WebScrollbar::Horizontal : blink::WebScrollbar::Vertical; - OwnPtr<WebScrollbarLayer> scrollbarLayer = adoptPtr(blink::Platform::current()->compositorSupport()->createSolidColorScrollbarLayer(webOrientation, thumbThickness, isLeftSideVerticalScrollbar)); + OwnPtr<WebScrollbarLayer> scrollbarLayer = adoptPtr(blink::Platform::current()->compositorSupport()->createSolidColorScrollbarLayer(webOrientation, thumbThickness, trackStart, isLeftSideVerticalScrollbar)); GraphicsLayer::registerContentsLayer(scrollbarLayer->layer()); return scrollbarLayer.release(); } @@ -250,7 +270,7 @@ static void detachScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer) scrollbarGraphicsLayer->setDrawsContent(true); } -static void setupScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer, WebScrollbarLayer* scrollbarLayer, WebLayer* scrollLayer) +static void setupScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer, WebScrollbarLayer* scrollbarLayer, WebLayer* scrollLayer, WebLayer* containerLayer) { ASSERT(scrollbarGraphicsLayer); ASSERT(scrollbarLayer); @@ -260,6 +280,7 @@ static void setupScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer, WebScroll return; } scrollbarLayer->setScrollLayer(scrollLayer); + scrollbarLayer->setClipLayer(containerLayer); scrollbarGraphicsLayer->setContentsToPlatformLayer(scrollbarLayer->layer()); scrollbarGraphicsLayer->setDrawsContent(false); } @@ -267,7 +288,7 @@ static void setupScrollbarLayer(GraphicsLayer* scrollbarGraphicsLayer, WebScroll WebScrollbarLayer* ScrollingCoordinator::addWebScrollbarLayer(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, PassOwnPtr<blink::WebScrollbarLayer> scrollbarLayer) { ScrollbarMap& scrollbars = orientation == HorizontalScrollbar ? m_horizontalScrollbars : m_verticalScrollbars; - return scrollbars.add(scrollableArea, scrollbarLayer).iterator->value.get(); + return scrollbars.add(scrollableArea, scrollbarLayer).storedValue->value.get(); } WebScrollbarLayer* ScrollingCoordinator::getWebScrollbarLayer(ScrollableArea* scrollableArea, ScrollbarOrientation orientation) @@ -296,7 +317,10 @@ void ScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(ScrollableArea* if (!isMainFrame && platformSupportsMainFrameOnly) return; - GraphicsLayer* scrollbarGraphicsLayer = orientation == HorizontalScrollbar ? horizontalScrollbarLayerForScrollableArea(scrollableArea) : verticalScrollbarLayerForScrollableArea(scrollableArea); + GraphicsLayer* scrollbarGraphicsLayer = orientation == HorizontalScrollbar + ? scrollableArea->layerForHorizontalScrollbar() + : scrollableArea->layerForVerticalScrollbar(); + if (scrollbarGraphicsLayer) { Scrollbar* scrollbar = orientation == HorizontalScrollbar ? scrollableArea->horizontalScrollbar() : scrollableArea->verticalScrollbar(); if (scrollbar->isCustomScrollbar()) { @@ -306,12 +330,12 @@ void ScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(ScrollableArea* WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea, orientation); if (!scrollbarLayer) { - Settings* settings = m_page->mainFrame()->document()->settings(); + Settings* settings = m_page->mainFrame()->settings(); OwnPtr<WebScrollbarLayer> webScrollbarLayer; if (settings->useSolidColorScrollbars()) { ASSERT(RuntimeEnabledFeatures::overlayScrollbarsEnabled()); - webScrollbarLayer = createSolidColorScrollbarLayer(orientation, scrollbar->theme()->thumbThickness(scrollbar), scrollableArea->shouldPlaceVerticalScrollbarOnLeft()); + webScrollbarLayer = createSolidColorScrollbarLayer(orientation, scrollbar->theme()->thumbThickness(scrollbar), scrollbar->theme()->trackPosition(scrollbar), scrollableArea->shouldPlaceVerticalScrollbarOnLeft()); } else { webScrollbarLayer = createScrollbarLayer(scrollbar); } @@ -325,64 +349,99 @@ void ScrollingCoordinator::scrollableAreaScrollbarLayerDidChange(ScrollableArea* scrollbarGraphicsLayer->setContentsOpaque(isMainFrame && isOpaqueScrollbar); scrollbarLayer->layer()->setOpaque(scrollbarGraphicsLayer->contentsOpaque()); - setupScrollbarLayer(scrollbarGraphicsLayer, scrollbarLayer, scrollingWebLayerForScrollableArea(scrollableArea)); + WebLayer* scrollLayer = toWebLayer(scrollableArea->layerForScrolling()); + WebLayer* containerLayer = toWebLayer(scrollableArea->layerForContainer()); + setupScrollbarLayer(scrollbarGraphicsLayer, scrollbarLayer, scrollLayer, containerLayer); } else removeWebScrollbarLayer(scrollableArea, orientation); } bool ScrollingCoordinator::scrollableAreaScrollLayerDidChange(ScrollableArea* scrollableArea) { - GraphicsLayer* scrollLayer = scrollLayerForScrollableArea(scrollableArea); + GraphicsLayer* scrollLayer = scrollableArea->layerForScrolling(); + if (scrollLayer) { - bool isMainFrame = isForMainFrame(scrollableArea); - scrollLayer->setScrollableArea(scrollableArea, isMainFrame); + ASSERT(m_page); + // With pinch virtual viewport we no longer need to special case the main frame. + bool pinchVirtualViewportEnabled = m_page->settings().pinchVirtualViewportEnabled(); + bool layerScrollShouldFireGraphicsLayerDidScroll = isForMainFrame(scrollableArea) && !pinchVirtualViewportEnabled; + scrollLayer->setScrollableArea(scrollableArea, layerScrollShouldFireGraphicsLayerDidScroll); } - WebLayer* webLayer = scrollingWebLayerForScrollableArea(scrollableArea); + WebLayer* webLayer = toWebLayer(scrollableArea->layerForScrolling()); + WebLayer* containerLayer = toWebLayer(scrollableArea->layerForContainer()); if (webLayer) { - webLayer->setScrollable(true); + webLayer->setScrollClipLayer(containerLayer); webLayer->setScrollPosition(IntPoint(scrollableArea->scrollPosition() - scrollableArea->minimumScrollPosition())); - webLayer->setMaxScrollPosition(IntSize(scrollableArea->scrollSize(HorizontalScrollbar), scrollableArea->scrollSize(VerticalScrollbar))); + webLayer->setBounds(scrollableArea->contentsSize()); bool canScrollX = scrollableArea->userInputScrollable(HorizontalScrollbar); bool canScrollY = scrollableArea->userInputScrollable(VerticalScrollbar); webLayer->setUserScrollable(canScrollX, canScrollY); } if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea, HorizontalScrollbar)) { - GraphicsLayer* horizontalScrollbarLayer = horizontalScrollbarLayerForScrollableArea(scrollableArea); + GraphicsLayer* horizontalScrollbarLayer = scrollableArea->layerForHorizontalScrollbar(); if (horizontalScrollbarLayer) - setupScrollbarLayer(horizontalScrollbarLayer, scrollbarLayer, webLayer); + setupScrollbarLayer(horizontalScrollbarLayer, scrollbarLayer, webLayer, containerLayer); } if (WebScrollbarLayer* scrollbarLayer = getWebScrollbarLayer(scrollableArea, VerticalScrollbar)) { - GraphicsLayer* verticalScrollbarLayer = verticalScrollbarLayerForScrollableArea(scrollableArea); + GraphicsLayer* verticalScrollbarLayer = scrollableArea->layerForVerticalScrollbar(); if (verticalScrollbarLayer) - setupScrollbarLayer(verticalScrollbarLayer, scrollbarLayer, webLayer); + setupScrollbarLayer(verticalScrollbarLayer, scrollbarLayer, webLayer, containerLayer); } return !!webLayer; } +typedef WTF::HashMap<const GraphicsLayer*, Vector<LayoutRect> > GraphicsLayerHitTestRects; + // In order to do a DFS cross-frame walk of the RenderLayer tree, we need to know which // RenderLayers have child frames inside of them. This computes a mapping for the // current frame which we can consult while walking the layers of that frame. // Whenever we descend into a new frame, a new map will be created. -typedef HashMap<const RenderLayer*, Vector<const Frame*> > LayerFrameMap; -static void makeLayerChildFrameMap(const Frame* currentFrame, LayerFrameMap* map) +typedef HashMap<const RenderLayer*, Vector<const LocalFrame*> > LayerFrameMap; +static void makeLayerChildFrameMap(const LocalFrame* currentFrame, LayerFrameMap* map) { map->clear(); const FrameTree& tree = currentFrame->tree(); for (const Frame* child = tree.firstChild(); child; child = child->tree().nextSibling()) { - const RenderLayer* containingLayer = child->ownerRenderer()->enclosingLayer(); + if (!child->isLocalFrame()) + continue; + const RenderObject* ownerRenderer = toLocalFrame(child)->ownerRenderer(); + if (!ownerRenderer) + continue; + const RenderLayer* containingLayer = ownerRenderer->enclosingLayer(); LayerFrameMap::iterator iter = map->find(containingLayer); if (iter == map->end()) - iter = map->add(containingLayer, Vector<const Frame*>()).iterator; - iter->value.append(child); + map->add(containingLayer, Vector<const LocalFrame*>()).storedValue->value.append(toLocalFrame(child)); + else + iter->value.append(toLocalFrame(child)); } } -static void convertLayerRectsToEnclosingCompositedLayerRecursive( +// Return the enclosingCompositedLayerForRepaint for the given RenderLayer +// including crossing frame boundaries. +static const RenderLayer* enclosingCompositedLayer(const RenderLayer* layer) +{ + RenderLayer* compositedLayer = 0; + while (!compositedLayer) { + compositedLayer = layer->enclosingCompositingLayerForRepaint(); + if (!compositedLayer) { + RenderObject* owner = layer->renderer()->frame()->ownerRenderer(); + if (!owner) + break; + layer = owner->enclosingLayer(); + } + } + // Since this machinery is used only when accelerated compositing is enabled, we expect + // that every layer should have an enclosing composited layer. + ASSERT(compositedLayer); + return compositedLayer; +} + +static void projectRectsToGraphicsLayerSpaceRecursive( const RenderLayer* curLayer, const LayerHitTestRects& layerRects, - LayerHitTestRects& compositorRects, + GraphicsLayerHitTestRects& graphicsRects, RenderGeometryMap& geometryMap, HashSet<const RenderLayer*>& layersWithRects, LayerFrameMap& layerChildFrameMap) @@ -391,27 +450,39 @@ static void convertLayerRectsToEnclosingCompositedLayerRecursive( LayerHitTestRects::const_iterator layerIter = layerRects.find(curLayer); if (layerIter != layerRects.end()) { // Find the enclosing composited layer when it's in another document (for non-composited iframes). - RenderLayer* compositedLayer = 0; - for (const RenderLayer* layer = layerIter->key; !compositedLayer;) { - compositedLayer = layer->enclosingCompositingLayerForRepaint(); - if (!compositedLayer) { - RenderObject* owner = layer->renderer()->frame()->ownerRenderer(); - if (!owner) - break; - layer = owner->enclosingLayer(); - } - } - if (!compositedLayer) { - // Since this machinery is used only when accelerated compositing is enabled, we expect - // that every layer should have an enclosing composited layer. - ASSERT_NOT_REACHED(); + const RenderLayer* compositedLayer = enclosingCompositedLayer(layerIter->key); + if (!compositedLayer) return; + + // Find the appropriate GraphicsLayer for the composited RenderLayer. + GraphicsLayer* graphicsLayer; + LayoutSize extraOffset; + if (compositedLayer->compositingState() == PaintsIntoGroupedBacking) { + graphicsLayer = compositedLayer->groupedMapping()->squashingLayer(); + extraOffset = -compositedLayer->offsetFromSquashingLayerOrigin(); + } else { + ASSERT(compositedLayer->hasCompositedLayerMapping()); + CompositedLayerMappingPtr compositedLayerMapping = compositedLayer->compositedLayerMapping(); + // The origin for the graphics layer does not have to be the same + // as the composited layer (e.g. when a child layer has negative + // offset and paints into this layer), so when projecting rects to + // graphics layer space they have to be offset by the origin for + // the composited layer. + extraOffset = compositedLayerMapping->contentOffsetInCompositingLayer(); + // If the layer is using composited scrolling, then it's the contents that these + // rects apply to. + graphicsLayer = compositedLayerMapping->scrollingContentsLayer(); + if (!graphicsLayer) + graphicsLayer = compositedLayerMapping->mainGraphicsLayer(); } - LayerHitTestRects::iterator compIter = compositorRects.find(compositedLayer); - if (compIter == compositorRects.end()) - compIter = compositorRects.add(compositedLayer, Vector<LayoutRect>()).iterator; - // Transform each rect to the co-ordinate space of it's enclosing composited layer. + GraphicsLayerHitTestRects::iterator glIter = graphicsRects.find(graphicsLayer); + Vector<LayoutRect>* glRects; + if (glIter == graphicsRects.end()) + glRects = &graphicsRects.add(graphicsLayer, Vector<LayoutRect>()).storedValue->value; + else + glRects = &glIter->value; + // Transform each rect to the co-ordinate space of the graphicsLayer. for (size_t i = 0; i < layerIter->value.size(); ++i) { LayoutRect rect = layerIter->value[i]; if (compositedLayer != curLayer) { @@ -423,7 +494,8 @@ static void convertLayerRectsToEnclosingCompositedLayerRecursive( if (compositedLayer->renderer()->hasOverflowClip()) rect.move(compositedLayer->renderBox()->scrolledContentOffset()); } - compIter->value.append(rect); + rect.move(extraOffset); + glRects->append(rect); } } @@ -431,7 +503,7 @@ static void convertLayerRectsToEnclosingCompositedLayerRecursive( for (const RenderLayer* childLayer = curLayer->firstChild(); childLayer; childLayer = childLayer->nextSibling()) { if (layersWithRects.contains(childLayer)) { geometryMap.pushMappingsToAncestor(childLayer, curLayer); - convertLayerRectsToEnclosingCompositedLayerRecursive(childLayer, layerRects, compositorRects, geometryMap, layersWithRects, layerChildFrameMap); + projectRectsToGraphicsLayerSpaceRecursive(childLayer, layerRects, graphicsRects, geometryMap, layersWithRects, layerChildFrameMap); geometryMap.popMappingsToAncestor(curLayer); } } @@ -440,22 +512,22 @@ static void convertLayerRectsToEnclosingCompositedLayerRecursive( LayerFrameMap::iterator mapIter = layerChildFrameMap.find(curLayer); if (mapIter != layerChildFrameMap.end()) { for (size_t i = 0; i < mapIter->value.size(); i++) { - const Frame* childFrame = mapIter->value[i]; + const LocalFrame* childFrame = mapIter->value[i]; const RenderLayer* childLayer = childFrame->view()->renderView()->layer(); if (layersWithRects.contains(childLayer)) { LayerFrameMap newLayerChildFrameMap; makeLayerChildFrameMap(childFrame, &newLayerChildFrameMap); geometryMap.pushMappingsToAncestor(childLayer, curLayer); - convertLayerRectsToEnclosingCompositedLayerRecursive(childLayer, layerRects, compositorRects, geometryMap, layersWithRects, newLayerChildFrameMap); + projectRectsToGraphicsLayerSpaceRecursive(childLayer, layerRects, graphicsRects, geometryMap, layersWithRects, newLayerChildFrameMap); geometryMap.popMappingsToAncestor(curLayer); } } } } -static void convertLayerRectsToEnclosingCompositedLayer(Frame* mainFrame, const LayerHitTestRects& layerRects, LayerHitTestRects& compositorRects) +static void projectRectsToGraphicsLayerSpace(LocalFrame* mainFrame, const LayerHitTestRects& layerRects, GraphicsLayerHitTestRects& graphicsRects) { - TRACE_EVENT0("input", "ScrollingCoordinator::convertLayerRectsToEnclosingCompositedLayer"); + TRACE_EVENT0("input", "ScrollingCoordinator::projectRectsToGraphicsLayerSpace"); bool touchHandlerInChildFrame = false; // We have a set of rects per RenderLayer, we need to map them to their bounding boxes in their @@ -482,10 +554,12 @@ static void convertLayerRectsToEnclosingCompositedLayer(Frame* mainFrame, const MapCoordinatesFlags flags = UseTransforms; if (touchHandlerInChildFrame) flags |= TraverseDocumentBoundaries; + RenderLayer* rootLayer = mainFrame->contentRenderer()->layer(); RenderGeometryMap geometryMap(flags); + geometryMap.pushMappingsToAncestor(rootLayer, 0); LayerFrameMap layerChildFrameMap; makeLayerChildFrameMap(mainFrame, &layerChildFrameMap); - convertLayerRectsToEnclosingCompositedLayerRecursive(mainFrame->contentRenderer()->layer(), layerRects, compositorRects, geometryMap, layersWithRects, layerChildFrameMap); + projectRectsToGraphicsLayerSpaceRecursive(rootLayer, layerRects, graphicsRects, geometryMap, layersWithRects, layerChildFrameMap); } void ScrollingCoordinator::updateTouchEventTargetRectsIfNeeded() @@ -502,6 +576,11 @@ void ScrollingCoordinator::updateTouchEventTargetRectsIfNeeded() void ScrollingCoordinator::reset() { + for (ScrollbarMap::iterator it = m_horizontalScrollbars.begin(); it != m_horizontalScrollbars.end(); ++it) + GraphicsLayer::unregisterContentsLayer(it->value->layer()); + for (ScrollbarMap::iterator it = m_verticalScrollbars.begin(); it != m_verticalScrollbars.end(); ++it) + GraphicsLayer::unregisterContentsLayer(it->value->layer()); + m_horizontalScrollbars.clear(); m_verticalScrollbars.clear(); m_layersWithTouchRects.clear(); @@ -514,63 +593,55 @@ void ScrollingCoordinator::reset() // Note that in principle this could be called more often than computeTouchEventTargetRects, for // example during a non-composited scroll (although that's not yet implemented - crbug.com/261307). -void ScrollingCoordinator::setTouchEventTargetRects(const LayerHitTestRects& layerRects) +void ScrollingCoordinator::setTouchEventTargetRects(LayerHitTestRects& layerRects) { TRACE_EVENT0("input", "ScrollingCoordinator::setTouchEventTargetRects"); - LayerHitTestRects compositorRects; - convertLayerRectsToEnclosingCompositedLayer(m_page->mainFrame(), layerRects, compositorRects); - + // Update the list of layers with touch hit rects. HashSet<const RenderLayer*> oldLayersWithTouchRects; m_layersWithTouchRects.swap(oldLayersWithTouchRects); + for (LayerHitTestRects::iterator it = layerRects.begin(); it != layerRects.end(); ++it) { + if (!it->value.isEmpty()) { + const RenderLayer* compositedLayer = enclosingCompositedLayer(it->key); + if (compositedLayer) + m_layersWithTouchRects.add(compositedLayer); + } + } - for (LayerHitTestRects::const_iterator iter = compositorRects.begin(); iter != compositorRects.end(); ++iter) { - const RenderLayer* layer = iter->key; + // Ensure we have an entry for each composited layer that previously had rects (so that old + // ones will get cleared out). Note that ideally we'd track this on GraphicsLayer instead of + // RenderLayer, but we have no good hook into the lifetime of a GraphicsLayer. + for (HashSet<const RenderLayer*>::iterator it = oldLayersWithTouchRects.begin(); it != oldLayersWithTouchRects.end(); ++it) { + if (!layerRects.contains(*it)) + layerRects.add(*it, Vector<LayoutRect>()); + } + + GraphicsLayerHitTestRects graphicsLayerRects; + projectRectsToGraphicsLayerSpace(m_page->deprecatedLocalMainFrame(), layerRects, graphicsLayerRects); + + for (GraphicsLayerHitTestRects::const_iterator iter = graphicsLayerRects.begin(); iter != graphicsLayerRects.end(); ++iter) { + const GraphicsLayer* graphicsLayer = iter->key; WebVector<WebRect> webRects(iter->value.size()); for (size_t i = 0; i < iter->value.size(); ++i) webRects[i] = enclosingIntRect(iter->value[i]); - // This should be ensured by convertLayerRectsToEnclosingCompositedLayer above. - ASSERT(layer->hasCompositedLayerMapping()); - CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping(); - // If the layer is using composited scrolling, then it's the contents that these - // rects apply to. - GraphicsLayer* graphicsLayer = compositedLayerMapping->scrollingContentsLayer(); - if (!graphicsLayer) - graphicsLayer = compositedLayerMapping->mainGraphicsLayer(); graphicsLayer->platformLayer()->setTouchEventHandlerRegion(webRects); - oldLayersWithTouchRects.remove(layer); - m_layersWithTouchRects.add(layer); - } - - // If there are any layers left that we haven't updated, clear them out. - for (HashSet<const RenderLayer*>::iterator it = oldLayersWithTouchRects.begin(); it != oldLayersWithTouchRects.end(); ++it) { - // FIXME: This is a bug. What's happening here is that we're clearing touch regions for - // layers that we didn't visit above. That assumes a 1:1 mapping between RenderLayer and - // the graphics layer that owns the touch rects. This is false in the case of - // HasOwnBackingButPaintsIntoAncestor and will be extra-false in the world of squashing. - if ((*it)->hasCompositedLayerMapping()) { - GraphicsLayer* graphicsLayer = (*it)->compositedLayerMapping()->scrollingContentsLayer(); - if (!graphicsLayer) - graphicsLayer = (*it)->compositedLayerMapping()->mainGraphicsLayer(); - graphicsLayer->platformLayer()->setTouchEventHandlerRegion(WebVector<WebRect>()); - } } } -void ScrollingCoordinator::touchEventTargetRectsDidChange(const Document*) +void ScrollingCoordinator::touchEventTargetRectsDidChange() { if (!touchHitTestingEnabled()) return; // Wait until after layout to update. - if (m_page->mainFrame()->view()->needsLayout()) + if (!m_page->deprecatedLocalMainFrame()->view() || m_page->deprecatedLocalMainFrame()->view()->needsLayout()) return; // FIXME: scheduleAnimation() is just a method of forcing the compositor to realize that it // needs to commit here. We should expose a cleaner API for this. - RenderView* renderView = m_page->mainFrame()->contentRenderer(); - if (renderView && renderView->compositor() && renderView->compositor()->inCompositingMode()) - m_page->mainFrame()->view()->scheduleAnimation(); + RenderView* renderView = m_page->deprecatedLocalMainFrame()->contentRenderer(); + if (renderView && renderView->compositor() && renderView->compositor()->staleInCompositingMode()) + m_page->deprecatedLocalMainFrame()->view()->scheduleAnimation(); m_touchEventTargetRectsAreDirty = true; } @@ -579,7 +650,7 @@ void ScrollingCoordinator::updateScrollParentForGraphicsLayer(GraphicsLayer* chi { WebLayer* scrollParentWebLayer = 0; if (parent && parent->hasCompositedLayerMapping()) - scrollParentWebLayer = scrollingWebLayerForGraphicsLayer(parent->compositedLayerMapping()->parentForSublayers()); + scrollParentWebLayer = toWebLayer(parent->compositedLayerMapping()->scrollingContentsLayer()); child->setScrollParent(scrollParentWebLayer); } @@ -588,7 +659,7 @@ void ScrollingCoordinator::updateClipParentForGraphicsLayer(GraphicsLayer* child { WebLayer* clipParentWebLayer = 0; if (parent && parent->hasCompositedLayerMapping()) - clipParentWebLayer = scrollingWebLayerForGraphicsLayer(parent->compositedLayerMapping()->parentForSublayers()); + clipParentWebLayer = toWebLayer(parent->compositedLayerMapping()->parentForSublayers()); child->setClipParent(clipParentWebLayer); } @@ -598,29 +669,53 @@ void ScrollingCoordinator::willDestroyRenderLayer(RenderLayer* layer) m_layersWithTouchRects.remove(layer); } -void ScrollingCoordinator::setWheelEventHandlerCount(unsigned count) +void ScrollingCoordinator::updateHaveWheelEventHandlers() { - if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainFrame()->view())) - scrollLayer->setHaveWheelEventHandlers(count > 0); + ASSERT(isMainThread()); + ASSERT(m_page); + if (!m_page->mainFrame()->isLocalFrame() || !m_page->deprecatedLocalMainFrame()->view()) + return; + + if (WebLayer* scrollLayer = toWebLayer(m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) { + bool haveHandlers = m_page->frameHost().eventHandlerRegistry().hasEventHandlers(EventHandlerRegistry::WheelEvent); + scrollLayer->setHaveWheelEventHandlers(haveHandlers); + } } -void ScrollingCoordinator::recomputeWheelEventHandlerCountForFrameView(FrameView*) +void ScrollingCoordinator::updateHaveScrollEventHandlers() { - setWheelEventHandlerCount(computeCurrentWheelEventHandlerCount()); + ASSERT(isMainThread()); + ASSERT(m_page); + if (!m_page->mainFrame()->isLocalFrame() || !m_page->deprecatedLocalMainFrame()->view()) + return; + + // Currently the compositor only cares whether there are scroll handlers anywhere on the page + // instead on a per-layer basis. We therefore only update this information for the root + // scrolling layer. + if (WebLayer* scrollLayer = toWebLayer(m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) { + bool haveHandlers = m_page->frameHost().eventHandlerRegistry().hasEventHandlers(EventHandlerRegistry::ScrollEvent); + scrollLayer->setHaveScrollEventHandlers(haveHandlers); + } } void ScrollingCoordinator::setShouldUpdateScrollLayerPositionOnMainThread(MainThreadScrollingReasons reasons) { - if (WebLayer* scrollLayer = scrollingWebLayerForScrollableArea(m_page->mainFrame()->view())) { + if (!m_page->mainFrame()->isLocalFrame()) + return; + if (WebLayer* scrollLayer = toWebLayer(m_page->deprecatedLocalMainFrame()->view()->layerForScrolling())) { m_lastMainThreadScrollingReasons = reasons; scrollLayer->setShouldScrollOnMainThread(reasons); } } -void ScrollingCoordinator::pageDestroyed() +void ScrollingCoordinator::willBeDestroyed() { ASSERT(m_page); m_page = 0; + for (ScrollbarMap::iterator it = m_horizontalScrollbars.begin(); it != m_horizontalScrollbars.end(); ++it) + GraphicsLayer::unregisterContentsLayer(it->value->layer()); + for (ScrollbarMap::iterator it = m_verticalScrollbars.begin(); it != m_verticalScrollbars.end(); ++it) + GraphicsLayer::unregisterContentsLayer(it->value->layer()); } bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView) const @@ -632,14 +727,17 @@ bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView if (&frameView->frame() != m_page->mainFrame()) return false; + if (!m_page->mainFrame()->isLocalFrame()) + return false; + // We currently only support composited mode. - RenderView* renderView = m_page->mainFrame()->contentRenderer(); + RenderView* renderView = m_page->deprecatedLocalMainFrame()->contentRenderer(); if (!renderView) return false; return renderView->usesCompositing(); } -Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion(const Frame* frame, const IntPoint& frameLocation) const +Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion(const LocalFrame* frame, const IntPoint& frameLocation) const { Region shouldHandleScrollGestureOnMainThreadRegion; FrameView* frameView = frame->view(); @@ -680,15 +778,17 @@ Region ScrollingCoordinator::computeShouldHandleScrollGestureOnMainThreadRegion( if (!(*it)->isPluginView()) continue; - PluginView* pluginView = toPluginView((*it).get()); + PluginView* pluginView = toPluginView(it->get()); if (pluginView->wantsWheelEvents()) shouldHandleScrollGestureOnMainThreadRegion.unite(pluginView->frameRect()); } } const FrameTree& tree = frame->tree(); - for (Frame* subFrame = tree.firstChild(); subFrame; subFrame = subFrame->tree().nextSibling()) - shouldHandleScrollGestureOnMainThreadRegion.unite(computeShouldHandleScrollGestureOnMainThreadRegion(subFrame, offset)); + for (Frame* subFrame = tree.firstChild(); subFrame; subFrame = subFrame->tree().nextSibling()) { + if (subFrame->isLocalFrame()) + shouldHandleScrollGestureOnMainThreadRegion.unite(computeShouldHandleScrollGestureOnMainThreadRegion(toLocalFrame(subFrame), offset)); + } return shouldHandleScrollGestureOnMainThreadRegion; } @@ -705,13 +805,19 @@ static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects, co // then we can quickly mark the entire document and skip looking at any other handlers. // Note that technically a handler on the body doesn't cover the whole document, but it's // reasonable to be conservative and report the whole document anyway. - for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { - Node* target = iter->key; - if (target == document || target == document->documentElement() || target == document->body()) { - if (RenderObject* renderer = document->renderer()) { - renderer->computeLayerHitTestRects(rects); + // + // Fullscreen HTML5 video when OverlayFullscreenVideo is enabled is implemented by replacing the + // root cc::layer with the video layer so doing this optimization causes the compositor to think + // that there are no handlers, therefore skip it. + if (!document->renderView()->compositor()->inOverlayFullscreenVideo()) { + for (TouchEventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) { + Node* target = iter->key; + if (target == document || target == document->documentElement() || target == document->body()) { + if (RenderView* rendererView = document->renderView()) { + rendererView->computeLayerHitTestRects(rects); + } + return; } - return; } } @@ -720,8 +826,7 @@ static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects, co if (!target->inDocument()) continue; - if (target->isDocumentNode()) { - ASSERT(target != document); + if (target->isDocumentNode() && target != document) { accumulateDocumentTouchEventTargetRects(rects, toDocument(target)); } else if (RenderObject* renderer = target->renderer()) { // If the set also contains one of our ancestor nodes then processing @@ -731,8 +836,24 @@ static void accumulateDocumentTouchEventTargetRects(LayerHitTestRects& rects, co if (targets->contains(ancestor)) hasTouchEventTargetAncestor = true; } - if (!hasTouchEventTargetAncestor) + if (!hasTouchEventTargetAncestor) { + // Walk up the tree to the outermost non-composited scrollable layer. + RenderLayer* enclosingNonCompositedScrollLayer = 0; + for (RenderLayer* parent = renderer->enclosingLayer(); parent && parent->compositingState() == NotComposited; parent = parent->parent()) { + if (parent->scrollsOverflow()) + enclosingNonCompositedScrollLayer = parent; + } + + // Report the whole non-composited scroll layer as a touch hit rect because any + // rects inside of it may move around relative to their enclosing composited layer + // without causing the rects to be recomputed. Non-composited scrolling occurs on + // the main thread, so we're not getting much benefit from compositor touch hit + // testing in this case anyway. + if (enclosingNonCompositedScrollLayer) + enclosingNonCompositedScrollLayer->computeSelfHitTestRects(rects); + renderer->computeLayerHitTestRects(rects); + } } } @@ -743,33 +864,13 @@ void ScrollingCoordinator::computeTouchEventTargetRects(LayerHitTestRects& rects TRACE_EVENT0("input", "ScrollingCoordinator::computeTouchEventTargetRects"); ASSERT(touchHitTestingEnabled()); - Document* document = m_page->mainFrame()->document(); + Document* document = m_page->deprecatedLocalMainFrame()->document(); if (!document || !document->view()) return; accumulateDocumentTouchEventTargetRects(rects, document); } -unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount() -{ - unsigned wheelEventHandlerCount = 0; - - for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { - if (frame->document()) - wheelEventHandlerCount += WheelController::from(frame->document())->wheelEventHandlerCount(); - } - - return wheelEventHandlerCount; -} - -void ScrollingCoordinator::frameViewWheelEventHandlerCountChanged(FrameView* frameView) -{ - ASSERT(isMainThread()); - ASSERT(m_page); - - recomputeWheelEventHandlerCountForFrameView(frameView); -} - void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* frameView) { ASSERT(isMainThread()); @@ -778,7 +879,7 @@ void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* fr if (!coordinatesScrollingForFrameView(frameView)) return; - updateShouldUpdateScrollLayerPositionOnMainThread(); + m_shouldScrollOnMainThreadDirty = true; } void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView) @@ -789,40 +890,12 @@ void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView) if (!coordinatesScrollingForFrameView(frameView)) return; - updateShouldUpdateScrollLayerPositionOnMainThread(); -} - -GraphicsLayer* ScrollingCoordinator::scrollLayerForScrollableArea(ScrollableArea* scrollableArea) -{ - return scrollableArea->layerForScrolling(); -} - -GraphicsLayer* ScrollingCoordinator::horizontalScrollbarLayerForScrollableArea(ScrollableArea* scrollableArea) -{ - return scrollableArea->layerForHorizontalScrollbar(); -} - -GraphicsLayer* ScrollingCoordinator::verticalScrollbarLayerForScrollableArea(ScrollableArea* scrollableArea) -{ - return scrollableArea->layerForVerticalScrollbar(); + m_shouldScrollOnMainThreadDirty = true; } bool ScrollingCoordinator::isForMainFrame(ScrollableArea* scrollableArea) const { - return scrollableArea == m_page->mainFrame()->view(); -} - -GraphicsLayer* ScrollingCoordinator::scrollLayerForFrameView(FrameView* frameView) -{ - RenderView* renderView = frameView->frame().contentRenderer(); - if (!renderView) - return 0; - return renderView->compositor()->scrollLayer(); -} - -GraphicsLayer* ScrollingCoordinator::counterScrollingLayerForFrameView(FrameView*) -{ - return 0; + return m_page->mainFrame()->isLocalFrame() ? scrollableArea == m_page->deprecatedLocalMainFrame()->view() : false; } void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView) @@ -834,8 +907,8 @@ void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView) return; notifyLayoutUpdated(); - recomputeWheelEventHandlerCountForFrameView(frameView); - updateShouldUpdateScrollLayerPositionOnMainThread(); + updateHaveWheelEventHandlers(); + updateHaveScrollEventHandlers(); } #if OS(MACOSX) @@ -846,7 +919,7 @@ void ScrollingCoordinator::handleWheelEventPhase(PlatformWheelEventPhase phase) if (!m_page) return; - FrameView* frameView = m_page->mainFrame()->view(); + FrameView* frameView = m_page->deprecatedLocalMainFrame()->view(); if (!frameView) return; @@ -882,7 +955,9 @@ MainThreadScrollingReasons ScrollingCoordinator::mainThreadScrollingReasons() co // The main thread scrolling reasons are applicable to scrolls of the main // frame. If it does not exist or if it is not scrollable, there is no // reason to force main thread scrolling. - FrameView* frameView = m_page->mainFrame()->view(); + if (!m_page->mainFrame()->isLocalFrame()) + return static_cast<MainThreadScrollingReasons>(0); + FrameView* frameView = m_page->deprecatedLocalMainFrame()->view(); if (!frameView) return static_cast<MainThreadScrollingReasons>(0); @@ -896,11 +971,6 @@ MainThreadScrollingReasons ScrollingCoordinator::mainThreadScrollingReasons() co return mainThreadScrollingReasons; } -void ScrollingCoordinator::updateShouldUpdateScrollLayerPositionOnMainThread() -{ - setShouldUpdateScrollLayerPositionOnMainThread(mainThreadScrollingReasons()); -} - String ScrollingCoordinator::mainThreadScrollingReasonsAsText(MainThreadScrollingReasons reasons) { StringBuilder stringBuilder; @@ -919,14 +989,20 @@ String ScrollingCoordinator::mainThreadScrollingReasonsAsText(MainThreadScrollin String ScrollingCoordinator::mainThreadScrollingReasonsAsText() const { + ASSERT(m_page->deprecatedLocalMainFrame()->document()->lifecycle().state() >= DocumentLifecycle::CompositingClean); return mainThreadScrollingReasonsAsText(m_lastMainThreadScrollingReasons); } -bool ScrollingCoordinator::frameViewIsScrollableIsDirty() const +bool ScrollingCoordinator::frameViewIsDirty() const { - FrameView* frameView = m_page->mainFrame()->view(); + FrameView* frameView = m_page->mainFrame()->isLocalFrame() ? m_page->deprecatedLocalMainFrame()->view() : 0; bool frameIsScrollable = frameView && frameView->isScrollable(); - return frameIsScrollable != m_wasFrameScrollable; + if (frameIsScrollable != m_wasFrameScrollable) + return true; + + if (WebLayer* scrollLayer = frameView ? toWebLayer(frameView->layerForScrolling()) : 0) + return blink::WebSize(frameView->contentsSize()) != scrollLayer->bounds(); + return false; } } // namespace WebCore |