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

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

<h3>Log Message</h3>
<pre>Cherry-pick <a href="http://trac.webkit.org/projects/webkit/changeset/287641">r287641</a>. rdar://problem/86338105

    Momentum Event Dispatcher: Momentum tails may get truncated if the duration runs longer than the system's
    https://bugs.webkit.org/show_bug.cgi?id=234535
    <rdar://problem/86338105>

    Reviewed by Simon Fraser.

    Source/WebKit:

    Currently, synthetic momentum dispatch is strictly tied to the duration
    of the real platform momentum phase, which has two unfortunate implications:

    - if our phase runs shorter than the platform phase, we'll keep dispatching
      zero-delta events until the platform momentum ends

    - more importantly, if our phase runs longer, it will be abruptly terminated
      when the platform momentum ends

    In practice, our synthetic phase is very close in duration to the system one,
    so the impact is minimal. But, to be safe, disentagle the two durations,
    using a new bit from the platform to determine if the system momentum phase
    was interrupted by the user (e.g. by tapping the trackpad) or naturally,
    and ignoring the ended event in the natural case, allowing synthetic
    events to continue being dispatched.

    * Shared/WebWheelEvent.cpp:
    (WebKit::WebWheelEvent::WebWheelEvent):
    (WebKit::WebWheelEvent::encode const):
    (WebKit::WebWheelEvent::decode):
    * Shared/WebWheelEvent.h:
    (WebKit::WebWheelEvent::momentumEndType const):
    * Shared/WebWheelEventCoalescer.cpp:
    (WebKit::WebWheelEventCoalescer::coalesce):
    Plumb momentumEndType along on WebWheelEvent. Platforms that don't
    provide information about the interruption reason will always say Unknown.

    * Shared/mac/WebEventFactory.mm:
    (WebKit::WebEventFactory::createWebWheelEvent):
    Only bother looking up the CGEvent/IOHIDEvent once, and extract all
    relevant details in one go.

    * WebProcess/WebPage/MomentumEventDispatcher.cpp:
    (WebKit::MomentumEventDispatcher::handleWheelEvent):
    Don't interrupt the synthetic momentum phase if the momentum-ended event
    comes from the natural end of the deceleration instead of an interruption
    (or an unknown reason).

    Keep track of whether we're in the middle of a platform momentum phase
    that we chose (at momentum-begin time) to override. When deciding
    whether to eat an incoming event, take *both* this new bit and whether
    we are currently in the middle of a synthetic phase into account. It
    is important to continue eating incoming events in the case where
    the synthetic phase ended early (so `active` became false) but the
    platform phase continues.

    (WebKit::MomentumEventDispatcher::dispatchSyntheticMomentumEvent):
    (WebKit::MomentumEventDispatcher::didEndMomentumPhase):
    Adjust some logging wording to be more precise.

    (WebKit::MomentumEventDispatcher::setScrollingAccelerationCurve):
    Make this log public so that the curve value is visible in logs.

    (WebKit::MomentumEventDispatcher::consumeDeltaForCurrentTime):
    Make consumeDeltaForCurrentTime inform the client via an optional when
    we are at the end of the delta table.

    (WebKit::MomentumEventDispatcher::displayWasRefreshed):
    Stop the synthetic momentum phase as soon as we run out of deltas.

    (WebKit::MomentumEventDispatcher::computeNextDelta):
    * WebProcess/WebPage/MomentumEventDispatcher.h:

    Source/WTF:

    * wtf/PlatformHave.h:
    Add a HAVE for kIOHIDEventScrollMomentumInterrupted.

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287641 268f45cc-cd09-0410-ab3c-d52691b4dbfc</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari612481branchSourceWTFChangeLog">branches/safari-612.4.8.1-branch/Source/WTF/ChangeLog</a></li>
<li><a href="#branchessafari612481branchSourceWTFwtfPlatformHaveh">branches/safari-612.4.8.1-branch/Source/WTF/wtf/PlatformHave.h</a></li>
<li><a href="#branchessafari612481branchSourceWebCorePALpalspimacIOKitSPIMach">branches/safari-612.4.8.1-branch/Source/WebCore/PAL/pal/spi/mac/IOKitSPIMac.h</a></li>
<li><a href="#branchessafari612481branchSourceWebKitChangeLog">branches/safari-612.4.8.1-branch/Source/WebKit/ChangeLog</a></li>
<li><a href="#branchessafari612481branchSourceWebKitSharedWebWheelEventcpp">branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.cpp</a></li>
<li><a href="#branchessafari612481branchSourceWebKitSharedWebWheelEventh">branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.h</a></li>
<li><a href="#branchessafari612481branchSourceWebKitSharedWebWheelEventCoalescercpp">branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEventCoalescer.cpp</a></li>
<li><a href="#branchessafari612481branchSourceWebKitSharedmacWebEventFactorymm">branches/safari-612.4.8.1-branch/Source/WebKit/Shared/mac/WebEventFactory.mm</a></li>
<li><a href="#branchessafari612481branchSourceWebKitWebProcessWebPageMomentumEventDispatchercpp">branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.cpp</a></li>
<li><a href="#branchessafari612481branchSourceWebKitWebProcessWebPageMomentumEventDispatcherh">branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari612481branchSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WTF/ChangeLog (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WTF/ChangeLog    2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WTF/ChangeLog       2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2022-01-06  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r287641. rdar://problem/86338105
+
+    Momentum Event Dispatcher: Momentum tails may get truncated if the duration runs longer than the system's
+    https://bugs.webkit.org/show_bug.cgi?id=234535
+    <rdar://problem/86338105>
+    
+    Reviewed by Simon Fraser.
+    
+    Source/WebKit:
+    
+    Currently, synthetic momentum dispatch is strictly tied to the duration
+    of the real platform momentum phase, which has two unfortunate implications:
+    
+    - if our phase runs shorter than the platform phase, we'll keep dispatching
+      zero-delta events until the platform momentum ends
+    
+    - more importantly, if our phase runs longer, it will be abruptly terminated
+      when the platform momentum ends
+    
+    In practice, our synthetic phase is very close in duration to the system one,
+    so the impact is minimal. But, to be safe, disentagle the two durations,
+    using a new bit from the platform to determine if the system momentum phase
+    was interrupted by the user (e.g. by tapping the trackpad) or naturally,
+    and ignoring the ended event in the natural case, allowing synthetic
+    events to continue being dispatched.
+    
+    * Shared/WebWheelEvent.cpp:
+    (WebKit::WebWheelEvent::WebWheelEvent):
+    (WebKit::WebWheelEvent::encode const):
+    (WebKit::WebWheelEvent::decode):
+    * Shared/WebWheelEvent.h:
+    (WebKit::WebWheelEvent::momentumEndType const):
+    * Shared/WebWheelEventCoalescer.cpp:
+    (WebKit::WebWheelEventCoalescer::coalesce):
+    Plumb momentumEndType along on WebWheelEvent. Platforms that don't
+    provide information about the interruption reason will always say Unknown.
+    
+    * Shared/mac/WebEventFactory.mm:
+    (WebKit::WebEventFactory::createWebWheelEvent):
+    Only bother looking up the CGEvent/IOHIDEvent once, and extract all
+    relevant details in one go.
+    
+    * WebProcess/WebPage/MomentumEventDispatcher.cpp:
+    (WebKit::MomentumEventDispatcher::handleWheelEvent):
+    Don't interrupt the synthetic momentum phase if the momentum-ended event
+    comes from the natural end of the deceleration instead of an interruption
+    (or an unknown reason).
+    
+    Keep track of whether we're in the middle of a platform momentum phase
+    that we chose (at momentum-begin time) to override. When deciding
+    whether to eat an incoming event, take *both* this new bit and whether
+    we are currently in the middle of a synthetic phase into account. It
+    is important to continue eating incoming events in the case where
+    the synthetic phase ended early (so `active` became false) but the
+    platform phase continues.
+    
+    (WebKit::MomentumEventDispatcher::dispatchSyntheticMomentumEvent):
+    (WebKit::MomentumEventDispatcher::didEndMomentumPhase):
+    Adjust some logging wording to be more precise.
+    
+    (WebKit::MomentumEventDispatcher::setScrollingAccelerationCurve):
+    Make this log public so that the curve value is visible in logs.
+    
+    (WebKit::MomentumEventDispatcher::consumeDeltaForCurrentTime):
+    Make consumeDeltaForCurrentTime inform the client via an optional when
+    we are at the end of the delta table.
+    
+    (WebKit::MomentumEventDispatcher::displayWasRefreshed):
+    Stop the synthetic momentum phase as soon as we run out of deltas.
+    
+    (WebKit::MomentumEventDispatcher::computeNextDelta):
+    * WebProcess/WebPage/MomentumEventDispatcher.h:
+    
+    Source/WTF:
+    
+    * wtf/PlatformHave.h:
+    Add a HAVE for kIOHIDEventScrollMomentumInterrupted.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287641 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-01-05  Tim Horton  <timothy_horton@apple.com>
+
+            Momentum Event Dispatcher: Momentum tails may get truncated if the duration runs longer than the system's
+            https://bugs.webkit.org/show_bug.cgi?id=234535
+            <rdar://problem/86338105>
+
+            Reviewed by Simon Fraser.
+
+            * wtf/PlatformHave.h:
+            Add a HAVE for kIOHIDEventScrollMomentumInterrupted.
+
</ins><span class="cx"> 2021-12-13  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Cherry-pick r286858. rdar://problem/86423741
</span></span></pre></div>
<a id="branchessafari612481branchSourceWTFwtfPlatformHaveh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WTF/wtf/PlatformHave.h (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WTF/wtf/PlatformHave.h   2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WTF/wtf/PlatformHave.h      2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -1154,3 +1154,7 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> #define HAVE_PUACTIVITYPROGRESSCONTROLLER 1
</span><span class="cx"> #endif
</span><ins>+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 120200
+#define HAVE_PLATFORM_SCROLL_MOMENTUM_INTERRUPTION_REASON 1
+#endif
</ins></span></pre></div>
<a id="branchessafari612481branchSourceWebCorePALpalspimacIOKitSPIMach"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebCore/PAL/pal/spi/mac/IOKitSPIMac.h (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebCore/PAL/pal/spi/mac/IOKitSPIMac.h    2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebCore/PAL/pal/spi/mac/IOKitSPIMac.h       2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -81,7 +81,6 @@
</span><span class="cx">     kIOHIDEventTypeDigitizer = 11,
</span><span class="cx">     kIOHIDEventTypeNavigationSwipe = 16,
</span><span class="cx">     kIOHIDEventTypeForce = 32,
</span><del>-
</del><span class="cx"> };
</span><span class="cx"> typedef uint32_t IOHIDEventType;
</span><span class="cx"> 
</span><span class="lines">@@ -88,6 +87,12 @@
</span><span class="cx"> typedef uint32_t IOHIDEventField;
</span><span class="cx"> typedef uint64_t IOHIDEventSenderID;
</span><span class="cx"> 
</span><ins>+
+enum {
+    kIOHIDEventScrollMomentumInterrupted = (1 << 4),
+};
+typedef uint8_t IOHIDEventScrollMomentumBits;
+
</ins><span class="cx"> #ifdef __LP64__
</span><span class="cx"> typedef double IOHIDFloat;
</span><span class="cx"> #else
</span><span class="lines">@@ -103,6 +108,7 @@
</span><span class="cx"> uint64_t IOHIDEventGetTimeStamp(IOHIDEventRef);
</span><span class="cx"> IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef, IOHIDEventField);
</span><span class="cx"> IOHIDEventSenderID IOHIDEventGetSenderID(IOHIDEventRef);
</span><ins>+IOHIDEventScrollMomentumBits IOHIDEventGetScrollMomentum(IOHIDEventRef);
</ins><span class="cx"> 
</span><span class="cx"> WTF_EXTERN_C_END
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/ChangeLog (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/ChangeLog 2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/ChangeLog    2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -1,3 +1,157 @@
</span><ins>+2022-01-06  Russell Epstein  <repstein@apple.com>
+
+        Cherry-pick r287641. rdar://problem/86338105
+
+    Momentum Event Dispatcher: Momentum tails may get truncated if the duration runs longer than the system's
+    https://bugs.webkit.org/show_bug.cgi?id=234535
+    <rdar://problem/86338105>
+    
+    Reviewed by Simon Fraser.
+    
+    Source/WebKit:
+    
+    Currently, synthetic momentum dispatch is strictly tied to the duration
+    of the real platform momentum phase, which has two unfortunate implications:
+    
+    - if our phase runs shorter than the platform phase, we'll keep dispatching
+      zero-delta events until the platform momentum ends
+    
+    - more importantly, if our phase runs longer, it will be abruptly terminated
+      when the platform momentum ends
+    
+    In practice, our synthetic phase is very close in duration to the system one,
+    so the impact is minimal. But, to be safe, disentagle the two durations,
+    using a new bit from the platform to determine if the system momentum phase
+    was interrupted by the user (e.g. by tapping the trackpad) or naturally,
+    and ignoring the ended event in the natural case, allowing synthetic
+    events to continue being dispatched.
+    
+    * Shared/WebWheelEvent.cpp:
+    (WebKit::WebWheelEvent::WebWheelEvent):
+    (WebKit::WebWheelEvent::encode const):
+    (WebKit::WebWheelEvent::decode):
+    * Shared/WebWheelEvent.h:
+    (WebKit::WebWheelEvent::momentumEndType const):
+    * Shared/WebWheelEventCoalescer.cpp:
+    (WebKit::WebWheelEventCoalescer::coalesce):
+    Plumb momentumEndType along on WebWheelEvent. Platforms that don't
+    provide information about the interruption reason will always say Unknown.
+    
+    * Shared/mac/WebEventFactory.mm:
+    (WebKit::WebEventFactory::createWebWheelEvent):
+    Only bother looking up the CGEvent/IOHIDEvent once, and extract all
+    relevant details in one go.
+    
+    * WebProcess/WebPage/MomentumEventDispatcher.cpp:
+    (WebKit::MomentumEventDispatcher::handleWheelEvent):
+    Don't interrupt the synthetic momentum phase if the momentum-ended event
+    comes from the natural end of the deceleration instead of an interruption
+    (or an unknown reason).
+    
+    Keep track of whether we're in the middle of a platform momentum phase
+    that we chose (at momentum-begin time) to override. When deciding
+    whether to eat an incoming event, take *both* this new bit and whether
+    we are currently in the middle of a synthetic phase into account. It
+    is important to continue eating incoming events in the case where
+    the synthetic phase ended early (so `active` became false) but the
+    platform phase continues.
+    
+    (WebKit::MomentumEventDispatcher::dispatchSyntheticMomentumEvent):
+    (WebKit::MomentumEventDispatcher::didEndMomentumPhase):
+    Adjust some logging wording to be more precise.
+    
+    (WebKit::MomentumEventDispatcher::setScrollingAccelerationCurve):
+    Make this log public so that the curve value is visible in logs.
+    
+    (WebKit::MomentumEventDispatcher::consumeDeltaForCurrentTime):
+    Make consumeDeltaForCurrentTime inform the client via an optional when
+    we are at the end of the delta table.
+    
+    (WebKit::MomentumEventDispatcher::displayWasRefreshed):
+    Stop the synthetic momentum phase as soon as we run out of deltas.
+    
+    (WebKit::MomentumEventDispatcher::computeNextDelta):
+    * WebProcess/WebPage/MomentumEventDispatcher.h:
+    
+    Source/WTF:
+    
+    * wtf/PlatformHave.h:
+    Add a HAVE for kIOHIDEventScrollMomentumInterrupted.
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@287641 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2022-01-05  Tim Horton  <timothy_horton@apple.com>
+
+            Momentum Event Dispatcher: Momentum tails may get truncated if the duration runs longer than the system's
+            https://bugs.webkit.org/show_bug.cgi?id=234535
+            <rdar://problem/86338105>
+
+            Reviewed by Simon Fraser.
+
+            Currently, synthetic momentum dispatch is strictly tied to the duration
+            of the real platform momentum phase, which has two unfortunate implications:
+
+            - if our phase runs shorter than the platform phase, we'll keep dispatching
+              zero-delta events until the platform momentum ends
+
+            - more importantly, if our phase runs longer, it will be abruptly terminated
+              when the platform momentum ends
+
+            In practice, our synthetic phase is very close in duration to the system one,
+            so the impact is minimal. But, to be safe, disentagle the two durations,
+            using a new bit from the platform to determine if the system momentum phase
+            was interrupted by the user (e.g. by tapping the trackpad) or naturally,
+            and ignoring the ended event in the natural case, allowing synthetic
+            events to continue being dispatched.
+
+            * Shared/WebWheelEvent.cpp:
+            (WebKit::WebWheelEvent::WebWheelEvent):
+            (WebKit::WebWheelEvent::encode const):
+            (WebKit::WebWheelEvent::decode):
+            * Shared/WebWheelEvent.h:
+            (WebKit::WebWheelEvent::momentumEndType const):
+            * Shared/WebWheelEventCoalescer.cpp:
+            (WebKit::WebWheelEventCoalescer::coalesce):
+            Plumb momentumEndType along on WebWheelEvent. Platforms that don't
+            provide information about the interruption reason will always say Unknown.
+
+            * Shared/mac/WebEventFactory.mm:
+            (WebKit::WebEventFactory::createWebWheelEvent):
+            Only bother looking up the CGEvent/IOHIDEvent once, and extract all
+            relevant details in one go.
+
+            * WebProcess/WebPage/MomentumEventDispatcher.cpp:
+            (WebKit::MomentumEventDispatcher::handleWheelEvent):
+            Don't interrupt the synthetic momentum phase if the momentum-ended event
+            comes from the natural end of the deceleration instead of an interruption
+            (or an unknown reason).
+
+            Keep track of whether we're in the middle of a platform momentum phase
+            that we chose (at momentum-begin time) to override. When deciding
+            whether to eat an incoming event, take *both* this new bit and whether
+            we are currently in the middle of a synthetic phase into account. It
+            is important to continue eating incoming events in the case where
+            the synthetic phase ended early (so `active` became false) but the
+            platform phase continues.
+
+            (WebKit::MomentumEventDispatcher::dispatchSyntheticMomentumEvent):
+            (WebKit::MomentumEventDispatcher::didEndMomentumPhase):
+            Adjust some logging wording to be more precise.
+
+            (WebKit::MomentumEventDispatcher::setScrollingAccelerationCurve):
+            Make this log public so that the curve value is visible in logs.
+
+            (WebKit::MomentumEventDispatcher::consumeDeltaForCurrentTime):
+            Make consumeDeltaForCurrentTime inform the client via an optional when
+            we are at the end of the delta table.
+
+            (WebKit::MomentumEventDispatcher::displayWasRefreshed):
+            Stop the synthetic momentum phase as soon as we run out of deltas.
+
+            (WebKit::MomentumEventDispatcher::computeNextDelta):
+            * WebProcess/WebPage/MomentumEventDispatcher.h:
+
</ins><span class="cx"> 2021-12-22  Alan Coon  <alancoon@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Cherry-pick r287366. rdar://problem/84379650
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitSharedWebWheelEventcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.cpp (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.cpp  2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.cpp     2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><del>-WebWheelEvent::WebWheelEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, const FloatSize& delta, const FloatSize& wheelTicks, Granularity granularity, bool directionInvertedFromDevice, Phase phase, Phase momentumPhase, bool hasPreciseScrollingDeltas, uint32_t scrollCount, const WebCore::FloatSize& unacceleratedScrollingDelta, OptionSet<Modifier> modifiers, WallTime timestamp, WallTime ioHIDEventTimestamp, std::optional<WebCore::FloatSize> rawPlatformDelta)
</del><ins>+WebWheelEvent::WebWheelEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, const FloatSize& delta, const FloatSize& wheelTicks, Granularity granularity, bool directionInvertedFromDevice, Phase phase, Phase momentumPhase, bool hasPreciseScrollingDeltas, uint32_t scrollCount, const WebCore::FloatSize& unacceleratedScrollingDelta, OptionSet<Modifier> modifiers, WallTime timestamp, WallTime ioHIDEventTimestamp, std::optional<WebCore::FloatSize> rawPlatformDelta, MomentumEndType momentumEndType)
</ins><span class="cx">     : WebEvent(type, modifiers, timestamp)
</span><span class="cx">     , m_position(position)
</span><span class="cx">     , m_globalPosition(globalPosition)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     , m_granularity(granularity)
</span><span class="cx">     , m_phase(phase)
</span><span class="cx">     , m_momentumPhase(momentumPhase)
</span><ins>+    , m_momentumEndType(momentumEndType)
</ins><span class="cx">     , m_directionInvertedFromDevice(directionInvertedFromDevice)
</span><span class="cx">     , m_hasPreciseScrollingDeltas(hasPreciseScrollingDeltas)
</span><span class="cx">     , m_ioHIDEventTimestamp(ioHIDEventTimestamp)
</span><span class="lines">@@ -87,6 +88,7 @@
</span><span class="cx">     encoder << m_delta;
</span><span class="cx">     encoder << m_wheelTicks;
</span><span class="cx">     encoder << m_granularity;
</span><ins>+    encoder << m_momentumEndType;
</ins><span class="cx">     encoder << m_directionInvertedFromDevice;
</span><span class="cx"> #if PLATFORM(COCOA) || PLATFORM(GTK) || USE(LIBWPE)
</span><span class="cx">     encoder << m_phase;
</span><span class="lines">@@ -115,6 +117,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (!decoder.decode(t.m_granularity))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(t.m_momentumEndType))
+        return false;
</ins><span class="cx">     if (!decoder.decode(t.m_directionInvertedFromDevice))
</span><span class="cx">         return false;
</span><span class="cx"> #if PLATFORM(COCOA) || PLATFORM(GTK) || USE(LIBWPE)
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitSharedWebWheelEventh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.h (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.h    2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEvent.h       2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include "WebEvent.h"
</span><span class="cx"> #include <WebCore/FloatSize.h>
</span><span class="cx"> #include <WebCore/IntPoint.h>
</span><ins>+#include <wtf/EnumTraits.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="lines">@@ -49,11 +50,17 @@
</span><span class="cx">         PhaseMayBegin    = 1 << 5,
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    enum class MomentumEndType : uint8_t {
+        Unknown,
+        Interrupted,
+        Natural,
+    };
+
</ins><span class="cx">     WebWheelEvent() = default;
</span><span class="cx"> 
</span><span class="cx">     WebWheelEvent(Type, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, Granularity, OptionSet<Modifier>, WallTime timestamp);
</span><span class="cx"> #if PLATFORM(COCOA)
</span><del>-    WebWheelEvent(Type, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, Granularity, bool directionInvertedFromDevice, Phase, Phase momentumPhase, bool hasPreciseScrollingDeltas, uint32_t scrollCount, const WebCore::FloatSize& unacceleratedScrollingDelta, OptionSet<Modifier>, WallTime timestamp, WallTime ioHIDEventTimestamp, std::optional<WebCore::FloatSize> rawPlatformDelta);
</del><ins>+    WebWheelEvent(Type, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, Granularity, bool directionInvertedFromDevice, Phase, Phase momentumPhase, bool hasPreciseScrollingDeltas, uint32_t scrollCount, const WebCore::FloatSize& unacceleratedScrollingDelta, OptionSet<Modifier>, WallTime timestamp, WallTime ioHIDEventTimestamp, std::optional<WebCore::FloatSize> rawPlatformDelta, MomentumEndType);
</ins><span class="cx"> #elif PLATFORM(GTK) || USE(LIBWPE)
</span><span class="cx">     WebWheelEvent(Type, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, Phase, Phase momentumPhase, Granularity, bool hasPreciseScrollingDeltas, OptionSet<Modifier>, WallTime timestamp);
</span><span class="cx"> #endif
</span><span class="lines">@@ -66,6 +73,7 @@
</span><span class="cx">     bool directionInvertedFromDevice() const { return m_directionInvertedFromDevice; }
</span><span class="cx">     Phase phase() const { return static_cast<Phase>(m_phase); }
</span><span class="cx">     Phase momentumPhase() const { return static_cast<Phase>(m_momentumPhase); }
</span><ins>+    MomentumEndType momentumEndType() const { return m_momentumEndType; }
</ins><span class="cx"> #if PLATFORM(COCOA) || PLATFORM(GTK) || USE(LIBWPE)
</span><span class="cx">     bool hasPreciseScrollingDeltas() const { return m_hasPreciseScrollingDeltas; }
</span><span class="cx"> #endif
</span><span class="lines">@@ -90,6 +98,7 @@
</span><span class="cx">     uint32_t m_phase { Phase::PhaseNone };
</span><span class="cx">     uint32_t m_momentumPhase { Phase::PhaseNone };
</span><span class="cx"> 
</span><ins>+    MomentumEndType m_momentumEndType { MomentumEndType::Unknown };
</ins><span class="cx">     bool m_directionInvertedFromDevice { false };
</span><span class="cx"> #if PLATFORM(COCOA) || PLATFORM(GTK) || USE(LIBWPE)
</span><span class="cx">     bool m_hasPreciseScrollingDeltas { false };
</span><span class="lines">@@ -103,3 +112,16 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span><ins>+
+namespace WTF {
+
+template<> struct EnumTraits<WebKit::WebWheelEvent::MomentumEndType> {
+    using values = EnumValues<
+    WebKit::WebWheelEvent::MomentumEndType,
+    WebKit::WebWheelEvent::MomentumEndType::Unknown,
+    WebKit::WebWheelEvent::MomentumEndType::Interrupted,
+    WebKit::WebWheelEvent::MomentumEndType::Natural
+    >;
+};
+
+} // namespace WTF
</ins></span></pre></div>
<a id="branchessafari612481branchSourceWebKitSharedWebWheelEventCoalescercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEventCoalescer.cpp (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEventCoalescer.cpp 2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/Shared/WebWheelEventCoalescer.cpp    2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx">     if (a.rawPlatformDelta() && b.rawPlatformDelta())
</span><span class="cx">         mergedRawPlatformScrollingDelta = a.rawPlatformDelta().value() + b.rawPlatformDelta().value();
</span><span class="cx"> 
</span><del>-    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp(), b.ioHIDEventTimestamp(), mergedRawPlatformScrollingDelta);
</del><ins>+    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp(), b.ioHIDEventTimestamp(), mergedRawPlatformScrollingDelta, b.momentumEndType());
</ins><span class="cx"> #elif PLATFORM(GTK) || USE(LIBWPE)
</span><span class="cx">     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.phase(), b.momentumPhase(), b.granularity(), b.hasPreciseScrollingDeltas(), b.modifiers(), b.timestamp());
</span><span class="cx"> #else
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitSharedmacWebEventFactorymm"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/Shared/mac/WebEventFactory.mm (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/Shared/mac/WebEventFactory.mm     2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/Shared/mac/WebEventFactory.mm        2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -410,37 +410,35 @@
</span><span class="cx"> 
</span><span class="cx">     auto modifiers = modifiersForEvent(event);
</span><span class="cx">     auto timestamp = WebCore::eventTimeStampSince1970(event.timestamp);
</span><del>-
-    auto ioHIDEventTimestamp = [&]() {
</del><ins>+    
+    auto ioHIDEventWallTime = timestamp;
+    std::optional<WebCore::FloatSize> rawPlatformDelta;
+    auto momentumEndType = WebWheelEvent::MomentumEndType::Unknown;
+    
+    ([&] {
</ins><span class="cx">         auto cgEvent = event.CGEvent;
</span><span class="cx">         if (!cgEvent)
</span><del>-            return event.timestamp;
</del><ins>+            return;
</ins><span class="cx"> 
</span><span class="cx">         auto ioHIDEvent = adoptCF(CGEventCopyIOHIDEvent(cgEvent));
</span><span class="cx">         if (!ioHIDEvent)
</span><del>-            return event.timestamp;
</del><ins>+            return;
</ins><span class="cx"> 
</span><span class="cx">         auto ioHIDEventTimestamp = IOHIDEventGetTimeStamp(ioHIDEvent.get()); // IOEventRef timestamp is mach_absolute_time units.
</span><del>-        return MonotonicTime::fromMachAbsoluteTime(ioHIDEventTimestamp).secondsSinceEpoch().seconds();
-    }();
-
-    auto rawPlatformDelta = [&]() -> std::optional<WebCore::FloatSize> {
-        auto cgEvent = event.CGEvent;
-        if (!cgEvent)
-            return std::nullopt;
-
-        auto ioHIDEvent = adoptCF(CGEventCopyIOHIDEvent(cgEvent));
-        if (!ioHIDEvent)
-            return std::nullopt;
</del><ins>+        auto monotonicIOHIDEventTimestamp = MonotonicTime::fromMachAbsoluteTime(ioHIDEventTimestamp).secondsSinceEpoch().seconds();
+        ioHIDEventWallTime = WebCore::eventTimeStampSince1970(monotonicIOHIDEventTimestamp);
</ins><span class="cx">         
</span><del>-        return { WebCore::FloatSize(-IOHIDEventGetFloatValue(ioHIDEvent.get(), kIOHIDEventFieldScrollX), -IOHIDEventGetFloatValue(ioHIDEvent.get(), kIOHIDEventFieldScrollY)) };
-    }();
</del><ins>+        rawPlatformDelta = { WebCore::FloatSize(-IOHIDEventGetFloatValue(ioHIDEvent.get(), kIOHIDEventFieldScrollX), -IOHIDEventGetFloatValue(ioHIDEvent.get(), kIOHIDEventFieldScrollY)) };
</ins><span class="cx"> 
</span><del>-    auto ioHIDEventWallTime = WebCore::eventTimeStampSince1970(ioHIDEventTimestamp);
</del><ins>+#if HAVE(PLATFORM_SCROLL_MOMENTUM_INTERRUPTION_REASON)
+        bool momentumWasInterrupted = IOHIDEventGetScrollMomentum(ioHIDEvent.get()) & kIOHIDEventScrollMomentumInterrupted;
+        momentumEndType = momentumWasInterrupted ? WebWheelEvent::MomentumEndType::Interrupted : WebWheelEvent::MomentumEndType::Natural;
+#endif
+    })();
</ins><span class="cx"> 
</span><span class="cx">     return WebWheelEvent(WebEvent::Wheel, WebCore::IntPoint(position), WebCore::IntPoint(globalPosition), WebCore::FloatSize(deltaX, deltaY), WebCore::FloatSize(wheelTicksX, wheelTicksY),
</span><span class="cx">         granularity, directionInvertedFromDevice, phase, momentumPhase, hasPreciseScrollingDeltas,
</span><del>-        scrollCount, unacceleratedScrollingDelta, modifiers, timestamp, ioHIDEventWallTime, rawPlatformDelta);
</del><ins>+        scrollCount, unacceleratedScrollingDelta, modifiers, timestamp, ioHIDEventWallTime, rawPlatformDelta, momentumEndType);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(NSEvent *event, bool handledByInputMethod, bool replacesSoftSpace, const Vector<WebCore::KeypressCommand>& commands)
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitWebProcessWebPageMomentumEventDispatchercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.cpp (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.cpp    2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.cpp       2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -87,8 +87,23 @@
</span><span class="cx">         // momentumPhase == PhaseEnded that interrupts.
</span><span class="cx">         bool eventShouldInterruptGesture = !isMomentumEvent || event.momentumPhase() != WebWheelEvent::PhaseChanged;
</span><span class="cx"> 
</span><del>-        if (pageIdentifierChanged || eventShouldInterruptGesture)
</del><ins>+        if (event.momentumPhase() == WebWheelEvent::PhaseEnded) {
+#if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
+            RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher saw momentum ended phase, interrupted=%d", static_cast<int>(event.momentumEndType()));
+#endif
+
+            // Ignore momentumPhase == PhaseEnded if it was due to the natural
+            // end of the animation (as opposed to interruption by placing fingers
+            // on the trackpad), so that our momentum is not cut short if the
+            // deceleration runs longer than the system curve.
+            if (event.momentumEndType() == WebWheelEvent::MomentumEndType::Natural)
+                eventShouldInterruptGesture = false;
+        }
+
+        if (pageIdentifierChanged || eventShouldInterruptGesture) {
+            RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher interrupting synthetic momentum phase");
</ins><span class="cx">             didEndMomentumPhase();
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (event.phase() == WebWheelEvent::PhaseBegan || event.phase() == WebWheelEvent::PhaseChanged) {
</span><span class="lines">@@ -100,18 +115,26 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (eventShouldStartSyntheticMomentumPhase(pageIdentifier, event))
</del><ins>+    if (eventShouldStartSyntheticMomentumPhase(pageIdentifier, event)) {
</ins><span class="cx">         didStartMomentumPhase(pageIdentifier, event);
</span><ins>+        m_isInOverriddenPlatformMomentumGesture = true;
+    }
</ins><span class="cx"> 
</span><del>-    bool isMomentumEventDuringSyntheticGesture = isMomentumEvent && m_currentGesture.active;
</del><ins>+    // Consume any incoming momentum events while we're generating a synthetic
+    // momentum gesture *or* a platform momentum phase that was overridden
+    // is still running after we finished the synthetic gesture.
+    bool shouldIgnoreIncomingPlatformEvent = isMomentumEvent && (m_isInOverriddenPlatformMomentumGesture || m_currentGesture.active);
</ins><span class="cx"> 
</span><ins>+    if (event.momentumPhase() == WebWheelEvent::PhaseEnded)
+        m_isInOverriddenPlatformMomentumGesture = false;
+
</ins><span class="cx"> #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
</span><del>-    if (isMomentumEventDuringSyntheticGesture)
</del><ins>+    if (shouldIgnoreIncomingPlatformEvent)
</ins><span class="cx">         m_currentGesture.accumulatedEventOffset += event.delta();
</span><span class="cx"> 
</span><span class="cx">     auto combinedPhase = (event.phase() << 8) | (event.momentumPhase());
</span><span class="cx">     m_currentLogState.totalEventOffset += event.delta().height();
</span><del>-    if (!isMomentumEventDuringSyntheticGesture) {
</del><ins>+    if (!shouldIgnoreIncomingPlatformEvent) {
</ins><span class="cx">         // Log events that we don't block to the generated offsets log as well,
</span><span class="cx">         // even though we didn't technically generate them, just passed them through.
</span><span class="cx">         m_currentLogState.totalGeneratedOffset += event.delta().height();
</span><span class="lines">@@ -121,8 +144,7 @@
</span><span class="cx">     
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    // Consume any normal momentum events while we're inside a synthetic momentum gesture.
-    return isMomentumEventDuringSyntheticGesture;
</del><ins>+    return shouldIgnoreIncomingPlatformEvent;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static float appKitScrollMultiplierForEvent(const WebWheelEvent& event)
</span><span class="lines">@@ -170,7 +192,8 @@
</span><span class="cx">         m_lastIncomingEvent->modifiers(),
</span><span class="cx">         time,
</span><span class="cx">         time,
</span><del>-        { });
</del><ins>+        { },
+        WebWheelEvent::MomentumEndType::Unknown);
</ins><span class="cx">     m_dispatcher.internalWheelEvent(m_currentGesture.pageIdentifier, syntheticEvent, m_lastRubberBandableEdges, EventDispatcher::WheelEventOrigin::MomentumEventDispatcher);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
</span><span class="lines">@@ -223,7 +246,7 @@
</span><span class="cx">     dispatchSyntheticMomentumEvent(WebWheelEvent::PhaseEnded, { });
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
</span><del>-    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher saw momentum end phase with total offset %.1f %.1f, duration %f (event offset would have been %.1f %.1f) (tail index %d of %zu)", m_currentGesture.currentOffset.width(), m_currentGesture.currentOffset.height(), (MonotonicTime::now() - m_currentGesture.startTime).seconds(), m_currentGesture.accumulatedEventOffset.width(), m_currentGesture.accumulatedEventOffset.height(), m_currentGesture.currentTailDeltaIndex, m_currentGesture.tailDeltaTable.size());
</del><ins>+    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher ending synthetic momentum phase with total offset %.1f %.1f, duration %f (event offset would have been %.1f %.1f) (tail index %d of %zu)", m_currentGesture.currentOffset.width(), m_currentGesture.currentOffset.height(), (MonotonicTime::now() - m_currentGesture.startTime).seconds(), m_currentGesture.accumulatedEventOffset.width(), m_currentGesture.accumulatedEventOffset.height(), m_currentGesture.currentTailDeltaIndex, m_currentGesture.tailDeltaTable.size());
</ins><span class="cx">     m_dispatcher.queue().dispatchAfter(1_s, [this] {
</span><span class="cx">         flushLog();
</span><span class="cx">     });
</span><span class="lines">@@ -242,7 +265,7 @@
</span><span class="cx"> #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
</span><span class="cx">     WTF::TextStream stream(WTF::TextStream::LineMode::SingleLine);
</span><span class="cx">     stream << curve;
</span><del>-    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher set curve %s", stream.release().utf8().data());
</del><ins>+    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher set curve %{public}s", stream.release().utf8().data());
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -299,7 +322,7 @@
</span><span class="cx">         startDisplayLink();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WebCore::FloatSize MomentumEventDispatcher::consumeDeltaForCurrentTime()
</del><ins>+std::optional<WebCore::FloatSize> MomentumEventDispatcher::consumeDeltaForCurrentTime()
</ins><span class="cx"> {
</span><span class="cx">     WebCore::FloatSize delta;
</span><span class="cx"> 
</span><span class="lines">@@ -311,7 +334,7 @@
</span><span class="cx">         if (m_currentGesture.currentTailDeltaIndex < m_currentGesture.tailDeltaTable.size())
</span><span class="cx">             delta = -m_currentGesture.tailDeltaTable[m_currentGesture.currentTailDeltaIndex++];
</span><span class="cx">         else
</span><del>-            delta = { };
</del><ins>+            return std::nullopt;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_currentGesture.currentOffset += delta;
</span><span class="lines">@@ -331,7 +354,16 @@
</span><span class="cx">     if (!displayProperties || displayID != displayProperties->displayID)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    dispatchSyntheticMomentumEvent(WebWheelEvent::PhaseChanged, consumeDeltaForCurrentTime());
</del><ins>+    auto delta = consumeDeltaForCurrentTime();
+    if (!delta) {
+#if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
+        RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher completed synthetic momentum phase");
+#endif
+        didEndMomentumPhase();
+        return;
+    }
+
+    dispatchSyntheticMomentumEvent(WebWheelEvent::PhaseChanged, *delta);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MomentumEventDispatcher::didReceiveScrollEventWithInterval(WebCore::FloatSize size, Seconds frameInterval)
</span></span></pre></div>
<a id="branchessafari612481branchSourceWebKitWebProcessWebPageMomentumEventDispatcherh"></a>
<div class="modfile"><h4>Modified: branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.h (287701 => 287702)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.h      2022-01-06 19:38:37 UTC (rev 287701)
+++ branches/safari-612.4.8.1-branch/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.h 2022-01-06 19:41:31 UTC (rev 287702)
</span><span class="lines">@@ -86,7 +86,7 @@
</span><span class="cx">     void equalizeTailGaps();
</span><span class="cx"> 
</span><span class="cx">     // Once consumed, this delta *must* be dispatched in an event.
</span><del>-    WebCore::FloatSize consumeDeltaForCurrentTime();
</del><ins>+    std::optional<WebCore::FloatSize> consumeDeltaForCurrentTime();
</ins><span class="cx"> 
</span><span class="cx">     WebCore::FloatSize offsetAtTime(Seconds);
</span><span class="cx">     std::pair<WebCore::FloatSize, WebCore::FloatSize> computeNextDelta(WebCore::FloatSize currentUnacceleratedDelta);
</span><span class="lines">@@ -125,6 +125,7 @@
</span><span class="cx">     std::optional<WallTime> m_lastScrollTimestamp;
</span><span class="cx">     std::optional<WebWheelEvent> m_lastIncomingEvent;
</span><span class="cx">     WebCore::RectEdges<bool> m_lastRubberBandableEdges;
</span><ins>+    bool m_isInOverriddenPlatformMomentumGesture { false };
</ins><span class="cx"> 
</span><span class="cx">     struct {
</span><span class="cx">         bool active { false };
</span></span></pre>
</div>
</div>

</body>
</html>