Title: [288777] trunk
Revision
288777
Author
nmouchta...@apple.com
Date
2022-01-28 18:56:40 -0800 (Fri, 28 Jan 2022)

Log Message

Implement CSS overscroll-behavior for asynchronous scroll on Mac
https://bugs.webkit.org/show_bug.cgi?id=220139

Reviewed by Simon Fraser.

Source/WebCore:

Split up patch by Cathie Chen and Frederic Wang. Add function for blocking scroll chaining
and filtering scroll delta depending on the values of overscroll behavior for a scrolling
node. This patch is for asynchronous scrolling only.

Tests: fast/scrolling/mac/async-overscroll-behavior-element.html
       fast/scrolling/mac/async-overscroll-behavior-iframe.html
       fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html
       fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html

* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::shouldBlockScrollChainingWithNode):
(WebCore::ScrollingTree::handleWheelEventWithNode):
* page/scrolling/ScrollingTree.h:
* page/scrolling/ScrollingTreeScrollingNode.h:
* page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
(WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsHorizontalStretching const):
(WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsVerticalStretching const):
* rendering/RenderLayerCompositor.cpp:
(WebCore::recompositeChangeRequiresGeometryUpdate):
(WebCore::RenderLayerCompositor::rootOrBodyStyleChanged):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::changeRequiresRecompositeLayer const):

LayoutTests:

* fast/scrolling/mac/async-overscroll-behavior-element-expected.txt: Added.
* fast/scrolling/mac/async-overscroll-behavior-element.html: Added.
* fast/scrolling/mac/async-overscroll-behavior-iframe-expected.txt: Added.
* fast/scrolling/mac/async-overscroll-behavior-iframe.html: Added.
* fast/scrolling/mac/async-overscroll-behavior-unscrollable-element-expected.txt: Added.
* fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html: Added.
* fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe-expected.txt: Added.
* fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html: Added.
* fast/scrolling/resources/overscroll-behavior-support.js: Added.
(getDeltas):
(async mouseWheelScrollAndWait):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (288776 => 288777)


--- trunk/LayoutTests/ChangeLog	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/LayoutTests/ChangeLog	2022-01-29 02:56:40 UTC (rev 288777)
@@ -1,3 +1,22 @@
+2022-01-28  Nikolaos Mouchtaris  <nmouchta...@apple.com>
+
+        Implement CSS overscroll-behavior for asynchronous scroll on Mac
+        https://bugs.webkit.org/show_bug.cgi?id=220139
+
+        Reviewed by Simon Fraser.
+
+        * fast/scrolling/mac/async-overscroll-behavior-element-expected.txt: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-element.html: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-iframe-expected.txt: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-iframe.html: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-unscrollable-element-expected.txt: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe-expected.txt: Added.
+        * fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html: Added.
+        * fast/scrolling/resources/overscroll-behavior-support.js: Added.
+        (getDeltas):
+        (async mouseWheelScrollAndWait):
+
 2022-01-28  Robert Jenner  <jen...@apple.com>
 
         [ BigSur+ Release wk1 arm64 ] Bots are flaky exiting testing after 500 layout-test failures (235733)

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element-expected.txt (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element-expected.txt	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,20 @@
+
+PASS Element horizontal scroll test with overscroll-behavior: auto auto.
+PASS Element vertical scroll test with overscroll-behavior: auto auto.
+PASS Element horizontal scroll test with overscroll-behavior: contain auto.
+PASS Element vertical scroll test with overscroll-behavior: contain auto.
+PASS Element horizontal scroll test with overscroll-behavior: none auto.
+PASS Element vertical scroll test with overscroll-behavior: none auto.
+PASS Element horizontal scroll test with overscroll-behavior: auto contain.
+PASS Element vertical scroll test with overscroll-behavior: auto contain.
+PASS Element horizontal scroll test with overscroll-behavior: contain contain.
+PASS Element vertical scroll test with overscroll-behavior: contain contain.
+PASS Element horizontal scroll test with overscroll-behavior: none contain.
+PASS Element vertical scroll test with overscroll-behavior: none contain.
+PASS Element horizontal scroll test with overscroll-behavior: auto none.
+PASS Element vertical scroll test with overscroll-behavior: auto none.
+PASS Element horizontal scroll test with overscroll-behavior: contain none.
+PASS Element vertical scroll test with overscroll-behavior: contain none.
+PASS Element horizontal scroll test with overscroll-behavior: none none.
+PASS Element vertical scroll test with overscroll-behavior: none none.
+

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element.html (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element.html	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-element.html	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,86 @@
+<!doctype html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+<script src=""
+<script src=""
+<script src=""
+<link rel="help" href=""
+<style>
+    .scrolling {
+        overflow: scroll;
+    }
+    .scrollContent {
+        width: 300px;
+        height: 300px;
+    }
+    #root {
+        width: 200px;
+        height: 200px;
+    }
+    #scroller {
+        width: 100px;
+        height: 100px;
+    }
+</style>
+<div id='root' class="scrolling">
+    <div id='scroller' class="scrolling">
+        <div class="scrollContent"></div>
+    </div>
+    <div class="scrollContent"></div>
+</div>
+
+<script>
+const root = document.getElementById('root');
+const scroller = document.getElementById('scroller');
+var overscrollDatas = [["auto", "auto", true, true],
+                        ["contain", "auto", false, true],
+                        ["none", "auto", false, true],
+                        ["auto", "contain", true, false],
+                        ["contain", "contain", false, false],
+                        ["none", "contain", false, false],
+                        ["auto", "none", true, false],
+                        ["contain", "none", false, false],
+                        ["none", "none", false, false]];
+
+function resetTest() {
+    // Try various methods to ensure the element position is reset immediately.
+    scroller.scrollLeft = 300;
+    scroller.scrollTop = 300;
+    scroller.scrollTo(300, 300);
+
+    root.scrollLeft = 0;
+    root.scrollTop = 0;
+    root.scrollTo(0, 0);
+}
+
+function startTest() {
+    overscrollDatas.forEach(([overscrollX, overscrollY, propagateX, propagateY]) => {
+        promise_test(() => {
+            resetTest();
+            scroller.style.overscrollBehaviorX = overscrollX;
+            scroller.style.overscrollBehaviorY = overscrollY;
+            document.body.clientWidth;
+
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("right");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollLeft > 0, propagateX, 'Propagate horizontal scroll');
+            });
+        }, 'Element horizontal scroll test with overscroll-behavior: ' + overscrollX + ' ' + overscrollY + '.');
+
+        promise_test(() => {
+            resetTest();
+            scroller.style.overscrollBehaviorX = overscrollX;
+            scroller.style.overscrollBehaviorY = overscrollY;
+
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("down");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollTop > 0, propagateY, 'Propagate vertical scroll');
+            });
+        }, 'Element vertical scroll test with overscroll-behavior: ' + overscrollX + ' ' + overscrollY + '.');
+    });
+}
+
+addEventListener("load", startTest);
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe-expected.txt (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe-expected.txt	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,21 @@
+
+
+PASS Iframe horizontal scroll test with overscroll-behavior: auto auto.
+PASS Iframe vertical scroll test with overscroll-behavior: auto auto.
+PASS Iframe horizontal scroll test with overscroll-behavior: contain auto.
+PASS Iframe vertical scroll test with overscroll-behavior: contain auto.
+PASS Iframe horizontal scroll test with overscroll-behavior: none auto.
+PASS Iframe vertical scroll test with overscroll-behavior: none auto.
+PASS Iframe horizontal scroll test with overscroll-behavior: auto contain.
+PASS Iframe vertical scroll test with overscroll-behavior: auto contain.
+PASS Iframe horizontal scroll test with overscroll-behavior: contain contain.
+PASS Iframe vertical scroll test with overscroll-behavior: contain contain.
+PASS Iframe horizontal scroll test with overscroll-behavior: none contain.
+PASS Iframe vertical scroll test with overscroll-behavior: none contain.
+PASS Iframe horizontal scroll test with overscroll-behavior: auto none.
+PASS Iframe vertical scroll test with overscroll-behavior: auto none.
+PASS Iframe horizontal scroll test with overscroll-behavior: contain none.
+PASS Iframe vertical scroll test with overscroll-behavior: contain none.
+PASS Iframe horizontal scroll test with overscroll-behavior: none none.
+PASS Iframe vertical scroll test with overscroll-behavior: none none.
+

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe.html (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-iframe.html	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,85 @@
+<!doctype html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+<script src=""
+<script src=""
+<script src=""
+<link rel="help" href=""
+<style>
+    .scrolling {
+        overflow: scroll;
+    }
+    .scrollContent {
+        width: 300px;
+        height: 300px;
+        background: linear-gradient(135deg, red, blue);
+    }
+    #root {
+        width: 200px;
+        height: 200px;
+    }
+    #scroller {
+        width: 100px;
+        height: 100px;
+        overscroll-behavior-y: auto;
+    }
+</style>
+<div id='root' class="scrolling">
+    <iframe id='scroller' srcdoc="<html><div style='width: 300px; height: 300px;'></div></html>
+        "></iframe>
+    <div class="scrollContent"></div>
+</div>
+
+<script>
+    const root = document.getElementById('root');
+    const scroller = document.getElementById('scroller');
+    var overscrollDatas = [["auto", "auto", true, true],
+                            ["contain", "auto", false, true],
+                            ["none", "auto", false, true],
+                            ["auto", "contain", true, false],
+                            ["contain", "contain", false, false],
+                            ["none", "contain", false, false],
+                            ["auto", "none", true, false],
+                            ["contain", "none", false, false],
+                            ["none", "none", false, false]];
+    function resetTest() {
+        // Try various methods to ensure the element position is reset immediately.
+        scroller.contentWindow.scrollX = 300;
+        scroller.contentWindow.scrollY = 300;
+        scroller.contentWindow.scrollTo(300, 300);
+        root.scrollLeft = 0;
+        root.scrollTop = 0;
+        root.scrollTo(0, 0);
+    }
+
+    function overscrollBehaviorTest() {
+        overscrollDatas.forEach(([overscrollX, overscrollY, propagateX, propagateY]) => {
+            promise_test(() => {
+                resetTest();
+                var target = scroller.contentWindow.document.getElementsByTagName("html")[0];
+                target.style.overscrollBehaviorX = overscrollX;
+                target.style.overscrollBehaviorY = overscrollY;
+                var x = scroller.clientWidth / 2;
+                var y = scroller.clientHeight / 2;
+                var delta = getDeltas("right");
+                return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                    assert_equals(root.scrollLeft > 0, propagateX, 'Propagate horizontal scroll');
+                });
+            }, 'Iframe horizontal scroll test with overscroll-behavior: ' + overscrollX + ' ' + overscrollY + '.');
+
+            promise_test(() => {
+                resetTest();
+                var target = scroller.contentWindow.document.getElementsByTagName("html")[0];
+                target.style.overscrollBehaviorX = overscrollX;
+                target.style.overscrollBehaviorY = overscrollY;
+
+                var x = scroller.clientWidth / 2;
+                var y = scroller.clientHeight / 2;
+                var delta = getDeltas("down");
+                return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                    assert_equals(root.scrollTop > 0, propagateY, 'Propagate vertical scroll');
+                });
+            }, 'Iframe vertical scroll test with overscroll-behavior: ' + overscrollX + ' ' + overscrollY + '.');
+        });
+    }
+
+    scroller.addEventListener("load", overscrollBehaviorTest);
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element-expected.txt (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element-expected.txt	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,4 @@
+
+PASS Unscrollable element horizontal scroll test with overscroll-behavior: none.
+PASS Unscrollable element vertical scroll test with overscroll-behavior: none.
+

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,67 @@
+<!doctype html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+
+<script src=""
+<script src=""
+<script src=""
+<link rel="help" href=""
+<style>
+    .scrolling {
+        overflow: scroll;
+    }
+    .scrollContent {
+        width: 300px;
+        height: 300px;
+    }
+    #root {
+        width: 200px;
+        height: 200px;
+    }
+    #scroller {
+        width: 100px;
+        height: 100px;
+        overscroll-behavior: none;
+        overflow: visible;
+        background: linear-gradient(135deg, red, blue);
+    }
+</style>
+<div id="root" class="scrolling">
+    <div id="scroller">
+        <div class="scrollContent"></div>
+    </div>
+    <div class="scrollContent"></div>
+</div>
+
+<script>
+const root = document.getElementById('root');
+const scroller = document.getElementById('scroller');
+
+function resetTest() {
+    root.scrollLeft = 0;
+    root.scrollTop = 0;
+    root.scrollTo(0, 0);
+}
+
+function startTest() {
+        promise_test(() => {
+            resetTest();
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("right");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollLeft > 0, true, 'Propagate horizontal scroll');
+            });
+        }, 'Unscrollable element horizontal scroll test with overscroll-behavior: none.');
+
+        promise_test(() => {
+            resetTest();
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("down");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollTop > 0, true, 'Propagate vertical scroll');
+            });
+        }, 'Unscrollable element vertical scroll test with overscroll-behavior: none.');
+}
+
+addEventListener("load", startTest);
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe-expected.txt (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe-expected.txt	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,5 @@
+
+
+PASS Unscrollable iframe horizontal scroll test with overscroll-behavior: none.
+PASS Unscrollable iframe vertical scroll test with overscroll-behavior: none.
+

Added: trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,66 @@
+<!doctype html> <!-- webkit-test-runner [ AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+
+<script src=""
+<script src=""
+<script src=""
+<link rel="help" href=""
+<style>
+    .scrolling {
+        overflow: scroll;
+    }
+    .scrollContent {
+        width: 300px;
+        height: 300px;
+    }
+    #root {
+        width: 200px;
+        height: 200px;
+    }
+    #scroller {
+        width: 200px;
+        height: 200px;
+        overscroll-behavior: none;
+        overflow: visible;
+        background: linear-gradient(135deg, red, blue);
+    }
+</style>
+<div id='root' class="scrolling">
+    <iframe id='scroller' srcdoc="<html style='overscroll-behavior: none;'><div style='width: 100px; height: 100px;'></div></html>
+        "></iframe>
+    <div class="scrollContent"></div>
+</div>
+
+<script>
+const root = document.getElementById('root');
+const scroller = document.getElementById('scroller');
+
+function resetTest() {
+    root.scrollLeft = 0;
+    root.scrollTop = 0;
+    root.scrollTo(0, 0);
+}
+
+function startTest() {
+        promise_test(() => {
+            resetTest();
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("right");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollLeft > 0, true, 'Propagate horizontal scroll');
+            });
+        }, 'Unscrollable iframe horizontal scroll test with overscroll-behavior: none.');
+
+        promise_test(() => {
+            resetTest();
+            var x = scroller.clientWidth / 2;
+            var y = scroller.clientHeight / 2;
+            var delta = getDeltas("down");
+            return mouseWheelScrollAndWait(x, y, delta.X, delta.Y, delta.X, delta.Y).then(() => {
+                assert_equals(root.scrollTop > 0, true, 'Propagate vertical scroll');
+            });
+        }, 'Unscrollable iframe vertical scroll test with overscroll-behavior: none.');
+}
+
+addEventListener("load", startTest);
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/fast/scrolling/resources/overscroll-behavior-support.js (0 => 288777)


--- trunk/LayoutTests/fast/scrolling/resources/overscroll-behavior-support.js	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/resources/overscroll-behavior-support.js	2022-01-29 02:56:40 UTC (rev 288777)
@@ -0,0 +1,39 @@
+function getDeltas(direction) {
+    var deltaX = 0;
+    var deltaY = 0;
+    if (direction == "down")
+        deltaY = -5
+    else if (direction == "up")
+        deltaY = 5;
+    else if (direction == "right")
+        deltaX = -5;
+    else if (direction == "left")
+        deltaX = 5;
+    return {
+        X: deltaX,
+        Y: deltaY
+    };
+}
+
+async function mouseWheelScrollAndWait(x, y, beginX, beginY, deltaX, deltaY)
+{
+    if (beginX === undefined)
+        beginX = 0;
+    if (beginY === undefined)
+        beginY = -1;
+    if (deltaX === undefined)
+        deltaX = 0;
+    if (deltaY === undefined)
+        deltaY = -10;
+
+    eventSender.monitorWheelEvents();
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseScrollByWithWheelAndMomentumPhases(beginX, beginY, "began", "none");
+    eventSender.mouseScrollByWithWheelAndMomentumPhases(deltaX, deltaY, "changed", "none");
+    eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, "ended", "none");
+    return new Promise(resolve => {
+        setTimeout(() => {
+            requestAnimationFrame(resolve);
+        }, 500);
+    });
+}
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (288776 => 288777)


--- trunk/Source/WebCore/ChangeLog	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/ChangeLog	2022-01-29 02:56:40 UTC (rev 288777)
@@ -1,3 +1,33 @@
+2022-01-28  Nikolaos Mouchtaris  <nmouchta...@apple.com>
+
+        Implement CSS overscroll-behavior for asynchronous scroll on Mac
+        https://bugs.webkit.org/show_bug.cgi?id=220139
+
+        Reviewed by Simon Fraser.
+
+        Split up patch by Cathie Chen and Frederic Wang. Add function for blocking scroll chaining
+        and filtering scroll delta depending on the values of overscroll behavior for a scrolling
+        node. This patch is for asynchronous scrolling only.
+
+        Tests: fast/scrolling/mac/async-overscroll-behavior-element.html
+               fast/scrolling/mac/async-overscroll-behavior-iframe.html
+               fast/scrolling/mac/async-overscroll-behavior-unscrollable-element.html
+               fast/scrolling/mac/async-overscroll-behavior-unscrollable-iframe.html
+
+        * page/scrolling/ScrollingTree.cpp:
+        (WebCore::ScrollingTree::shouldBlockScrollChainingWithNode):
+        (WebCore::ScrollingTree::handleWheelEventWithNode):
+        * page/scrolling/ScrollingTree.h:
+        * page/scrolling/ScrollingTreeScrollingNode.h:
+        * page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm:
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsHorizontalStretching const):
+        (WebCore::ScrollingTreeScrollingNodeDelegateMac::allowsVerticalStretching const):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::recompositeChangeRequiresGeometryUpdate):
+        (WebCore::RenderLayerCompositor::rootOrBodyStyleChanged):
+        * rendering/style/RenderStyle.cpp:
+        (WebCore::RenderStyle::changeRequiresRecompositeLayer const):
+
 2022-01-28  Tyler Wilcock  <tyle...@apple.com>
 
         AX: AccessibilitySlider::inputElement should check if the renderer has become null

Modified: trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp (288776 => 288777)


--- trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp	2022-01-29 02:56:40 UTC (rev 288777)
@@ -787,8 +787,8 @@
     scrollingNode.setScrollableAreaSize(scrollableArea.visibleSize());
 
     ScrollableAreaParameters scrollParameters;
-    scrollParameters.horizontalScrollElasticity = scrollableArea.horizontalScrollElasticity();
-    scrollParameters.verticalScrollElasticity = scrollableArea.verticalScrollElasticity();
+    scrollParameters.horizontalScrollElasticity = scrollableArea.horizontalOverscrollBehavior() == OverscrollBehavior::None ? ScrollElasticity::None : scrollableArea.horizontalScrollElasticity();
+    scrollParameters.verticalScrollElasticity = scrollableArea.verticalOverscrollBehavior() == OverscrollBehavior::None ? ScrollElasticity::None : scrollableArea.verticalScrollElasticity();
     scrollParameters.allowsHorizontalScrolling = scrollableArea.allowsHorizontalScrolling();
     scrollParameters.allowsVerticalScrolling = scrollableArea.allowsVerticalScrolling();
     scrollParameters.horizontalOverscrollBehavior = scrollableArea.horizontalOverscrollBehavior();

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp (288776 => 288777)


--- trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp	2022-01-29 02:56:40 UTC (rev 288777)
@@ -31,6 +31,7 @@
 #include "EventNames.h"
 #include "Logging.h"
 #include "PlatformWheelEvent.h"
+#include "ScrollingEffectsController.h"
 #include "ScrollingStateFrameScrollingNode.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingTreeFrameScrollingNode.h"
@@ -201,19 +202,27 @@
 
 WheelEventHandlingResult ScrollingTree::handleWheelEventWithNode(const PlatformWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> processingSteps, ScrollingTreeNode* node, EventTargeting eventTargeting)
 {
+    auto adjustedWheelEvent = wheelEvent;
     while (node) {
         if (is<ScrollingTreeScrollingNode>(*node)) {
             auto& scrollingNode = downcast<ScrollingTreeScrollingNode>(*node);
-            auto result = scrollingNode.handleWheelEvent(wheelEvent, eventTargeting);
+            auto result = scrollingNode.handleWheelEvent(adjustedWheelEvent, eventTargeting);
 
             if (result.wasHandled) {
-                m_latchingController.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), processingSteps, wheelEvent, m_allowLatching);
-                m_gestureState.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), wheelEvent);
+                m_latchingController.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), processingSteps, adjustedWheelEvent, m_allowLatching);
+                m_gestureState.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), adjustedWheelEvent);
                 return result;
             }
 
             if (result.needsMainThreadProcessing() || eventTargeting != EventTargeting::Propagate)
                 return result;
+            
+            if (scrollingNode.shouldBlockScrollPropagation(adjustedWheelEvent.delta())) {
+                m_latchingController.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), processingSteps, adjustedWheelEvent, m_allowLatching);
+                m_gestureState.nodeDidHandleEvent(scrollingNode.scrollingNodeID(), adjustedWheelEvent);
+                return WheelEventHandlingResult::handled();
+            }
+            adjustedWheelEvent = scrollingNode.eventForPropagation(adjustedWheelEvent);
         }
 
         if (is<ScrollingTreeOverflowScrollProxyNode>(*node)) {

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (288776 => 288777)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp	2022-01-29 02:56:40 UTC (rev 288777)
@@ -32,6 +32,7 @@
 #if ENABLE(SCROLLING_THREAD)
 #include "ScrollingStateFrameScrollingNode.h"
 #endif
+#include "ScrollingEffectsController.h"
 #include "ScrollingStateScrollingNode.h"
 #include "ScrollingStateTree.h"
 #include "ScrollingTree.h"
@@ -121,6 +122,15 @@
     return scrollingTree().latchedNodeID() == scrollingNodeID();
 }
 
+bool ScrollingTreeScrollingNode::shouldRubberBand(const PlatformWheelEvent& wheelEvent, EventTargeting eventTargeting) const
+{
+    // We always rubber-band the latched node, or the root node.
+    // The stateless wheel event doesn't trigger rubber-band.
+    // Also rubberband when we should block scroll propagation
+    // at this node, which has overscroll behavior that is not none.
+    return (isLatchedNode() || eventTargeting == EventTargeting::NodeOnly || (isRootNode() && !wheelEvent.isNonGestureEvent()) || (shouldBlockScrollPropagation(wheelEvent.delta()) && overscrollBehaviorAllowRubberBand()));
+}
+
 bool ScrollingTreeScrollingNode::canHandleWheelEvent(const PlatformWheelEvent& wheelEvent, EventTargeting eventTargeting) const
 {
     if (!canHaveScrollbars())
@@ -130,9 +140,7 @@
     if (wheelEvent.phase() == PlatformWheelEventPhase::MayBegin)
         return true;
 
-    // We always rubber-band the latched node, or the root node.
-    // The stateless wheel event doesn't trigger rubber-band.
-    if (isLatchedNode() || eventTargeting == EventTargeting::NodeOnly || (isRootNode() && !wheelEvent.isNonGestureEvent()))
+    if (shouldRubberBand(wheelEvent, eventTargeting))
         return true;
 
     return eventCanScrollContents(wheelEvent);
@@ -392,6 +400,29 @@
     m_currentVerticalSnapPointIndex = index;
 }
 
+PlatformWheelEvent ScrollingTreeScrollingNode::eventForPropagation(const PlatformWheelEvent& wheelEvent) const
+{
+    auto filteredDelta = wheelEvent.delta();
+#if PLATFORM(MAC)
+    auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent);
+#else
+    auto biasedDelta = wheelEvent.delta();
+#endif
+    if (horizontalOverscrollBehaviorPreventsPropagation() || verticalOverscrollBehaviorPreventsPropagation()) {
+        if(horizontalOverscrollBehaviorPreventsPropagation() || (verticalOverscrollBehaviorPreventsPropagation() && !biasedDelta.width()))
+           filteredDelta.setWidth(0);
+        if(verticalOverscrollBehaviorPreventsPropagation() || (horizontalOverscrollBehaviorPreventsPropagation() && !biasedDelta.height()))
+           filteredDelta.setHeight(0);
+        return wheelEvent.copyWithDeltaAndVelocity(filteredDelta, wheelEvent.scrollingVelocity());
+    }
+    return wheelEvent;
+}
+
+bool ScrollingTreeScrollingNode::shouldBlockScrollPropagation(const FloatSize& delta) const
+{
+    return ((horizontalOverscrollBehaviorPreventsPropagation() || verticalOverscrollBehaviorPreventsPropagation()) && ((horizontalOverscrollBehaviorPreventsPropagation() && verticalOverscrollBehaviorPreventsPropagation()) || (horizontalOverscrollBehaviorPreventsPropagation() && !delta.height()) || (verticalOverscrollBehaviorPreventsPropagation() && !delta.width())));
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(ASYNC_SCROLLING)

Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (288776 => 288777)


--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h	2022-01-29 02:56:40 UTC (rev 288777)
@@ -159,7 +159,14 @@
 
     bool allowsHorizontalScrolling() const { return m_scrollableAreaParameters.allowsHorizontalScrolling; }
     bool allowsVerticalScrolling() const { return m_scrollableAreaParameters.allowsVerticalScrolling; }
-
+    OverscrollBehavior horizontalOverscrollBehavior() const { return m_scrollableAreaParameters.horizontalOverscrollBehavior; }
+    OverscrollBehavior verticalOverscrollBehavior() const { return m_scrollableAreaParameters.verticalOverscrollBehavior; }
+    bool horizontalOverscrollBehaviorPreventsPropagation() const { return m_scrollableAreaParameters.horizontalOverscrollBehavior != OverscrollBehavior::Auto; }
+    bool verticalOverscrollBehaviorPreventsPropagation() const { return m_scrollableAreaParameters.verticalOverscrollBehavior != OverscrollBehavior::Auto; }
+    PlatformWheelEvent eventForPropagation(const PlatformWheelEvent&) const;
+    bool shouldBlockScrollPropagation(const FloatSize&) const;
+    bool overscrollBehaviorAllowRubberBand() const { return m_scrollableAreaParameters.horizontalOverscrollBehavior != OverscrollBehavior::None ||  m_scrollableAreaParameters.verticalOverscrollBehavior != OverscrollBehavior::None; }
+    bool shouldRubberBand(const PlatformWheelEvent&, EventTargeting) const;
     void dumpProperties(WTF::TextStream&, OptionSet<ScrollingStateTreeAsTextBehavior>) const override;
 
 private:

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (288776 => 288777)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2022-01-29 02:56:40 UTC (rev 288777)
@@ -1651,7 +1651,9 @@
         || oldStyle.offsetPosition() != newStyle.offsetPosition()
         || oldStyle.offsetDistance() != newStyle.offsetDistance()
         || oldStyle.offsetRotate() != newStyle.offsetRotate()
-        || !arePointingToEqualData(oldStyle.clipPath(), newStyle.clipPath());
+        || !arePointingToEqualData(oldStyle.clipPath(), newStyle.clipPath())
+        || oldStyle.overscrollBehaviorX() != newStyle.overscrollBehaviorX()
+        || oldStyle.overscrollBehaviorY() != newStyle.overscrollBehaviorY();
 }
 
 void RenderLayerCompositor::layerStyleChanged(StyleDifference diff, RenderLayer& layer, const RenderStyle* oldStyle)
@@ -3944,6 +3946,11 @@
     bool hadFixedBackground = oldStyle && oldStyle->hasEntirelyFixedBackground();
     if (hadFixedBackground != renderer.style().hasEntirelyFixedBackground())
         rootLayerConfigurationChanged();
+    
+    if (oldStyle && (oldStyle->overscrollBehaviorX() != renderer.style().overscrollBehaviorX() || oldStyle->overscrollBehaviorY() != renderer.style().overscrollBehaviorY())) {
+        if (auto* layer = m_renderView.layer())
+            layer->setNeedsCompositingGeometryUpdate();
+    }
 }
 
 void RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged()

Modified: trunk/Source/WebCore/rendering/style/RenderStyle.cpp (288776 => 288777)


--- trunk/Source/WebCore/rendering/style/RenderStyle.cpp	2022-01-29 02:42:21 UTC (rev 288776)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.cpp	2022-01-29 02:56:40 UTC (rev 288777)
@@ -1189,7 +1189,9 @@
             || m_rareNonInheritedData->backfaceVisibility != other.m_rareNonInheritedData->backfaceVisibility
             || m_rareNonInheritedData->perspective != other.m_rareNonInheritedData->perspective
             || m_rareNonInheritedData->perspectiveOriginX != other.m_rareNonInheritedData->perspectiveOriginX
-            || m_rareNonInheritedData->perspectiveOriginY != other.m_rareNonInheritedData->perspectiveOriginY)
+            || m_rareNonInheritedData->perspectiveOriginY != other.m_rareNonInheritedData->perspectiveOriginY
+            || m_rareNonInheritedData->overscrollBehaviorX != other.m_rareNonInheritedData->overscrollBehaviorX
+            || m_rareNonInheritedData->overscrollBehaviorY != other.m_rareNonInheritedData->overscrollBehaviorY)
             return true;
     }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to