summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/page/scrolling/ScrollingCoordinator.cpp')
-rw-r--r--Source/WebCore/page/scrolling/ScrollingCoordinator.cpp345
1 files changed, 217 insertions, 128 deletions
diff --git a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
index 93dfb0cec..ff34266a7 100644
--- a/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
+++ b/Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
@@ -28,6 +28,7 @@
#include "ScrollingCoordinator.h"
#include "Document.h"
+#include "EventNames.h"
#include "FrameView.h"
#include "GraphicsLayer.h"
#include "IntRect.h"
@@ -36,35 +37,38 @@
#include "PlatformWheelEvent.h"
#include "PluginViewBase.h"
#include "Region.h"
+#include "RenderLayerCompositor.h"
#include "RenderView.h"
#include "ScrollAnimator.h"
+#include "Settings.h"
+#include "TextStream.h"
#include <wtf/MainThread.h>
#include <wtf/text/StringBuilder.h>
-#if USE(ACCELERATED_COMPOSITING)
-#include "RenderLayerCompositor.h"
-#endif
-
#if USE(COORDINATED_GRAPHICS)
#include "ScrollingCoordinatorCoordinatedGraphics.h"
#endif
+#if ENABLE(WEB_REPLAY)
+#include "ReplayController.h"
+#include <replay/InputCursor.h>
+#endif
+
namespace WebCore {
-#if !PLATFORM(MAC)
-PassRefPtr<ScrollingCoordinator> ScrollingCoordinator::create(Page* page)
+#if !PLATFORM(COCOA)
+Ref<ScrollingCoordinator> ScrollingCoordinator::create(Page* page)
{
#if USE(COORDINATED_GRAPHICS)
- return adoptRef(new ScrollingCoordinatorCoordinatedGraphics(page));
+ return adoptRef(*new ScrollingCoordinatorCoordinatedGraphics(page));
#endif
- return adoptRef(new ScrollingCoordinator(page));
+ return adoptRef(*new ScrollingCoordinator(page));
}
#endif
ScrollingCoordinator::ScrollingCoordinator(Page* page)
: m_page(page)
- , m_forceSynchronousScrollLayerPositionUpdates(false)
{
}
@@ -76,88 +80,112 @@ ScrollingCoordinator::~ScrollingCoordinator()
void ScrollingCoordinator::pageDestroyed()
{
ASSERT(m_page);
- m_page = 0;
+ m_page = nullptr;
}
-bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView) const
+bool ScrollingCoordinator::coordinatesScrollingForFrameView(const FrameView& frameView) const
{
ASSERT(isMainThread());
ASSERT(m_page);
- // We currently only handle the main frame.
- if (!frameView->frame().isMainFrame())
+ if (!frameView.frame().isMainFrame() && !m_page->settings().scrollingTreeIncludesFrames())
return false;
- // We currently only support composited mode.
-#if USE(ACCELERATED_COMPOSITING)
RenderView* renderView = m_page->mainFrame().contentRenderer();
if (!renderView)
return false;
return renderView->usesCompositing();
-#else
- return false;
-#endif
}
-Region ScrollingCoordinator::computeNonFastScrollableRegion(const Frame* frame, const IntPoint& frameLocation) const
+EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegionsForFrame(const Frame& frame) const
{
- Region nonFastScrollableRegion;
- FrameView* frameView = frame->view();
+ auto* renderView = frame.contentRenderer();
+ if (!renderView || renderView->renderTreeBeingDestroyed())
+ return EventTrackingRegions();
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+ // On iOS, we use nonFastScrollableRegion to represent the region covered by elements with touch event handlers.
+ ASSERT(frame.isMainFrame());
+ auto* document = frame.document();
+ if (!document)
+ return EventTrackingRegions();
+ return document->eventTrackingRegions();
+#else
+ auto* frameView = frame.view();
if (!frameView)
- return nonFastScrollableRegion;
+ return EventTrackingRegions();
- IntPoint offset = frameLocation;
- offset.moveBy(frameView->frameRect().location());
+ Region nonFastScrollableRegion;
- if (const FrameView::ScrollableAreaSet* scrollableAreas = frameView->scrollableAreas()) {
- for (FrameView::ScrollableAreaSet::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
- ScrollableArea* scrollableArea = *it;
-#if USE(ACCELERATED_COMPOSITING)
+ // FIXME: should ASSERT(!frameView->needsLayout()) here, but need to fix DebugPageOverlays
+ // to not ask for regions at bad times.
+
+ if (auto* scrollableAreas = frameView->scrollableAreas()) {
+ for (auto& scrollableArea : *scrollableAreas) {
// Composited scrollable areas can be scrolled off the main thread.
- if (scrollableArea->usesCompositedScrolling())
+ if (scrollableArea->usesAsyncScrolling())
continue;
-#endif
- IntRect box = scrollableArea->scrollableAreaBoundingBox();
- box.moveBy(offset);
+
+ bool isInsideFixed;
+ IntRect box = scrollableArea->scrollableAreaBoundingBox(&isInsideFixed);
+ if (isInsideFixed)
+ box = IntRect(frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(box)));
+
nonFastScrollableRegion.unite(box);
}
}
- for (auto it = frameView->children().begin(), end = frameView->children().end(); it != end; ++it) {
- if (!(*it)->isPluginViewBase())
+ for (auto& widget : frameView->widgetsInRenderTree()) {
+ if (!is<PluginViewBase>(*widget))
+ continue;
+ if (!downcast<PluginViewBase>(*widget).wantsWheelEvents())
+ continue;
+ auto* renderWidget = RenderWidget::find(*widget);
+ if (!renderWidget)
continue;
- PluginViewBase* pluginViewBase = toPluginViewBase((*it).get());
- if (pluginViewBase->wantsWheelEvents())
- nonFastScrollableRegion.unite(pluginViewBase->frameRect());
+ nonFastScrollableRegion.unite(renderWidget->absoluteBoundingBoxRect());
}
+
+ EventTrackingRegions eventTrackingRegions;
- for (Frame* subframe = frame->tree().firstChild(); subframe; subframe = subframe->tree().nextSibling())
- nonFastScrollableRegion.unite(computeNonFastScrollableRegion(subframe, offset));
+ // FIXME: if we've already accounted for this subframe as a scrollable area, we can avoid recursing into it here.
+ for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().nextSibling()) {
+ auto* subframeView = subframe->view();
+ if (!subframeView)
+ continue;
- return nonFastScrollableRegion;
-}
+ EventTrackingRegions subframeRegion = absoluteEventTrackingRegionsForFrame(*subframe);
+ // Map from the frame document to our document.
+ IntPoint offset = subframeView->contentsToContainingViewContents(IntPoint());
-unsigned ScrollingCoordinator::computeCurrentWheelEventHandlerCount()
-{
- unsigned wheelEventHandlerCount = 0;
+ // FIXME: this translation ignores non-trival transforms on the frame.
+ subframeRegion.translate(toIntSize(offset));
+ eventTrackingRegions.unite(subframeRegion);
+ }
- for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (frame->document())
- wheelEventHandlerCount += frame->document()->wheelEventHandlerCount();
+ auto wheelHandlerRegion = frame.document()->absoluteRegionForEventTargets(frame.document()->wheelEventTargets());
+ bool wheelHandlerInFixedContent = wheelHandlerRegion.second;
+ if (wheelHandlerInFixedContent) {
+ // FIXME: need to handle position:sticky here too.
+ LayoutRect inflatedWheelHandlerBounds = frameView->fixedScrollableAreaBoundsInflatedForScrolling(LayoutRect(wheelHandlerRegion.first.bounds()));
+ wheelHandlerRegion.first.unite(enclosingIntRect(inflatedWheelHandlerBounds));
}
+
+ nonFastScrollableRegion.unite(wheelHandlerRegion.first);
+
+ // FIXME: If this is not the main frame, we could clip the region to the frame's bounds.
+ eventTrackingRegions.uniteSynchronousRegion(eventNames().wheelEvent, nonFastScrollableRegion);
- return wheelEventHandlerCount;
+ return eventTrackingRegions;
+#endif
}
-void ScrollingCoordinator::frameViewWheelEventHandlerCountChanged(FrameView* frameView)
+EventTrackingRegions ScrollingCoordinator::absoluteEventTrackingRegions() const
{
- ASSERT(isMainThread());
- ASSERT(m_page);
-
- recomputeWheelEventHandlerCountForFrameView(frameView);
+ return absoluteEventTrackingRegionsForFrame(m_page->mainFrame());
}
-void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* frameView)
+void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView& frameView)
{
ASSERT(isMainThread());
ASSERT(m_page);
@@ -165,10 +193,10 @@ void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* fr
if (!coordinatesScrollingForFrameView(frameView))
return;
- updateSynchronousScrollingReasons();
+ updateSynchronousScrollingReasons(frameView);
}
-void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView)
+void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView& frameView)
{
ASSERT(isMainThread());
ASSERT(m_page);
@@ -176,75 +204,80 @@ void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView)
if (!coordinatesScrollingForFrameView(frameView))
return;
- updateSynchronousScrollingReasons();
+ updateSynchronousScrollingReasons(frameView);
}
-#if USE(ACCELERATED_COMPOSITING)
-GraphicsLayer* ScrollingCoordinator::scrollLayerForScrollableArea(ScrollableArea* scrollableArea)
+GraphicsLayer* ScrollingCoordinator::scrollLayerForScrollableArea(ScrollableArea& scrollableArea)
{
- return scrollableArea->layerForScrolling();
+ return scrollableArea.layerForScrolling();
}
-GraphicsLayer* ScrollingCoordinator::horizontalScrollbarLayerForScrollableArea(ScrollableArea* scrollableArea)
+GraphicsLayer* ScrollingCoordinator::scrollLayerForFrameView(FrameView& frameView)
{
- return scrollableArea->layerForHorizontalScrollbar();
-}
-
-GraphicsLayer* ScrollingCoordinator::verticalScrollbarLayerForScrollableArea(ScrollableArea* scrollableArea)
-{
- return scrollableArea->layerForVerticalScrollbar();
-}
-#endif
-
-GraphicsLayer* ScrollingCoordinator::scrollLayerForFrameView(FrameView* frameView)
-{
-#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* renderView = frameView->frame().contentRenderer())
+ if (RenderView* renderView = frameView.frame().contentRenderer())
return renderView->compositor().scrollLayer();
- return 0;
-#else
- UNUSED_PARAM(frameView);
- return 0;
-#endif
+ return nullptr;
}
-GraphicsLayer* ScrollingCoordinator::headerLayerForFrameView(FrameView* frameView)
+GraphicsLayer* ScrollingCoordinator::headerLayerForFrameView(FrameView& frameView)
{
-#if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING)
- if (RenderView* renderView = frameView->frame().contentRenderer())
- renderView->compositor().headerLayer();
- return 0;
+#if ENABLE(RUBBER_BANDING)
+ if (RenderView* renderView = frameView.frame().contentRenderer())
+ return renderView->compositor().headerLayer();
+ return nullptr;
#else
UNUSED_PARAM(frameView);
- return 0;
+ return nullptr;
#endif
}
-GraphicsLayer* ScrollingCoordinator::footerLayerForFrameView(FrameView* frameView)
+GraphicsLayer* ScrollingCoordinator::footerLayerForFrameView(FrameView& frameView)
{
-#if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING)
- if (RenderView* renderView = frameView->frame().contentRenderer())
+#if ENABLE(RUBBER_BANDING)
+ if (RenderView* renderView = frameView.frame().contentRenderer())
return renderView->compositor().footerLayer();
- return 0;
+ return nullptr;
#else
UNUSED_PARAM(frameView);
- return 0;
+ return nullptr;
#endif
}
-GraphicsLayer* ScrollingCoordinator::counterScrollingLayerForFrameView(FrameView* frameView)
+GraphicsLayer* ScrollingCoordinator::counterScrollingLayerForFrameView(FrameView& frameView)
{
-#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* renderView = frameView->frame().contentRenderer())
+ if (RenderView* renderView = frameView.frame().contentRenderer())
return renderView->compositor().fixedRootBackgroundLayer();
- return 0;
+ return nullptr;
+}
+
+GraphicsLayer* ScrollingCoordinator::insetClipLayerForFrameView(FrameView& frameView)
+{
+ if (RenderView* renderView = frameView.frame().contentRenderer())
+ return renderView->compositor().clipLayer();
+ return nullptr;
+}
+
+GraphicsLayer* ScrollingCoordinator::contentShadowLayerForFrameView(FrameView& frameView)
+{
+#if ENABLE(RUBBER_BANDING)
+ if (RenderView* renderView = frameView.frame().contentRenderer())
+ return renderView->compositor().layerForContentShadow();
+
+ return nullptr;
#else
UNUSED_PARAM(frameView);
- return 0;
+ return nullptr;
#endif
}
-void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView)
+GraphicsLayer* ScrollingCoordinator::rootContentLayerForFrameView(FrameView& frameView)
+{
+ if (RenderView* renderView = frameView.frame().contentRenderer())
+ return renderView->compositor().rootContentLayer();
+ return nullptr;
+}
+
+void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView& frameView)
{
ASSERT(isMainThread());
ASSERT(m_page);
@@ -253,11 +286,10 @@ void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView)
return;
frameViewLayoutUpdated(frameView);
- recomputeWheelEventHandlerCountForFrameView(frameView);
- updateSynchronousScrollingReasons();
+ updateSynchronousScrollingReasons(frameView);
}
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
void ScrollingCoordinator::handleWheelEventPhase(PlatformWheelEventPhase phase)
{
ASSERT(isMainThread());
@@ -269,57 +301,58 @@ void ScrollingCoordinator::handleWheelEventPhase(PlatformWheelEventPhase phase)
if (!frameView)
return;
- frameView->scrollAnimator()->handleWheelEventPhase(phase);
+ frameView->scrollAnimator().handleWheelEventPhase(phase);
}
#endif
-bool ScrollingCoordinator::hasVisibleSlowRepaintViewportConstrainedObjects(FrameView* frameView) const
+bool ScrollingCoordinator::hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView& frameView) const
{
- const FrameView::ViewportConstrainedObjectSet* viewportConstrainedObjects = frameView->viewportConstrainedObjects();
+ const FrameView::ViewportConstrainedObjectSet* viewportConstrainedObjects = frameView.viewportConstrainedObjects();
if (!viewportConstrainedObjects)
return false;
-#if USE(ACCELERATED_COMPOSITING)
- for (FrameView::ViewportConstrainedObjectSet::const_iterator it = viewportConstrainedObjects->begin(), end = viewportConstrainedObjects->end(); it != end; ++it) {
- RenderObject* viewportConstrainedObject = *it;
- if (!viewportConstrainedObject->isBoxModelObject() || !viewportConstrainedObject->hasLayer())
+ for (auto& viewportConstrainedObject : *viewportConstrainedObjects) {
+ if (!is<RenderBoxModelObject>(*viewportConstrainedObject) || !viewportConstrainedObject->hasLayer())
return true;
- RenderLayer* layer = toRenderBoxModelObject(viewportConstrainedObject)->layer();
+ RenderLayer& layer = *downcast<RenderBoxModelObject>(*viewportConstrainedObject).layer();
// Any explicit reason that a fixed position element is not composited shouldn't cause slow scrolling.
- if (!layer->isComposited() && layer->viewportConstrainedNotCompositedReason() == RenderLayer::NoNotCompositedReason)
+ if (!layer.isComposited() && layer.viewportConstrainedNotCompositedReason() == RenderLayer::NoNotCompositedReason)
return true;
}
return false;
-#else
- return viewportConstrainedObjects->size();
-#endif
}
-SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons() const
+SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons(const FrameView& frameView) const
{
- FrameView* frameView = m_page->mainFrame().view();
- if (!frameView)
- return static_cast<SynchronousScrollingReasons>(0);
-
SynchronousScrollingReasons synchronousScrollingReasons = (SynchronousScrollingReasons)0;
if (m_forceSynchronousScrollLayerPositionUpdates)
synchronousScrollingReasons |= ForcedOnMainThread;
- if (frameView->hasSlowRepaintObjects())
+#if ENABLE(WEB_REPLAY)
+ InputCursor& cursor = m_page->replayController().activeInputCursor();
+ if (cursor.isCapturing() || cursor.isReplaying())
+ synchronousScrollingReasons |= ForcedOnMainThread;
+#endif
+ if (frameView.hasSlowRepaintObjects())
synchronousScrollingReasons |= HasSlowRepaintObjects;
- if (!supportsFixedPositionLayers() && frameView->hasViewportConstrainedObjects())
+ if (!supportsFixedPositionLayers() && frameView.hasViewportConstrainedObjects())
synchronousScrollingReasons |= HasViewportConstrainedObjectsWithoutSupportingFixedLayers;
if (supportsFixedPositionLayers() && hasVisibleSlowRepaintViewportConstrainedObjects(frameView))
synchronousScrollingReasons |= HasNonLayerViewportConstrainedObjects;
- if (m_page->mainFrame().document() && m_page->mainFrame().document()->isImageDocument())
+ if (frameView.frame().mainFrame().document() && frameView.frame().document()->isImageDocument())
synchronousScrollingReasons |= IsImageDocument;
return synchronousScrollingReasons;
}
-void ScrollingCoordinator::updateSynchronousScrollingReasons()
+void ScrollingCoordinator::updateSynchronousScrollingReasons(const FrameView& frameView)
{
- setSynchronousScrollingReasons(synchronousScrollingReasons());
+ // FIXME: Once we support async scrolling of iframes, we'll have to track the synchronous scrolling
+ // reasons per frame (maybe on scrolling tree nodes).
+ if (!frameView.frame().isMainFrame())
+ return;
+
+ setSynchronousScrollingReasons(synchronousScrollingReasons(frameView));
}
void ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates(bool forceSynchronousScrollLayerPositionUpdates)
@@ -328,9 +361,27 @@ void ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates(bool fo
return;
m_forceSynchronousScrollLayerPositionUpdates = forceSynchronousScrollLayerPositionUpdates;
- updateSynchronousScrollingReasons();
+ if (FrameView* frameView = m_page->mainFrame().view())
+ updateSynchronousScrollingReasons(*frameView);
}
+bool ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously(const FrameView& frameView) const
+{
+ if (&frameView == m_page->mainFrame().view())
+ return synchronousScrollingReasons(frameView);
+
+ return true;
+}
+
+#if ENABLE(WEB_REPLAY)
+void ScrollingCoordinator::replaySessionStateDidChange()
+{
+ // FIXME: Once we support async scrolling of iframes, this should go through all subframes.
+ if (FrameView* frameView = m_page->mainFrame().view())
+ updateSynchronousScrollingReasons(*frameView);
+}
+#endif
+
ScrollingNodeID ScrollingCoordinator::uniqueScrollLayerID()
{
static ScrollingNodeID uniqueScrollLayerID = 1;
@@ -347,15 +398,15 @@ String ScrollingCoordinator::synchronousScrollingReasonsAsText(SynchronousScroll
StringBuilder stringBuilder;
if (reasons & ScrollingCoordinator::ForcedOnMainThread)
- stringBuilder.append("Forced on main thread, ");
+ stringBuilder.appendLiteral("Forced on main thread, ");
if (reasons & ScrollingCoordinator::HasSlowRepaintObjects)
- stringBuilder.append("Has slow repaint objects, ");
+ stringBuilder.appendLiteral("Has slow repaint objects, ");
if (reasons & ScrollingCoordinator::HasViewportConstrainedObjectsWithoutSupportingFixedLayers)
- stringBuilder.append("Has viewport constrained objects without supporting fixed layers, ");
+ stringBuilder.appendLiteral("Has viewport constrained objects without supporting fixed layers, ");
if (reasons & ScrollingCoordinator::HasNonLayerViewportConstrainedObjects)
- stringBuilder.append("Has non-layer viewport-constrained objects, ");
+ stringBuilder.appendLiteral("Has non-layer viewport-constrained objects, ");
if (reasons & ScrollingCoordinator::IsImageDocument)
- stringBuilder.append("Is image document, ");
+ stringBuilder.appendLiteral("Is image document, ");
if (stringBuilder.length())
stringBuilder.resize(stringBuilder.length() - 2);
@@ -364,7 +415,45 @@ String ScrollingCoordinator::synchronousScrollingReasonsAsText(SynchronousScroll
String ScrollingCoordinator::synchronousScrollingReasonsAsText() const
{
- return synchronousScrollingReasonsAsText(synchronousScrollingReasons());
+ if (FrameView* frameView = m_page->mainFrame().view())
+ return synchronousScrollingReasonsAsText(synchronousScrollingReasons(*frameView));
+
+ return String();
+}
+
+TextStream& operator<<(TextStream& ts, ScrollingNodeType nodeType)
+{
+ switch (nodeType) {
+ case FrameScrollingNode:
+ ts << "frame-scrolling";
+ break;
+ case OverflowScrollingNode:
+ ts << "overflow-scrolling";
+ break;
+ case FixedNode:
+ ts << "fixed";
+ break;
+ case StickyNode:
+ ts << "sticky";
+ break;
+ }
+ return ts;
+}
+
+TextStream& operator<<(TextStream& ts, ScrollingLayerPositionAction action)
+{
+ switch (action) {
+ case ScrollingLayerPositionAction::Set:
+ ts << "set";
+ break;
+ case ScrollingLayerPositionAction::SetApproximate:
+ ts << "set approximate";
+ break;
+ case ScrollingLayerPositionAction::Sync:
+ ts << "sync";
+ break;
+ }
+ return ts;
}
} // namespace WebCore