Diff
Modified: trunk/LayoutTests/ChangeLog (289073 => 289074)
--- trunk/LayoutTests/ChangeLog 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/LayoutTests/ChangeLog 2022-02-03 21:32:43 UTC (rev 289074)
@@ -1,3 +1,21 @@
+2022-02-03 Nikolaos Mouchtaris <nmouchta...@apple.com>
+
+ Implement CSS overscroll-behavior for synchronous scroll
+ https://bugs.webkit.org/show_bug.cgi?id=222968
+
+ Reviewed by Simon Fraser.
+
+ * fast/scrolling/sync-scroll-overscroll-behavior-element-expected.txt: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-element.html: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-iframe-expected.txt: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-iframe.html: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element-expected.txt: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe-expected.txt: Added.
+ * fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html: Added.
+ * platform/mac-wk1/TestExpectations:
+ * platform/win/TestExpectations:
+
2022-02-03 Kimmo Kinnunen <kkinnu...@apple.com>
ANGLE Metal and ANGLE OpenGL cannot be initialised one after the other
Added: trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element-expected.txt (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element-expected.txt 2022-02-03 21:32:43 UTC (rev 289074)
@@ -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/sync-scroll-overscroll-behavior-element.html (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-element.html 2022-02-03 21:32:43 UTC (rev 289074)
@@ -0,0 +1,86 @@
+<!doctype html>
+<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/sync-scroll-overscroll-behavior-iframe-expected.txt (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-iframe-expected.txt 2022-02-03 21:32:43 UTC (rev 289074)
@@ -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/sync-scroll-overscroll-behavior-iframe.html (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-iframe.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-iframe.html 2022-02-03 21:32:43 UTC (rev 289074)
@@ -0,0 +1,85 @@
+<!doctype html>
+<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/sync-scroll-overscroll-behavior-unscrollable-element-expected.txt (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element-expected.txt 2022-02-03 21:32:43 UTC (rev 289074)
@@ -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/sync-scroll-overscroll-behavior-unscrollable-element.html (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html 2022-02-03 21:32:43 UTC (rev 289074)
@@ -0,0 +1,66 @@
+<!doctype html>
+<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/sync-scroll-overscroll-behavior-unscrollable-iframe-expected.txt (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe-expected.txt 2022-02-03 21:32:43 UTC (rev 289074)
@@ -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/sync-scroll-overscroll-behavior-unscrollable-iframe.html (0 => 289074)
--- trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html 2022-02-03 21:32:43 UTC (rev 289074)
@@ -0,0 +1,65 @@
+<!doctype html>
+<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
Modified: trunk/LayoutTests/platform/ios/TestExpectations (289073 => 289074)
--- trunk/LayoutTests/platform/ios/TestExpectations 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/LayoutTests/platform/ios/TestExpectations 2022-02-03 21:32:43 UTC (rev 289074)
@@ -814,6 +814,12 @@
svg/text/selection-tripleclick.svg [ Skip ]
imported/w3c/web-platform-tests/css/css-shadow-parts/invalidation-part-pseudo.html [ Skip ]
+# Overscroll-behavior on iOS needs SkyEcho19E179/StarE21E168a: https://bugs.webkit.org/show_bug.cgi?id=235852
+fast/scrolling/sync-scroll-overscroll-behavior-element.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-iframe.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html [ Skip ]
+
# IOS does not implement setAutomaticLinkDetectionEnabled
editing/inserting/typing-space-to-trigger-smart-link.html [ Skip ]
editing/inserting/smart-link-when-caret-is-moved-before-URL.html [ Skip ]
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (289073 => 289074)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2022-02-03 21:32:43 UTC (rev 289074)
@@ -684,6 +684,10 @@
imported/w3c/web-platform-tests/css/css-scroll-snap/scroll-snap-stop-change.html [ Failure ]
css3/scroll-snap/scroll-padding-mainframe-paging.html [ Failure ]
+# Lack of ways to control the cross-frame scroll chaining in WK1.
+fast/scrolling/sync-scroll-overscroll-behavior-iframe.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html [ Skip ]
+
### END OF (2) Failures without bug reports
########################################
Modified: trunk/LayoutTests/platform/win/TestExpectations (289073 => 289074)
--- trunk/LayoutTests/platform/win/TestExpectations 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/LayoutTests/platform/win/TestExpectations 2022-02-03 21:32:43 UTC (rev 289074)
@@ -765,6 +765,12 @@
http/tests/pointer-lock/ [ Skip ]
fast/js-promise/js-promise-invalid-context-access.html [ Skip ]
+# Overscroll-behavior is not supported on Windows
+fast/scrolling/sync-scroll-overscroll-behavior-element.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-iframe.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html [ Skip ]
+fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html [ Skip ]
+
# Datalist is unsupported on Windows
accessibility/datalist.html [ WontFix ]
fast/forms/datalist [ WontFix ]
Modified: trunk/Source/WebCore/ChangeLog (289073 => 289074)
--- trunk/Source/WebCore/ChangeLog 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/ChangeLog 2022-02-03 21:32:43 UTC (rev 289074)
@@ -1,3 +1,42 @@
+2022-02-03 Nikolaos Mouchtaris <nmouchta...@apple.com>
+
+ Implement CSS overscroll-behavior for synchronous scroll
+ https://bugs.webkit.org/show_bug.cgi?id=222968
+
+ Reviewed by Simon Fraser.
+
+ Tests: fast/scrolling/sync-scroll-overscroll-behavior-element.html
+ fast/scrolling/sync-scroll-overscroll-behavior-iframe.html
+ fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-element.html
+ fast/scrolling/sync-scroll-overscroll-behavior-unscrollable-iframe.html
+
+ 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 scrollable
+ area. This patch is for synchronous scrolling only.
+
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleWheelEventInternal):
+ (WebCore::scrollViaNonPlatformEvent):
+ (WebCore::EventHandler::handleWheelEventInAppropriateEnclosingBox):
+ (WebCore::EventHandler::scrollableAreaCanHandleEvent):
+ * page/EventHandler.h:
+ * page/mac/EventHandlerMac.mm:
+ (WebCore::findEnclosingScrollableContainer):
+ * page/scrolling/ScrollingTreeScrollingNode.cpp:
+ (WebCore::ScrollingTreeScrollingNode::eventForPropagation const):
+ * platform/ScrollableArea.cpp:
+ (WebCore::ScrollableArea::deltaForPropagation const):
+ (WebCore::ScrollableArea::shouldBlockScrollPropagation const):
+ * platform/ScrollableArea.h:
+ (WebCore::ScrollableArea::horizontalOverscrollBehaviorPreventsPropagation const):
+ (WebCore::ScrollableArea::verticalOverscrollBehaviorPreventsPropagation const):
+ * platform/ScrollingEffectsController.h:
+ * platform/mac/ScrollAnimatorMac.mm:
+ (WebCore::ScrollAnimatorMac::allowsVerticalStretching const):
+ (WebCore::ScrollAnimatorMac::allowsHorizontalStretching const):
+ * platform/mac/ScrollingEffectsController.mm:
+ (WebCore::ScrollingEffectsController::wheelDeltaBiasingTowardsVertical):
+
2022-02-03 Kimmo Kinnunen <kkinnu...@apple.com>
ANGLE Metal and ANGLE OpenGL cannot be initialised one after the other
Modified: trunk/Source/WebCore/page/EventHandler.cpp (289073 => 289074)
--- trunk/Source/WebCore/page/EventHandler.cpp 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/page/EventHandler.cpp 2022-02-03 21:32:43 UTC (rev 289074)
@@ -3027,11 +3027,17 @@
if (allowScrolling)
allowScrolling = m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, scrollableArea);
#endif
+ auto adjustedWheelEvent = event;
+ auto filteredDelta = adjustedWheelEvent.delta();
+ filteredDelta = view->deltaForPropagation(filteredDelta);
+ if (view->shouldBlockScrollPropagation(filteredDelta))
+ return true;
if (allowScrolling) {
// FIXME: processWheelEventForScrolling() is only called for FrameView scrolling, not overflow scrolling, which is confusing.
- handledEvent = processWheelEventForScrolling(event, scrollableArea, handling);
- processWheelEventForScrollSnap(event, scrollableArea);
+ adjustedWheelEvent = adjustedWheelEvent.copyWithDeltaAndVelocity(filteredDelta, adjustedWheelEvent.scrollingVelocity());
+ handledEvent = processWheelEventForScrolling(adjustedWheelEvent, scrollableArea, handling);
+ processWheelEventForScrollSnap(adjustedWheelEvent, scrollableArea);
}
return handledEvent;
@@ -3050,18 +3056,19 @@
static bool scrollViaNonPlatformEvent(ScrollableArea& scrollableArea, const WheelEvent& wheelEvent)
{
+ auto filteredDelta = FloatSize(wheelEvent.deltaX(), wheelEvent.deltaY());
+ filteredDelta = scrollableArea.deltaForPropagation(filteredDelta);
ScrollGranularity scrollGranularity = wheelGranularityToScrollGranularity(wheelEvent.deltaMode());
bool didHandleWheelEvent = false;
- if (float absoluteDelta = std::abs(wheelEvent.deltaX()))
- didHandleWheelEvent |= scrollableArea.scroll(wheelEvent.deltaX() > 0 ? ScrollRight : ScrollLeft, scrollGranularity, absoluteDelta);
+ if (float absoluteDelta = std::abs(filteredDelta.width()))
+ didHandleWheelEvent |= scrollableArea.scroll(filteredDelta.width() > 0 ? ScrollRight : ScrollLeft, scrollGranularity, absoluteDelta);
- if (float absoluteDelta = std::abs(wheelEvent.deltaY()))
- didHandleWheelEvent |= scrollableArea.scroll(wheelEvent.deltaY() > 0 ? ScrollDown : ScrollUp, scrollGranularity, absoluteDelta);
-
+ if (float absoluteDelta = std::abs(filteredDelta.height()))
+ didHandleWheelEvent |= scrollableArea.scroll(filteredDelta.height() > 0 ? ScrollDown : ScrollUp, scrollGranularity, absoluteDelta);
return didHandleWheelEvent;
}
-bool EventHandler::handleWheelEventInAppropriateEnclosingBox(Node* startNode, const WheelEvent& wheelEvent, const FloatSize& filteredPlatformDelta, const FloatSize& filteredVelocity, OptionSet<EventHandling> eventHandling)
+bool EventHandler::handleWheelEventInAppropriateEnclosingBox(Node* startNode, const WheelEvent& wheelEvent, FloatSize& filteredPlatformDelta, const FloatSize& filteredVelocity, OptionSet<EventHandling> eventHandling)
{
bool shouldHandleEvent = wheelEvent.deltaX() || wheelEvent.deltaY();
#if ENABLE(WHEEL_EVENT_LATCHING)
@@ -3091,6 +3098,12 @@
};
RenderBox* currentEnclosingBox = &initialEnclosingBox;
+#if PLATFORM(MAC)
+ auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(FloatSize(wheelEvent.deltaX(), wheelEvent.deltaY()));
+#else
+ auto biasedDelta = FloatSize(wheelEvent.deltaX(), wheelEvent.deltaY());
+#endif
+
while (currentEnclosingBox) {
if (auto* boxScrollableArea = scrollableAreaForBox(*currentEnclosingBox)) {
auto platformEvent = wheelEvent.underlyingPlatformEvent();
@@ -3103,6 +3116,10 @@
if (scrollingWasHandled)
return true;
+
+ biasedDelta = boxScrollableArea->deltaForPropagation(biasedDelta);
+ if (boxScrollableArea->shouldBlockScrollPropagation(biasedDelta))
+ return true;
}
currentEnclosingBox = currentEnclosingBox->containingBlock();
@@ -3115,7 +3132,7 @@
bool EventHandler::scrollableAreaCanHandleEvent(const PlatformWheelEvent& wheelEvent, ScrollableArea& scrollableArea)
{
#if PLATFORM(MAC)
- auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent);
+ auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent.delta());
#else
auto biasedDelta = wheelEvent.delta();
#endif
@@ -3127,6 +3144,8 @@
auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-biasedDelta, ScrollEventAxis::Horizontal);
if (horizontalSide && !scrollableArea.isPinnedOnSide(*horizontalSide))
return true;
+ if (scrollableArea.shouldBlockScrollPropagation(biasedDelta) && scrollableArea.overscrollBehaviorAllowsRubberBand())
+ return true;
return false;
}
Modified: trunk/Source/WebCore/page/EventHandler.h (289073 => 289074)
--- trunk/Source/WebCore/page/EventHandler.h 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/page/EventHandler.h 2022-02-03 21:32:43 UTC (rev 289074)
@@ -475,7 +475,7 @@
void processWheelEventForScrollSnap(const PlatformWheelEvent&, const WeakPtr<ScrollableArea>&);
bool completeWidgetWheelEvent(const PlatformWheelEvent&, const WeakPtr<Widget>&, const WeakPtr<ScrollableArea>&);
- bool handleWheelEventInAppropriateEnclosingBox(Node* startNode, const WheelEvent&, const FloatSize& filteredPlatformDelta, const FloatSize& filteredVelocity, OptionSet<EventHandling>);
+ bool handleWheelEventInAppropriateEnclosingBox(Node* startNode, const WheelEvent&, FloatSize& filteredPlatformDelta, const FloatSize& filteredVelocity, OptionSet<EventHandling>);
bool handleWheelEventInScrollableArea(const PlatformWheelEvent&, ScrollableArea&, OptionSet<EventHandling>);
std::optional<WheelScrollGestureState> updateWheelGestureState(const PlatformWheelEvent&, OptionSet<EventHandling>);
Modified: trunk/Source/WebCore/page/mac/EventHandlerMac.mm (289073 => 289074)
--- trunk/Source/WebCore/page/mac/EventHandlerMac.mm 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/page/mac/EventHandlerMac.mm 2022-02-03 21:32:43 UTC (rev 289074)
@@ -815,7 +815,10 @@
auto* scrollableArea = scrollableAreaForBox(*box);
if (!scrollableArea)
continue;
-
+
+ if (scrollableArea->shouldBlockScrollPropagation(wheelEvent.delta()))
+ return candidate;
+
if (wheelEvent.phase() == PlatformWheelEventPhase::MayBegin || wheelEvent.phase() == PlatformWheelEventPhase::Cancelled)
return candidate;
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp (289073 => 289074)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp 2022-02-03 21:32:43 UTC (rev 289074)
@@ -128,7 +128,7 @@
// 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()));
+ return (isLatchedNode() || eventTargeting == EventTargeting::NodeOnly || (isRootNode() && !wheelEvent.isNonGestureEvent()) || (shouldBlockScrollPropagation(wheelEvent.delta()) && overscrollBehaviorAllowsRubberBand()));
}
bool ScrollingTreeScrollingNode::canHandleWheelEvent(const PlatformWheelEvent& wheelEvent, EventTargeting eventTargeting) const
@@ -404,7 +404,7 @@
{
auto filteredDelta = wheelEvent.delta();
#if PLATFORM(MAC)
- auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent);
+ auto biasedDelta = ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(wheelEvent.delta());
#else
auto biasedDelta = wheelEvent.delta();
#endif
Modified: trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h (289073 => 289074)
--- trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h 2022-02-03 21:32:43 UTC (rev 289074)
@@ -165,7 +165,7 @@
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 overscrollBehaviorAllowsRubberBand() 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;
Modified: trunk/Source/WebCore/platform/ScrollableArea.cpp (289073 => 289074)
--- trunk/Source/WebCore/platform/ScrollableArea.cpp 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/platform/ScrollableArea.cpp 2022-02-03 21:32:43 UTC (rev 289074)
@@ -807,4 +807,22 @@
return ts;
}
+FloatSize ScrollableArea::deltaForPropagation(const FloatSize& biasedDelta) const
+{
+ auto filteredDelta = biasedDelta;
+ if (horizontalOverscrollBehaviorPreventsPropagation())
+ filteredDelta.setWidth(0);
+ if (verticalOverscrollBehaviorPreventsPropagation())
+ filteredDelta.setHeight(0);
+ return filteredDelta;
+}
+
+bool ScrollableArea::shouldBlockScrollPropagation(const FloatSize& biasedDelta) const
+{
+ return ((horizontalOverscrollBehaviorPreventsPropagation() || verticalOverscrollBehaviorPreventsPropagation())
+ && ((horizontalOverscrollBehaviorPreventsPropagation() && verticalOverscrollBehaviorPreventsPropagation())
+ || (horizontalOverscrollBehaviorPreventsPropagation() && !biasedDelta.height()) || (verticalOverscrollBehaviorPreventsPropagation()
+ && !biasedDelta.width())));
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/ScrollableArea.h (289073 => 289074)
--- trunk/Source/WebCore/platform/ScrollableArea.h 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/platform/ScrollableArea.h 2022-02-03 21:32:43 UTC (rev 289074)
@@ -373,6 +373,12 @@
}
virtual void didStartScrollAnimation() { }
+
+ bool horizontalOverscrollBehaviorPreventsPropagation() const { return horizontalOverscrollBehavior() != OverscrollBehavior::Auto; }
+ bool verticalOverscrollBehaviorPreventsPropagation() const { return verticalOverscrollBehavior() != OverscrollBehavior::Auto; }
+ bool overscrollBehaviorAllowsRubberBand() const { return horizontalOverscrollBehavior() != OverscrollBehavior::None || verticalOverscrollBehavior() != OverscrollBehavior::None; }
+ bool shouldBlockScrollPropagation(const FloatSize&) const;
+ FloatSize deltaForPropagation(const FloatSize&) const;
protected:
WEBCORE_EXPORT ScrollableArea();
Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.h (289073 => 289074)
--- trunk/Source/WebCore/platform/ScrollingEffectsController.h 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.h 2022-02-03 21:32:43 UTC (rev 289074)
@@ -174,7 +174,7 @@
bool isUserScrollInProgress() const;
#if PLATFORM(MAC)
- static FloatSize wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent&);
+ static FloatSize wheelDeltaBiasingTowardsVertical(const FloatSize&);
// Returns true if handled.
bool processWheelEventForScrollSnap(const PlatformWheelEvent&);
Modified: trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm (289073 => 289074)
--- trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm 2022-02-03 21:32:43 UTC (rev 289074)
@@ -105,6 +105,9 @@
bool ScrollAnimatorMac::allowsVerticalStretching(const PlatformWheelEvent& wheelEvent) const
{
+ if (m_scrollableArea.verticalOverscrollBehavior() == OverscrollBehavior::None)
+ return false;
+
switch (m_scrollableArea.verticalScrollElasticity()) {
case ScrollElasticity::Automatic: {
Scrollbar* hScroller = m_scrollableArea.horizontalScrollbar();
@@ -128,6 +131,9 @@
bool ScrollAnimatorMac::allowsHorizontalStretching(const PlatformWheelEvent& wheelEvent) const
{
+ if (m_scrollableArea.horizontalOverscrollBehavior() == OverscrollBehavior::None)
+ return false;
+
switch (m_scrollableArea.horizontalScrollElasticity()) {
case ScrollElasticity::Automatic: {
Scrollbar* hScroller = m_scrollableArea.horizontalScrollbar();
Modified: trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm (289073 => 289074)
--- trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm 2022-02-03 21:30:22 UTC (rev 289073)
+++ trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm 2022-02-03 21:32:43 UTC (rev 289074)
@@ -345,9 +345,9 @@
return canStartAnimation;
}
-FloatSize ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent& wheelEvent)
+FloatSize ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(const FloatSize& wheelDelta)
{
- return deltaAlignedToDominantAxis(wheelEvent.delta());
+ return deltaAlignedToDominantAxis(wheelDelta);
}
void ScrollingEffectsController::updateRubberBandAnimatingState()