Title: [285917] trunk
Revision
285917
Author
simon.fra...@apple.com
Date
2021-11-16 22:25:17 -0800 (Tue, 16 Nov 2021)

Log Message

Stop a momentum scroll animation when receiving a momentum end event
https://bugs.webkit.org/show_bug.cgi?id=233236

Reviewed by Tim Horton.

Source/WebCore:

The stream of momentum events is terminated by an "end" event under two circumstances:
1. The gesture finished naturally without interruption.
2. The user tapped the trackpad with two fingers.

Unfortunately we can't tell these apart, so we always have to stop the animation.

Sadly this reveals a hole in the testing infrastructure. All the "changed" momentum
events in the sequence handed to UIHelper.mouseWheelSequence() are ignored while the
animation is running, but the "ended" event stops the animation. So any test without
a reasonable number of "changed" events will terminate its animation prematurely.
We can't fix this without new testing infrastructure (webkit.org/b/233234).

Test: fast/scrolling/mac/momentum-animator-end-event-stops.html

* platform/ScrollingEffectsController.h:
* platform/mac/ScrollingEffectsController.mm:
(WebCore::ScrollingEffectsController::handleWheelEvent):

LayoutTests:

New test, and skip one that breaks now because we need a fix for webkit.org/b/233234.

* fast/scrolling/mac/momentum-animator-end-event-stops-expected.txt: Added.
* fast/scrolling/mac/momentum-animator-end-event-stops.html: Added.
* platform/mac-wk2/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (285916 => 285917)


--- trunk/LayoutTests/ChangeLog	2021-11-17 06:24:11 UTC (rev 285916)
+++ trunk/LayoutTests/ChangeLog	2021-11-17 06:25:17 UTC (rev 285917)
@@ -1,3 +1,16 @@
+2021-11-16  Simon Fraser  <simon.fra...@apple.com>
+
+        Stop a momentum scroll animation when receiving a momentum end event
+        https://bugs.webkit.org/show_bug.cgi?id=233236
+
+        Reviewed by Tim Horton.
+
+        New test, and skip one that breaks now because we need a fix for webkit.org/b/233234.
+
+        * fast/scrolling/mac/momentum-animator-end-event-stops-expected.txt: Added.
+        * fast/scrolling/mac/momentum-animator-end-event-stops.html: Added.
+        * platform/mac-wk2/TestExpectations:
+
 2021-11-16  Sihui Liu  <sihui_...@apple.com>
 
         Implement FileSystemFileHandle.getFile()

Added: trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops-expected.txt (0 => 285917)


--- trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops-expected.txt	2021-11-17 06:25:17 UTC (rev 285917)
@@ -0,0 +1,7 @@
+Momentum event reached main thread
+PASS scrollEventCount > 0 is true
+PASS scrollEventCount is scrollEventCountAtMomentumEnded
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops.html (0 => 285917)


--- trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops.html	                        (rev 0)
+++ trunk/LayoutTests/fast/scrolling/mac/momentum-animator-end-event-stops.html	2021-11-17 06:25:17 UTC (rev 285917)
@@ -0,0 +1,119 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ MomentumScrollingAnimatorEnabled=true ] -->
+<html>
+<head>
+    <style>
+        body {
+            height: 2000px;
+            width: 200%;
+        }
+    </style>
+    <script src=""
+    <script src=""
+    <script>
+        var jsTestIsAsync = true;
+        
+        let sawMomentumEvent = false;
+        let sawFingersDown = false;
+        let scrollEventCount = 0;
+        let scrollEventCountAtMomentumEnded = 0;
+        
+        async function testEventSequence()
+        {
+            const events = [
+                {
+                    type : "wheel",
+                    viewX : 100,
+                    viewY : 100,
+                    deltaY : -10, // Note that this delta is currently ignored.
+                    phase : "began"
+                },
+                {
+                    type : "wheel",
+                    deltaY : -50,
+                    phase : "changed"
+                },
+                {
+                    type : "wheel",
+                    phase : "ended"
+                },
+                {
+                    type : "wheel",
+                    deltaY : -60,
+                    momentumPhase : "began"
+                },
+                {
+                    type: "wheel",
+                    viewX : 101, // defeat coalescing
+                    deltaY : -99,
+                    momentumPhase: "changed"
+                },
+                {
+                    type: "wheel",
+                    viewX : 102, // defeat coalescing
+                    deltaY : -80,
+                    momentumPhase: "changed"
+                },
+                {
+                    type: "wheel",
+                    viewX : 101, // defeat coalescing
+                    deltaY : -60,
+                    momentumPhase: "changed"
+                }
+            ];
+
+            await UIHelper.mouseWheelSequence({ events }, { waitForCompletion: false});
+            await UIHelper.waitForCondition(() => { return sawMomentumEvent });
+            shouldBeTrue('scrollEventCount > 0');
+
+            const fingersTapGesture = [
+                {
+                    type : "wheel",
+                    momentumPhase : "ended"
+                }
+            ];
+
+            await UIHelper.mouseWheelSequence({ events: fingersTapGesture }, { waitForCompletion: false});
+            // We can't detect the "ended" via events. so wait for a presentation update to make
+            // sure it got to the main thread.
+            await UIHelper.ensurePresentationUpdate();
+            
+            scrollEventCountAtMomentumEnded = scrollEventCount;
+            await UIHelper.renderingUpdate();
+            await UIHelper.renderingUpdate();
+            
+            // Make sure no more scroll events fire.
+            shouldBe('scrollEventCount', 'scrollEventCountAtMomentumEnded');
+            finishJSTest();
+        }
+
+        async function scrollTest()
+        {
+            await testEventSequence();
+        }
+
+        window.addEventListener('load', () => {
+            window.addEventListener('wheel', (event) => {
+                if (event.deltaY == 99) {
+                    debug('Momentum event reached main thread');
+                    sawMomentumEvent = true;
+                }
+
+                if (event.deltaY == 12) {
+                    debug('Saw the fingers down gesture');
+                    sawFingersDown = true;
+                }
+                // console.log(`wheel ${event.deltaX} ${event.deltaY}`);
+            }, { passive: true });
+
+            window.addEventListener('scroll', (event) => {
+                ++scrollEventCount;
+            });
+            
+            setTimeout(scrollTest, 0);
+        }, false);
+    </script>
+</head>
+<body>
+    <script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/mac-wk2/TestExpectations (285916 => 285917)


--- trunk/LayoutTests/platform/mac-wk2/TestExpectations	2021-11-17 06:24:11 UTC (rev 285916)
+++ trunk/LayoutTests/platform/mac-wk2/TestExpectations	2021-11-17 06:25:17 UTC (rev 285917)
@@ -1562,6 +1562,7 @@
 [ Monterey arm64 ] fast/text/canvas-color-fonts/stroke-gradient-COLR-5.html [ ImageOnlyFailure ]
 
 webkit.org/b/228591 fast/scrolling/mac/programmatic-scroll-overrides-rubberband.html [ Pass Failure ]
+webkit.org/b/233234 fast/scrolling/mac/momentum-animator-in-overflow.html [ Failure ]
 
 webkit.org/b/229156 [ BigSur+ ] webrtc/video-addTrack.html [ Pass Failure ]
 

Modified: trunk/Source/WebCore/ChangeLog (285916 => 285917)


--- trunk/Source/WebCore/ChangeLog	2021-11-17 06:24:11 UTC (rev 285916)
+++ trunk/Source/WebCore/ChangeLog	2021-11-17 06:25:17 UTC (rev 285917)
@@ -1,3 +1,28 @@
+2021-11-16  Simon Fraser  <simon.fra...@apple.com>
+
+        Stop a momentum scroll animation when receiving a momentum end event
+        https://bugs.webkit.org/show_bug.cgi?id=233236
+
+        Reviewed by Tim Horton.
+
+        The stream of momentum events is terminated by an "end" event under two circumstances:
+        1. The gesture finished naturally without interruption.
+        2. The user tapped the trackpad with two fingers.
+
+        Unfortunately we can't tell these apart, so we always have to stop the animation.
+        
+        Sadly this reveals a hole in the testing infrastructure. All the "changed" momentum
+        events in the sequence handed to UIHelper.mouseWheelSequence() are ignored while the
+        animation is running, but the "ended" event stops the animation. So any test without
+        a reasonable number of "changed" events will terminate its animation prematurely.
+        We can't fix this without new testing infrastructure (webkit.org/b/233234).
+
+        Test: fast/scrolling/mac/momentum-animator-end-event-stops.html
+
+        * platform/ScrollingEffectsController.h:
+        * platform/mac/ScrollingEffectsController.mm:
+        (WebCore::ScrollingEffectsController::handleWheelEvent):
+
 2021-11-16  Said Abou-Hallawa  <s...@apple.com>
 
         [GPU Process] Build a postfix _expression_ for applying the FilterEffects of the SVGFilter

Modified: trunk/Source/WebCore/platform/ScrollingEffectsController.h (285916 => 285917)


--- trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-11-17 06:24:11 UTC (rev 285916)
+++ trunk/Source/WebCore/platform/ScrollingEffectsController.h	2021-11-17 06:25:17 UTC (rev 285917)
@@ -263,7 +263,9 @@
     FloatSize m_scrollingVelocityForMomentumAnimation; // Do we need both this, m_scrollingVelocityForScrollSnap and m_momentumVelocity?
     FloatSize m_scrollingVelocityForScrollSnap;
 #if !LOG_DISABLED
+    FloatPoint m_eventDrivenScrollMomentumStartOffset;
     FloatPoint m_eventDrivenScrollOffset;
+    WallTime m_momentumBeganEventTime;
 #endif
 
     bool m_momentumScrollInProgress { false };

Modified: trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm (285916 => 285917)


--- trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-11-17 06:24:11 UTC (rev 285916)
+++ trunk/Source/WebCore/platform/mac/ScrollingEffectsController.mm	2021-11-17 06:25:17 UTC (rev 285917)
@@ -180,6 +180,24 @@
         return true;
     }
 
+#if !LOG_DISABLED
+    if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Began)
+        m_momentumBeganEventTime = wheelEvent.timestamp();
+#endif
+
+    if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Ended && momentumScrollingAnimatorEnabled()) {
+#if !LOG_DISABLED
+        auto timeSinceStart = wheelEvent.timestamp() - m_momentumBeganEventTime;
+        auto distance = m_eventDrivenScrollOffset - m_eventDrivenScrollMomentumStartOffset;
+#endif
+        // FIXME: We can't distinguish between the natural end of a momentum sequence, and a two-finger tap on the trackpad (rdar://85414238),
+        // so we always have to end the animation here.
+        LOG(ScrollAnimations, "Event (%s, %s): stopping event scroll duration %.2fms distance %.2f %.2f",
+            phaseToString(wheelEvent.phase()), phaseToString(wheelEvent.momentumPhase()), timeSinceStart.milliseconds(),
+            fabs(distance.width()), fabs(distance.height()));
+        stopAnimatedNonRubberbandingScroll();
+    }
+
     bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhase::None);
     if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_isAnimatingRubberBand)) {
         if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Ended) {
@@ -213,6 +231,7 @@
             startMomentumScrollWithInitialVelocity(m_client.scrollOffset(), m_scrollingVelocityForMomentumAnimation, -wheelEvent.delta(), [](const FloatPoint& targetOffset) { return targetOffset; });
 #if !LOG_DISABLED
             m_eventDrivenScrollOffset = m_client.scrollOffset();
+            m_eventDrivenScrollMomentumStartOffset = m_eventDrivenScrollOffset;
 #endif
         }
     }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to