Work towards having frames in the scrolling tree
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jun 2014 00:37:06 +0000 (00:37 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Jun 2014 00:37:06 +0000 (00:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133665

Reviewed by Tim Horton.

Source/WebCore:
Optionally (based on Setting) create nodes in the scrolling tree for frames which
contain async-scrollable content. This will be used on iOS/WK2 to support accelerated
overflow-scroll in iframes. The setting allows for testing on OS X.

The change breaks an assumption in ScrollingCoordinator/AsyncScrollingCoordinator
that we're always dealing with the main frame, and changes logic in RenderLayerCompositor
so that we can connect the scrolling tree across frame boundaries. RenderLayerCompositor
maintains a m_subframeScrollLayersNeedReattach flag that gets set whenever we add or remove
scroll-coordinated layers in the current frame. When set, after updating compositing
layers we walk child frames, and, if they have scrolling nodes, re-attach them to the
scrolling tree (which will find the new ancestor node).

Tests: platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html
       platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html

* WebCore.exp.in:
* page/FrameView.cpp:
(WebCore::FrameView::scrollLayerID): Use the new "for role" way of getting the node ID.
* page/Settings.cpp:
* page/Settings.in: Add scrollingTreeIncludesFrames.
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
(WebCore::AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Only set
the region for the main frame.
(WebCore::AsyncScrollingCoordinator::frameViewForScrollingNode): updateScrollPositionAfterAsyncScroll()
needs to know which FrameView a given nodeID is hosted in; doing a walk of the frame tree for
non-main frames seems to be the safest way.
(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
(WebCore::AsyncScrollingCoordinator::syncChildPositions):
* page/scrolling/AsyncScrollingCoordinator.h:
* page/scrolling/ScrollingCoordinator.cpp:
(WebCore::ScrollingCoordinator::coordinatesScrollingForFrameView): Consult the new setting.
(WebCore::ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange):
(WebCore::ScrollingCoordinator::frameViewFixedObjectsDidChange):
(WebCore::ScrollingCoordinator::frameViewRootLayerDidChange):
(WebCore::ScrollingCoordinator::synchronousScrollingReasons):
(WebCore::ScrollingCoordinator::updateSynchronousScrollingReasons):
(WebCore::ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates):
(WebCore::ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously):
(WebCore::ScrollingCoordinator::replaySessionStateDidChange):
(WebCore::ScrollingCoordinator::synchronousScrollingReasonsAsText):
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously): Deleted.
* rendering/RenderLayerBacking.h: Rather than separate functions to get the two scrolling
node IDs, having one scrollingNodeIDForRole() makes calling code cleaner.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::RenderLayerCompositor):
(WebCore::RenderLayerCompositor::updateCompositingLayers):  call reattachSubframeScrollLayers()
after a compositing tree update.
(WebCore::RenderLayerCompositor::isAsyncScrollableStickyLayer): Deals with the various configurations
in which we can do async scrolling of sticky elements.
(WebCore::RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer):
(WebCore::useCoordinatedScrollingForLayer):
(WebCore::RenderLayerCompositor::requiresCompositingForPosition):
(WebCore::RenderLayerCompositor::requiresCompositingForScrolling): Moved.
(WebCore::RenderLayerCompositor::notifyIFramesOfCompositingChange): This is a bug fix;
we only need to notify child frames, not all descendant frames.
(WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus):
(WebCore::RenderLayerCompositor::removeFromScrollCoordinatedLayers):
(WebCore::enclosingScrollingNodeID):
(WebCore::scrollCoordinatedAncestorInParentOfFrame):
(WebCore::RenderLayerCompositor::reattachSubframeScrollLayers):
(WebCore::RenderLayerCompositor::attachScrollingNode):
(WebCore::RenderLayerCompositor::updateScrollCoordinationForThisFrame):
(WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer):
(WebCore::RenderLayerCompositor::detachScrollCoordinatedLayer):
(WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers):
(WebCore::RenderLayerCompositor::willRemoveScrollingLayer):
(WebCore::isStickyInAcceleratedScrollingLayerOrViewport): Deleted.
(WebCore::isViewportConstrainedFixedOrStickyLayer): Deleted.
(WebCore::isMainFrameScrollingOrOverflowScrolling): Deleted.
(WebCore::nearestScrollCoordinatedAncestor): Deleted.
* rendering/RenderLayerCompositor.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::setSelection): Added comment.
* testing/InternalSettings.cpp:
(WebCore::InternalSettings::setScrollingTreeIncludesFrames):
* testing/InternalSettings.h: Removed some useless parameter names.
* testing/InternalSettings.idl: Added setScrollingTreeIncludesFrames() setting.

Source/WebKit2:
Override coordinatesScrollingForFrameView() to always return true for composited
frames, for iOS WK2 (eventually this class will have to be specialized for iOS and OS X).

* WebProcess/Scrolling/RemoteScrollingCoordinator.h:
* WebProcess/Scrolling/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::coordinatesScrollingForFrameView):

LayoutTests:
Tests that dump the scrolling tree with subframes.

* platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt: Added.
* platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt: Added.
* platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html: Added.
* platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html: Added.
* platform/mac-wk2/tiled-drawing/scrolling/frames/resources/doc-with-sticky.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@169733 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html [new file with mode: 0644]
LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html [new file with mode: 0644]
LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/resources/doc-with-sticky.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/Settings.cpp
Source/WebCore/page/Settings.in
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingCoordinator.cpp
Source/WebCore/page/scrolling/ScrollingCoordinator.h
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/testing/InternalSettings.cpp
Source/WebCore/testing/InternalSettings.h
Source/WebCore/testing/InternalSettings.idl
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.h
Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.mm

index 4f26b3c..fc8c998 100644 (file)
@@ -1,3 +1,18 @@
+2014-06-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Work towards having frames in the scrolling tree
+        https://bugs.webkit.org/show_bug.cgi?id=133665
+
+        Reviewed by Tim Horton.
+        
+        Tests that dump the scrolling tree with subframes.
+
+        * platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt: Added.
+        * platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt: Added.
+        * platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html: Added.
+        * platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html: Added.
+        * platform/mac-wk2/tiled-drawing/scrolling/frames/resources/doc-with-sticky.html: Added.
+
 2014-06-09  Eric Carlson  <eric.carlson@apple.com>
 
         Automatic text track selection can select more than one track
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt b/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-expected.txt
new file mode 100644 (file)
index 0000000..b673b25
--- /dev/null
@@ -0,0 +1,22 @@
+(Frame scrolling node
+  (scrollable area size 785 600)
+  (contents size 785 1016)
+  (children 1
+    (Frame scrolling node
+      (scrollable area size 485 300)
+      (contents size 485 1868)
+      (children 1
+        (Sticky node
+          (anchor edges: AnchorEdgeTop )
+          (top offset 10.00)
+          (containing block rect 8.00, 10.00 469.00 x 1850.00)
+          (sticky box rect 8.00 830.00 100.00 100.00)
+          (sticky box rect 8.00 830.00 100.00 100.00)
+          (sticky offset at last layout 0.00 0.00)
+          (layer position at last layout 8.00 830.00)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt b/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed-expected.txt
new file mode 100644 (file)
index 0000000..aa21acc
--- /dev/null
@@ -0,0 +1,29 @@
+(Frame scrolling node
+  (scrollable area size 785 600)
+  (contents size 785 1016)
+  (children 1
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 600.00)
+      (layer position at last layout 8.00 0.00)
+      (children 1
+        (Frame scrolling node
+          (scrollable area size 485 300)
+          (contents size 485 1868)
+          (children 1
+            (Sticky node
+              (anchor edges: AnchorEdgeTop )
+              (top offset 10.00)
+              (containing block rect 8.00, 10.00 469.00 x 1850.00)
+              (sticky box rect 8.00 830.00 100.00 100.00)
+              (sticky box rect 8.00 830.00 100.00 100.00)
+              (sticky offset at last layout 0.00 0.00)
+              (layer position at last layout 8.00 830.00)
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html b/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html
new file mode 100644 (file)
index 0000000..e3eb73e
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+    <style>\r
+        body {\r
+            height: 1000px;\r
+        }\r
+        \r
+        iframe {\r
+            display: block;\r
+            margin: 10px;\r
+            border: 5px solid black;\r
+        }\r
+        \r
+        #container {\r
+            position: absolute;\r
+            top: 10px;\r
+            border: 4px solid green;\r
+            padding: 10px;\r
+        }\r
+        \r
+        #container {\r
+            position: fixed;\r
+            top: 0;\r
+            border: 4px solid orange;\r
+        }\r
+        \r
+        #tree {\r
+            position: absolute;\r
+            top: 375px;\r
+        }\r
+    </style>\r
+    <script>\r
+        if (window.testRunner) {\r
+            testRunner.dumpAsText();\r
+            window.internals.settings.setScrollingTreeIncludesFrames(true);\r
+        }\r
+\r
+        function startTest()\r
+        {\r
+            if (window.internals)\r
+                document.getElementById('tree').innerText = internals.scrollingStateTreeAsText();\r
+        }\r
+        \r
+        window.addEventListener('load', startTest, false);\r
+    </script>\r
+</head>\r
+<body>\r
+    \r
+    <div id="container">\r
+        <iframe src="resources/doc-with-sticky.html" width="500" height="300"></iframe>\r
+    </div>\r
+<pre id="tree">Scrolling tree goes here</pre>\r
+</body>\r
+</html>\r
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html b/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html
new file mode 100644 (file)
index 0000000..8fd0f6d
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+    <style>\r
+        body {\r
+            height: 1000px;\r
+        }\r
+        \r
+        iframe {\r
+            display: block;\r
+            margin: 10px;\r
+            border: 5px solid black;\r
+        }\r
+        \r
+        #container {\r
+            position: absolute;\r
+            top: 10px;\r
+            border: 4px solid green;\r
+            padding: 10px;\r
+        }\r
+        \r
+        #container {\r
+            border: 4px solid orange;\r
+        }\r
+        \r
+        #tree {\r
+            position: absolute;\r
+            top: 375px;\r
+        }\r
+    </style>\r
+    <script>\r
+        if (window.testRunner) {\r
+            testRunner.dumpAsText();\r
+            window.internals.settings.setScrollingTreeIncludesFrames(true);\r
+        }\r
+\r
+        function startTest()\r
+        {\r
+            if (window.internals)\r
+                document.getElementById('tree').innerText = internals.scrollingStateTreeAsText();\r
+        }\r
+        \r
+        window.addEventListener('load', startTest, false);\r
+    </script>\r
+</head>\r
+<body>\r
+    \r
+    <div id="container">\r
+        <iframe src="resources/doc-with-sticky.html" width="500" height="300"></iframe>\r
+    </div>\r
+<pre id="tree">Scrolling tree goes here</pre>\r
+</body>\r
+</html>\r
diff --git a/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/resources/doc-with-sticky.html b/LayoutTests/platform/mac-wk2/tiled-drawing/scrolling/frames/resources/doc-with-sticky.html
new file mode 100644 (file)
index 0000000..e8bef59
--- /dev/null
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .box {
+            height: 100px;
+            width: 100px;
+            background-color: blue;
+        }
+        
+        .spacer {
+            height: 400px;
+            margin: 10px;
+            background-color: silver;
+        }
+        .sticky {
+            position: -webkit-sticky;
+            top: 10px;
+        }
+        
+        .composited {
+            -webkit-transform: translateZ(0);
+        }
+    </style>
+</head>
+<body>
+    <div class="spacer"></div>
+    <div class="spacer"></div>
+    <div class="sticky box"></div>
+    <div class="spacer"></div>
+    <div class="spacer"></div>
+    <div class="composited box"></div>
+</body>
+</html>
index a5d626e..22389ad 100644 (file)
@@ -1,3 +1,90 @@
+2014-06-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Work towards having frames in the scrolling tree
+        https://bugs.webkit.org/show_bug.cgi?id=133665
+
+        Reviewed by Tim Horton.
+        
+        Optionally (based on Setting) create nodes in the scrolling tree for frames which
+        contain async-scrollable content. This will be used on iOS/WK2 to support accelerated
+        overflow-scroll in iframes. The setting allows for testing on OS X.
+        
+        The change breaks an assumption in ScrollingCoordinator/AsyncScrollingCoordinator
+        that we're always dealing with the main frame, and changes logic in RenderLayerCompositor
+        so that we can connect the scrolling tree across frame boundaries. RenderLayerCompositor
+        maintains a m_subframeScrollLayersNeedReattach flag that gets set whenever we add or remove
+        scroll-coordinated layers in the current frame. When set, after updating compositing
+        layers we walk child frames, and, if they have scrolling nodes, re-attach them to the
+        scrolling tree (which will find the new ancestor node).
+
+        Tests: platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame-in-fixed.html
+               platform/mac-wk2/tiled-drawing/scrolling/frames/coordinated-frame.html
+
+        * WebCore.exp.in:
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollLayerID): Use the new "for role" way of getting the node ID.
+        * page/Settings.cpp:
+        * page/Settings.in: Add scrollingTreeIncludesFrames.
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
+        (WebCore::AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged): Only set
+        the region for the main frame.
+        (WebCore::AsyncScrollingCoordinator::frameViewForScrollingNode): updateScrollPositionAfterAsyncScroll()
+        needs to know which FrameView a given nodeID is hosted in; doing a walk of the frame tree for
+        non-main frames seems to be the safest way.
+        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
+        (WebCore::AsyncScrollingCoordinator::syncChildPositions):
+        * page/scrolling/AsyncScrollingCoordinator.h:
+        * page/scrolling/ScrollingCoordinator.cpp:
+        (WebCore::ScrollingCoordinator::coordinatesScrollingForFrameView): Consult the new setting.
+        (WebCore::ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange):
+        (WebCore::ScrollingCoordinator::frameViewFixedObjectsDidChange):
+        (WebCore::ScrollingCoordinator::frameViewRootLayerDidChange):
+        (WebCore::ScrollingCoordinator::synchronousScrollingReasons):
+        (WebCore::ScrollingCoordinator::updateSynchronousScrollingReasons):
+        (WebCore::ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates):
+        (WebCore::ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously):
+        (WebCore::ScrollingCoordinator::replaySessionStateDidChange):
+        (WebCore::ScrollingCoordinator::synchronousScrollingReasonsAsText):
+        * page/scrolling/ScrollingCoordinator.h:
+        (WebCore::ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously): Deleted.
+        * rendering/RenderLayerBacking.h: Rather than separate functions to get the two scrolling
+        node IDs, having one scrollingNodeIDForRole() makes calling code cleaner.
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::RenderLayerCompositor):
+        (WebCore::RenderLayerCompositor::updateCompositingLayers):  call reattachSubframeScrollLayers()
+        after a compositing tree update.
+        (WebCore::RenderLayerCompositor::isAsyncScrollableStickyLayer): Deals with the various configurations
+        in which we can do async scrolling of sticky elements.
+        (WebCore::RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer):
+        (WebCore::useCoordinatedScrollingForLayer):
+        (WebCore::RenderLayerCompositor::requiresCompositingForPosition):
+        (WebCore::RenderLayerCompositor::requiresCompositingForScrolling): Moved.
+        (WebCore::RenderLayerCompositor::notifyIFramesOfCompositingChange): This is a bug fix;
+        we only need to notify child frames, not all descendant frames.
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedStatus):
+        (WebCore::RenderLayerCompositor::removeFromScrollCoordinatedLayers):
+        (WebCore::enclosingScrollingNodeID):
+        (WebCore::scrollCoordinatedAncestorInParentOfFrame):
+        (WebCore::RenderLayerCompositor::reattachSubframeScrollLayers):
+        (WebCore::RenderLayerCompositor::attachScrollingNode):
+        (WebCore::RenderLayerCompositor::updateScrollCoordinationForThisFrame):
+        (WebCore::RenderLayerCompositor::updateScrollCoordinatedLayer):
+        (WebCore::RenderLayerCompositor::detachScrollCoordinatedLayer):
+        (WebCore::RenderLayerCompositor::registerAllViewportConstrainedLayers):
+        (WebCore::RenderLayerCompositor::willRemoveScrollingLayer):
+        (WebCore::isStickyInAcceleratedScrollingLayerOrViewport): Deleted.
+        (WebCore::isViewportConstrainedFixedOrStickyLayer): Deleted.
+        (WebCore::isMainFrameScrollingOrOverflowScrolling): Deleted.
+        (WebCore::nearestScrollCoordinatedAncestor): Deleted.
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::setSelection): Added comment.
+        * testing/InternalSettings.cpp:
+        (WebCore::InternalSettings::setScrollingTreeIncludesFrames):
+        * testing/InternalSettings.h: Removed some useless parameter names.
+        * testing/InternalSettings.idl: Added setScrollingTreeIncludesFrames() setting.
+
 2014-06-09  Benjamin Poulain  <bpoulain@apple.com>
 
         Improve CSSPrimitiveValue::customCSSText for ARMv7
index af7315e..b222f92 100644 (file)
@@ -1521,6 +1521,7 @@ __ZNK7WebCore10PluginData16supportsMimeTypeERKN3WTF6StringENS0_18AllowedPluginTy
 __ZNK7WebCore10RenderText16firstRunLocationEv
 __ZNK7WebCore10RenderText16linesBoundingBoxEv
 __ZNK7WebCore10RenderView12documentRectEv
+__ZNK7WebCore10RenderView15usesCompositingEv
 __ZNK7WebCore10RenderView20unscaledDocumentRectEv
 __ZNK7WebCore10ScrollView12contentsSizeEv
 __ZNK7WebCore10ScrollView12documentViewEv
index 061fbdf..bfa77b1 100644 (file)
@@ -804,7 +804,7 @@ uint64_t FrameView::scrollLayerID() const
     if (!backing)
         return 0;
 
-    return backing->scrollingNodeID();
+    return backing->scrollingNodeIDForRole(FrameScrollingNode);
 }
 
 ScrollableArea* FrameView::scrollableAreaForScrollLayerID(uint64_t nodeID) const
index 514a5a1..d7b0bee 100644 (file)
@@ -127,6 +127,7 @@ static const bool defaultAcceleratedCompositingForFixedPositionEnabled = true;
 static const bool defaultMediaPlaybackAllowsInline = false;
 static const bool defaultMediaPlaybackRequiresUserGesture = true;
 static const bool defaultShouldRespectImageOrientation = true;
+static const bool defaultScrollingTreeIncludesFrames = true;
 #else
 static const bool defaultFixedPositionCreatesStackingContext = false;
 static const bool defaultFixedBackgroundsPaintRelativeToDocument = false;
@@ -134,6 +135,7 @@ static const bool defaultAcceleratedCompositingForFixedPositionEnabled = false;
 static const bool defaultMediaPlaybackAllowsInline = true;
 static const bool defaultMediaPlaybackRequiresUserGesture = false;
 static const bool defaultShouldRespectImageOrientation = false;
+static const bool defaultScrollingTreeIncludesFrames = false;
 #endif
 
 static const double defaultIncrementalRenderingSuppressionTimeoutInSeconds = 5;
index cfa0e74..76e8001 100644 (file)
@@ -132,6 +132,7 @@ shouldDisplaySubtitles initial=false, conditional=VIDEO_TRACK
 shouldDisplayCaptions initial=false, conditional=VIDEO_TRACK
 shouldDisplayTextDescriptions initial=false, conditional=VIDEO_TRACK
 scrollingCoordinatorEnabled initial=false
+scrollingTreeIncludesFrames initial=defaultScrollingTreeIncludesFrames
 scrollAnimatorEnabled initial=true, conditional=SMOOTH_SCROLLING
 notificationsEnabled initial=true
 
index 779652c..31f0db9 100644 (file)
@@ -72,7 +72,8 @@ void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView)
     // frame view whose layout was updated is not the main frame.
     // In the future, we may want to have the ability to set non-fast scrolling regions for more than
     // just the root node. But right now, this concept only applies to the root.
-    m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(&m_page->mainFrame(), IntPoint()));
+    if (frameView->frame().isMainFrame())
+        m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(&frameView->frame(), IntPoint()));
 
     if (!coordinatesScrollingForFrameView(frameView))
         return;
@@ -105,12 +106,13 @@ void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView* frameView)
     node->setScrollableAreaParameters(scrollParameters);
 }
 
-void AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged(FrameView*)
+void AsyncScrollingCoordinator::frameViewNonFastScrollableRegionChanged(FrameView* frameView)
 {
     if (!m_scrollingStateTree->rootStateNode())
         return;
 
-    m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(&m_page->mainFrame(), IntPoint()));
+    if (frameView->frame().isMainFrame())
+        m_scrollingStateTree->rootStateNode()->setNonFastScrollableRegion(computeNonFastScrollableRegion(&frameView->frame(), IntPoint()));
 }
 
 void AsyncScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView)
@@ -193,6 +195,35 @@ void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired(T
     updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
 }
 
+FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID scrollingNodeID) const
+{
+    if (scrollingNodeID == m_scrollingStateTree->rootStateNode()->scrollingNodeID())
+        return m_page->mainFrame().view();
+
+    ScrollingStateNode* stateNode = m_scrollingStateTree->stateNodeForID(scrollingNodeID);
+    if (!stateNode)
+        return nullptr;
+
+    // Find the enclosing frame scrolling node.
+    ScrollingStateNode* parentNode = stateNode;
+    while (parentNode && parentNode->nodeType() != FrameScrollingNode)
+        parentNode = parentNode->parent();
+    
+    if (!parentNode)
+        return nullptr;
+    
+    // Walk the frame tree to find the matching FrameView. This is not ideal, but avoids back pointers to FrameViews
+    // from ScrollingTreeStateNodes.
+    for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
+        if (FrameView* view = frame->view()) {
+            if (view->scrollLayerID() == parentNode->scrollingNodeID())
+                return view;
+        }
+    }
+
+    return nullptr;
+}
+
 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
     ASSERT(isMainThread());
@@ -200,11 +231,10 @@ void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNo
     if (!m_page)
         return;
 
-    FrameView* frameView = m_page->mainFrame().view();
+    FrameView* frameView = frameViewForScrollingNode(scrollingNodeID);
     if (!frameView)
         return;
 
-    // Main frame.
     if (scrollingNodeID == frameView->scrollLayerID()) {
         bool oldProgrammaticScroll = frameView->inProgrammaticScroll();
         frameView->setInProgrammaticScroll(programmaticScroll);
@@ -316,11 +346,8 @@ void AsyncScrollingCoordinator::syncChildPositions(const LayoutRect& viewportRec
         return;
 
     // FIXME: We'll have to traverse deeper into the tree at some point.
-    size_t size = children->size();
-    for (size_t i = 0; i < size; ++i) {
-        ScrollingStateNode* child = children->at(i).get();
+    for (auto& child : *children)
         child->syncLayerPositionForViewportRect(viewportRect);
-    }
 }
 
 void AsyncScrollingCoordinator::ensureRootStateNodeForFrameView(FrameView* frameView)
index a6e77ae..f547fb1 100644 (file)
@@ -70,6 +70,8 @@ protected:
 
     void updateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
 
+    virtual String scrollingStateTreeAsText() const override;
+
 private:
     virtual bool isAsyncScrollingCoordinator() const override { return true; }
 
@@ -91,7 +93,6 @@ private:
     virtual void updateFrameScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, GraphicsLayer* counterScrollingLayer, GraphicsLayer* insetClipLayer, const ScrollingGeometry* = nullptr);
     virtual void updateOverflowScrollingNode(ScrollingNodeID, GraphicsLayer* scrollLayer, GraphicsLayer* scrolledContentsLayer, const ScrollingGeometry* = nullptr);
     
-    virtual String scrollingStateTreeAsText() const override;
     virtual bool isRubberBandInProgress() const override;
     virtual void setScrollPinningBehavior(ScrollPinningBehavior) override;
 
@@ -107,6 +108,8 @@ private:
     void updateMainFrameScrollLayerPosition();
 
     void updateScrollPositionAfterAsyncScrollTimerFired(Timer<AsyncScrollingCoordinator>*);
+    
+    FrameView* frameViewForScrollingNode(ScrollingNodeID) const;
 
     Timer<AsyncScrollingCoordinator> m_updateNodeScrollPositionTimer;
 
index e751f2d..61e7bf9 100644 (file)
@@ -39,6 +39,7 @@
 #include "RenderLayerCompositor.h"
 #include "RenderView.h"
 #include "ScrollAnimator.h"
+#include "Settings.h"
 #include <wtf/MainThread.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -86,11 +87,9 @@ bool ScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView
     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.
     RenderView* renderView = m_page->mainFrame().contentRenderer();
     if (!renderView)
         return false;
@@ -181,7 +180,7 @@ void ScrollingCoordinator::frameViewHasSlowRepaintObjectsDidChange(FrameView* fr
     if (!coordinatesScrollingForFrameView(frameView))
         return;
 
-    updateSynchronousScrollingReasons();
+    updateSynchronousScrollingReasons(frameView);
 }
 
 void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView)
@@ -192,7 +191,7 @@ void ScrollingCoordinator::frameViewFixedObjectsDidChange(FrameView* frameView)
     if (!coordinatesScrollingForFrameView(frameView))
         return;
 
-    updateSynchronousScrollingReasons();
+    updateSynchronousScrollingReasons(frameView);
 }
 
 GraphicsLayer* ScrollingCoordinator::scrollLayerForScrollableArea(ScrollableArea* scrollableArea)
@@ -285,7 +284,7 @@ void ScrollingCoordinator::frameViewRootLayerDidChange(FrameView* frameView)
 
     frameViewLayoutUpdated(frameView);
     recomputeWheelEventHandlerCountForFrameView(frameView);
-    updateSynchronousScrollingReasons();
+    updateSynchronousScrollingReasons(frameView);
 }
 
 #if PLATFORM(COCOA)
@@ -322,9 +321,8 @@ bool ScrollingCoordinator::hasVisibleSlowRepaintViewportConstrainedObjects(Frame
     return false;
 }
 
-SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons() const
+SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons(FrameView* frameView) const
 {
-    FrameView* frameView = m_page->mainFrame().view();
     if (!frameView)
         return static_cast<SynchronousScrollingReasons>(0);
 
@@ -343,15 +341,20 @@ SynchronousScrollingReasons ScrollingCoordinator::synchronousScrollingReasons()
         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(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)
@@ -360,13 +363,19 @@ void ScrollingCoordinator::setForceSynchronousScrollLayerPositionUpdates(bool fo
         return;
 
     m_forceSynchronousScrollLayerPositionUpdates = forceSynchronousScrollLayerPositionUpdates;
-    updateSynchronousScrollingReasons();
+    updateSynchronousScrollingReasons(m_page->mainFrame().view());
+}
+
+bool ScrollingCoordinator::shouldUpdateScrollLayerPositionSynchronously() const
+{
+    return synchronousScrollingReasons(m_page->mainFrame().view());
 }
 
 #if ENABLE(WEB_REPLAY)
 void ScrollingCoordinator::replaySessionStateDidChange()
 {
-    updateSynchronousScrollingReasons();
+    // FIXME: Once we support async scrolling of iframes, this should go through all subframes.
+    updateSynchronousScrollingReasons(m_page->mainFrame().view());
 }
 #endif
 
@@ -403,7 +412,7 @@ String ScrollingCoordinator::synchronousScrollingReasonsAsText(SynchronousScroll
 
 String ScrollingCoordinator::synchronousScrollingReasonsAsText() const
 {
-    return synchronousScrollingReasonsAsText(synchronousScrollingReasons());
+    return synchronousScrollingReasonsAsText(synchronousScrollingReasons(m_page->mainFrame().view()));
 }
 
 } // namespace WebCore
index 5a8701c..fee29a8 100644 (file)
@@ -110,7 +110,7 @@ public:
     virtual bool isRemoteScrollingCoordinator() const { return false; }
 
     // Return whether this scrolling coordinator handles scrolling for the given frame view.
-    bool coordinatesScrollingForFrameView(FrameView*) const;
+    virtual bool coordinatesScrollingForFrameView(FrameView*) const;
 
     // Should be called whenever the given frame view has been laid out.
     virtual void frameViewLayoutUpdated(FrameView*) { }
@@ -183,8 +183,8 @@ public:
         IsImageDocument = 1 << 4
     };
 
-    SynchronousScrollingReasons synchronousScrollingReasons() const;
-    bool shouldUpdateScrollLayerPositionSynchronously() const { return synchronousScrollingReasons(); }
+    SynchronousScrollingReasons synchronousScrollingReasons(FrameView*) const;
+    bool shouldUpdateScrollLayerPositionSynchronously() const;
 
     virtual void willDestroyScrollableArea(ScrollableArea*) { }
     virtual void scrollableAreaScrollLayerDidChange(ScrollableArea*) { }
@@ -218,7 +218,7 @@ private:
     virtual void setSynchronousScrollingReasons(SynchronousScrollingReasons) { }
 
     virtual bool hasVisibleSlowRepaintViewportConstrainedObjects(FrameView*) const;
-    void updateSynchronousScrollingReasons();
+    void updateSynchronousScrollingReasons(FrameView*);
     
     bool m_forceSynchronousScrollLayerPositionUpdates;
 };
index 0d42cb7..3438785 100644 (file)
@@ -108,12 +108,33 @@ public:
     GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
 
     void detachFromScrollingCoordinator();
-
-    ScrollingNodeID viewportConstrainedNodeID() const { return m_viewportConstrainedNodeID; }
-    void setViewportConstrainedNodeID(ScrollingNodeID nodeID) { m_viewportConstrainedNodeID = nodeID; }
-
-    ScrollingNodeID scrollingNodeID() const { return m_scrollingNodeID; }
-    void setScrollingNodeID(ScrollingNodeID nodeID) { m_scrollingNodeID = nodeID; }
+    
+    ScrollingNodeID scrollingNodeIDForRole(ScrollingNodeType nodeType) const
+    {
+        switch (nodeType) {
+        case FrameScrollingNode:
+        case OverflowScrollingNode:
+            return m_scrollingNodeID;
+        case FixedNode:
+        case StickyNode:
+            return m_viewportConstrainedNodeID;
+        }
+        return 0;
+    }
+    
+    void setScrollingNodeIDForRole(ScrollingNodeID nodeID, ScrollingNodeType nodeType)
+    {
+        switch (nodeType) {
+        case FrameScrollingNode:
+        case OverflowScrollingNode:
+            m_scrollingNodeID = nodeID;
+            break;
+        case FixedNode:
+        case StickyNode:
+            m_viewportConstrainedNodeID = nodeID;
+            break;
+        }
+    }
     
     ScrollingNodeID scrollingNodeIDForChildren() const { return m_scrollingNodeID ? m_scrollingNodeID : m_viewportConstrainedNodeID; }
 
index 2a4d9c6..3b6bd90 100644 (file)
@@ -279,6 +279,7 @@ RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
     , m_shouldFlushOnReattach(false)
     , m_forceCompositingMode(false)
     , m_inPostLayoutUpdate(false)
+    , m_subframeScrollLayersNeedReattach(false)
     , m_isTrackingRepaints(false)
     , m_layersWithTiledBackingCount(0)
     , m_rootLayerAttachment(RootLayerUnattached)
@@ -729,10 +730,13 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
             else if (m_rootContentLayer)
                 m_rootContentLayer->setChildren(childList);
         }
+        
+        reattachSubframeScrollLayers();
     } else if (needGeometryUpdate) {
         // We just need to do a geometry update. This is only used for position:fixed scrolling;
         // most of the time, geometry is updated via RenderLayer::styleChanged().
         updateLayerTreeGeometry(*updateRoot, 0);
+        ASSERT(!isFullUpdate || !m_subframeScrollLayersNeedReattach);
     }
     
 #if !LOG_DISABLED
@@ -2523,21 +2527,6 @@ bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerMode
     return false;
 }
 
-#if PLATFORM(IOS)
-bool RenderLayerCompositor::requiresCompositingForScrolling(const RenderLayer& layer) const
-{
-    if (!layer.hasAcceleratedTouchScrolling())
-        return false;
-
-    if (!m_inPostLayoutUpdate) {
-        m_reevaluateCompositingAfterLayout = true;
-        return layer.isComposited();
-    }
-
-    return layer.hasTouchScrollableOverflow();
-}
-#endif
-
 bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const
 {
 #if ENABLE(CSS_FILTERS)
@@ -2551,31 +2540,41 @@ bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject
 #endif
 }
 
-#if PLATFORM(IOS)
-static bool isStickyInAcceleratedScrollingLayerOrViewport(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer = 0)
+bool RenderLayerCompositor::isAsyncScrollableStickyLayer(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer) const
 {
     ASSERT(layer.renderer().isStickyPositioned());
 
     RenderLayer* enclosingOverflowLayer = layer.enclosingOverflowClipLayer(ExcludeSelf);
+
+#if PLATFORM(IOS)
     if (enclosingOverflowLayer && enclosingOverflowLayer->hasTouchScrollableOverflow()) {
         if (enclosingAcceleratedOverflowLayer)
             *enclosingAcceleratedOverflowLayer = enclosingOverflowLayer;
         return true;
     }
-
-    return !enclosingOverflowLayer;
-}
+#else
+    UNUSED_PARAM(enclosingAcceleratedOverflowLayer);
 #endif
+    // If the layer is inside normal overflow, it's not async-scrollable.
+    if (enclosingOverflowLayer)
+        return false;
+
+    // No overflow ancestor, so see if the frame supports async scrolling.
+    if (hasCoordinatedScrolling())
+        return true;
 
-static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
-{
 #if PLATFORM(IOS)
-    if (layer.renderer().isStickyPositioned())
-        return isStickyInAcceleratedScrollingLayerOrViewport(layer);
+    // iOS WK1 has fixed/sticky support in the main frame via WebFixedPositionContent.
+    return m_renderView.frameView().frame().isMainFrame();
 #else
-    if (layer.renderer().isStickyPositioned())
-        return !layer.enclosingOverflowClipLayer(ExcludeSelf);
+    return false;
 #endif
+}
+
+bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer) const
+{
+    if (layer.renderer().isStickyPositioned())
+        return isAsyncScrollableStickyLayer(layer);
 
     if (layer.renderer().style().position() != FixedPosition)
         return false;
@@ -2589,9 +2588,9 @@ static bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer)
     return true;
 }
 
-static bool isMainFrameScrollingOrOverflowScrolling(RenderView& view, const RenderLayer& layer)
+static bool useCoordinatedScrollingForLayer(RenderView& view, const RenderLayer& layer)
 {
-    if (layer.isRootLayer() && !view.document().ownerElement())
+    if (layer.isRootLayer() && view.frameView().frame().isMainFrame())
         return true;
 
 #if PLATFORM(IOS)
@@ -2624,7 +2623,7 @@ bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObjec
         return false;
 
     if (isSticky)
-        return hasCoordinatedScrolling() && isViewportConstrainedFixedOrStickyLayer(layer);
+        return isAsyncScrollableStickyLayer(layer);
 
     auto container = renderer.container();
     // If the renderer is not hooked up yet then we have to wait until it is.
@@ -2674,6 +2673,21 @@ bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const Render
     return layer.needsCompositedScrolling();
 }
 
+#if PLATFORM(IOS)
+bool RenderLayerCompositor::requiresCompositingForScrolling(const RenderLayer& layer) const
+{
+    if (!layer.hasAcceleratedTouchScrolling())
+        return false;
+
+    if (!m_inPostLayoutUpdate) {
+        m_reevaluateCompositingAfterLayout = true;
+        return layer.isComposited();
+    }
+
+    return layer.hasTouchScrollableOverflow();
+}
+#endif
+
 bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderLayerModelObject& renderer) const
 {
     if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
@@ -3426,9 +3440,7 @@ void RenderLayerCompositor::rootLayerAttachmentChanged()
 // to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
 void RenderLayerCompositor::notifyIFramesOfCompositingChange()
 {
-    Frame& frame = m_renderView.frameView().frame();
-
-    for (Frame* child = frame.tree().firstChild(); child; child = child->tree().traverseNext(&frame)) {
+    for (Frame* child = m_renderView.frameView().frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
         if (child->document() && child->document()->ownerElement())
             child->document()->ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
     }
@@ -3493,11 +3505,13 @@ void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer)
     if (isViewportConstrainedFixedOrStickyLayer(layer))
         coordinationReasons |= FixedOrSticky;
 
-    if (isMainFrameScrollingOrOverflowScrolling(m_renderView, layer))
+    if (useCoordinatedScrollingForLayer(m_renderView, layer))
         coordinationReasons |= Scrolling;
-        
+
     if (coordinationReasons) {
-        m_scrollCoordinatedLayers.add(&layer);
+        if (m_scrollCoordinatedLayers.add(&layer).isNewEntry)
+            m_subframeScrollLayersNeedReattach = true;
+
         updateScrollCoordinatedLayer(layer, coordinationReasons);
     } else
         removeFromScrollCoordinatedLayers(layer);
@@ -3508,6 +3522,8 @@ void RenderLayerCompositor::removeFromScrollCoordinatedLayers(RenderLayer& layer
     if (!m_scrollCoordinatedLayers.contains(&layer))
         return;
 
+    m_subframeScrollLayersNeedReattach = true;
+    
     m_scrollCoordinatedLayers.remove(&layer);
     m_scrollCoordinatedLayersNeedingUpdate.remove(&layer);
 
@@ -3571,30 +3587,99 @@ StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportCo
     return constraints;
 }
 
-static RenderLayerBacking* nearestScrollCoordinatedAncestor(RenderLayer& layer)
+static ScrollingNodeID enclosingScrollingNodeID(RenderLayer& layer, IncludeSelfOrNot includeSelf)
 {
-    RenderLayer* ancestor = layer.parent();
-    while (ancestor) {
-        if (RenderLayerBacking* backing = ancestor->backing()) {
-            if (backing->scrollingNodeIDForChildren())
-                return backing;
+    RenderLayer* currLayer = includeSelf == IncludeSelf ? &layer : layer.parent();
+    while (currLayer) {
+        if (RenderLayerBacking* backing = currLayer->backing()) {
+            if (ScrollingNodeID nodeID = backing->scrollingNodeIDForChildren())
+                return nodeID;
         }
-        ancestor = ancestor->parent();
+        currLayer = currLayer->parent();
     }
 
-    return nullptr;
+    return 0;
 }
 
-void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, ScrollCoordinationReasons reasons)
+static ScrollingNodeID scrollCoordinatedAncestorInParentOfFrame(Frame& frame)
 {
-    // FIXME: support scrolling layers in iframes.
-    if (m_renderView.document().ownerElement())
+    if (!frame.document() || !frame.view())
+        return 0;
+
+    // Find the frame's enclosing layer in our render tree.
+    HTMLFrameOwnerElement* ownerElement = frame.document()->ownerElement();
+    RenderElement* frameRenderer = ownerElement ? ownerElement->renderer() : nullptr;
+    if (!frameRenderer)
+        return 0;
+
+    RenderLayer* layerInParentDocument = frameRenderer->enclosingLayer();
+    if (!layerInParentDocument)
+        return 0;
+
+    return enclosingScrollingNodeID(*layerInParentDocument, IncludeSelf);
+}
+
+void RenderLayerCompositor::reattachSubframeScrollLayers()
+{
+    if (!m_subframeScrollLayersNeedReattach)
         return;
+    
+    m_subframeScrollLayersNeedReattach = false;
 
     ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
-    if (!scrollingCoordinator)
-        return;
+
+    for (Frame* child = m_renderView.frameView().frame().tree().firstChild(); child; child = child->tree().nextSibling()) {
+        if (!child->document() || !child->view())
+            continue;
+
+        // Ignore frames that are not scroll-coordinated.
+        FrameView* childFrameView = child->view();
+        ScrollingNodeID frameScrollingNodeID = childFrameView->scrollLayerID();
+        if (!frameScrollingNodeID)
+            continue;
+
+        ScrollingNodeID parentNodeID = scrollCoordinatedAncestorInParentOfFrame(*child);
+        if (!parentNodeID)
+            continue;
+
+        scrollingCoordinator->attachToStateTree(FrameScrollingNode, frameScrollingNodeID, parentNodeID);
+    }
+}
+
+ScrollingNodeID RenderLayerCompositor::attachScrollingNode(RenderLayer& layer, ScrollingNodeType nodeType, ScrollingNodeID parentNodeID)
+{
+    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+    RenderLayerBacking* backing = layer.backing();
+
+    ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(nodeType);
+    if (!nodeID)
+        nodeID = scrollingCoordinator->uniqueScrollLayerID();
+
+    nodeID = scrollingCoordinator->attachToStateTree(nodeType, nodeID, parentNodeID);
+    if (!nodeID)
+        return 0;
+
+    backing->setScrollingNodeIDForRole(nodeID, nodeType);
+    m_scrollingNodeToLayerMap.add(nodeID, &layer);
     
+    return nodeID;
+}
+
+void RenderLayerCompositor::updateScrollCoordinationForThisFrame(ScrollingNodeID parentNodeID)
+{
+    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+    ASSERT(scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView()));
+
+    ScrollingNodeID nodeID = attachScrollingNode(*m_renderView.layer(), FrameScrollingNode, parentNodeID);
+    scrollingCoordinator->updateFrameScrollingNode(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer());
+}
+
+void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, ScrollCoordinationReasons reasons)
+{
+    ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator();
+    if (!scrollingCoordinator || !scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView()))
+        return;
+
     bool isRootLayer = &layer == m_renderView.layer();
 
     // FIXME: Remove supportsFixedPositionLayers() since all platforms support them now.
@@ -3608,19 +3693,23 @@ void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, Scr
     if (!backing)
         return;
 
-    RenderLayerBacking* parent = nearestScrollCoordinatedAncestor(layer);
-    if (!parent && !isRootLayer)
-        return;
+    if (!m_renderView.frame().isMainFrame()) {
+        ScrollingNodeID parentDocumentHostingNodeID = scrollCoordinatedAncestorInParentOfFrame(m_renderView.frame());
+        if (!parentDocumentHostingNodeID)
+            return;
 
-    ScrollingNodeID parentNodeID = parent ? parent->scrollingNodeIDForChildren() : 0;
+        updateScrollCoordinationForThisFrame(parentDocumentHostingNodeID);
+        if (!(reasons & FixedOrSticky) && isRootLayer)
+            return;
+    }
+
+    ScrollingNodeID parentNodeID = enclosingScrollingNodeID(layer, ExcludeSelf);
+    if (!parentNodeID && !isRootLayer)
+        return;
     
     // Always call this even if the backing is already attached because the parent may have changed.
     // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling.
     if (reasons & FixedOrSticky) {
-        ScrollingNodeID nodeID = backing->viewportConstrainedNodeID();
-        if (!nodeID)
-            nodeID = scrollingCoordinator->uniqueScrollLayerID();
-
         ScrollingNodeType nodeType = FrameScrollingNode;
         if (layer.renderer().style().position() == FixedPosition)
             nodeType = FixedNode;
@@ -3629,12 +3718,10 @@ void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, Scr
         else
             ASSERT_NOT_REACHED();
 
-        nodeID = scrollingCoordinator->attachToStateTree(nodeType, nodeID, parentNodeID);
+        ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
         if (!nodeID)
             return;
 
-        backing->setViewportConstrainedNodeID(nodeID);
-
         switch (nodeType) {
         case FixedNode:
             scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer());
@@ -3651,35 +3738,20 @@ void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, Scr
     }
 
     if (reasons & Scrolling) {
-        ScrollingNodeID nodeID = backing->scrollingNodeID();
-        if (!nodeID)
-            nodeID = scrollingCoordinator->uniqueScrollLayerID();
-
-        nodeID = scrollingCoordinator->attachToStateTree(isRootLayer ? FrameScrollingNode : OverflowScrollingNode, nodeID, parentNodeID);
-        if (!nodeID)
-            return;
+        if (isRootLayer)
+            updateScrollCoordinationForThisFrame(parentNodeID);
+        else {
+            ScrollingNodeType nodeType = isRootLayer ? FrameScrollingNode : OverflowScrollingNode;
+            ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID);
+            if (!nodeID)
+                return;
 
-        backing->setScrollingNodeID(nodeID);
-        m_scrollingNodeToLayerMap.add(nodeID, &layer);
-
-        GraphicsLayer* scrollingLayer = backing->scrollingLayer();
-        GraphicsLayer* scrolledContentsLayer = backing->scrollingContentsLayer();
-        GraphicsLayer* counterScrollingLayer = nullptr;
-        GraphicsLayer* insetClipLayer = nullptr;
-
-        if (isRootLayer) {
-            scrollingLayer = m_scrollLayer.get();
-            scrolledContentsLayer = m_rootContentLayer.get();
-            counterScrollingLayer = fixedRootBackgroundLayer();
-            insetClipLayer = clipLayer();
-            scrollingCoordinator->updateFrameScrollingNode(nodeID, scrollingLayer, scrolledContentsLayer, counterScrollingLayer, insetClipLayer);
-        } else {
             ScrollingCoordinator::ScrollingGeometry scrollingGeometry;
             scrollingGeometry.scrollOrigin = layer.scrollOrigin();
             scrollingGeometry.scrollPosition = layer.scrollPosition();
             scrollingGeometry.scrollableAreaSize = layer.visibleSize();
             scrollingGeometry.contentSize = layer.contentsSize();
-            scrollingCoordinator->updateOverflowScrollingNode(nodeID, scrollingLayer, scrolledContentsLayer, &scrollingGeometry);
+            scrollingCoordinator->updateOverflowScrollingNode(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer(), &scrollingGeometry);
         }
     }
 }
@@ -3690,10 +3762,13 @@ void RenderLayerCompositor::detachScrollCoordinatedLayer(RenderLayer& layer)
     if (!backing)
         return;
 
-    backing->detachFromScrollingCoordinator();
+    if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(FrameScrollingNode))
+        m_scrollingNodeToLayerMap.remove(nodeID);
 
-    if (ScrollingNodeID nodeID = backing->scrollingNodeID())
+    if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(FixedNode))
         m_scrollingNodeToLayerMap.remove(nodeID);
+
+    backing->detachFromScrollingCoordinator();
 }
 
 ScrollableArea* RenderLayerCompositor::scrollableAreaForScrollLayerID(ScrollingNodeID nodeID) const
@@ -3728,7 +3803,7 @@ void RenderLayerCompositor::registerAllViewportConstrainedLayers()
         if (layer.renderer().isStickyPositioned()) {
             constraints = std::make_unique<StickyPositionViewportConstraints>(computeStickyViewportConstraints(layer));
             const RenderLayer* enclosingTouchScrollableLayer = nullptr;
-            if (isStickyInAcceleratedScrollingLayerOrViewport(layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) {
+            if (isAsyncScrollableStickyLayer(layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) {
                 ASSERT(enclosingTouchScrollableLayer->isComposited());
                 stickyContainerMap.add(layer.backing()->graphicsLayer()->platformLayer(), enclosingTouchScrollableLayer->backing()->scrollingLayer()->platformLayer());
             }
@@ -3791,7 +3866,7 @@ void RenderLayerCompositor::willRemoveScrollingLayer(RenderLayer& layer)
         RenderLayerBacking* backing = layer.backing();
     
         if (backing)
-            scrollingCoordinator->detachFromStateTree(backing->scrollingNodeID());
+            backing->detachFromScrollingCoordinator();
 
         // For Coordinated Graphics.
         scrollingCoordinator->scrollableAreaScrollLayerDidChange(&layer);
index 10573b8..eeeb0f9 100644 (file)
@@ -395,7 +395,6 @@ private:
     PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const;
 #endif
 
-    // Whether a running transition or animation enforces the need for a compositing layer.
     bool requiresCompositingForAnimation(RenderLayerModelObject&) const;
     bool requiresCompositingForTransform(RenderLayerModelObject&) const;
     bool requiresCompositingForBackfaceVisibility(RenderLayerModelObject&) const;
@@ -424,9 +423,12 @@ private:
     };
     typedef unsigned ScrollCoordinationReasons;
 
+    void updateScrollCoordinationForThisFrame(ScrollingNodeID);
+    ScrollingNodeID attachScrollingNode(RenderLayer&, ScrollingNodeType, ScrollingNodeID parentNodeID);
     void updateScrollCoordinatedLayer(RenderLayer&, ScrollCoordinationReasons);
     void detachScrollCoordinatedLayer(RenderLayer&);
-
+    void reattachSubframeScrollLayers();
+    
     FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer&) const;
     StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer&) const;
 
@@ -439,7 +441,12 @@ private:
     bool requiresContentShadowLayer() const;
 #endif
 
+    // True if the FrameView uses a ScrollingCoordinator.
     bool hasCoordinatedScrolling() const;
+
+    bool isAsyncScrollableStickyLayer(const RenderLayer&, const RenderLayer** enclosingAcceleratedOverflowLayer = nullptr) const;
+    bool isViewportConstrainedFixedOrStickyLayer(const RenderLayer&) const;
+    
     bool shouldCompositeOverflowControls() const;
 
     void scheduleLayerFlushNow();
@@ -480,6 +487,7 @@ private:
     bool m_shouldFlushOnReattach;
     bool m_forceCompositingMode;
     bool m_inPostLayoutUpdate; // true when it's OK to trust layout information (e.g. layer sizes and positions)
+    bool m_subframeScrollLayersNeedReattach;
 
     bool m_isTrackingRepaints; // Used for testing.
 
index 0f39e7f..834aba6 100644 (file)
@@ -839,6 +839,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
     if ((start && !end) || (end && !start))
         return;
 
+    // FIXME: view() is just *this here.
     bool caretChanged = m_selectionWasCaret != view().frame().selection().isCaret();
     m_selectionWasCaret = view().frame().selection().isCaret();
     // Just return if the selection hasn't changed.
index 8554bde..fc910c5 100644 (file)
@@ -486,4 +486,10 @@ void InternalSettings::setShouldConvertPositionStyleOnCopy(bool convert, Excepti
     settings()->setShouldConvertPositionStyleOnCopy(convert);
 }
 
+void InternalSettings::setScrollingTreeIncludesFrames(bool enabled, ExceptionCode& ec)
+{
+    InternalSettingsGuardForSettings();
+    settings()->setScrollingTreeIncludesFrames(enabled);
+}
+
 }
index 39e35b7..ba32756 100644 (file)
@@ -100,8 +100,8 @@ public:
     virtual ~InternalSettings();
     void resetToConsistentState();
 
-    void setUsesOverlayScrollbars(bool enabled, ExceptionCode&);
-    void setTouchEventEmulationEnabled(bool enabled, ExceptionCode&);
+    void setUsesOverlayScrollbars(bool, ExceptionCode&);
+    void setTouchEventEmulationEnabled(bool, ExceptionCode&);
     void setStandardFontFamily(const String& family, const String& script, ExceptionCode&);
     void setSerifFontFamily(const String& family, const String& script, ExceptionCode&);
     void setSansSerifFontFamily(const String& family, const String& script, ExceptionCode&);
@@ -113,25 +113,25 @@ public:
     void setTextAutosizingWindowSizeOverride(int width, int height, ExceptionCode&);
     void setTextAutosizingFontScaleFactor(float fontScaleFactor, ExceptionCode&);
     void setMediaTypeOverride(const String& mediaType, ExceptionCode&);
-    void setCSSExclusionsEnabled(bool enabled, ExceptionCode&);
-    void setCSSShapesEnabled(bool enabled, ExceptionCode&);
+    void setCSSExclusionsEnabled(bool, ExceptionCode&);
+    void setCSSShapesEnabled(bool, ExceptionCode&);
     void setCanStartMedia(bool, ExceptionCode&);
     void setEditingBehavior(const String&, ExceptionCode&);
     void setShouldDisplayTrackKind(const String& kind, bool enabled, ExceptionCode&);
     bool shouldDisplayTrackKind(const String& kind, ExceptionCode&);
     void setStorageBlockingPolicy(const String&, ExceptionCode&);
     void setLangAttributeAwareFormControlUIEnabled(bool);
-    void setImagesEnabled(bool enabled, ExceptionCode&);
+    void setImagesEnabled(bool, ExceptionCode&);
     void setMinimumTimerInterval(double intervalInSeconds, ExceptionCode&);
     void setDefaultVideoPosterURL(const String& url, ExceptionCode&);
     void setTimeWithoutMouseMovementBeforeHidingControls(double time, ExceptionCode&);
-    void setUseLegacyBackgroundSizeShorthandBehavior(bool enabled, ExceptionCode&);
-    void setAutoscrollForDragAndDropEnabled(bool enabled, ExceptionCode&);
-    void setFontFallbackPrefersPictographs(bool preferPictographs, ExceptionCode&);
+    void setUseLegacyBackgroundSizeShorthandBehavior(bool, ExceptionCode&);
+    void setAutoscrollForDragAndDropEnabled(bool, ExceptionCode&);
+    void setFontFallbackPrefersPictographs(bool, ExceptionCode&);
     void setPluginReplacementEnabled(bool);
-    void setBackgroundShouldExtendBeyondPage(bool hasExtendedBackground, ExceptionCode&);
-    void setShouldConvertPositionStyleOnCopy(bool convert, ExceptionCode&);
-
+    void setBackgroundShouldExtendBeyondPage(bool, ExceptionCode&);
+    void setShouldConvertPositionStyleOnCopy(bool, ExceptionCode&);
+    void setScrollingTreeIncludesFrames(bool, ExceptionCode&);
 
 private:
     explicit InternalSettings(Page*);
index 9785895..da47c13 100644 (file)
@@ -68,6 +68,7 @@
     [RaisesException] void setUseLegacyBackgroundSizeShorthandBehavior(boolean enabled);
     [RaisesException] void setAutoscrollForDragAndDropEnabled(boolean enabled);
     [RaisesException] void setBackgroundShouldExtendBeyondPage(boolean hasExtendedBackground);
+    [RaisesException] void setScrollingTreeIncludesFrames(boolean enabled);
 
     [RaisesException] void setMinimumTimerInterval(unrestricted double intervalInSeconds);
 };
index 0a73f28..9180ffa 100644 (file)
@@ -1,3 +1,17 @@
+2014-06-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Work towards having frames in the scrolling tree
+        https://bugs.webkit.org/show_bug.cgi?id=133665
+
+        Reviewed by Tim Horton.
+        
+        Override coordinatesScrollingForFrameView() to always return true for composited
+        frames, for iOS WK2 (eventually this class will have to be specialized for iOS and OS X).
+
+        * WebProcess/Scrolling/RemoteScrollingCoordinator.h:
+        * WebProcess/Scrolling/RemoteScrollingCoordinator.mm:
+        (WebKit::RemoteScrollingCoordinator::coordinatesScrollingForFrameView):
+
 2014-06-09  Anders Carlsson  <andersca@apple.com>
 
         Give callbacks real status codes
index a03e789..05da1d8 100644 (file)
@@ -61,6 +61,7 @@ private:
     virtual bool isRemoteScrollingCoordinator() const override { return true; }
     
     // ScrollingCoordinator
+    virtual bool coordinatesScrollingForFrameView(WebCore::FrameView*) const override;
     virtual void scheduleTreeStateCommit() override;
 
     virtual PassOwnPtr<WebCore::ScrollingTreeNode> createScrollingTreeNode(WebCore::ScrollingNodeType, WebCore::ScrollingNodeID) override;
index 506816b..1fe696e 100644 (file)
@@ -74,6 +74,12 @@ PassOwnPtr<ScrollingTreeNode> RemoteScrollingCoordinator::createScrollingTreeNod
     return nullptr;
 }
 
+bool RemoteScrollingCoordinator::coordinatesScrollingForFrameView(FrameView* frameView) const
+{
+    RenderView* renderView = frameView->renderView();
+    return renderView && renderView->usesCompositing();
+}
+
 bool RemoteScrollingCoordinator::isRubberBandInProgress() const
 {
     // FIXME: need to maintain state in the web process?