Implement visual-viewport based position:fixed handling for Mac async scrolling
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 23:41:14 +0000 (23:41 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 23:41:14 +0000 (23:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164495

Reviewed by Tim Horton.

Source/WebCore:

Educate the scrolling tree about visual and layout viewports. This is runtime-switchable,
so we push the enable flag to via the root state node, then push the layout viewport,
and the min/max scroll position that contstrain it, through frame state nodes.

When a scroll happens, we compute a new layout viewport when the visual viewport hits
an edge, and push that down through setScrollLayerPosition() since it's used to position
fixed and sticky layers.

When the main thread gets notified about an async scroll, we set the new layout viewport
on the FrameView, but do so in such a way that does not trigger layout. This is OK because
we do a RenderLayer update which udpates all the layoutViewport-dependent state, and is
necessary to avoid repaints every main thread update.

The iOS code is made to compile, but not work yet.

Tests: compositing/tiling/visiblerect-accumulated-offset.html
       fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html
       fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html
       fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html

* page/FrameView.cpp:
(WebCore::FrameView::setLayoutViewportOrigin):
(WebCore::FrameView::updateLayoutViewport):
(WebCore::FrameView::visualViewportRect):
(WebCore::FrameView::unscaledMinimumScrollPosition):
(WebCore::FrameView::scrollPositionChanged):
* page/FrameView.h:
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
(WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
(WebCore::AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll):
(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired):
(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
(WebCore::AsyncScrollingCoordinator::visualViewportEnabled):
* page/scrolling/AsyncScrollingCoordinator.h:
(WebCore::AsyncScrollingCoordinator::ScheduledScrollUpdate::ScheduledScrollUpdate):
* page/scrolling/ScrollingStateFrameScrollingNode.cpp:
(WebCore::ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode):
(WebCore::ScrollingStateFrameScrollingNode::setLayoutViewport):
(WebCore::ScrollingStateFrameScrollingNode::setMinLayoutViewportOrigin):
(WebCore::ScrollingStateFrameScrollingNode::setMaxLayoutViewportOrigin):
(WebCore::ScrollingStateFrameScrollingNode::setVisualViewportEnabled):
(WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
* page/scrolling/ScrollingStateFrameScrollingNode.h:
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::viewportChangedViaDelegatedScrolling):
(WebCore::ScrollingTree::scrollPositionChangedViaDelegatedScrolling):
(WebCore::ScrollingTree::commitTreeState):
* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::visualViewportEnabled):
(WebCore::ScrollingTree::setVisualViewportEnabled):
* page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
(WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren):
(WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition):
* page/scrolling/ScrollingTreeFrameScrollingNode.h:
(WebCore::ScrollingTreeFrameScrollingNode::layoutViewport):
(WebCore::ScrollingTreeFrameScrollingNode::minLayoutViewportOrigin):
(WebCore::ScrollingTreeFrameScrollingNode::maxLayoutViewportOrigin):
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::setScrollPositionWithoutContentEdgeConstraints):
* page/scrolling/ScrollingTreeScrollingNode.h:
* page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::scrollingTreeNodeDidScroll):
* page/scrolling/ThreadedScrollingTree.h:
* page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.h:
* page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.mm:
(WebCore::ScrollingTreeFrameScrollingNodeIOS::setScrollPositionWithoutContentEdgeConstraints):
(WebCore::ScrollingTreeFrameScrollingNodeIOS::setScrollLayerPosition):
* page/scrolling/ios/ScrollingTreeIOS.cpp:
(WebCore::ScrollingTreeIOS::scrollingTreeNodeDidScroll):
* page/scrolling/ios/ScrollingTreeIOS.h:
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollPositionWithoutContentEdgeConstraints):
(WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition):

Source/WebKit2:

Educate the scrolling tree about visual and layout viewports. This is runtime-switchable,
so we push the enable flag to via the root state node, then push the layout viewport,
and the min/max scroll position that contstrain it, through frame state nodes.

When a scroll happens, we compute a new layout viewport when the visual viewport hits
an edge, and push that down through setScrollLayerPosition() since it's used to position
fixed and sticky layers.

The iOS code is made to compile, but not work yet.

* Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
(ArgumentCoder<ScrollingStateFrameScrollingNode>::encode):
(ArgumentCoder<ScrollingStateFrameScrollingNode>::decode):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
(WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll):
* UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
* UIProcess/Scrolling/RemoteScrollingTree.cpp:
(WebKit::RemoteScrollingTree::scrollingTreeNodeDidScroll):
* UIProcess/Scrolling/RemoteScrollingTree.h:
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
* UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
(WebKit::ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition):
* WebProcess/Scrolling/RemoteScrollingCoordinator.mm:
(WebKit::RemoteScrollingCoordinator::scrollPositionChangedForNode):

LayoutTests:

Tests that dump the scrolling state tree, and the layer tree.

* TestExpectations:
* compositing/tiling/visiblerect-accumulated-offset.html: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-expected.txt: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up-expected.txt: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state-expected.txt: Added.
* fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html: Added.
* platform/mac-wk2/TestExpectations:
* platform/mac/compositing/tiling/visiblerect-accumulated-offset-expected.txt: Added.

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

41 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/compositing/tiling/visiblerect-accumulated-offset.html [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-expected.txt [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up-expected.txt [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state-expected.txt [new file with mode: 0644]
LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html [new file with mode: 0644]
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/platform/mac/compositing/tiling/visiblerect-accumulated-offset-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h
Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingStateFrameScrollingNode.h
Source/WebCore/page/scrolling/ScrollingTree.cpp
Source/WebCore/page/scrolling/ScrollingTree.h
Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.h
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp
Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp
Source/WebCore/page/scrolling/ThreadedScrollingTree.h
Source/WebCore/page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.h
Source/WebCore/page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.mm
Source/WebCore/page/scrolling/ios/ScrollingTreeIOS.cpp
Source/WebCore/page/scrolling/ios/ScrollingTreeIOS.h
Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h
Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.cpp
Source/WebKit2/UIProcess/Scrolling/RemoteScrollingTree.h
Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h
Source/WebKit2/UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm
Source/WebKit2/WebProcess/Scrolling/RemoteScrollingCoordinator.mm

index e074c21..f706e3b 100644 (file)
@@ -1,3 +1,23 @@
+2016-11-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Implement visual-viewport based position:fixed handling for Mac async scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=164495
+
+        Reviewed by Tim Horton.
+
+        Tests that dump the scrolling state tree, and the layer tree.
+
+        * TestExpectations:
+        * compositing/tiling/visiblerect-accumulated-offset.html: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-expected.txt: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up-expected.txt: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state-expected.txt: Added.
+        * fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html: Added.
+        * platform/mac-wk2/TestExpectations:
+        * platform/mac/compositing/tiling/visiblerect-accumulated-offset-expected.txt: Added.
+
 2016-11-09  Brady Eidson  <beidson@apple.com>
 
         IndexedDB 2.0: Implement new IDBCursor.continuePrimaryKey function.
index 9d18526..8bcca84 100644 (file)
@@ -15,6 +15,7 @@ displaylists [ Skip ]
 editing/mac [ Skip ]
 editing/pasteboard/gtk [ Skip ]
 tiled-drawing [ Skip ]
+fast/visual-viewport/tiled-drawing [ Skip ]
 swipe [ Skip ]
 fast/zooming/ios [ Skip ]
 fast/forms/ios [ Skip ]
diff --git a/LayoutTests/compositing/tiling/visiblerect-accumulated-offset.html b/LayoutTests/compositing/tiling/visiblerect-accumulated-offset.html
new file mode 100644 (file)
index 0000000..2af539e
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .container {
+            width: 600px;
+            height: 600px;
+            border: 1px solid black;
+        }
+        
+        .inner {
+            width: 200px;
+            height: 200px;
+            overflow: hidden;
+            -webkit-transform: translate3d(600px, 600px, 0);
+        }
+        
+        .tiled {
+            width: 3000px;
+            height: 200px;
+            background-color: green;
+            border: 1px solid black;
+            -webkit-transform: translate3d(-2002px, -101px, 0);
+        }
+        
+        .tiled:hover {
+            height: 201px;
+        }
+        
+    </style>
+</head>
+<body>
+<div class="outer container">
+    <div class="inner container">
+        <div class="tiled">
+        </div>
+    </div>
+</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-expected.txt b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-expected.txt
new file mode 100644 (file)
index 0000000..512277c
--- /dev/null
@@ -0,0 +1,62 @@
+(Frame scrolling node
+  (scrollable area size 785 585)
+  (contents size 4016 4042)
+  (requested scroll position 40 1000)
+  (frame scale factor 2.00)
+  (layout viewport at (0,207.50) size 785x585)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (1223,1436))
+  (children 4
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 207.50 785.00 585.00)
+      (layer position at last layout 0.00 207.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeBottom)
+      (viewport rect at last layout: 0.00 207.50 785.00 585.00)
+      (layer position at last layout 0.00 692.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 207.50 785.00 585.00)
+      (layer position at last layout 0.00 207.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeRight AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 207.50 785.00 585.00)
+      (layer position at last layout 685.00 207.00)
+    )
+  )
+)
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 4016.00 4042.00)
+  (children 1
+    (GraphicsLayer
+      (anchor 0.00 0.00)
+      (bounds 2008.00 2021.00)
+      (contentsOpaque 1)
+      (transform [2.00 0.00 0.00 0.00] [0.00 2.00 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+      (children 4
+        (GraphicsLayer
+          (position 0.00 207.00)
+          (bounds 785.00 101.00)
+        )
+        (GraphicsLayer
+          (position 0.00 692.00)
+          (bounds 785.00 101.00)
+        )
+        (GraphicsLayer
+          (position 0.00 207.00)
+          (bounds 100.00 586.00)
+        )
+        (GraphicsLayer
+          (position 685.00 207.00)
+          (bounds 100.00 586.00)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up-expected.txt b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up-expected.txt
new file mode 100644 (file)
index 0000000..bfcb599
--- /dev/null
@@ -0,0 +1,66 @@
+(Frame scrolling node
+  (scrollable area size 785 585)
+  (contents size 4016 4042)
+  (requested scroll position 40 460)
+  (frame scale factor 2.00)
+  (layout viewport at (0,230) size 785x585)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (1223,1436))
+  (children 4
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 230.00 785.00 585.00)
+      (layer position at last layout 0.00 230.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeBottom)
+      (viewport rect at last layout: 0.00 230.00 785.00 585.00)
+      (layer position at last layout 0.00 715.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 230.00 785.00 585.00)
+      (layer position at last layout 0.00 230.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeRight AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 230.00 785.00 585.00)
+      (layer position at last layout 685.00 230.00)
+    )
+  )
+)
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 4016.00 4042.00)
+  (children 1
+    (GraphicsLayer
+      (anchor 0.00 0.00)
+      (bounds 2008.00 2021.00)
+      (contentsOpaque 1)
+      (transform [2.00 0.00 0.00 0.00] [0.00 2.00 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+      (children 4
+        (GraphicsLayer
+          (position 0.00 230.00)
+          (bounds 785.00 100.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (position 0.00 715.00)
+          (bounds 785.00 100.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (position 0.00 230.00)
+          (bounds 100.00 585.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (position 685.00 230.00)
+          (bounds 100.00 585.00)
+          (contentsOpaque 1)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html
new file mode 100644 (file)
index 0000000..0143c60
--- /dev/null
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            width: 2000px;
+        }
+        
+        .fixed {
+            position: fixed;
+            background-color: gray;
+        }
+        
+        #top, #bottom {
+            width: 100%;
+            left: 0;
+            height: 100px;
+        }
+
+        #left, #right {
+            width: 100px;
+            top: 0;
+            height: 100%;
+        }
+
+        #top { top: 0; }
+        #bottom { bottom: 0; }
+
+        #left { left: 0; }
+        #right { right: 0; }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        if (window.internals)
+            internals.settings.setVisualViewportEnabled(true);
+        
+        function doAfterZooming()
+        {
+            window.scrollTo(20, 875);
+            window.scrollTo(20, 230);
+
+            if (window.internals) {
+                document.getElementById('scrolling-tree').textContent = internals.scrollingStateTreeAsText();
+                document.getElementById('layer-tree').textContent = internals.layerTreeAsText(document);
+            }
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+
+        function getUIScript()
+        {
+            return `(function() {
+                uiController.zoomToScale(2, function() {
+                    uiController.uiScriptComplete(uiController.zoomScale);
+                });
+            })();`;
+        }
+
+        function doTest()
+        {
+            if (!window.testRunner)
+                return;
+
+            testRunner.runUIScript(getUIScript(), function(zoomScale) {
+                doAfterZooming();
+            });
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="top" class="fixed"></div>
+    <div id="bottom" class="fixed"></div>
+    <div id="left" class="fixed"></div>
+    <div id="right" class="fixed"></div>
+<pre id="scrolling-tree">Scrolling tree goes here</pre>
+<pre id="layer-tree">Layer tree goes here</pre>
+</body>
+</html>
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html
new file mode 100644 (file)
index 0000000..9f7466c
--- /dev/null
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            width: 2000px;
+        }
+        
+        .fixed {
+            position: fixed;
+            background-color: gray;
+        }
+        
+        #top, #bottom {
+            width: 100%;
+            left: 0;
+            height: 100px;
+        }
+
+        #left, #right {
+            width: 100px;
+            top: 0;
+            height: 100%;
+        }
+
+        #top { top: 0; }
+        #bottom { bottom: 0; }
+
+        #left { left: 0; }
+        #right { right: 0; }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        if (window.internals)
+            internals.settings.setVisualViewportEnabled(true);
+        
+        function doAfterZooming()
+        {
+            window.scrollTo(20, 500);
+
+            if (window.internals) {
+                document.getElementById('scrolling-tree').textContent = internals.scrollingStateTreeAsText();
+                document.getElementById('layer-tree').textContent = internals.layerTreeAsText(document);
+            }
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+
+        function getUIScript()
+        {
+            return `(function() {
+                uiController.zoomToScale(2, function() {
+                    uiController.uiScriptComplete(uiController.zoomScale);
+                });
+            })();`;
+        }
+
+        function doTest()
+        {
+            if (!window.testRunner)
+                return;
+
+            testRunner.runUIScript(getUIScript(), function(zoomScale) {
+                doAfterZooming();
+            });
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="top" class="fixed"></div>
+    <div id="bottom" class="fixed"></div>
+    <div id="left" class="fixed"></div>
+    <div id="right" class="fixed"></div>
+<pre id="scrolling-tree">Scrolling tree goes here</pre>
+<pre id="layer-tree">Layer tree goes here</pre>
+</body>
+</html>
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state-expected.txt b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state-expected.txt
new file mode 100644 (file)
index 0000000..32aa29b
--- /dev/null
@@ -0,0 +1,61 @@
+(Frame scrolling node
+  (scrollable area size 785 585)
+  (contents size 4016 4042)
+  (frame scale factor 2.00)
+  (layout viewport at (0,0) size 785x585)
+  (min layout viewport origin (0,0))
+  (max layout viewport origin (1223,1436))
+  (children 4
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 585.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeBottom)
+      (viewport rect at last layout: 0.00 0.00 785.00 585.00)
+      (layer position at last layout 0.00 485.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeLeft AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 585.00)
+    )
+    (Fixed node
+      (anchor edges: AnchorEdgeRight AnchorEdgeTop)
+      (viewport rect at last layout: 0.00 0.00 785.00 585.00)
+      (layer position at last layout 685.00 0.00)
+    )
+  )
+)
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 4016.00 4042.00)
+  (children 1
+    (GraphicsLayer
+      (anchor 0.00 0.00)
+      (bounds 2008.00 2021.00)
+      (contentsOpaque 1)
+      (transform [2.00 0.00 0.00 0.00] [0.00 2.00 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 0.00 1.00])
+      (children 4
+        (GraphicsLayer
+          (bounds 785.00 100.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (position 0.00 485.00)
+          (bounds 785.00 100.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (bounds 100.00 585.00)
+          (contentsOpaque 1)
+        )
+        (GraphicsLayer
+          (position 685.00 0.00)
+          (bounds 100.00 585.00)
+          (contentsOpaque 1)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html b/LayoutTests/fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html
new file mode 100644 (file)
index 0000000..3970530
--- /dev/null
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            width: 2000px;
+        }
+        
+        .fixed {
+            position: fixed;
+            background-color: gray;
+        }
+        
+        #top, #bottom {
+            width: 100%;
+            left: 0;
+            height: 100px;
+        }
+
+        #left, #right {
+            width: 100px;
+            top: 0;
+            height: 100%;
+        }
+
+        #top { top: 0; }
+        #bottom { bottom: 0; }
+
+        #left { left: 0; }
+        #right { right: 0; }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        if (window.internals)
+            internals.settings.setVisualViewportEnabled(true);
+        
+        function doAfterZooming()
+        {
+            // Zooming may scroll the view away from the origin.
+            window.scrollTo(0, 0);
+
+            if (window.internals) {
+                document.getElementById('scrolling-tree').textContent = internals.scrollingStateTreeAsText();
+                document.getElementById('layer-tree').textContent = internals.layerTreeAsText(document);
+            }
+            
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+
+        function getUIScript()
+        {
+            return `(function() {
+                uiController.zoomToScale(2, function() {
+                    uiController.uiScriptComplete(uiController.zoomScale);
+                });
+            })();`;
+        }
+
+        function doTest()
+        {
+            if (!window.testRunner)
+                return;
+
+            testRunner.runUIScript(getUIScript(), function(zoomScale) {
+                doAfterZooming();
+            });
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="top" class="fixed"></div>
+    <div id="bottom" class="fixed"></div>
+    <div id="left" class="fixed"></div>
+    <div id="right" class="fixed"></div>
+<pre id="scrolling-tree">Scrolling tree goes here</pre>
+<pre id="layer-tree">Layer tree goes here</pre>
+</body>
+</html>
index c9e525d..2bd8a0c 100644 (file)
@@ -6,6 +6,7 @@
 #//////////////////////////////////////////////////////////////////////////////////////////
 
 tiled-drawing [ Pass ]
+fast/visual-viewport/tiled-drawing [ Pass ]
 swipe [ Pass ]
 
 fast/events/cancelled-force-click-link-navigation.html [ Pass ]
diff --git a/LayoutTests/platform/mac/compositing/tiling/visiblerect-accumulated-offset-expected.txt b/LayoutTests/platform/mac/compositing/tiling/visiblerect-accumulated-offset-expected.txt
new file mode 100644 (file)
index 0000000..4f30dec
--- /dev/null
@@ -0,0 +1,8 @@
+layer at (0,0) size 811x811
+  RenderView at (0,0) size 785x585
+layer at (0,0) size 785x618
+  RenderBlock {HTML} at (0,0) size 785x618
+    RenderBody {BODY} at (8,8) size 769x602
+      RenderBlock {DIV} at (0,0) size 602x602 [border: (1px solid #000000)]
+layer at (9,9) size 202x202 clip at (10,10) size 200x200 scrollWidth 1000 scrollHeight 202
+  RenderBlock {DIV} at (1,1) size 202x202 [border: (1px solid #000000)]
index a40d22e..5875482 100644 (file)
@@ -1,3 +1,86 @@
+2016-11-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Implement visual-viewport based position:fixed handling for Mac async scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=164495
+
+        Reviewed by Tim Horton.
+
+        Educate the scrolling tree about visual and layout viewports. This is runtime-switchable,
+        so we push the enable flag to via the root state node, then push the layout viewport,
+        and the min/max scroll position that contstrain it, through frame state nodes.
+
+        When a scroll happens, we compute a new layout viewport when the visual viewport hits
+        an edge, and push that down through setScrollLayerPosition() since it's used to position
+        fixed and sticky layers.
+
+        When the main thread gets notified about an async scroll, we set the new layout viewport
+        on the FrameView, but do so in such a way that does not trigger layout. This is OK because
+        we do a RenderLayer update which udpates all the layoutViewport-dependent state, and is
+        necessary to avoid repaints every main thread update.
+
+        The iOS code is made to compile, but not work yet.
+
+        Tests: compositing/tiling/visiblerect-accumulated-offset.html
+               fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down-then-up.html
+               fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolled-down.html
+               fast/visual-viewport/tiled-drawing/zoomed-fixed-scrolling-layers-state.html
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::setLayoutViewportOrigin):
+        (WebCore::FrameView::updateLayoutViewport):
+        (WebCore::FrameView::visualViewportRect):
+        (WebCore::FrameView::unscaledMinimumScrollPosition):
+        (WebCore::FrameView::scrollPositionChanged):
+        * page/FrameView.h:
+        * page/scrolling/AsyncScrollingCoordinator.cpp:
+        (WebCore::AsyncScrollingCoordinator::frameViewLayoutUpdated):
+        (WebCore::AsyncScrollingCoordinator::requestScrollPositionUpdate):
+        (WebCore::AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll):
+        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired):
+        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
+        (WebCore::AsyncScrollingCoordinator::visualViewportEnabled):
+        * page/scrolling/AsyncScrollingCoordinator.h:
+        (WebCore::AsyncScrollingCoordinator::ScheduledScrollUpdate::ScheduledScrollUpdate):
+        * page/scrolling/ScrollingStateFrameScrollingNode.cpp:
+        (WebCore::ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode):
+        (WebCore::ScrollingStateFrameScrollingNode::setLayoutViewport):
+        (WebCore::ScrollingStateFrameScrollingNode::setMinLayoutViewportOrigin):
+        (WebCore::ScrollingStateFrameScrollingNode::setMaxLayoutViewportOrigin):
+        (WebCore::ScrollingStateFrameScrollingNode::setVisualViewportEnabled):
+        (WebCore::ScrollingStateFrameScrollingNode::dumpProperties):
+        * page/scrolling/ScrollingStateFrameScrollingNode.h:
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::viewportChangedViaDelegatedScrolling):
+        (WebCore::ScrollingTree::scrollPositionChangedViaDelegatedScrolling):
+        (WebCore::ScrollingTree::commitTreeState):
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::visualViewportEnabled):
+        (WebCore::ScrollingTree::setVisualViewportEnabled):
+        * page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
+        (WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren):
+        (WebCore::ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition):
+        * page/scrolling/ScrollingTreeFrameScrollingNode.h:
+        (WebCore::ScrollingTreeFrameScrollingNode::layoutViewport):
+        (WebCore::ScrollingTreeFrameScrollingNode::minLayoutViewportOrigin):
+        (WebCore::ScrollingTreeFrameScrollingNode::maxLayoutViewportOrigin):
+        * page/scrolling/ScrollingTreeScrollingNode.cpp:
+        (WebCore::ScrollingTreeScrollingNode::setScrollPositionWithoutContentEdgeConstraints):
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        * page/scrolling/ThreadedScrollingTree.cpp:
+        (WebCore::ThreadedScrollingTree::scrollingTreeNodeDidScroll):
+        * page/scrolling/ThreadedScrollingTree.h:
+        * page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.h:
+        * page/scrolling/ios/ScrollingTreeFrameScrollingNodeIOS.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeIOS::setScrollPositionWithoutContentEdgeConstraints):
+        (WebCore::ScrollingTreeFrameScrollingNodeIOS::setScrollLayerPosition):
+        * page/scrolling/ios/ScrollingTreeIOS.cpp:
+        (WebCore::ScrollingTreeIOS::scrollingTreeNodeDidScroll):
+        * page/scrolling/ios/ScrollingTreeIOS.h:
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.h:
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollPositionWithoutContentEdgeConstraints):
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition):
+
 2016-11-09  Brady Eidson  <beidson@apple.com>
 
         IndexedDB 2.0: W3C test IndexedDB/idbtransaction_objectStoreNames.html fails.
index 776476d..a11985d 100644 (file)
@@ -1792,6 +1792,7 @@ void FrameView::removeViewportConstrainedObject(RenderElement* object)
     }
 }
 
+// visualViewport and layoutViewport are both in content coordinates (unzoomed).
 LayoutPoint FrameView::computeLayoutViewportOrigin(const LayoutRect& visualViewport, const LayoutPoint& stableLayoutViewportOriginMin, const LayoutPoint& stableLayoutViewportOriginMax, const LayoutRect& layoutViewport)
 {
     LayoutPoint layoutViewportOrigin = layoutViewport.location();
@@ -1811,7 +1812,7 @@ LayoutPoint FrameView::computeLayoutViewportOrigin(const LayoutRect& visualViewp
     return layoutViewportOrigin;
 }
 
-void FrameView::setLayoutViewportOrigin(LayoutPoint origin)
+void FrameView::setLayoutViewportOrigin(LayoutPoint origin, TriggerLayoutOrNot layoutTriggering)
 {
     ASSERT(frame().settings().visualViewportEnabled());
 
@@ -1819,7 +1820,8 @@ void FrameView::setLayoutViewportOrigin(LayoutPoint origin)
         return;
 
     m_layoutViewportOrigin = origin;
-    setViewportConstrainedObjectsNeedLayout();
+    if (layoutTriggering == TriggerLayoutOrNot::Yes)
+        setViewportConstrainedObjectsNeedLayout();
     
     if (TiledBacking* tiledBacking = this->tiledBacking()) {
         FloatRect layoutViewport = layoutViewportRect();
@@ -1842,8 +1844,8 @@ void FrameView::updateLayoutViewport()
 
     LayoutPoint newLayoutViewportOrigin = computeLayoutViewportOrigin(visualViewportRect(), minStableLayoutViewportOrigin(), maxStableLayoutViewportOrigin(), layoutViewport);
     if (newLayoutViewportOrigin != layoutViewportOrigin()) {
-        LOG_WITH_STREAM(Scrolling, stream << "layoutViewport changed to " << layoutViewport);
         setLayoutViewportOrigin(newLayoutViewportOrigin);
+        LOG_WITH_STREAM(Scrolling, stream << "layoutViewport changed to " << layoutViewportRect());
     }
 }
 
@@ -1875,7 +1877,7 @@ LayoutRect FrameView::visualViewportRect() const
 {
     // This isn't visibleContentRect(), because that uses a scaled scroll origin. Confused? Me too.
     FloatRect visibleContentRect = this->visibleContentRect(LegacyIOSDocumentVisibleRect);
-    visibleContentRect.scale(1 / frameScaleFactor());
+    visibleContentRect.scale(1 / frameScaleFactor()); // Note that frameScaleFactor() returns 1 for delegated scrolling (e.g. iOS WK2)
     return LayoutRect(visibleContentRect);
 }
 
@@ -2049,7 +2051,7 @@ ScrollPosition FrameView::unscaledMinimumScrollPosition() const
 {
     if (RenderView* renderView = this->renderView()) {
         IntRect unscaledDocumentRect = renderView->unscaledDocumentRect();
-        ScrollPosition minimumPosition = unscaledDocumentRect.location() - visibleSize();
+        ScrollPosition minimumPosition = unscaledDocumentRect.location();
 
         if (frame().isMainFrame() && m_scrollPinningBehavior == PinToBottom)
             minimumPosition.setY(unscaledMaximumScrollPosition().y());
@@ -2402,6 +2404,7 @@ void FrameView::scrollOffsetChangedViaPlatformWidgetImpl(const ScrollOffset& old
     scrollPositionChanged(scrollPositionFromOffset(oldOffset), scrollPositionFromOffset(newOffset));
 }
 
+// These scroll positions are affected by zooming.
 void FrameView::scrollPositionChanged(const ScrollPosition& oldPosition, const ScrollPosition& newPosition)
 {
     Page* page = frame().page();
@@ -2421,7 +2424,7 @@ void FrameView::scrollPositionChanged(const ScrollPosition& oldPosition, const S
             renderView->compositor().frameViewDidScroll();
     }
 
-    LOG_WITH_STREAM(Scrolling, stream << "FrameView " << this << " scrollPositionChanged from " << oldPosition << " to " << newPosition);
+    LOG_WITH_STREAM(Scrolling, stream << "FrameView " << this << " scrollPositionChanged from " << oldPosition << " to " << newPosition << " (scale " << frameScaleFactor() << " )");
     updateLayoutViewport();
     viewportContentsChanged();
 }
index 5d78aae..bb29b40 100644 (file)
@@ -252,7 +252,11 @@ public:
 
     IntPoint unscaledScrollOrigin() const;
 
-    void setLayoutViewportOrigin(LayoutPoint);
+    enum class TriggerLayoutOrNot {
+        No,
+        Yes
+    };
+    void setLayoutViewportOrigin(LayoutPoint, TriggerLayoutOrNot = TriggerLayoutOrNot::Yes);
     LayoutPoint layoutViewportOrigin() const { return m_layoutViewportOrigin; }
     
     LayoutPoint minStableLayoutViewportOrigin() const;
index 887718a..2566dd2 100644 (file)
@@ -43,6 +43,7 @@
 #include "ScrollingStateOverflowScrollingNode.h"
 #include "ScrollingStateStickyNode.h"
 #include "ScrollingStateTree.h"
+#include "Settings.h"
 #include "WheelEventTestTrigger.h"
 
 namespace WebCore {
@@ -135,6 +136,11 @@ void AsyncScrollingCoordinator::frameViewLayoutUpdated(FrameView& frameView)
     node->setFooterHeight(frameView.footerHeight());
     node->setTopContentInset(frameView.topContentInset());
 
+    node->setVisualViewportEnabled(visualViewportEnabled());
+    node->setLayoutViewport(frameView.layoutViewportRect());
+    node->setMinLayoutViewportOrigin(frameView.minStableLayoutViewportOrigin());
+    node->setMaxLayoutViewportOrigin(frameView.maxStableLayoutViewportOrigin());
+
     node->setScrollOrigin(frameView.scrollOrigin());
     node->setScrollableAreaSize(frameView.visibleContentRect().size());
     node->setTotalContentsSize(frameView.totalContentsSize());
@@ -213,7 +219,7 @@ bool AsyncScrollingCoordinator::requestScrollPositionUpdate(FrameView& frameView
 
     bool isProgrammaticScroll = frameView.inProgrammaticScroll();
     if (isProgrammaticScroll || frameView.frame().document()->pageCacheState() != Document::NotInPageCache)
-        updateScrollPositionAfterAsyncScroll(frameView.scrollLayerID(), scrollPosition, isProgrammaticScroll, SetScrollingLayerPosition);
+        updateScrollPositionAfterAsyncScroll(frameView.scrollLayerID(), scrollPosition, Nullopt, isProgrammaticScroll, SetScrollingLayerPosition);
 
     // If this frame view's document is being put into the page cache, we don't want to update our
     // main frame scroll position. Just let the FrameView think that we did.
@@ -228,9 +234,9 @@ bool AsyncScrollingCoordinator::requestScrollPositionUpdate(FrameView& frameView
     return true;
 }
 
-void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
-    ScheduledScrollUpdate scrollUpdate(nodeID, scrollPosition, programmaticScroll, scrollingLayerPositionAction);
+    ScheduledScrollUpdate scrollUpdate(nodeID, scrollPosition, layoutViewportOrigin, programmaticScroll, scrollingLayerPositionAction);
     
     // For programmatic scrolls, requestScrollPositionUpdate() has already called updateScrollPositionAfterAsyncScroll().
     if (programmaticScroll)
@@ -244,8 +250,8 @@ void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(Scr
     
         // If the parameters don't match what was previously scheduled, dispatch immediately.
         m_updateNodeScrollPositionTimer.stop();
-        updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
-        updateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, programmaticScroll, scrollingLayerPositionAction);
+        updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.layoutViewportOrigin, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
+        updateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, layoutViewportOrigin, programmaticScroll, scrollingLayerPositionAction);
         return;
     }
 
@@ -255,7 +261,7 @@ void AsyncScrollingCoordinator::scheduleUpdateScrollPositionAfterAsyncScroll(Scr
 
 void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScrollTimerFired()
 {
-    updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
+    updateScrollPositionAfterAsyncScroll(m_scheduledScrollUpdate.nodeID, m_scheduledScrollUpdate.scrollPosition, m_scheduledScrollUpdate.layoutViewportOrigin, m_scheduledScrollUpdate.isProgrammaticScroll, m_scheduledScrollUpdate.updateLayerPositionAction);
 }
 
 FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID scrollingNodeID) const
@@ -290,7 +296,7 @@ FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID
     return nullptr;
 }
 
-void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, Optional<FloatPoint> layoutViewportOrigin, bool programmaticScroll, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
     ASSERT(isMainThread());
 
@@ -307,10 +313,12 @@ void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNo
         bool oldProgrammaticScroll = frameView.inProgrammaticScroll();
         frameView.setInProgrammaticScroll(programmaticScroll);
 
+        if (layoutViewportOrigin)
+            frameView.setLayoutViewportOrigin(LayoutPoint(layoutViewportOrigin.value()), FrameView::TriggerLayoutOrNot::No);
+
         frameView.setConstrainsScrollingToContentEdge(false);
         frameView.notifyScrollPositionChanged(roundedIntPoint(scrollPosition));
         frameView.setConstrainsScrollingToContentEdge(true);
-
         frameView.setInProgrammaticScroll(oldProgrammaticScroll);
 
         if (GraphicsLayer* scrollLayer = scrollLayerForFrameView(frameView)) {
@@ -320,11 +328,16 @@ void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNo
             GraphicsLayer* scrolledContentsLayer = rootContentLayerForFrameView(frameView);
             GraphicsLayer* headerLayer = headerLayerForFrameView(frameView);
             GraphicsLayer* footerLayer = footerLayerForFrameView(frameView);
-            LayoutPoint scrollPositionForFixed = frameView.scrollPositionForFixedPosition();
 
+            ASSERT(frameView.scrollPosition() == roundedIntPoint(scrollPosition));
+            LayoutPoint scrollPositionForFixed = visualViewportEnabled() ? frameView.layoutViewportOrigin() : frameView.scrollPositionForFixedPosition();
             float topContentInset = frameView.topContentInset();
-            FloatPoint positionForInsetClipLayer = FloatPoint(insetClipLayer ? insetClipLayer->position().x() : 0, FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
+
+            FloatPoint positionForInsetClipLayer;
+            if (insetClipLayer)
+                positionForInsetClipLayer = FloatPoint(insetClipLayer->position().x(), FrameView::yPositionForInsetClipLayer(scrollPosition, topContentInset));
             FloatPoint positionForContentsLayer = frameView.positionForRootContentLayer();
+            
             FloatPoint positionForHeaderLayer = FloatPoint(scrollPositionForFixed.x(), FrameView::yPositionForHeaderLayer(scrollPosition, topContentInset));
             FloatPoint positionForFooterLayer = FloatPoint(scrollPositionForFixed.x(),
                 FrameView::yPositionForFooterLayer(scrollPosition, topContentInset, frameView.totalContentsSize().height(), frameView.footerHeight()));
@@ -549,6 +562,11 @@ void AsyncScrollingCoordinator::setScrollPinningBehavior(ScrollPinningBehavior p
     scrollingTree()->setScrollPinningBehavior(pinning);
 }
 
+bool AsyncScrollingCoordinator::visualViewportEnabled() const
+{
+    return m_page->mainFrame().settings().visualViewportEnabled();
+}
+
 String AsyncScrollingCoordinator::scrollingStateTreeAsText() const
 {
     if (m_scrollingStateTree->rootStateNode()) {
index e9c1b2f..3cbb4f3 100644 (file)
@@ -52,7 +52,7 @@ public:
 
     void scrollingStateTreePropertiesChanged();
 
-    WEBCORE_EXPORT void scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
+    WEBCORE_EXPORT void scheduleUpdateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, const Optional<FloatPoint>& layoutViewportOrigin, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
 
 #if PLATFORM(COCOA)
     WEBCORE_EXPORT void setActiveScrollSnapIndices(ScrollingNodeID, unsigned horizontalIndex, unsigned verticalIndex);
@@ -73,7 +73,7 @@ protected:
 
     PassRefPtr<ScrollingTree> releaseScrollingTree() { return WTFMove(m_scrollingTree); }
 
-    void updateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
+    void updateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, Optional<FloatPoint> layoutViewportOrigin, bool programmaticScroll, SetOrSyncScrollingLayerPosition);
 
     WEBCORE_EXPORT String scrollingStateTreeAsText() const override;
     WEBCORE_EXPORT void willCommitTree() override;
@@ -85,6 +85,8 @@ private:
 
     bool supportsFixedPositionLayers() const override { return true; }
     bool hasVisibleSlowRepaintViewportConstrainedObjects(const FrameView&) const override { return false; }
+    
+    bool visualViewportEnabled() const;
 
     WEBCORE_EXPORT void frameViewLayoutUpdated(FrameView&) override;
     WEBCORE_EXPORT void frameViewRootLayerDidChange(FrameView&) override;
@@ -127,23 +129,20 @@ private:
     Timer m_updateNodeScrollPositionTimer;
 
     struct ScheduledScrollUpdate {
-        ScheduledScrollUpdate()
-            : nodeID(0)
-            , isProgrammaticScroll(false)
-            , updateLayerPositionAction(SyncScrollingLayerPosition)
-        { }
-
-        ScheduledScrollUpdate(ScrollingNodeID scrollingNodeID, FloatPoint point, bool isProgrammatic, SetOrSyncScrollingLayerPosition udpateAction)
+        ScheduledScrollUpdate() = default;
+        ScheduledScrollUpdate(ScrollingNodeID scrollingNodeID, FloatPoint point, Optional<FloatPoint> viewportOrigin, bool isProgrammatic, SetOrSyncScrollingLayerPosition udpateAction)
             : nodeID(scrollingNodeID)
             , scrollPosition(point)
+            , layoutViewportOrigin(viewportOrigin)
             , isProgrammaticScroll(isProgrammatic)
             , updateLayerPositionAction(udpateAction)
         { }
 
-        ScrollingNodeID nodeID;
+        ScrollingNodeID nodeID { 0 };
         FloatPoint scrollPosition;
-        bool isProgrammaticScroll;
-        SetOrSyncScrollingLayerPosition updateLayerPositionAction;
+        Optional<FloatPoint> layoutViewportOrigin;
+        bool isProgrammaticScroll { false };
+        SetOrSyncScrollingLayerPosition updateLayerPositionAction { SyncScrollingLayerPosition };
         
         bool matchesUpdateType(const ScheduledScrollUpdate& other) const
         {
index fbd46ff..f518127 100644 (file)
@@ -51,6 +51,9 @@ ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode(const Scrolli
 #endif
     , m_eventTrackingRegions(stateNode.eventTrackingRegions())
     , m_requestedScrollPosition(stateNode.requestedScrollPosition())
+    , m_layoutViewport(stateNode.layoutViewport())
+    , m_minLayoutViewportOrigin(stateNode.minLayoutViewportOrigin())
+    , m_maxLayoutViewportOrigin(stateNode.maxLayoutViewportOrigin())
     , m_frameScaleFactor(stateNode.frameScaleFactor())
     , m_topContentInset(stateNode.topContentInset())
     , m_headerHeight(stateNode.headerHeight())
@@ -59,6 +62,7 @@ ScrollingStateFrameScrollingNode::ScrollingStateFrameScrollingNode(const Scrolli
     , m_behaviorForFixed(stateNode.scrollBehaviorForFixedElements())
     , m_requestedScrollPositionRepresentsProgrammaticScroll(stateNode.requestedScrollPositionRepresentsProgrammaticScroll())
     , m_fixedElementsLayoutRelativeToFrame(stateNode.fixedElementsLayoutRelativeToFrame())
+    , m_visualViewportEnabled(stateNode.visualViewportEnabled())
 {
     if (hasChangedProperty(ScrolledContentsLayer))
         setScrolledContentsLayer(stateNode.scrolledContentsLayer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
@@ -124,7 +128,34 @@ void ScrollingStateFrameScrollingNode::setScrollBehaviorForFixedElements(ScrollB
     m_behaviorForFixed = behaviorForFixed;
     setPropertyChanged(BehaviorForFixedElements);
 }
-    
+
+void ScrollingStateFrameScrollingNode::setLayoutViewport(const FloatRect& r)
+{
+    if (m_layoutViewport == r)
+        return;
+
+    m_layoutViewport = r;
+    setPropertyChanged(LayoutViewport);
+}
+
+void ScrollingStateFrameScrollingNode::setMinLayoutViewportOrigin(const FloatPoint& p)
+{
+    if (m_minLayoutViewportOrigin == p)
+        return;
+
+    m_minLayoutViewportOrigin = p;
+    setPropertyChanged(MinLayoutViewportOrigin);
+}
+
+void ScrollingStateFrameScrollingNode::setMaxLayoutViewportOrigin(const FloatPoint& p)
+{
+    if (m_maxLayoutViewportOrigin == p)
+        return;
+
+    m_maxLayoutViewportOrigin = p;
+    setPropertyChanged(MaxLayoutViewportOrigin);
+}
+
 void ScrollingStateFrameScrollingNode::setHeaderHeight(int headerHeight)
 {
     if (m_headerHeight == headerHeight)
@@ -215,6 +246,16 @@ void ScrollingStateFrameScrollingNode::setFixedElementsLayoutRelativeToFrame(boo
     setPropertyChanged(FixedElementsLayoutRelativeToFrame);
 }
 
+// Only needed while visual viewports are runtime-switchable.
+void ScrollingStateFrameScrollingNode::setVisualViewportEnabled(bool visualViewportEnabled)
+{
+    if (visualViewportEnabled == m_visualViewportEnabled)
+        return;
+    
+    m_visualViewportEnabled = visualViewportEnabled;
+    setPropertyChanged(VisualViewportEnabled);
+}
+
 #if !PLATFORM(MAC)
 void ScrollingStateFrameScrollingNode::setScrollerImpsFromScrollbars(Scrollbar*, Scrollbar*)
 {
@@ -231,6 +272,15 @@ void ScrollingStateFrameScrollingNode::dumpProperties(TextStream& ts, int indent
         writeIndent(ts, indent + 1);
         ts << "(frame scale factor " << m_frameScaleFactor << ")\n";
     }
+    
+    if (m_visualViewportEnabled) {
+        writeIndent(ts, indent + 1);
+        ts << "(layout viewport " << m_layoutViewport << ")\n";
+        writeIndent(ts, indent + 1);
+        ts << "(min layout viewport origin " << m_minLayoutViewportOrigin << ")\n";
+        writeIndent(ts, indent + 1);
+        ts << "(max layout viewport origin " << m_maxLayoutViewportOrigin << ")\n";
+    }
 
     if (!m_eventTrackingRegions.asynchronousDispatchRegion.isEmpty()) {
         ++indent;
index 6cda1bc..eeaa71f 100644 (file)
@@ -61,6 +61,10 @@ public:
         BehaviorForFixedElements,
         TopContentInset,
         FixedElementsLayoutRelativeToFrame,
+        VisualViewportEnabled,
+        LayoutViewport,
+        MinLayoutViewportOrigin,
+        MaxLayoutViewportOrigin,
     };
 
     float frameScaleFactor() const { return m_frameScaleFactor; }
@@ -75,6 +79,15 @@ public:
     ScrollBehaviorForFixedElements scrollBehaviorForFixedElements() const { return m_behaviorForFixed; }
     WEBCORE_EXPORT void setScrollBehaviorForFixedElements(ScrollBehaviorForFixedElements);
 
+    FloatRect layoutViewport() const { return m_layoutViewport; };
+    WEBCORE_EXPORT void setLayoutViewport(const FloatRect&);
+
+    FloatPoint minLayoutViewportOrigin() const { return m_minLayoutViewportOrigin; }
+    WEBCORE_EXPORT void setMinLayoutViewportOrigin(const FloatPoint&);
+
+    FloatPoint maxLayoutViewportOrigin() const { return m_maxLayoutViewportOrigin; }
+    WEBCORE_EXPORT void setMaxLayoutViewportOrigin(const FloatPoint&);
+
     int headerHeight() const { return m_headerHeight; }
     WEBCORE_EXPORT void setHeaderHeight(int);
 
@@ -112,6 +125,9 @@ public:
     bool fixedElementsLayoutRelativeToFrame() const { return m_fixedElementsLayoutRelativeToFrame; }
     WEBCORE_EXPORT void setFixedElementsLayoutRelativeToFrame(bool);
 
+    bool visualViewportEnabled() const { return m_visualViewportEnabled; };
+    WEBCORE_EXPORT void setVisualViewportEnabled(bool);
+
 #if PLATFORM(MAC)
     NSScrollerImp *verticalScrollerImp() const { return m_verticalScrollerImp.get(); }
     NSScrollerImp *horizontalScrollerImp() const { return m_horizontalScrollerImp.get(); }
@@ -138,6 +154,11 @@ private:
 
     EventTrackingRegions m_eventTrackingRegions;
     FloatPoint m_requestedScrollPosition;
+
+    FloatRect m_layoutViewport;
+    FloatPoint m_minLayoutViewportOrigin;
+    FloatPoint m_maxLayoutViewportOrigin;
+
     float m_frameScaleFactor { 1 };
     float m_topContentInset { 0 };
     int m_headerHeight { 0 };
@@ -146,6 +167,7 @@ private:
     ScrollBehaviorForFixedElements m_behaviorForFixed { StickToDocumentBounds };
     bool m_requestedScrollPositionRepresentsProgrammaticScroll { false };
     bool m_fixedElementsLayoutRelativeToFrame { false };
+    bool m_visualViewportEnabled { false };
 };
 
 } // namespace WebCore
index f8e9e76..10f25ea 100644 (file)
@@ -93,7 +93,7 @@ void ScrollingTree::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
         downcast<ScrollingTreeScrollingNode>(*m_rootNode).handleWheelEvent(wheelEvent);
 }
 
-void ScrollingTree::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatRect& fixedPositionRect, double scale)
+void ScrollingTree::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale)
 {
     ScrollingTreeNode* node = nodeForID(nodeID);
     if (!is<ScrollingTreeScrollingNode>(node))
@@ -112,7 +112,7 @@ void ScrollingTree::scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID n
     downcast<ScrollingTreeOverflowScrollingNode>(*node).updateLayersAfterDelegatedScroll(scrollPosition);
 
     // Update GraphicsLayers and scroll state.
-    scrollingTreeNodeDidScroll(nodeID, scrollPosition, inUserInteration ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
+    scrollingTreeNodeDidScroll(nodeID, scrollPosition, Nullopt, inUserInteration ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
 }
 
 void ScrollingTree::commitTreeState(std::unique_ptr<ScrollingStateTree> scrollingStateTree)
@@ -123,13 +123,18 @@ void ScrollingTree::commitTreeState(std::unique_ptr<ScrollingStateTree> scrollin
     if (rootNode
         && (rootStateNodeChanged
             || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::EventTrackingRegion)
-            || rootNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))) {
+            || rootNode->hasChangedProperty(ScrollingStateNode::ScrollLayer)
+            || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::VisualViewportEnabled))) {
         LockHolder lock(m_mutex);
 
         if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateNode::ScrollLayer))
             m_mainFrameScrollPosition = FloatPoint();
+
         if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::EventTrackingRegion))
             m_eventTrackingRegions = scrollingStateTree->rootStateNode()->eventTrackingRegions();
+
+        if (rootStateNodeChanged || rootNode->hasChangedProperty(ScrollingStateFrameScrollingNode::VisualViewportEnabled))
+            m_visualViewportEnabled = scrollingStateTree->rootStateNode()->visualViewportEnabled();
     }
     
     bool scrollRequestIsProgammatic = rootNode ? rootNode->requestedScrollPositionRepresentsProgrammaticScroll() : false;
index ec1adf3..9403a18 100644 (file)
@@ -59,6 +59,8 @@ public:
     virtual bool isRemoteScrollingTree() const { return false; }
     virtual bool isScrollingTreeIOS() const { return false; }
 
+    bool visualViewportEnabled() const { return m_visualViewportEnabled; }
+
     virtual EventResult tryToHandleWheelEvent(const PlatformWheelEvent&) = 0;
     WEBCORE_EXPORT bool shouldHandleWheelEventSynchronously(const PlatformWheelEvent&);
     
@@ -76,7 +78,7 @@ public:
 
     // Called after a scrolling tree node has handled a scroll and updated its layers.
     // Updates FrameView/RenderLayer scrolling state and GraphicsLayers.
-    virtual void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) = 0;
+    virtual void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) = 0;
 
     // Called for requested scroll position updates.
     virtual void scrollingTreeNodeRequestsScroll(ScrollingNodeID, const FloatPoint& /*scrollPosition*/, bool /*representsProgrammaticScroll*/) { }
@@ -145,6 +147,8 @@ public:
     
 protected:
     void setMainFrameScrollPosition(FloatPoint);
+    void setVisualViewportEnabled(bool b) { m_visualViewportEnabled = b; }
+
     WEBCORE_EXPORT virtual void handleWheelEvent(const PlatformWheelEvent&);
 
 private:
@@ -182,6 +186,7 @@ private:
     bool m_mainFrameIsScrollSnapping { false };
     bool m_scrollingPerformanceLoggingEnabled { false };
     bool m_isHandlingProgrammaticScroll { false };
+    bool m_visualViewportEnabled { false };
 };
     
 } // namespace WebCore
index 3748246..844fa6e 100644 (file)
 
 #if ENABLE(ASYNC_SCROLLING)
 
+#include "FrameView.h"
+#include "Logging.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingTree.h"
+#include "TextStream.h"
 
 namespace WebCore {
 
@@ -68,6 +71,15 @@ void ScrollingTreeFrameScrollingNode::commitStateBeforeChildren(const ScrollingS
 
     if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::FixedElementsLayoutRelativeToFrame))
         m_fixedElementsLayoutRelativeToFrame = state.fixedElementsLayoutRelativeToFrame();
+
+    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::LayoutViewport))
+        m_layoutViewport = state.layoutViewport();
+
+    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MinLayoutViewportOrigin))
+        m_minLayoutViewportOrigin = state.minLayoutViewportOrigin();
+
+    if (state.hasChangedProperty(ScrollingStateFrameScrollingNode::MaxLayoutViewportOrigin))
+        m_maxLayoutViewportOrigin = state.maxLayoutViewportOrigin();
 }
 
 void ScrollingTreeFrameScrollingNode::scrollBy(const FloatSize& delta)
@@ -86,6 +98,36 @@ void ScrollingTreeFrameScrollingNode::setScrollPosition(const FloatPoint& scroll
     setScrollPositionWithoutContentEdgeConstraints(newScrollPosition);
 }
 
+FloatRect ScrollingTreeFrameScrollingNode::layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale) const
+{
+    ASSERT(scrollingTree().visualViewportEnabled());
+
+    FloatSize visibleContentSize = scrollableAreaSize();
+#if PLATFORM(MAC)
+    // On Mac, FrameView.visibleContentRect(), which was used to set scrollableAreaSize(), returns a rect with scale applied (so it's not really a "content rect"),
+    // so we have to convert back to unscaled coordinates here.
+    visibleContentSize.scale(1 / scale);
+#else
+    UNUSED_PARAM(scale);
+#endif
+    FloatRect visualViewport(visibleContentOrigin, visibleContentSize);
+    LayoutRect layoutViewport(m_layoutViewport);
+
+    LOG_WITH_STREAM(Scrolling, stream << "\nScrolling thread: " << "(visibleContentOrigin " << visibleContentOrigin << ")");
+    LOG_WITH_STREAM(Scrolling, stream << "layoutViewport: " << layoutViewport);
+    LOG_WITH_STREAM(Scrolling, stream << "visualViewport: " << visualViewport);
+    LOG_WITH_STREAM(Scrolling, stream << "scroll positions: min: " << minLayoutViewportOrigin() << " max: "<< maxLayoutViewportOrigin());
+
+    LayoutPoint newLocation = FrameView::computeLayoutViewportOrigin(LayoutRect(visualViewport), LayoutPoint(minLayoutViewportOrigin()), LayoutPoint(maxLayoutViewportOrigin()), layoutViewport);
+
+    if (layoutViewport.location() != newLocation) {
+        LOG_WITH_STREAM(Scrolling, stream << " new layoutViewport " << layoutViewport);
+        layoutViewport.setLocation(newLocation);
+    }
+
+    return layoutViewport;
+}
+
 FloatSize ScrollingTreeFrameScrollingNode::viewToContentsOffset(const FloatPoint& scrollPosition) const
 {
     return toFloatSize(scrollPosition) - FloatSize(0, headerHeight() + topContentInset());
index ffeb04f..4cd308c 100644 (file)
@@ -56,6 +56,7 @@ public:
     bool fixedElementsLayoutRelativeToFrame() const { return m_fixedElementsLayoutRelativeToFrame; }
 
     FloatSize viewToContentsOffset(const FloatPoint& scrollPosition) const;
+    FloatRect layoutViewportForScrollPosition(const FloatPoint& visibleContentOrigin, float scale) const;
 
 protected:
     ScrollingTreeFrameScrollingNode(ScrollingTree&, ScrollingNodeID);
@@ -67,10 +68,18 @@ protected:
     int headerHeight() const { return m_headerHeight; }
     int footerHeight() const { return m_footerHeight; }
     float topContentInset() const { return m_topContentInset; }
-    
+
+    FloatRect layoutViewport() const { return m_layoutViewport; };
+    FloatPoint minLayoutViewportOrigin() const { return m_minLayoutViewportOrigin; }
+    FloatPoint maxLayoutViewportOrigin() const { return m_maxLayoutViewportOrigin; }
+
     ScrollBehaviorForFixedElements scrollBehaviorForFixedElements() const { return m_behaviorForFixed; }
     
 private:
+    FloatRect m_layoutViewport;
+    FloatPoint m_minLayoutViewportOrigin;
+    FloatPoint m_maxLayoutViewportOrigin;
+    
     float m_frameScaleFactor { 1 };
     float m_topContentInset { 0 };
 
index 09c72c6..ed16eb8 100644 (file)
@@ -109,8 +109,8 @@ void ScrollingTreeScrollingNode::setScrollPosition(const FloatPoint& scrollPosit
 
 void ScrollingTreeScrollingNode::setScrollPositionWithoutContentEdgeConstraints(const FloatPoint& scrollPosition)
 {
-    setScrollLayerPosition(scrollPosition);
-    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition);
+    setScrollLayerPosition(scrollPosition, { });
+    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, Nullopt);
 }
 
 FloatPoint ScrollingTreeScrollingNode::minimumScrollPosition() const
index 5774bbe..ef238b4 100644 (file)
@@ -70,7 +70,7 @@ protected:
     WEBCORE_EXPORT virtual FloatPoint minimumScrollPosition() const;
     WEBCORE_EXPORT virtual FloatPoint maximumScrollPosition() const;
 
-    virtual void setScrollLayerPosition(const FloatPoint&) = 0;
+    virtual void setScrollLayerPosition(const FloatPoint&, const FloatRect& layoutViewport) = 0;
 
     FloatPoint lastCommittedScrollPosition() const { return m_lastCommittedScrollPosition; }
     const FloatSize& scrollableAreaSize() const { return m_scrollableAreaSize; }
index 08cd075..435b5b3 100644 (file)
@@ -92,7 +92,7 @@ void ThreadedScrollingTree::commitTreeState(std::unique_ptr<ScrollingStateTree>
     ScrollingTree::commitTreeState(WTFMove(scrollingStateTree));
 }
 
-void ThreadedScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void ThreadedScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
     if (!m_scrollingCoordinator)
         return;
@@ -100,8 +100,8 @@ void ThreadedScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, c
     if (nodeID == rootNode()->scrollingNodeID())
         setMainFrameScrollPosition(scrollPosition);
 
-    RunLoop::main().dispatch([scrollingCoordinator = m_scrollingCoordinator, nodeID, scrollPosition, localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll(), scrollingLayerPositionAction] {
-        scrollingCoordinator->scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction);
+    RunLoop::main().dispatch([scrollingCoordinator = m_scrollingCoordinator, nodeID, scrollPosition, layoutViewportOrigin, localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll(), scrollingLayerPositionAction] {
+        scrollingCoordinator->scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, layoutViewportOrigin, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction);
     });
 }
 
index af6de2d..ca911c4 100644 (file)
@@ -57,7 +57,7 @@ public:
 protected:
     explicit ThreadedScrollingTree(AsyncScrollingCoordinator*);
 
-    void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) override;
+    void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) override;
     void currentSnapPointIndicesDidChange(ScrollingNodeID, unsigned horizontal, unsigned vertical) override;
 #if PLATFORM(MAC)
     void handleWheelEventPhase(PlatformWheelEventPhase) override;
index 5b58b80..22394e4 100644 (file)
@@ -54,7 +54,7 @@ protected:
     void updateLayersAfterViewportChange(const FloatRect& fixedPositionRect, double scale) override;
     void updateLayersAfterDelegatedScroll(const FloatPoint&) override;
 
-    void setScrollLayerPosition(const FloatPoint&) override;
+    void setScrollLayerPosition(const FloatPoint&, const FloatRect& layoutViewport) override;
 
     FloatPoint minimumScrollPosition() const override;
     FloatPoint maximumScrollPosition() const override;
index 30f1476..300d3fa 100644 (file)
@@ -109,15 +109,16 @@ void ScrollingTreeFrameScrollingNodeIOS::setScrollPositionWithoutContentEdgeCons
 {
     if (shouldUpdateScrollLayerPositionSynchronously()) {
         m_probableMainThreadScrollPosition = scrollPosition;
-        scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, SetScrollingLayerPosition);
+        scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, Nullopt, SetScrollingLayerPosition);
         return;
     }
 
-    setScrollLayerPosition(scrollPosition);
-    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition);
+    FloatRect layoutViewport; // FIXME: implement for iOS WK1.
+    setScrollLayerPosition(scrollPosition, layoutViewport);
+    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, Nullopt);
 }
 
-void ScrollingTreeFrameScrollingNodeIOS::setScrollLayerPosition(const FloatPoint& scrollPosition)
+void ScrollingTreeFrameScrollingNodeIOS::setScrollLayerPosition(const FloatPoint& scrollPosition, const FloatRect&)
 {
     ASSERT(!shouldUpdateScrollLayerPositionSynchronously());
     [m_scrollLayer setPosition:-scrollPosition];
index 0744a02..b2f44af 100644 (file)
@@ -70,7 +70,7 @@ void ScrollingTreeIOS::invalidate()
     });
 }
 
-void ScrollingTreeIOS::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void ScrollingTreeIOS::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
     if (!m_scrollingCoordinator)
         return;
@@ -78,8 +78,8 @@ void ScrollingTreeIOS::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const
     if (nodeID == rootNode()->scrollingNodeID())
         setMainFrameScrollPosition(scrollPosition);
 
-    callOnMainThread([scrollingCoordinator = m_scrollingCoordinator, nodeID, scrollPosition, localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll(), scrollingLayerPositionAction] {
-        scrollingCoordinator->scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction);
+    callOnMainThread([scrollingCoordinator = m_scrollingCoordinator, nodeID, scrollPosition, layoutViewportOrigin, localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll(), scrollingLayerPositionAction] {
+        scrollingCoordinator->scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, layoutViewportOrigin, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction);
     });
 }
 
index 02dc62d..8d12fea 100644 (file)
@@ -53,7 +53,7 @@ private:
 
     PassRefPtr<ScrollingTreeNode> createScrollingTreeNode(ScrollingNodeType, ScrollingNodeID) override;
 
-    void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) override;
+    void scrollingTreeNodeDidScroll(ScrollingNodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition = SyncScrollingLayerPosition) override;
 
     void currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID, unsigned horizontal, unsigned vertical) override;
 
index 78d5292..a7947ff 100644 (file)
@@ -71,7 +71,7 @@ private:
 
     void updateLayersAfterViewportChange(const FloatRect& fixedPositionRect, double scale) override;
 
-    void setScrollLayerPosition(const FloatPoint&) override;
+    void setScrollLayerPosition(const FloatPoint&, const FloatRect& layoutViewport) override;
 
     FloatPoint minimumScrollPosition() const override;
     FloatPoint maximumScrollPosition() const override;
index 4a58020..22c6122 100644 (file)
@@ -388,30 +388,49 @@ void ScrollingTreeFrameScrollingNodeMac::setScrollPositionWithoutContentEdgeCons
 {
     updateMainFramePinState(scrollPosition);
 
+    FloatRect layoutViewport;
+    Optional<FloatPoint> layoutViewportOrigin;
+    if (scrollingTree().visualViewportEnabled()) {
+        FloatPoint visibleContentOrigin = scrollPosition;
+        float counterScale = 1 / frameScaleFactor();
+        visibleContentOrigin.scale(counterScale, counterScale);
+        layoutViewport = layoutViewportForScrollPosition(visibleContentOrigin, frameScaleFactor());
+        layoutViewportOrigin = layoutViewport.location();
+    }
+
     if (shouldUpdateScrollLayerPositionSynchronously()) {
         m_probableMainThreadScrollPosition = scrollPosition;
-        scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, SetScrollingLayerPosition);
+        scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, layoutViewportOrigin, SetScrollingLayerPosition);
         return;
     }
 
-    setScrollLayerPosition(scrollPosition);
-    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition);
+    setScrollLayerPosition(scrollPosition, layoutViewport);
+    scrollingTree().scrollingTreeNodeDidScroll(scrollingNodeID(), scrollPosition, layoutViewportOrigin);
 }
 
-void ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition(const FloatPoint& position)
+void ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition(const FloatPoint& position, const FloatRect& layoutViewport)
 {
     ASSERT(!shouldUpdateScrollLayerPositionSynchronously());
 
     m_scrollLayer.get().position = -position;
 
-    ScrollBehaviorForFixedElements behaviorForFixed = scrollBehaviorForFixedElements();
-    FloatRect viewportRect(position, scrollableAreaSize());
-    
-    FloatPoint scrollPositionForFixedChildren = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(viewportRect), LayoutSize(totalContentsSize()), LayoutPoint(position), scrollOrigin(), frameScaleFactor(),
-        fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight());
+    FloatRect visibleContentRect(position, scrollableAreaSize());
+    FloatRect fixedPositionRect;
+    ScrollBehaviorForFixedElements behaviorForFixed = StickToViewportBounds;
+
+    if (scrollingTree().visualViewportEnabled())
+        fixedPositionRect = layoutViewport;
+    else {
+        behaviorForFixed = scrollBehaviorForFixedElements();
+        
+        FloatPoint scrollPositionForFixedChildren = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(visibleContentRect), LayoutSize(totalContentsSize()),
+            LayoutPoint(position), scrollOrigin(), frameScaleFactor(), fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight());
+
+        fixedPositionRect = { scrollPositionForFixedChildren, visibleContentRect.size() };
+    }
     
     if (m_counterScrollingLayer)
-        m_counterScrollingLayer.get().position = scrollPositionForFixedChildren;
+        m_counterScrollingLayer.get().position = fixedPositionRect.location();
 
     float topContentInset = this->topContentInset();
     if (m_insetClipLayer && m_scrolledContentsLayer && topContentInset) {
@@ -424,18 +443,18 @@ void ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition(const FloatPoint
     if (m_headerLayer || m_footerLayer) {
         // Generally the banners should have the same horizontal-position computation as a fixed element. However,
         // the banners are not affected by the frameScaleFactor(), so if there is currently a non-1 frameScaleFactor()
-        // then we should recompute scrollOffsetForFixedChildren for the banner with a scale factor of 1.
-        float horizontalScrollOffsetForBanner = scrollPositionForFixedChildren.x();
-        if (frameScaleFactor() != 1)
-            horizontalScrollOffsetForBanner = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(viewportRect), LayoutSize(totalContentsSize()), LayoutPoint(position), scrollOrigin(), 1, fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight()).x();
+        // then we should recompute fixedPositionRect.x() for the banner with a scale factor of 1.
+        float horizontalScrollOffsetForBanner = fixedPositionRect.x();
+        if (!scrollingTree().visualViewportEnabled() && frameScaleFactor() != 1) {
+            horizontalScrollOffsetForBanner = FrameView::scrollPositionForFixedPosition(enclosingLayoutRect(visibleContentRect), LayoutSize(totalContentsSize()),
+                LayoutPoint(position), scrollOrigin(), 1, fixedElementsLayoutRelativeToFrame(), behaviorForFixed, headerHeight(), footerHeight()).x();
+        }
 
         if (m_headerLayer)
             m_headerLayer.get().position = FloatPoint(horizontalScrollOffsetForBanner, FrameView::yPositionForHeaderLayer(position, topContentInset));
 
-        if (m_footerLayer) {
-            m_footerLayer.get().position = FloatPoint(horizontalScrollOffsetForBanner,
-                FrameView::yPositionForFooterLayer(position, topContentInset, totalContentsSize().height(), footerHeight()));
-        }
+        if (m_footerLayer)
+            m_footerLayer.get().position = FloatPoint(horizontalScrollOffsetForBanner, FrameView::yPositionForFooterLayer(position, topContentInset, totalContentsSize().height(), footerHeight()));
     }
 
     if (m_verticalScrollerImp || m_horizontalScrollerImp) {
@@ -445,16 +464,17 @@ void ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition(const FloatPoint
         if ([m_verticalScrollerImp shouldUsePresentationValue]) {
             float presentationValue;
             float overhangAmount;
-            ScrollableArea::computeScrollbarValueAndOverhang(position.y(), totalContentsSize().height(), viewportRect.height(), presentationValue, overhangAmount);
+            ScrollableArea::computeScrollbarValueAndOverhang(position.y(), totalContentsSize().height(), visibleContentRect.height(), presentationValue, overhangAmount);
             [m_verticalScrollerImp setPresentationValue:presentationValue];
         }
 
         if ([m_horizontalScrollerImp shouldUsePresentationValue]) {
             float presentationValue;
             float overhangAmount;
-            ScrollableArea::computeScrollbarValueAndOverhang(position.x(), totalContentsSize().width(), viewportRect.width(), presentationValue, overhangAmount);
+            ScrollableArea::computeScrollbarValueAndOverhang(position.x(), totalContentsSize().width(), visibleContentRect.width(), presentationValue, overhangAmount);
             [m_horizontalScrollerImp setPresentationValue:presentationValue];
         }
+
         [CATransaction unlock];
         [CATransaction commit];
     }
@@ -462,10 +482,8 @@ void ScrollingTreeFrameScrollingNodeMac::setScrollLayerPosition(const FloatPoint
     if (!m_children)
         return;
 
-    viewportRect.setLocation(scrollPositionForFixedChildren);
-
     for (auto& child : *m_children)
-        child->updateLayersAfterAncestorChange(*this, viewportRect, FloatSize());
+        child->updateLayersAfterAncestorChange(*this, fixedPositionRect, FloatSize());
 }
 
 void ScrollingTreeFrameScrollingNodeMac::updateLayersAfterViewportChange(const FloatRect&, double)
index fc3f077..359a760 100644 (file)
@@ -1,3 +1,35 @@
+2016-11-09  Simon Fraser  <simon.fraser@apple.com>
+
+        Implement visual-viewport based position:fixed handling for Mac async scrolling
+        https://bugs.webkit.org/show_bug.cgi?id=164495
+
+        Reviewed by Tim Horton.
+
+        Educate the scrolling tree about visual and layout viewports. This is runtime-switchable,
+        so we push the enable flag to via the root state node, then push the layout viewport,
+        and the min/max scroll position that contstrain it, through frame state nodes.
+
+        When a scroll happens, we compute a new layout viewport when the visual viewport hits
+        an edge, and push that down through setScrollLayerPosition() since it's used to position
+        fixed and sticky layers.
+
+        The iOS code is made to compile, but not work yet.
+
+        * Shared/Scrolling/RemoteScrollingCoordinatorTransaction.cpp:
+        (ArgumentCoder<ScrollingStateFrameScrollingNode>::encode):
+        (ArgumentCoder<ScrollingStateFrameScrollingNode>::decode):
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.cpp:
+        (WebKit::RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll):
+        * UIProcess/Scrolling/RemoteScrollingCoordinatorProxy.h:
+        * UIProcess/Scrolling/RemoteScrollingTree.cpp:
+        (WebKit::RemoteScrollingTree::scrollingTreeNodeDidScroll):
+        * UIProcess/Scrolling/RemoteScrollingTree.h:
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.h:
+        * UIProcess/Scrolling/ios/ScrollingTreeOverflowScrollingNodeIOS.mm:
+        (WebKit::ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition):
+        * WebProcess/Scrolling/RemoteScrollingCoordinator.mm:
+        (WebKit::RemoteScrollingCoordinator::scrollPositionChangedForNode):
+
 2016-11-09  Beth Dakin  <bdakin@apple.com>
 
         More attempted build fix.
index bdaffab..bbde74c 100644 (file)
@@ -147,6 +147,10 @@ void ArgumentCoder<ScrollingStateFrameScrollingNode>::encode(Encoder& encoder, c
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::FooterHeight, footerHeight)
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::TopContentInset, topContentInset)
     SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::FixedElementsLayoutRelativeToFrame, fixedElementsLayoutRelativeToFrame)
+    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::VisualViewportEnabled, visualViewportEnabled)
+    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::LayoutViewport, layoutViewport)
+    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::MinLayoutViewportOrigin, minLayoutViewportOrigin)
+    SCROLLING_NODE_ENCODE(ScrollingStateFrameScrollingNode::MaxLayoutViewportOrigin, maxLayoutViewportOrigin)
 
     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer))
         encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.scrolledContentsLayer());
@@ -232,6 +236,10 @@ bool ArgumentCoder<ScrollingStateFrameScrollingNode>::decode(Decoder& decoder, S
     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::FooterHeight, int, setFooterHeight);
     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::TopContentInset, float, setTopContentInset);
     SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::FixedElementsLayoutRelativeToFrame, bool, setFixedElementsLayoutRelativeToFrame);
+    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::VisualViewportEnabled, bool, setVisualViewportEnabled)
+    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::LayoutViewport, FloatRect, setLayoutViewport)
+    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::MinLayoutViewportOrigin, FloatPoint, setMinLayoutViewportOrigin)
+    SCROLLING_NODE_DECODE(ScrollingStateFrameScrollingNode::MaxLayoutViewportOrigin, FloatPoint, setMaxLayoutViewportOrigin)
 
     if (node.hasChangedProperty(ScrollingStateFrameScrollingNode::ScrolledContentsLayer)) {
         GraphicsLayer::PlatformLayerID layerID;
index 930a110..ac20019 100644 (file)
@@ -163,7 +163,7 @@ void RemoteScrollingCoordinatorProxy::currentSnapPointIndicesDidChange(WebCore::
 }
 
 // This comes from the scrolling tree.
-void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void RemoteScrollingCoordinatorProxy::scrollingTreeNodeDidScroll(ScrollingNodeID scrolledNodeID, const FloatPoint& newScrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
     // Scroll updates for the main frame are sent via WebPageProxy::updateVisibleContentRects()
     // so don't send them here.
index 62faef9..0f2627d 100644 (file)
@@ -53,7 +53,7 @@ public:
     virtual ~RemoteScrollingCoordinatorProxy();
     
     // Inform the web process that the scroll position changed (called from the scrolling tree)
-    void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, WebCore::SetOrSyncScrollingLayerPosition);
+    void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& newScrollPosition, const Optional<WebCore::FloatPoint>& layoutViewportOrigin, WebCore::SetOrSyncScrollingLayerPosition);
     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll);
 
     WebCore::TrackingType eventTrackingTypeForPoint(const AtomicString& eventName, WebCore::IntPoint) const;
index a3b9407..3c0d072 100644 (file)
@@ -100,9 +100,9 @@ void RemoteScrollingTree::scrollingTreeNodeDidEndScroll()
 
 #endif
 
-void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
+void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, const Optional<FloatPoint>& layoutViewportOrigin, SetOrSyncScrollingLayerPosition scrollingLayerPositionAction)
 {
-    m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(nodeID, scrollPosition, scrollingLayerPositionAction);
+    m_scrollingCoordinatorProxy.scrollingTreeNodeDidScroll(nodeID, scrollPosition, layoutViewportOrigin, scrollingLayerPositionAction);
 }
 
 void RemoteScrollingTree::scrollingTreeNodeRequestsScroll(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool representsProgrammaticScroll)
index ef37ac7..8422bb0 100644 (file)
@@ -46,8 +46,9 @@ public:
 
     const RemoteScrollingCoordinatorProxy& scrollingCoordinatorProxy() const { return m_scrollingCoordinatorProxy; }
 
-    void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, WebCore::SetOrSyncScrollingLayerPosition = WebCore::SyncScrollingLayerPosition) override;
+    void scrollingTreeNodeDidScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, const Optional<WebCore::FloatPoint>& layoutViewportOrigin, WebCore::SetOrSyncScrollingLayerPosition = WebCore::SyncScrollingLayerPosition) override;
     void scrollingTreeNodeRequestsScroll(WebCore::ScrollingNodeID, const WebCore::FloatPoint& scrollPosition, bool representsProgrammaticScroll) override;
+
     void currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID, unsigned horizontal, unsigned vertical) override;
 
 private:
index 23a6082..02c8de9 100644 (file)
@@ -57,7 +57,7 @@ private:
     
     WebCore::FloatPoint scrollPosition() const override;
 
-    void setScrollLayerPosition(const WebCore::FloatPoint&) override;
+    void setScrollLayerPosition(const WebCore::FloatPoint&, const WebCore::FloatRect& layoutViewport) override;
 
     void updateLayersAfterViewportChange(const WebCore::FloatRect& fixedPositionRect, double scale) override { }
     void updateLayersAfterDelegatedScroll(const WebCore::FloatPoint& scrollPosition) override;
index 9323fa1..8c0f146 100644 (file)
@@ -254,7 +254,7 @@ FloatPoint ScrollingTreeOverflowScrollingNodeIOS::scrollPosition() const
     END_BLOCK_OBJC_EXCEPTIONS
 }
 
-void ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition(const FloatPoint& scrollPosition)
+void ScrollingTreeOverflowScrollingNodeIOS::setScrollLayerPosition(const FloatPoint& scrollPosition, const FloatRect&)
 {
     [m_scrollLayer setPosition:CGPointMake(-scrollPosition.x() + scrollOrigin().x(), -scrollPosition.y() + scrollOrigin().y())];
 
index 55603da..ba0b810 100644 (file)
@@ -97,7 +97,7 @@ void RemoteScrollingCoordinator::buildTransaction(RemoteScrollingCoordinatorTran
 // Notification from the UI process that we scrolled.
 void RemoteScrollingCoordinator::scrollPositionChangedForNode(ScrollingNodeID nodeID, const FloatPoint& scrollPosition, bool syncLayerPosition)
 {
-    scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, false /* FIXME */, syncLayerPosition ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
+    scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, Nullopt, false /* FIXME */, syncLayerPosition ? SyncScrollingLayerPosition : SetScrollingLayerPosition);
 }
 
 void RemoteScrollingCoordinator::currentSnapPointIndicesChangedForNode(ScrollingNodeID nodeID, unsigned horizontal, unsigned vertical)