Title: [268287] trunk/Source
Revision
268287
Author
[email protected]
Date
2020-10-09 13:56:25 -0700 (Fri, 09 Oct 2020)

Log Message

Refactor wheel event coalescing into its own class
https://bugs.webkit.org/show_bug.cgi?id=217523

Reviewed by Sam Weinig.
Source/WebCore:

Export the TextStream outputter.

* platform/PlatformWheelEvent.h:

Source/WebKit:

WebPageProxy had some confusing code for coalescing wheel events, first added in r116466.
To prepare this code for partial re-use in another place, factor it into its own class, WebWheelEventCoalescer.

WebWheelEventCoalescer holds a queue of pending NativeWebWheelEvents, and a queue of sequences of
NativeWebWheelEvents, where each sequence has been coalesced into a single WebWeelEvent which was
sent to the Web Process.

When the UI process receives a message back from the Web Process, it calls takeOldestEventBeingProcessed()
which removes the first sequence from m_eventsBeingProcessed. This code has to track NativeWebWheelEvents, because
we need to dig the NSEvent out of the NativeWebWheelEvent at this stage.

* Platform/Logging.h: Add a WheelEvents log channel.
* Shared/NativeWebWheelEvent.h:
* Shared/WebWheelEventCoalescer.cpp: Added.
(WebKit::operator<<):
(WebKit::WebWheelEventCoalescer::canCoalesce):
(WebKit::WebWheelEventCoalescer::coalesce):
(WebKit::WebWheelEventCoalescer::shouldDispatchEventNow const):
(WebKit::WebWheelEventCoalescer::nextEventToDispatch):
(WebKit::WebWheelEventCoalescer::shouldDispatchEvent):
(WebKit::WebWheelEventCoalescer::takeOldestEventBeingProcessed):
(WebKit::WebWheelEventCoalescer::clear):
* Shared/WebWheelEventCoalescer.h: Added.
(WebKit::WebWheelEventCoalescer::hasEventsBeingProcessed const):
* Sources.txt:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handleWheelEvent):
(WebKit::WebPageProxy::wheelEventCoalescer):
(WebKit::WebPageProxy::didReceiveEvent):
(WebKit::WebPageProxy::resetStateAfterProcessExited):
(WebKit::canCoalesce): Deleted.
(WebKit::coalesce): Deleted.
(WebKit::coalescedWheelEvent): Deleted.
(WebKit::WebPageProxy::processNextQueuedWheelEvent): Deleted.
(WebKit::WebPageProxy::shouldProcessWheelEventNow const): Deleted.
* UIProcess/WebPageProxy.h:
* WebKit.xcodeproj/project.pbxproj:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (268286 => 268287)


--- trunk/Source/WebCore/ChangeLog	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebCore/ChangeLog	2020-10-09 20:56:25 UTC (rev 268287)
@@ -1,3 +1,14 @@
+2020-10-09  Simon Fraser  <[email protected]>
+
+        Refactor wheel event coalescing into its own class
+        https://bugs.webkit.org/show_bug.cgi?id=217523
+
+        Reviewed by Sam Weinig.
+
+        Export the TextStream outputter.
+
+        * platform/PlatformWheelEvent.h:
+
 2020-10-09  Zalan Bujtas  <[email protected]>
 
         [LFC][Integration] Overflow clip blocks visual overflow

Modified: trunk/Source/WebCore/platform/PlatformWheelEvent.h (268286 => 268287)


--- trunk/Source/WebCore/platform/PlatformWheelEvent.h	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebCore/platform/PlatformWheelEvent.h	2020-10-09 20:56:25 UTC (rev 268287)
@@ -270,7 +270,7 @@
 
 #endif // ENABLE(KINETIC_SCROLLING)
 
-WTF::TextStream& operator<<(WTF::TextStream&, const PlatformWheelEvent&);
-WTF::TextStream& operator<<(WTF::TextStream&, WheelEventProcessingSteps);
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const PlatformWheelEvent&);
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, WheelEventProcessingSteps);
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (268286 => 268287)


--- trunk/Source/WebKit/ChangeLog	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/ChangeLog	2020-10-09 20:56:25 UTC (rev 268287)
@@ -1,3 +1,48 @@
+2020-10-09  Simon Fraser  <[email protected]>
+
+        Refactor wheel event coalescing into its own class
+        https://bugs.webkit.org/show_bug.cgi?id=217523
+
+        Reviewed by Sam Weinig.
+        
+        WebPageProxy had some confusing code for coalescing wheel events, first added in r116466.
+        To prepare this code for partial re-use in another place, factor it into its own class, WebWheelEventCoalescer.
+
+        WebWheelEventCoalescer holds a queue of pending NativeWebWheelEvents, and a queue of sequences of
+        NativeWebWheelEvents, where each sequence has been coalesced into a single WebWeelEvent which was
+        sent to the Web Process.
+
+        When the UI process receives a message back from the Web Process, it calls takeOldestEventBeingProcessed()
+        which removes the first sequence from m_eventsBeingProcessed. This code has to track NativeWebWheelEvents, because
+        we need to dig the NSEvent out of the NativeWebWheelEvent at this stage.
+
+        * Platform/Logging.h: Add a WheelEvents log channel.
+        * Shared/NativeWebWheelEvent.h:
+        * Shared/WebWheelEventCoalescer.cpp: Added.
+        (WebKit::operator<<):
+        (WebKit::WebWheelEventCoalescer::canCoalesce):
+        (WebKit::WebWheelEventCoalescer::coalesce):
+        (WebKit::WebWheelEventCoalescer::shouldDispatchEventNow const):
+        (WebKit::WebWheelEventCoalescer::nextEventToDispatch):
+        (WebKit::WebWheelEventCoalescer::shouldDispatchEvent):
+        (WebKit::WebWheelEventCoalescer::takeOldestEventBeingProcessed):
+        (WebKit::WebWheelEventCoalescer::clear):
+        * Shared/WebWheelEventCoalescer.h: Added.
+        (WebKit::WebWheelEventCoalescer::hasEventsBeingProcessed const):
+        * Sources.txt:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::handleWheelEvent):
+        (WebKit::WebPageProxy::wheelEventCoalescer):
+        (WebKit::WebPageProxy::didReceiveEvent):
+        (WebKit::WebPageProxy::resetStateAfterProcessExited):
+        (WebKit::canCoalesce): Deleted.
+        (WebKit::coalesce): Deleted.
+        (WebKit::coalescedWheelEvent): Deleted.
+        (WebKit::WebPageProxy::processNextQueuedWheelEvent): Deleted.
+        (WebKit::WebPageProxy::shouldProcessWheelEventNow const): Deleted.
+        * UIProcess/WebPageProxy.h:
+        * WebKit.xcodeproj/project.pbxproj:
+
 2020-10-09  Per Arne Vollan  <[email protected]>
 
         [GPU Process] Use correct GPU runtime settings when creating the dynamic IOKit sandbox extensions for the WebContent process

Modified: trunk/Source/WebKit/Platform/Logging.h (268286 => 268287)


--- trunk/Source/WebKit/Platform/Logging.h	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/Platform/Logging.h	2020-10-09 20:56:25 UTC (rev 268287)
@@ -100,6 +100,7 @@
     M(VisibleRects) \
     M(WebGL) \
     M(WebRTC) \
+    M(WheelEvents) \
 
 WEBKIT2_LOG_CHANNELS(DECLARE_LOG_CHANNEL)
 

Modified: trunk/Source/WebKit/Shared/NativeWebWheelEvent.h (268286 => 268287)


--- trunk/Source/WebKit/Shared/NativeWebWheelEvent.h	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/Shared/NativeWebWheelEvent.h	2020-10-09 20:56:25 UTC (rev 268287)
@@ -30,6 +30,7 @@
 #if USE(APPKIT)
 #include <wtf/RetainPtr.h>
 OBJC_CLASS NSView;
+OBJC_CLASS NSEvent;
 #endif
 
 #if PLATFORM(GTK)

Added: trunk/Source/WebKit/Shared/WebWheelEventCoalescer.cpp (0 => 268287)


--- trunk/Source/WebKit/Shared/WebWheelEventCoalescer.cpp	                        (rev 0)
+++ trunk/Source/WebKit/Shared/WebWheelEventCoalescer.cpp	2020-10-09 20:56:25 UTC (rev 268287)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebWheelEventCoalescer.h"
+
+#include "Logging.h"
+#include "NativeWebWheelEvent.h"
+#include "WebEventConversion.h"
+#include <wtf/text/TextStream.h>
+
+namespace WebKit {
+
+// Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
+constexpr unsigned wheelEventQueueSizeThreshold = 10;
+
+#if !LOG_DISABLED
+static WTF::TextStream& operator<<(WTF::TextStream& ts, const WebWheelEvent& wheelEvent)
+{
+    ts << platform(wheelEvent);
+    return ts;
+}
+#endif
+
+bool WebWheelEventCoalescer::canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
+{
+    if (a.position() != b.position())
+        return false;
+    if (a.globalPosition() != b.globalPosition())
+        return false;
+    if (a.modifiers() != b.modifiers())
+        return false;
+    if (a.granularity() != b.granularity())
+        return false;
+#if PLATFORM(COCOA)
+    if (a.phase() != b.phase())
+        return false;
+    if (a.momentumPhase() != b.momentumPhase())
+        return false;
+    if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
+        return false;
+#endif
+
+    return true;
+}
+
+WebWheelEvent WebWheelEventCoalescer::coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
+{
+    ASSERT(canCoalesce(a, b));
+
+    auto mergedDelta = a.delta() + b.delta();
+    auto mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
+
+#if PLATFORM(COCOA)
+    auto mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
+
+    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());
+#else
+    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
+#endif
+}
+
+bool WebWheelEventCoalescer::shouldDispatchEventNow(const WebWheelEvent& event) const
+{
+#if PLATFORM(GTK)
+    // Don't queue events representing a non-trivial scrolling phase to
+    // avoid having them trapped in the queue, potentially preventing a
+    // scrolling session to beginning or end correctly.
+    // This is only needed by platforms whose WebWheelEvent has this phase
+    // information (Cocoa and GTK+) but Cocoa was fine without it.
+    if (event.phase() == WebWheelEvent::Phase::PhaseNone
+        || event.phase() == WebWheelEvent::Phase::PhaseChanged
+        || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
+        || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
+        return true;
+#else
+    UNUSED_PARAM(event);
+#endif
+
+    return m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold;
+}
+
+Optional<WebWheelEvent> WebWheelEventCoalescer::nextEventToDispatch()
+{
+    if (m_wheelEventQueue.isEmpty())
+        return WTF::nullopt;
+
+    auto coalescedEvent = m_wheelEventQueue.takeFirst();
+
+    auto coalescedSequence = makeUnique<CoalescedEventSequence>();
+    coalescedSequence->append(coalescedEvent);
+
+    WebWheelEvent coalescedWebEvent = coalescedEvent;
+
+    while (!m_wheelEventQueue.isEmpty() && canCoalesce(coalescedWebEvent, m_wheelEventQueue.first())) {
+        auto firstEvent = m_wheelEventQueue.takeFirst();
+        coalescedSequence->append(firstEvent);
+        coalescedWebEvent = coalesce(coalescedWebEvent, firstEvent);
+    }
+
+#if !LOG_DISABLED
+    if (coalescedSequence->size() > 1)
+        LOG_WITH_STREAM(WheelEvents, stream << "WebWheelEventCoalescer::wheelEventWithCoalescing coalsesced " << *coalescedSequence << " into " << coalescedWebEvent);
+#endif
+
+    m_eventsBeingProcessed.append(WTFMove(coalescedSequence));
+    return coalescedWebEvent;
+}
+
+bool WebWheelEventCoalescer::shouldDispatchEvent(const NativeWebWheelEvent& event)
+{
+    LOG_WITH_STREAM(WheelEvents, stream << "WebWheelEventCoalescer::shouldDispatchEvent " << event << " (" << m_wheelEventQueue.size() << " events in the queue, " << m_eventsBeingProcessed.size() << " event sequences being processed)");
+
+    m_wheelEventQueue.append(event);
+
+    if (!m_eventsBeingProcessed.isEmpty()) {
+        if (!shouldDispatchEventNow(m_wheelEventQueue.last())) {
+            LOG_WITH_STREAM(WheelEvents, stream << "WebWheelEventCoalescer::shouldDispatchEvent -  " << m_wheelEventQueue.size() << " events queued; not dispatching");
+            return false;
+        }
+        // The queue has too many wheel events, so push a new event.
+        // FIXME: This logic is confusing, and possibly not necessary.
+    }
+
+    return true;
+}
+
+NativeWebWheelEvent WebWheelEventCoalescer::takeOldestEventBeingProcessed()
+{
+    ASSERT(hasEventsBeingProcessed());
+    auto oldestSequence = m_eventsBeingProcessed.takeFirst();
+    return oldestSequence->last();
+}
+
+void WebWheelEventCoalescer::clear()
+{
+    m_wheelEventQueue.clear();
+    m_eventsBeingProcessed.clear();
+}
+
+} // namespace WebKit

Added: trunk/Source/WebKit/Shared/WebWheelEventCoalescer.h (0 => 268287)


--- trunk/Source/WebKit/Shared/WebWheelEventCoalescer.h	                        (rev 0)
+++ trunk/Source/WebKit/Shared/WebWheelEventCoalescer.h	2020-10-09 20:56:25 UTC (rev 268287)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "NativeWebWheelEvent.h"
+#include <wtf/Deque.h>
+#include <wtf/FastMalloc.h>
+
+namespace WebKit {
+
+class WebWheelEventCoalescer {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    // If this returns true, use nextEventToDispatch() to get the event to dispatch.
+    bool shouldDispatchEvent(const NativeWebWheelEvent&);
+    Optional<WebWheelEvent> nextEventToDispatch();
+    
+    NativeWebWheelEvent takeOldestEventBeingProcessed();
+
+    bool hasEventsBeingProcessed() const { return !m_eventsBeingProcessed.isEmpty(); }
+    
+    void clear();
+
+private:
+    using CoalescedEventSequence = Vector<NativeWebWheelEvent>;
+
+    static bool canCoalesce(const WebWheelEvent&, const WebWheelEvent&);
+    static WebWheelEvent coalesce(const WebWheelEvent&, const WebWheelEvent&);
+
+    bool shouldDispatchEventNow(const WebWheelEvent&) const;
+
+    Deque<NativeWebWheelEvent, 2> m_wheelEventQueue;
+    Deque<std::unique_ptr<CoalescedEventSequence>> m_eventsBeingProcessed;
+};
+
+} // namespace WebKit

Modified: trunk/Source/WebKit/Sources.txt (268286 => 268287)


--- trunk/Source/WebKit/Sources.txt	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/Sources.txt	2020-10-09 20:56:25 UTC (rev 268287)
@@ -211,6 +211,7 @@
 Shared/API/c/WKRenderObject.cpp
 Shared/WebTouchEvent.cpp @no-unify
 Shared/WebUserContentControllerDataTypes.cpp
+Shared/WebWheelEventCoalescer.cpp
 Shared/WebWheelEvent.cpp @no-unify
 Shared/WebsiteDataStoreParameters.cpp
 Shared/WebsitePoliciesData.cpp

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (268286 => 268287)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-10-09 20:56:25 UTC (rev 268287)
@@ -137,6 +137,7 @@
 #include "WebURLSchemeHandler.h"
 #include "WebUserContentControllerProxy.h"
 #include "WebViewDidMoveToWindowObserver.h"
+#include "WebWheelEventCoalescer.h"
 #include "WebsiteDataStore.h"
 #include <WebCore/AdClickAttribution.h>
 #include <WebCore/BitmapImage.h>
@@ -2613,70 +2614,6 @@
     m_callbackHandlersAfterProcessingPendingMouseEvents.clear();
 }
 
-#if MERGE_WHEEL_EVENTS
-static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
-{
-    if (a.position() != b.position())
-        return false;
-    if (a.globalPosition() != b.globalPosition())
-        return false;
-    if (a.modifiers() != b.modifiers())
-        return false;
-    if (a.granularity() != b.granularity())
-        return false;
-#if PLATFORM(COCOA)
-    if (a.phase() != b.phase())
-        return false;
-    if (a.momentumPhase() != b.momentumPhase())
-        return false;
-    if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
-        return false;
-#endif
-
-    return true;
-}
-
-static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
-{
-    ASSERT(canCoalesce(a, b));
-
-    FloatSize mergedDelta = a.delta() + b.delta();
-    FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
-
-#if PLATFORM(COCOA)
-    FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
-
-    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());
-#else
-    return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
-#endif
-}
-#endif // MERGE_WHEEL_EVENTS
-
-static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
-{
-    ASSERT(!queue.isEmpty());
-    ASSERT(coalescedEvents.isEmpty());
-
-#if MERGE_WHEEL_EVENTS
-    NativeWebWheelEvent firstEvent = queue.takeFirst();
-    coalescedEvents.append(firstEvent);
-
-    WebWheelEvent event = firstEvent;
-    while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
-        NativeWebWheelEvent firstEvent = queue.takeFirst();
-        coalescedEvents.append(firstEvent);
-        event = coalesce(event, firstEvent);
-    }
-
-    return event;
-#else
-    while (!queue.isEmpty())
-        coalescedEvents.append(queue.takeFirst());
-    return coalescedEvents.last();
-#endif
-}
-
 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
 {
 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
@@ -2689,32 +2626,12 @@
 
     closeOverlayedViews();
 
-    if (!m_currentlyProcessedWheelEvents.isEmpty()) {
-        m_wheelEventQueue.append(event);
-        if (!shouldProcessWheelEventNow(event))
-            return;
-        // The queue has too many wheel events, so push a new event.
+    if (wheelEventCoalescer().shouldDispatchEvent(event)) {
+        auto event = wheelEventCoalescer().nextEventToDispatch();
+        sendWheelEvent(*event);
     }
-
-    if (!m_wheelEventQueue.isEmpty()) {
-        processNextQueuedWheelEvent();
-        return;
-    }
-
-    auto coalescedWheelEvent = makeUnique<Vector<NativeWebWheelEvent>>();
-    coalescedWheelEvent->append(event);
-    m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
-    sendWheelEvent(event);
 }
 
-void WebPageProxy::processNextQueuedWheelEvent()
-{
-    auto nextCoalescedEvent = makeUnique<Vector<NativeWebWheelEvent>>();
-    WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
-    m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
-    sendWheelEvent(nextWheelEvent);
-}
-
 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
 {
 #if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
@@ -2736,25 +2653,12 @@
     m_process->isResponsiveWithLazyStop();
 }
 
-bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
+WebWheelEventCoalescer& WebPageProxy::wheelEventCoalescer()
 {
-#if PLATFORM(GTK)
-    // Don't queue events representing a non-trivial scrolling phase to
-    // avoid having them trapped in the queue, potentially preventing a
-    // scrolling session to beginning or end correctly.
-    // This is only needed by platforms whose WebWheelEvent has this phase
-    // information (Cocoa and GTK+) but Cocoa was fine without it.
-    if (event.phase() == WebWheelEvent::Phase::PhaseNone
-        || event.phase() == WebWheelEvent::Phase::PhaseChanged
-        || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
-        || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
-        return true;
-#else
-    UNUSED_PARAM(event);
-#endif
-    if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
-        return true;
-    return false;
+    if (!m_wheelEventCoalescer)
+        m_wheelEventCoalescer = makeUnique<WebWheelEventCoalescer>();
+
+    return *m_wheelEventCoalescer;
 }
 
 bool WebPageProxy::hasQueuedKeyEvent() const
@@ -7004,7 +6908,7 @@
 
         // Retire the last sent event now that WebProcess is done handling it.
         MESSAGE_CHECK(m_process, !m_mouseEventQueue.isEmpty());
-        NativeWebMouseEvent event = m_mouseEventQueue.takeFirst();
+        auto event = m_mouseEventQueue.takeFirst();
         MESSAGE_CHECK(m_process, type == event.type());
 
         if (!m_mouseEventQueue.isEmpty()) {
@@ -7015,23 +6919,21 @@
                 automationSession->mouseEventsFlushedForPage(*this);
             didFinishProcessingAllPendingMouseEvents();
         }
-
         break;
     }
 
     case WebEvent::Wheel: {
-        MESSAGE_CHECK(m_process, !m_currentlyProcessedWheelEvents.isEmpty());
+        MESSAGE_CHECK(m_process, wheelEventCoalescer().hasEventsBeingProcessed());
+        auto oldestProcessedEvent = wheelEventCoalescer().takeOldestEventBeingProcessed();
 
-        std::unique_ptr<Vector<NativeWebWheelEvent>> oldestCoalescedEvent = m_currentlyProcessedWheelEvents.takeFirst();
-
         // FIXME: Dispatch additional events to the didNotHandleWheelEvent client function.
         if (!handled) {
-            m_uiClient->didNotHandleWheelEvent(this, oldestCoalescedEvent->last());
-            pageClient().wheelEventWasNotHandledByWebCore(oldestCoalescedEvent->last());
+            m_uiClient->didNotHandleWheelEvent(this, oldestProcessedEvent);
+            pageClient().wheelEventWasNotHandledByWebCore(oldestProcessedEvent);
         }
 
-        if (!m_wheelEventQueue.isEmpty())
-            processNextQueuedWheelEvent();
+        if (auto eventToSend = wheelEventCoalescer().nextEventToDispatch())
+            sendWheelEvent(*eventToSend);
         break;
     }
 
@@ -7042,8 +6944,7 @@
         LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty());
 
         MESSAGE_CHECK(m_process, !m_keyEventQueue.isEmpty());
-        NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst();
-
+        auto event = m_keyEventQueue.takeFirst();
         MESSAGE_CHECK(m_process, type == event.type());
 
 #if PLATFORM(WIN)
@@ -7077,8 +6978,7 @@
     case WebEvent::GestureChange:
     case WebEvent::GestureEnd: {
         MESSAGE_CHECK(m_process, !m_gestureEventQueue.isEmpty());
-        NativeWebGestureEvent event = m_gestureEventQueue.takeFirst();
-
+        auto event = m_gestureEventQueue.takeFirst();
         MESSAGE_CHECK(m_process, type == event.type());
 
         if (!handled)
@@ -7085,7 +6985,6 @@
             pageClient().gestureEventWasNotHandledByWebCore(event);
         break;
     }
-        break;
 #endif
 #if ENABLE(IOS_TOUCH_EVENTS)
     case WebEvent::TouchStart:
@@ -7099,8 +6998,7 @@
     case WebEvent::TouchEnd:
     case WebEvent::TouchCancel: {
         MESSAGE_CHECK(m_process, !m_touchEventQueue.isEmpty());
-        QueuedTouchEvents queuedEvents = m_touchEventQueue.takeFirst();
-
+        auto queuedEvents = m_touchEventQueue.takeFirst();
         MESSAGE_CHECK(m_process, type == queuedEvents.forwardedEvent.type());
 
         pageClient().doneWithTouchEvent(queuedEvents.forwardedEvent, handled);
@@ -7732,8 +7630,9 @@
     // Can't expect DidReceiveEvent notifications from a crashed web process.
     m_mouseEventQueue.clear();
     m_keyEventQueue.clear();
-    m_wheelEventQueue.clear();
-    m_currentlyProcessedWheelEvents.clear();
+    if (m_wheelEventCoalescer)
+        m_wheelEventCoalescer->clear();
+
 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
     m_touchEventQueue.clear();
 #endif

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (268286 => 268287)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-10-09 20:56:25 UTC (rev 268287)
@@ -327,6 +327,7 @@
 class WebUserContentControllerProxy;
 class WebViewDidMoveToWindowObserver;
 class WebWheelEvent;
+class WebWheelEventCoalescer;
 class WebsiteDataStore;
 
 struct WebBackForwardListCounts;
@@ -2231,10 +2232,10 @@
 
     void setRenderTreeSize(uint64_t treeSize) { m_renderTreeSize = treeSize; }
 
-    void processNextQueuedWheelEvent();
     void sendWheelEvent(const WebWheelEvent&);
-    bool shouldProcessWheelEventNow(const WebWheelEvent&) const;
 
+    WebWheelEventCoalescer& wheelEventCoalescer();
+
 #if ENABLE(TOUCH_EVENTS)
     void updateTouchEventTracking(const WebTouchEvent&);
     WebCore::TrackingType touchEventTrackingType(const WebTouchEvent&) const;
@@ -2577,10 +2578,10 @@
     bool m_shouldSuppressSOAuthorizationInAllNavigationPolicyDecision { false };
 #endif
 
+    std::unique_ptr<WebWheelEventCoalescer> m_wheelEventCoalescer;
+
     Deque<NativeWebMouseEvent> m_mouseEventQueue;
     Deque<NativeWebKeyboardEvent> m_keyEventQueue;
-    Deque<NativeWebWheelEvent> m_wheelEventQueue;
-    Deque<std::unique_ptr<Vector<NativeWebWheelEvent>>> m_currentlyProcessedWheelEvents;
 #if ENABLE(MAC_GESTURE_EVENTS)
     Deque<NativeWebGestureEvent> m_gestureEventQueue;
 #endif

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (268286 => 268287)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-10-09 20:53:50 UTC (rev 268286)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-10-09 20:56:25 UTC (rev 268287)
@@ -2235,6 +2235,8 @@
 		0F45A334239D89AF00294ABF /* WKWebViewTestingMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewTestingMac.mm; sourceTree = "<group>"; };
 		0F45A33B239D8CC400294ABF /* WKWebViewPrivateForTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebViewPrivateForTesting.h; sourceTree = "<group>"; };
 		0F45A33C239D8CC400294ABF /* WKWebViewTesting.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewTesting.mm; sourceTree = "<group>"; };
+		0F5403002531006E00082BB9 /* WebWheelEventCoalescer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebWheelEventCoalescer.cpp; sourceTree = "<group>"; };
+		0F5403012531006E00082BB9 /* WebWheelEventCoalescer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebWheelEventCoalescer.h; sourceTree = "<group>"; };
 		0F59478D187B3B3A00437857 /* RemoteScrollingCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteScrollingCoordinator.h; sourceTree = "<group>"; };
 		0F59478E187B3B3A00437857 /* RemoteScrollingCoordinator.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RemoteScrollingCoordinator.messages.in; sourceTree = "<group>"; };
 		0F59478F187B3B3A00437857 /* RemoteScrollingCoordinator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteScrollingCoordinator.mm; sourceTree = "<group>"; };
@@ -6211,6 +6213,8 @@
 				4960A3BC23C5286400961842 /* WebViewCategory.h */,
 				C0337DD0127A2980008FF4F4 /* WebWheelEvent.cpp */,
 				0F4000FD2527D69D00E91DA7 /* WebWheelEvent.h */,
+				0F5403002531006E00082BB9 /* WebWheelEventCoalescer.cpp */,
+				0F5403012531006E00082BB9 /* WebWheelEventCoalescer.h */,
 			);
 			path = Shared;
 			sourceTree = "<group>";
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to