- Revision
- 284448
- Author
- commit-qu...@webkit.org
- Date
- 2021-10-19 06:46:40 -0700 (Tue, 19 Oct 2021)
Log Message
[css-scroll-snap] Triggering a layout during scroll causes jittery scrolling on iOS
https://bugs.webkit.org/show_bug.cgi?id=173887
<rdar://problem/67153673>
Patch by Martin Robinson <mrobin...@igalia.com> on 2021-10-19
Reviewed by Simon Fraser.
Source/WebKit:
Tests: fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html
fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html
Ensure that when the root node is scrolling, it is added to the list of nodes
with an active user scroll. This prevents the web process from resnapping during
layout when the user is actively scrolling.
* UIProcess/API/ios/WKWebViewIOS.mm:
(-[WKWebView scrollViewWillBeginDragging:]): Call RemoteScrollingCoordinatorProxy::setRootNodeIsInUserScroll
when a scdroll starts and ends.
* UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h: Added method declaration.
* UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxy::setRootNodeIsInUserScroll): Added setRootNodeIsInUserScroll method.
LayoutTests:
* fast/scrolling/ios/scroll-snap-with-relayouts-horizontal-expected.txt: Added.
* fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html: Added.
* fast/scrolling/ios/scroll-snap-with-relayouts-vertical-expected.txt: Added.
* fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (284447 => 284448)
--- trunk/LayoutTests/ChangeLog 2021-10-19 13:40:40 UTC (rev 284447)
+++ trunk/LayoutTests/ChangeLog 2021-10-19 13:46:40 UTC (rev 284448)
@@ -1,3 +1,16 @@
+2021-10-19 Martin Robinson <mrobin...@igalia.com>
+
+ [css-scroll-snap] Triggering a layout during scroll causes jittery scrolling on iOS
+ https://bugs.webkit.org/show_bug.cgi?id=173887
+ <rdar://problem/67153673>
+
+ Reviewed by Simon Fraser.
+
+ * fast/scrolling/ios/scroll-snap-with-relayouts-horizontal-expected.txt: Added.
+ * fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html: Added.
+ * fast/scrolling/ios/scroll-snap-with-relayouts-vertical-expected.txt: Added.
+ * fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html: Added.
+
2021-10-19 Rob Buis <rb...@igalia.com>
Remove support for some SVG properties
Added: trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal-expected.txt (0 => 284448)
--- trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal-expected.txt 2021-10-19 13:46:40 UTC (rev 284448)
@@ -0,0 +1,6 @@
+PASS horizontal drag snapped to next snap point
+PASS relayouts should not caused the scroll area to snap back
+PASS successfullyParsed is true
+
+TEST COMPLETE
+980
Added: trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html (0 => 284448)
--- trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html 2021-10-19 13:46:40 UTC (rev 284448)
@@ -0,0 +1,74 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+<html>
+ <head>
+ <title>Dragging a view should not snap back when the scroll event triggers a relayout</title>
+ <style type="text/css">
+ html {
+ scroll-snap-type: both mandatory
+ }
+
+ html, body {
+ margin: 0;
+ height: 100%;
+ width: 100%;
+ }
+
+ .horizontal-drawer {
+ width: 500%;
+ height: 100%;
+ }
+
+ .block {
+ float: left;
+ height: 100%;
+ width: 20%;
+ scroll-snap-align: start;
+ }
+
+ #console, #output {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ }
+ </style>
+ <script src=""
+ <script src=""
+ <script>
+ window.jsTestIsAsync = true;
+
+ async function onLoad()
+ {
+ let sawZero = false;
+ window.addEventListener('scroll', () => {
+ document.getElementById('output').innerText = document.scrollingElement.scrollLeft;
+ sawZero ||= document.scrollingElement.scrollLeft == 0;
+ })
+
+ if (window.eventSender == undefined) {
+ document.getElementById('console').innerText = "A scroll drag should not snap until user interaction is finished.";
+ return;
+ }
+
+ try {
+ await UIHelper.dragFromPointToPoint(150, 150, 50, 150, 0.1);
+ await UIHelper.waitForTargetScrollAnimationToSettle(document.scrollingElement);
+ expectTrue(document.scrollingElement.scrollLeft == window.innerWidth, "horizontal drag snapped to next snap point");
+ expectTrue(sawZero === false, "relayouts should not caused the scroll area to snap back");
+ } catch (e) {
+ console.log(e);
+ } finally {
+ finishJSTest();
+ }
+ }
+ </script>
+ </head>
+ <body _onload_="onLoad();">
+ <div class="horizontal-drawer">
+ <div class="block" style="background: #80475E"></div>
+ <div class="block" style="background: #CC5A71"></div>
+ <div class="block" style="background: #80475E"></div>
+ </div>
+ <p id="console"></p>
+ <p id="output"></p>
+ </body>
+</html>
Added: trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical-expected.txt (0 => 284448)
--- trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical-expected.txt 2021-10-19 13:46:40 UTC (rev 284448)
@@ -0,0 +1,6 @@
+PASS vertical drag snapped to next snap point
+PASS relayouts should not have snapped back
+PASS successfullyParsed is true
+
+TEST COMPLETE
+1678
Added: trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html (0 => 284448)
--- trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html (rev 0)
+++ trunk/LayoutTests/fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html 2021-10-19 13:46:40 UTC (rev 284448)
@@ -0,0 +1,71 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true AsyncOverflowScrollingEnabled=true AsyncFrameScrollingEnabled=true ] -->
+<html>
+ <head>
+ <title>Dragging a view should not snap back when the scroll event triggers a relayout</title>
+ <style type="text/css">
+ html {
+ scroll-snap-type: both mandatory
+ }
+
+ html, body {
+ margin: 0;
+ height: 100%;
+ width: 100%;
+ }
+
+ .horizontal-drawer {
+ width: 500%;
+ height: 100%;
+ }
+
+ .block {
+ height: 100%;
+ width: 100%;
+ scroll-snap-align: start;
+ }
+
+ #console, #output {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ }
+ </style>
+ <script src=""
+ <script src=""
+ <script>
+ window.jsTestIsAsync = true;
+
+ async function onLoad()
+ {
+ let sawZero = false;
+ window.addEventListener('scroll', () => {
+ document.getElementById('output').innerText = document.scrollingElement.scrollTop;
+ sawZero ||= document.scrollingElement.scrollTop == 0;
+ })
+
+ if (window.eventSender == undefined) {
+ document.getElementById('console').innerText = "A scroll drag should not snap until user interaction is finished.";
+ return;
+ }
+
+ try {
+ await UIHelper.dragFromPointToPoint(150, 150, 150, 50, 0.1);
+ await UIHelper.waitForTargetScrollAnimationToSettle(document.scrollingElement);
+ expectTrue(document.scrollingElement.scrollTop == window.innerHeight, "vertical drag snapped to next snap point");
+ expectTrue(sawZero === false, "relayouts should not have snapped back");
+ } catch (e) {
+ console.log(e);
+ } finally {
+ finishJSTest();
+ }
+ }
+ </script>
+ </head>
+ <body _onload_="onLoad();">
+ <div class="block" style="background: #CC5A71"></div>
+ <div class="block" style="background: #80475E"></div>
+ <div class="block" style="background: #CC5A71"></div>
+ <p id="console"></p>
+ <p id="output"></p>
+ </body>
+</html>
Modified: trunk/Source/WebKit/ChangeLog (284447 => 284448)
--- trunk/Source/WebKit/ChangeLog 2021-10-19 13:40:40 UTC (rev 284447)
+++ trunk/Source/WebKit/ChangeLog 2021-10-19 13:46:40 UTC (rev 284448)
@@ -1,3 +1,25 @@
+2021-10-19 Martin Robinson <mrobin...@igalia.com>
+
+ [css-scroll-snap] Triggering a layout during scroll causes jittery scrolling on iOS
+ https://bugs.webkit.org/show_bug.cgi?id=173887
+ <rdar://problem/67153673>
+
+ Reviewed by Simon Fraser.
+
+ Tests: fast/scrolling/ios/scroll-snap-with-relayouts-horizontal.html
+ fast/scrolling/ios/scroll-snap-with-relayouts-vertical.html
+
+ Ensure that when the root node is scrolling, it is added to the list of nodes
+ with an active user scroll. This prevents the web process from resnapping during
+ layout when the user is actively scrolling.
+
+ * UIProcess/API/ios/WKWebViewIOS.mm:
+ (-[WKWebView scrollViewWillBeginDragging:]): Call RemoteScrollingCoordinatorProxy::setRootNodeIsInUserScroll
+ when a scdroll starts and ends.
+ * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h: Added method declaration.
+ * UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
+ (WebKit::RemoteScrollingCoordinatorProxy::setRootNodeIsInUserScroll): Added setRootNodeIsInUserScroll method.
+
2021-10-19 Youenn Fablet <you...@apple.com>
getDisplayMedia MediaStreamTrack.applyConstraints behavior regressed in Safari 15
Modified: trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm (284447 => 284448)
--- trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2021-10-19 13:40:40 UTC (rev 284447)
+++ trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm 2021-10-19 13:46:40 UTC (rev 284448)
@@ -1631,6 +1631,8 @@
CGFloat scrollDecelerationFactor = (coordinator && coordinator->shouldSetScrollViewDecelerationRateFast()) ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal;
scrollView.horizontalScrollDecelerationFactor = scrollDecelerationFactor;
scrollView.verticalScrollDecelerationFactor = scrollDecelerationFactor;
+
+ coordinator->setRootNodeIsInUserScroll(true);
#endif
}
@@ -1641,6 +1643,10 @@
[self _scheduleVisibleContentRectUpdate];
[_contentView didFinishScrolling];
+
+#if ENABLE(ASYNC_SCROLLING)
+ _page->scrollingCoordinatorProxy()->setRootNodeIsInUserScroll(false);
+#endif
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h (284447 => 284448)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h 2021-10-19 13:40:40 UTC (rev 284447)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h 2021-10-19 13:46:40 UTC (rev 284448)
@@ -99,6 +99,7 @@
bool hasActiveSnapPoint() const;
CGPoint nearestActiveContentInsetAdjustedSnapOffset(CGFloat topInset, const CGPoint&) const;
bool shouldSetScrollViewDecelerationRateFast() const;
+ void setRootNodeIsInUserScroll(bool);
#endif
String scrollingTreeAsText() const;
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm (284447 => 284448)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm 2021-10-19 13:40:40 UTC (rev 284447)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm 2021-10-19 13:46:40 UTC (rev 284448)
@@ -218,6 +218,20 @@
return shouldSnapForMainFrameScrolling(ScrollEventAxis::Horizontal) || shouldSnapForMainFrameScrolling(ScrollEventAxis::Vertical);
}
+void RemoteScrollingCoordinatorProxy::setRootNodeIsInUserScroll(bool value)
+{
+ ScrollingTreeNode* root = m_scrollingTree->rootNode();
+ if (!root || !root->isFrameScrollingNode())
+ return;
+
+ if (value)
+ m_uiState.addNodeWithActiveUserScroll(root->scrollingNodeID());
+ else
+ m_uiState.removeNodeWithActiveUserScroll(root->scrollingNodeID());
+
+ sendUIStateChangedIfNecessary();
+}
+
bool RemoteScrollingCoordinatorProxy::shouldSnapForMainFrameScrolling(ScrollEventAxis axis) const
{
ScrollingTreeNode* root = m_scrollingTree->rootNode();