<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[242997] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/242997">242997</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2019-03-15 09:26:09 -0700 (Fri, 15 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Async overflow Scrolling] Update positioned node layers when overflows are scrolled
https://bugs.webkit.org/show_bug.cgi?id=195733
rdar://problem/11642295

Reviewed by Antti Koivisto.

Source/WebCore:

Make ScrollingTree positioned nodes in the two cases where we need them, as
detected by RenderLayerCompositor::computeCoordinatedPositioningForLayer().

For "Moves" layers we know that the overflow is not in the z-order ancestor chain,
so ScrollingTree needs a map of overflow node -> affected positioned nodes which
notifyRelatedNodesAfterScrollPositionChange() uses to find nodes to update after
a scroll. Computing these dependent nodes in RenderLayerCompositor() would require
correct dependency analysis between an overflow layers and "positioned" layers which
is hard. It's easier to have "positioned" layers figure out which overflow nodes
affect them, then compute the inverse relationship when the scrolling tree is updated
which happens in ScrollingTreePositionedNode::commitStateBeforeChildren().

Tests: scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html
       scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html

* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::commitTreeState):
(WebCore::ScrollingTree::applyLayerPositions):
(WebCore::ScrollingTree::notifyRelatedNodesAfterScrollPositionChange):
(WebCore::ScrollingTree::scrollingTreeAsText):
* page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::overflowRelatedNodes):
* page/scrolling/ScrollingTreeOverflowScrollingNode.cpp:
(WebCore::ScrollingTreeOverflowScrollingNode::dumpProperties const):
* page/scrolling/ScrollingTreeOverflowScrollingNode.h:
* page/scrolling/cocoa/ScrollingTreePositionedNode.mm:
(WebCore::ScrollingTreePositionedNode::commitStateBeforeChildren):
(WebCore::ScrollingTreePositionedNode::applyLayerPositions):
(WebCore::ScrollingTreePositionedNode::relatedNodeScrollPositionDidChange):
* rendering/RenderLayerCompositor.cpp:
(WebCore::layerContainingBlockCrossesCoordinatedScrollingBoundary):
(WebCore::layerParentedAcrossCoordinatedScrollingBoundary):
(WebCore::RenderLayerCompositor::computeCoordinatedPositioningForLayer const):
(WebCore::collectRelatedCoordinatedScrollingNodes):
(WebCore::RenderLayerCompositor::updateScrollingNodeForPositioningRole):

LayoutTests:

New tests that use uiController.scrollUpdatesDisabled, and are the two move/stationary
cases.

* platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt:
* scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html: Added.
* scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html: Added.
* scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html: Added.
* scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html: Added.
* scrollingcoordinator/ios/ui-scrolling-tree-expected.txt: Fixed the last paren showing up.
* scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt: We make positioned nodes now.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformioswk2scrollingcoordinatorscrollingtreepositionednodesexpectedtxt">trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt</a></li>
<li><a href="#trunkLayoutTestsscrollingcoordinatoriosuiscrollingtreeexpectedtxt">trunk/LayoutTests/scrollingcoordinator/ios/ui-scrolling-tree-expected.txt</a></li>
<li><a href="#trunkLayoutTestsscrollingcoordinatorscrollingtreepositionednodesexpectedtxt">trunk/LayoutTests/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreecpp">trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeh">trunk/Source/WebCore/page/scrolling/ScrollingTree.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeOverflowScrollingNodecpp">trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollingTreeOverflowScrollingNodeh">trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingcocoaScrollingTreePositionedNodeh">trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h</a></li>
<li><a href="#trunkSourceWebCorepagescrollingcocoaScrollingTreePositionedNodemm">trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderLayerCompositorcpp">trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsscrollingcoordinatoriosabsolutelayershouldnotmovewithscrollexpectedhtml">trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html</a></li>
<li><a href="#trunkLayoutTestsscrollingcoordinatoriosabsolutelayershouldnotmovewithscrollhtml">trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html</a></li>
<li><a href="#trunkLayoutTestsscrollingcoordinatoriosrelativelayershouldmovewithscrollexpectedhtml">trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html</a></li>
<li><a href="#trunkLayoutTestsscrollingcoordinatoriosrelativelayershouldmovewithscrollhtml">trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/LayoutTests/ChangeLog 2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2019-03-15  Simon Fraser  <simon.fraser@apple.com>
+
+        [Async overflow Scrolling] Update positioned node layers when overflows are scrolled
+        https://bugs.webkit.org/show_bug.cgi?id=195733
+        rdar://problem/11642295
+
+        Reviewed by Antti Koivisto.
+
+        New tests that use uiController.scrollUpdatesDisabled, and are the two move/stationary
+        cases.
+
+        * platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt:
+        * scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html: Added.
+        * scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html: Added.
+        * scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html: Added.
+        * scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html: Added.
+        * scrollingcoordinator/ios/ui-scrolling-tree-expected.txt: Fixed the last paren showing up.
+        * scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt: We make positioned nodes now.
+
</ins><span class="cx"> 2019-03-15  Fujii Hironori  <Hironori.Fujii@sony.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed test gardening for WinCairo port
</span></span></pre></div>
<a id="trunkLayoutTestsplatformioswk2scrollingcoordinatorscrollingtreepositionednodesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt     2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/LayoutTests/platform/ios-wk2/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt        2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">   (min layout viewport origin (0,0))
</span><span class="cx">   (max layout viewport origin (0,141))
</span><span class="cx">   (behavior for fixed 0)
</span><del>-  (children 4
</del><ins>+  (children 5
</ins><span class="cx">     (Overflow scrolling node
</span><span class="cx">       (scrollable area size 220 170)
</span><span class="cx">       (contents size 220 1020)
</span><span class="lines">@@ -54,6 +54,12 @@
</span><span class="cx">         )
</span><span class="cx">       )
</span><span class="cx">     )
</span><ins>+    (Positioned node
+      (layout constraints 
+        (layer-position-at-last-layout (10,30))
+        (positioning-behavior moves))
+      (related overflow nodes 1)
+    )
</ins><span class="cx">     (Overflow scrolling node
</span><span class="cx">       (scrollable area size 220 170)
</span><span class="cx">       (contents size 220 1020)
</span></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatoriosabsolutelayershouldnotmovewithscrollexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html (0 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html                              (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll-expected.html 2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=1.0">
+    <style>
+        #scroller {
+            margin: 10px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            overflow: scroll;
+            opacity: 0.999; /* Make this a stacking context */
+        }
+        
+        .box {
+            width: 200px;
+            height: 200px;
+            background-color: gray;
+        }
+        
+        .absolute {
+            position: absolute;
+            top: 200px;
+            background-color: blue;
+            transform: translateZ(0); /* Currently need to trigger compositing */
+        }
+        
+        .scroll-content {
+            height: 2000px;
+        }
+    </style>
+    <script src="../../resources/ui-helper.js"></script>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        if (window.internals)
+            window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+        async function doTest()
+        {
+            await UIHelper.ensurePresentationUpdate(); // Not sure why this is necessary, but it is.
+            scroller.scrollTo(0, 100);
+            await UIHelper.ensurePresentationUpdate();
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="scroller">
+        <div class="scroll-content">
+            <div class="box"></div>
+            <div class="absolute box"></div>
+        </div>
+    </div>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatoriosabsolutelayershouldnotmovewithscrollhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html (0 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html                               (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html  2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=1.0">
+    <style>
+        #scroller {
+            margin: 10px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            overflow: scroll;
+            opacity: 0.999; /* Make this a stacking context */
+        }
+        
+        .box {
+            width: 200px;
+            height: 200px;
+            background-color: gray;
+        }
+        
+        .absolute {
+            position: absolute;
+            top: 200px;
+            background-color: blue;
+            transform: translateZ(0); /* Currently need to trigger compositing */
+        }
+        
+        .scroll-content {
+            height: 2000px;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        if (window.internals)
+            window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+        function getUnstableScrollScript(x, y, scrollX, scrollY)
+        {
+            return `(function() {
+                uiController.scrollUpdatesDisabled = true;
+                uiController.immediateScrollElementAtContentPointToOffset(${x}, ${y}, ${scrollX}, ${scrollY});
+                uiController.doAfterPresentationUpdate(function() {
+                    uiController.uiScriptComplete();
+                });
+            })();`;
+        }
+
+        function doTest()
+        {
+            if (!testRunner.runUIScript)
+                return
+
+            testRunner.runUIScript(getUnstableScrollScript(50, 50, 0, 100), () => {
+                testRunner.notifyDone();
+            });
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="scroller">
+        <div class="scroll-content">
+            <div class="box"></div>
+            <div class="absolute box"></div>
+        </div>
+    </div>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatoriosrelativelayershouldmovewithscrollexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html (0 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html                          (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll-expected.html     2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=1.0">
+    <style>
+        #scroller {
+            margin: 10px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            overflow: scroll;
+        }
+        
+        .box {
+            position: relative;
+            z-index: 0; /* stacking context ancestor is the root */
+            top: 250px;
+            width: 200px;
+            height: 200px;
+            background-color: blue;
+        }
+        
+        .scroll-content {
+            height: 2000px;
+        }
+    </style>
+    <script src="../../resources/ui-helper.js"></script>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        if (window.internals)
+            window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+        async function doTest()
+        {
+            await UIHelper.ensurePresentationUpdate(); // Not sure why this is necessary, but it is.
+            scroller.scrollTo(0, 250);
+            await UIHelper.ensurePresentationUpdate();
+
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="scroller">
+        <div class="scroll-content">
+            <div class="box"></div>
+        </div>
+    </div>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatoriosrelativelayershouldmovewithscrollhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html (0 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html                           (rev 0)
+++ trunk/LayoutTests/scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html      2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=1.0">
+    <style>
+        #scroller {
+            margin: 10px;
+            height: 300px;
+            width: 300px;
+            border: 1px solid black;
+            overflow: scroll;
+        }
+        
+        .box {
+            position: relative;
+            z-index: 0; /* stacking context ancestor is the root */
+            top: 250px;
+            width: 200px;
+            height: 200px;
+            background-color: blue;
+        }
+        
+        .scroll-content {
+            height: 2000px;
+        }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+
+        if (window.internals)
+            window.internals.settings.setAsyncOverflowScrollingEnabled(true);
+
+        function getUnstableScrollScript(x, y, scrollX, scrollY)
+        {
+            return `(function() {
+                uiController.scrollUpdatesDisabled = true;
+                uiController.immediateScrollElementAtContentPointToOffset(${x}, ${y}, ${scrollX}, ${scrollY});
+                uiController.doAfterPresentationUpdate(function() {
+                    uiController.uiScriptComplete();
+                });
+            })();`;
+        }
+
+        function doTest()
+        {
+            if (!testRunner.runUIScript)
+                return
+
+            testRunner.runUIScript(getUnstableScrollScript(50, 50, 0, 250), () => {
+                testRunner.notifyDone();
+            });
+        }
+        
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div id="scroller">
+        <div class="scroll-content">
+            <div class="box"></div>
+        </div>
+    </div>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatoriosuiscrollingtreeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/scrollingcoordinator/ios/ui-scrolling-tree-expected.txt (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/ios/ui-scrolling-tree-expected.txt        2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/LayoutTests/scrollingcoordinator/ios/ui-scrolling-tree-expected.txt   2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -17,4 +17,4 @@
</span><span class="cx">       (fixed constraints 
</span><span class="cx">         (viewport-rect-at-last-layout (0,0) width=320 height=548)
</span><span class="cx">         (layer-position-at-last-layout (12,10)))
</span><del>-      (layer top left (12,10))))
</del><ins>+      (layer top left (12,10)))))
</ins></span></pre></div>
<a id="trunkLayoutTestsscrollingcoordinatorscrollingtreepositionednodesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt      2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/LayoutTests/scrollingcoordinator/scrolling-tree/positioned-nodes-expected.txt 2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx">   (min layout viewport origin (0,0))
</span><span class="cx">   (max layout viewport origin (0,141))
</span><span class="cx">   (behavior for fixed 0)
</span><del>-  (children 4
</del><ins>+  (children 5
</ins><span class="cx">     (Overflow scrolling node
</span><span class="cx">       (scrollable area size 205 155)
</span><span class="cx">       (contents size 205 1020)
</span><span class="lines">@@ -55,6 +55,12 @@
</span><span class="cx">         )
</span><span class="cx">       )
</span><span class="cx">     )
</span><ins>+    (Positioned node
+      (layout constraints 
+        (layer-position-at-last-layout (10,28))
+        (positioning-behavior moves))
+      (related overflow nodes 1)
+    )
</ins><span class="cx">     (Overflow scrolling node
</span><span class="cx">       (scrollable area size 205 155)
</span><span class="cx">       (contents size 205 1020)
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/ChangeLog      2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2019-03-15  Simon Fraser  <simon.fraser@apple.com>
+
+        [Async overflow Scrolling] Update positioned node layers when overflows are scrolled
+        https://bugs.webkit.org/show_bug.cgi?id=195733
+        rdar://problem/11642295
+
+        Reviewed by Antti Koivisto.
+
+        Make ScrollingTree positioned nodes in the two cases where we need them, as
+        detected by RenderLayerCompositor::computeCoordinatedPositioningForLayer().
+
+        For "Moves" layers we know that the overflow is not in the z-order ancestor chain,
+        so ScrollingTree needs a map of overflow node -> affected positioned nodes which
+        notifyRelatedNodesAfterScrollPositionChange() uses to find nodes to update after
+        a scroll. Computing these dependent nodes in RenderLayerCompositor() would require
+        correct dependency analysis between an overflow layers and "positioned" layers which
+        is hard. It's easier to have "positioned" layers figure out which overflow nodes
+        affect them, then compute the inverse relationship when the scrolling tree is updated
+        which happens in ScrollingTreePositionedNode::commitStateBeforeChildren().
+
+        Tests: scrollingcoordinator/ios/absolute-layer-should-not-move-with-scroll.html
+               scrollingcoordinator/ios/relative-layer-should-move-with-scroll.html
+
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::commitTreeState):
+        (WebCore::ScrollingTree::applyLayerPositions):
+        (WebCore::ScrollingTree::notifyRelatedNodesAfterScrollPositionChange):
+        (WebCore::ScrollingTree::scrollingTreeAsText):
+        * page/scrolling/ScrollingTree.h:
+        (WebCore::ScrollingTree::overflowRelatedNodes):
+        * page/scrolling/ScrollingTreeOverflowScrollingNode.cpp:
+        (WebCore::ScrollingTreeOverflowScrollingNode::dumpProperties const):
+        * page/scrolling/ScrollingTreeOverflowScrollingNode.h:
+        * page/scrolling/cocoa/ScrollingTreePositionedNode.mm:
+        (WebCore::ScrollingTreePositionedNode::commitStateBeforeChildren):
+        (WebCore::ScrollingTreePositionedNode::applyLayerPositions):
+        (WebCore::ScrollingTreePositionedNode::relatedNodeScrollPositionDidChange):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::layerContainingBlockCrossesCoordinatedScrollingBoundary):
+        (WebCore::layerParentedAcrossCoordinatedScrollingBoundary):
+        (WebCore::RenderLayerCompositor::computeCoordinatedPositioningForLayer const):
+        (WebCore::collectRelatedCoordinatedScrollingNodes):
+        (WebCore::RenderLayerCompositor::updateScrollingNodeForPositioningRole):
+
</ins><span class="cx"> 2019-03-15  Antti Koivisto  <antti@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Optimize Region for single rectangle case
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp    2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp       2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -174,6 +174,8 @@
</span><span class="cx">     for (auto nodeID : m_nodeMap.keys())
</span><span class="cx">         unvisitedNodes.add(nodeID);
</span><span class="cx"> 
</span><ins>+    m_overflowRelatedNodesMap.clear();
+
</ins><span class="cx">     // orphanNodes keeps child nodes alive while we rebuild child lists.
</span><span class="cx">     OrphanScrollingNodeMap orphanNodes;
</span><span class="cx">     updateTreeFromStateNode(rootNode, orphanNodes, unvisitedNodes);
</span><span class="lines">@@ -185,6 +187,8 @@
</span><span class="cx">         LOG(Scrolling, "ScrollingTree::commitTreeState - removing unvisited node %" PRIu64, nodeID);
</span><span class="cx">         m_nodeMap.remove(nodeID);
</span><span class="cx">     }
</span><ins>+
+    LOG(Scrolling, "committed ScrollingTree\n%s", scrollingTreeAsText(ScrollingStateTreeAsTextBehaviorDebug).utf8().data());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTree::updateTreeFromStateNode(const ScrollingStateNode* stateNode, OrphanScrollingNodeMap& orphanNodes, HashSet<ScrollingNodeID>& unvisitedNodes)
</span><span class="lines">@@ -263,7 +267,11 @@
</span><span class="cx">     if (!m_rootNode)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    LOG(Scrolling, "\nScrollingTree %p applyLayerPositions", this);
+
</ins><span class="cx">     applyLayerPositionsRecursive(*m_rootNode, { }, { });
</span><ins>+
+    LOG(Scrolling, "ScrollingTree %p applyLayerPositions - done\n", this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTree::applyLayerPositionsRecursive(ScrollingTreeNode& currNode, FloatRect layoutViewport, FloatSize cumulativeDelta)
</span><span class="lines">@@ -291,6 +299,8 @@
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTree::notifyRelatedNodesAfterScrollPositionChange(ScrollingTreeScrollingNode& changedNode)
</span><span class="cx"> {
</span><ins>+    Vector<ScrollingNodeID> additionalUpdateRoots;
+    
</ins><span class="cx">     FloatSize deltaFromLastCommittedScrollPosition;
</span><span class="cx">     FloatRect currentFrameLayoutViewport;
</span><span class="cx">     if (is<ScrollingTreeFrameScrollingNode>(changedNode))
</span><span class="lines">@@ -300,9 +310,17 @@
</span><span class="cx"> 
</span><span class="cx">         if (auto* frameScrollingNode = changedNode.enclosingFrameNodeIncludingSelf())
</span><span class="cx">             currentFrameLayoutViewport = frameScrollingNode->layoutViewport();
</span><ins>+        
+        additionalUpdateRoots = overflowRelatedNodes().get(changedNode.scrollingNodeID());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     notifyRelatedNodesRecursive(changedNode, changedNode, currentFrameLayoutViewport, deltaFromLastCommittedScrollPosition);
</span><ins>+    
+    for (auto positionedNodeID : additionalUpdateRoots) {
+        auto* positionedNode = nodeForID(positionedNodeID);
+        if (positionedNode)
+            notifyRelatedNodesRecursive(changedNode, *positionedNode, currentFrameLayoutViewport, deltaFromLastCommittedScrollPosition);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTree::notifyRelatedNodesRecursive(ScrollingTreeScrollingNode& changedNode, ScrollingTreeNode& currNode, const FloatRect& layoutViewport, FloatSize cumulativeDelta)
</span><span class="lines">@@ -451,26 +469,37 @@
</span><span class="cx">     m_treeState.latchedNodeID = 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String ScrollingTree::scrollingTreeAsText()
</del><ins>+String ScrollingTree::scrollingTreeAsText(ScrollingStateTreeAsTextBehavior behavior)
</ins><span class="cx"> {
</span><span class="cx">     TextStream ts(TextStream::LineMode::MultipleLine);
</span><span class="cx"> 
</span><del>-    TextStream::GroupScope scope(ts);
-    ts << "scrolling tree";
</del><ins>+    {
+        TextStream::GroupScope scope(ts);
+        ts << "scrolling tree";
</ins><span class="cx"> 
</span><del>-    LockHolder locker(m_treeStateMutex);
</del><ins>+        LockHolder locker(m_treeStateMutex);
</ins><span class="cx"> 
</span><del>-    if (m_treeState.latchedNodeID)
-        ts.dumpProperty("latched node", m_treeState.latchedNodeID);
</del><ins>+        if (m_treeState.latchedNodeID)
+            ts.dumpProperty("latched node", m_treeState.latchedNodeID);
</ins><span class="cx"> 
</span><del>-    if (!m_treeState.mainFrameScrollPosition.isZero())
-        ts.dumpProperty("main frame scroll position", m_treeState.mainFrameScrollPosition);
-    
-    if (m_rootNode) {
-        TextStream::GroupScope scope(ts);
-        m_rootNode->dump(ts, ScrollingStateTreeAsTextBehaviorIncludeLayerPositions);
</del><ins>+        if (!m_treeState.mainFrameScrollPosition.isZero())
+            ts.dumpProperty("main frame scroll position", m_treeState.mainFrameScrollPosition);
+        
+        if (m_rootNode) {
+            TextStream::GroupScope scope(ts);
+            m_rootNode->dump(ts, behavior | ScrollingStateTreeAsTextBehaviorIncludeLayerPositions);
+        }
+        
+        if (behavior & ScrollingStateTreeAsTextBehaviorIncludeNodeIDs && !m_overflowRelatedNodesMap.isEmpty()) {
+            TextStream::GroupScope scope(ts);
+            ts << "overflow related nodes";
+            {
+                TextStream::IndentScope indentScope(ts);
+                for (auto& it : m_overflowRelatedNodesMap)
+                    ts << "\n" << indent << it.key << " -> " << it.value;
+            }
+        }
</ins><span class="cx">     }
</span><del>-
</del><span class="cx">     return ts.release();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.h (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTree.h      2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.h 2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -144,9 +144,14 @@
</span><span class="cx">         ASSERT(m_fixedOrStickyNodeCount);
</span><span class="cx">         --m_fixedOrStickyNodeCount;
</span><span class="cx">     }
</span><ins>+
+    // A map of overflow scrolling nodes to positioned nodes which need to be updated
+    // when the scroller changes, but are not descendants.
+    using RelatedNodesMap = HashMap<ScrollingNodeID, Vector<ScrollingNodeID>>;
+    RelatedNodesMap& overflowRelatedNodes() { return m_overflowRelatedNodesMap; }
+
+    WEBCORE_EXPORT String scrollingTreeAsText(ScrollingStateTreeAsTextBehavior = ScrollingStateTreeAsTextBehaviorNormal);
</ins><span class="cx">     
</span><del>-    WEBCORE_EXPORT String scrollingTreeAsText();
-    
</del><span class="cx"> protected:
</span><span class="cx">     void setMainFrameScrollPosition(FloatPoint);
</span><span class="cx"> 
</span><span class="lines">@@ -167,6 +172,8 @@
</span><span class="cx">     using ScrollingTreeNodeMap = HashMap<ScrollingNodeID, ScrollingTreeNode*>;
</span><span class="cx">     ScrollingTreeNodeMap m_nodeMap;
</span><span class="cx"> 
</span><ins>+    RelatedNodesMap m_overflowRelatedNodesMap;
+
</ins><span class="cx">     struct TreeState {
</span><span class="cx">         ScrollingNodeID latchedNodeID { 0 };
</span><span class="cx">         EventTrackingRegions eventTrackingRegions;
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeOverflowScrollingNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.cpp (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.cpp       2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.cpp  2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -40,6 +40,12 @@
</span><span class="cx"> 
</span><span class="cx"> ScrollingTreeOverflowScrollingNode::~ScrollingTreeOverflowScrollingNode() = default;
</span><span class="cx"> 
</span><ins>+void ScrollingTreeOverflowScrollingNode::dumpProperties(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const
+{
+    ts << "overflow scrolling node";
+    ScrollingTreeNode::dumpProperties(ts, behavior);
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(ASYNC_SCROLLING)
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollingTreeOverflowScrollingNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.h (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.h 2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeOverflowScrollingNode.h    2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -37,6 +37,8 @@
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     WEBCORE_EXPORT ScrollingTreeOverflowScrollingNode(ScrollingTree&, ScrollingNodeID);
</span><ins>+    
+    WEBCORE_EXPORT void dumpProperties(TextStream&, ScrollingStateTreeAsTextBehavior) const;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingcocoaScrollingTreePositionedNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h  2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.h     2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx"> 
</span><span class="cx">     void applyLayerPositions(const FloatRect& layoutViewport, FloatSize& cumulativeDelta) override;
</span><span class="cx"> 
</span><del>-    void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const override;
</del><ins>+    WEBCORE_EXPORT void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const override;
</ins><span class="cx"> 
</span><span class="cx">     Vector<ScrollingNodeID> m_relatedOverflowScrollingNodes;
</span><span class="cx">     LayoutConstraints m_constraints;
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingcocoaScrollingTreePositionedNodemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm 2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/page/scrolling/cocoa/ScrollingTreePositionedNode.mm    2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #import "Logging.h"
</span><span class="cx"> #import "ScrollingStatePositionedNode.h"
</span><span class="cx"> #import "ScrollingTree.h"
</span><ins>+#import "ScrollingTreeOverflowScrollingNode.h"
</ins><span class="cx"> #import "ScrollingTreeScrollingNode.h"
</span><span class="cx"> #import <QuartzCore/CALayer.h>
</span><span class="cx"> #import <wtf/text/TextStream.h>
</span><span class="lines">@@ -61,30 +62,51 @@
</span><span class="cx"> 
</span><span class="cx">     if (positionedStateNode.hasChangedProperty(ScrollingStatePositionedNode::LayoutConstraintData))
</span><span class="cx">         m_constraints = positionedStateNode.layoutConstraints();
</span><ins>+
+    // Tell the ScrollingTree about non-ancestor overflow nodes which affect this node.
+    if (m_constraints.scrollPositioningBehavior() == ScrollPositioningBehavior::Moves) {
+        auto& relatedNodes = scrollingTree().overflowRelatedNodes();
+        for (auto overflowNodeID : m_relatedOverflowScrollingNodes) {
+            relatedNodes.ensure(overflowNodeID, [] {
+                return Vector<ScrollingNodeID>();
+            }).iterator->value.append(scrollingNodeID());
+        }
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTreePositionedNode::applyLayerPositions(const FloatRect&, FloatSize& cumulativeDelta)
</span><span class="cx"> {
</span><del>-    FloatSize layerOffset; // FIXME: layerOffset needs to be computed by looking at scrolling tree deltas
-    // in the overflow nodes that affect this node. Some of that may come in via cumulativeDelta.
</del><ins>+    // Note that we ignore cumulativeDelta because it will contain the delta for ancestor scrollers,
+    // but not non-ancestor ones, so it's simpler to just recompute from the scrollers we know about here.
+    FloatSize scrollOffsetSinceLastCommit;
+    for (auto nodeID : m_relatedOverflowScrollingNodes) {
+        if (auto* node = scrollingTree().nodeForID(nodeID)) {
+            if (is<ScrollingTreeOverflowScrollingNode>(node)) {
+                auto& overflowNode = downcast<ScrollingTreeOverflowScrollingNode>(*node);
+                scrollOffsetSinceLastCommit += overflowNode.lastCommittedScrollPosition() - overflowNode.currentScrollPosition();
+            }
+        }
+    }
+    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: overflow delta " << scrollOffsetSinceLastCommit);
</ins><span class="cx"> 
</span><del>-    LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreePositionedNode " << scrollingNodeID() << " applyLayerPositions: total overflow delta " << layerOffset);
-
-    layerOffset += cumulativeDelta;
-    // Stationary nodes move in the opposite direction.
-    if (m_constraints.scrollPositioningBehavior() == ScrollPositioningBehavior::Stationary)
</del><ins>+    auto layerOffset = -scrollOffsetSinceLastCommit;
+    if (m_constraints.scrollPositioningBehavior() == ScrollPositioningBehavior::Stationary) {
+        // Stationary nodes move in the opposite direction.
</ins><span class="cx">         layerOffset = -layerOffset;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     FloatPoint layerPosition = m_constraints.layerPositionAtLastLayout() - layerOffset;
</span><span class="cx">     [m_layer _web_setLayerTopLeftPosition:layerPosition - m_constraints.alignmentOffset()];
</span><span class="cx"> 
</span><del>-    cumulativeDelta += layerPosition - m_constraints.layerPositionAtLastLayout();
</del><ins>+    // FIXME: Should our scroller deltas propagate to descendants?
+    cumulativeDelta = layerPosition - m_constraints.layerPositionAtLastLayout();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ScrollingTreePositionedNode::relatedNodeScrollPositionDidChange(const ScrollingTreeScrollingNode& changedNode, const FloatRect& layoutViewport, FloatSize& cumulativeDelta)
</span><span class="cx"> {
</span><del>-    UNUSED_PARAM(changedNode);
-    // FIXME: This will avoid doing work if we can determine that changedNode doesn't affect this positioned node.
</del><ins>+    if (!m_relatedOverflowScrollingNodes.contains(changedNode.scrollingNodeID()))
+        return;
+
</ins><span class="cx">     applyLayerPositions(layoutViewport, cumulativeDelta);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderLayerCompositorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (242996 => 242997)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp 2019-03-15 16:20:31 UTC (rev 242996)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp    2019-03-15 16:26:09 UTC (rev 242997)
</span><span class="lines">@@ -2869,17 +2869,117 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// Is this layer's containingBlock an ancestor of scrollable overflow, and is the layer's compositing ancestor inside that overflow?
+static bool layerContainingBlockCrossesCoordinatedScrollingBoundary(const RenderLayer& layer, const RenderLayer& compositedAncestor)
+{
+    ASSERT(layer.isComposited());
+    ASSERT(layer.renderer().style().position() == PositionType::Absolute);
+
+    bool sawCompositingAncestor = false;
+    for (const auto* currLayer = layer.parent(); currLayer; currLayer = currLayer->parent()) {
+        if (currLayer->renderer().canContainAbsolutelyPositionedObjects())
+            return false;
+
+        if (currLayer == &compositedAncestor)
+            sawCompositingAncestor = true;
+
+        if (currLayer->hasCompositedScrollableOverflow())
+            return sawCompositingAncestor;
+    }
+
+    return false;
+}
+
+// Is there scrollable overflow between this layer and its composited ancestor?
+static bool layerParentedAcrossCoordinatedScrollingBoundary(const RenderLayer& layer, const RenderLayer& compositedAncestor)
+{
+    ASSERT(layer.isComposited());
+
+    for (const auto* currLayer = layer.parent(); currLayer != &compositedAncestor; currLayer = currLayer->parent()) {
+        if (currLayer->hasCompositedScrollableOverflow())
+            return true;
+    }
+
+    return false;
+}
+
</ins><span class="cx"> ScrollPositioningBehavior RenderLayerCompositor::computeCoordinatedPositioningForLayer(const RenderLayer& layer) const
</span><span class="cx"> {
</span><span class="cx">     if (layer.isRenderViewLayer())
</span><span class="cx">         return ScrollPositioningBehavior::None;
</span><span class="cx"> 
</span><del>-    // FIXME: This will look at the containing block and stacking context ancestor chains and determine
-    // whether this layer needs to be repositioned when a composited overflow scroll scrolls.
</del><ins>+    auto* scrollingCoordinator = this->scrollingCoordinator();
+    if (!scrollingCoordinator)
+        return ScrollPositioningBehavior::None;
</ins><span class="cx"> 
</span><ins>+    // There are two cases we have to deal with here:
+    // 1. There's a composited overflow:scroll in the parent chain between the renderer and its containing block, and the layer's
+    //    composited (z-order) ancestor is inside the scroller or is the scroller. In this case, we have to compensate for scroll position
+    //    changes to make the positioned layer stay in the same place. This only applies to position:absolute (since we handle fixed elsewhere).
+    auto* compositedAncestor = layer.ancestorCompositingLayer();
+
+    auto& renderer = layer.renderer();
+    if (renderer.isOutOfFlowPositioned() && renderer.style().position() == PositionType::Absolute) {
+        if (layerContainingBlockCrossesCoordinatedScrollingBoundary(layer, *compositedAncestor))
+            return ScrollPositioningBehavior::Stationary;
+
+        return ScrollPositioningBehavior::None;
+    }
+
+    // 2. The layer's containing block is the overflow or inside the overflow:scroll, but its z-order ancestor is
+    //    outside the overflow:scroll. In that case, we have to move the layer via the scrolling tree to make
+    //    it move along with the overflow scrolling.
+    if (layerParentedAcrossCoordinatedScrollingBoundary(layer, *compositedAncestor))
+        return ScrollPositioningBehavior::Moves;
+
</ins><span class="cx">     return ScrollPositioningBehavior::None;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static Vector<ScrollingNodeID> collectRelatedCoordinatedScrollingNodes(const RenderLayer& layer, ScrollPositioningBehavior positioningBehavior)
+{
+    Vector<ScrollingNodeID> overflowNodeData;
+
+    switch (positioningBehavior) {
+    case ScrollPositioningBehavior::Moves: {
+        // Collect all the composited scrollers between this layer and its composited ancestor.
+        auto* compositedAncestor = layer.ancestorCompositingLayer();
+        for (const auto* currLayer = layer.parent(); currLayer != compositedAncestor; currLayer = currLayer->parent()) {
+            if (currLayer->hasCompositedScrollableOverflow()) {
+                auto scrollingNodeID = currLayer->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling);
+                if (scrollingNodeID)
+                    overflowNodeData.append(scrollingNodeID);
+                else
+                    LOG(Scrolling, "Layer %p doesn't have scrolling node ID yet", &layer);
+            }
+        }
+        break;
+    }
+    case ScrollPositioningBehavior::Stationary: {
+        // Collect all the composited scrollers between this layer and its containing block.
+        ASSERT(layer.renderer().style().position() == PositionType::Absolute);
+        for (const auto* currLayer = layer.parent(); currLayer; currLayer = currLayer->parent()) {
+            if (currLayer->renderer().canContainAbsolutelyPositionedObjects())
+                break;
+
+            if (currLayer->hasCompositedScrollableOverflow()) {
+                auto scrollingNodeID = currLayer->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling);
+                if (scrollingNodeID)
+                    overflowNodeData.append(scrollingNodeID);
+                else
+                    LOG(Scrolling, "Layer %p doesn't have scrolling node ID yet", &layer);
+            }
+        }
+        // Don't need to do anything because the layer is a descendant of the overflow in stacking.
+        break;
+    }
+    case ScrollPositioningBehavior::None:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+
+    return overflowNodeData;
+}
+
</ins><span class="cx"> bool RenderLayerCompositor::isLayerForIFrameWithScrollCoordinatedContents(const RenderLayer& layer) const
</span><span class="cx"> {
</span><span class="cx">     if (!is<RenderWidget>(layer.renderer()))
</span><span class="lines">@@ -4078,7 +4178,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (changes & ScrollingNodeChangeFlags::LayerGeometry && treeState.parentNodeID) {
</span><del>-        Vector<ScrollingNodeID> relatedNodeIDs; // FIXME: This will do a tree walk to figure out which composited overflows affect this positioned node.
</del><ins>+        // Would be nice to avoid calling computeCoordinatedPositioningForLayer() again.
+        auto positioningBehavior = computeCoordinatedPositioningForLayer(layer);
+        auto relatedNodeIDs = collectRelatedCoordinatedScrollingNodes(layer, positioningBehavior);
</ins><span class="cx">         scrollingCoordinator->setRelatedOverflowScrollingNodes(newNodeID, WTFMove(relatedNodeIDs));
</span><span class="cx"> 
</span><span class="cx">         auto* graphicsLayer = layer.backing()->graphicsLayer();
</span><span class="lines">@@ -4085,8 +4187,7 @@
</span><span class="cx">         LayoutConstraints constraints;
</span><span class="cx">         constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset());
</span><span class="cx">         constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
</span><del>-        // Would be nice to avoid calling computeCoordinatedPositioningForLayer() again.
-        constraints.setScrollPositioningBehavior(computeCoordinatedPositioningForLayer(layer));
</del><ins>+        constraints.setScrollPositioningBehavior(positioningBehavior);
</ins><span class="cx">         scrollingCoordinator->setPositionedNodeGeometry(newNodeID, constraints);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>