Title: [279779] trunk/Source/WebKit
Revision
279779
Author
[email protected]
Date
2021-07-09 04:47:35 -0700 (Fri, 09 Jul 2021)

Log Message

[GTK] Touchscreen navigation swipe doesn't work when the page scrolls horizontally
https://bugs.webkit.org/show_bug.cgi?id=227691

Patch by Alexander Mikhaylenko <[email protected]> on 2021-07-09
Reviewed by Michael Catanzaro.

When the page scrolls horizontally, we have a separate code path for events that
WebCore didn't handle and which are considered safe to use to start a swipe
gesture. Unfortunately, that code relies on the NativeWebWheelEvents containing a
GdkEvent, which is only the case for actual scroll events, but not synthesized
scroll events on touchscreen, and the needed info (input source type and a proper
timestamp instead of the truncated one wallTimeForEventTime() produces) is not
stored in NativeWebWheelEvent.

While we don't have GdkEvents for every situation we synthesize wheel events in,
we do have them for touchscreen gestures. They aren't GdkScrollEvents, but that
isn't a problem - the only things we use that are specific to GdkScrollEvent are
scroll deltas and whether it's a scroll stop event, and that's also stored in
NativeWebWheelEvent, and we only need GdkEvent for the time and input source type,
where the event type doesn't really matter.

Since touch GdkEvents are controlled via event sequences rather than stop/propagate
return values, don't try and propagate them if web process has returned them: we've
already claimed their sequence before sending them to web process, so they will be
of no use to other widgets.

* Shared/NativeWebWheelEvent.h:
* Shared/gtk/NativeWebWheelEventGtk.cpp:
(WebKit::NativeWebWheelEvent::NativeWebWheelEvent):
Add a GdkEvent parameter to the remaining constructor.
* UIProcess/API/gtk/PageClientImpl.cpp:
(WebKit::PageClientImpl::wheelEventWasNotHandledByWebCore):
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseZoomBegin):
(webkitWebViewBaseTouchDragBegin):
(webkitWebViewBaseTouchDragUpdate):
(webkitWebViewBaseTouchSwipe):
(webkitWebViewBaseSynthesizeWheelEvent):
Split into versions with and without a GdkEvent parameter.
* UIProcess/API/gtk/WebKitWebViewBasePrivate.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (279778 => 279779)


--- trunk/Source/WebKit/ChangeLog	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/ChangeLog	2021-07-09 11:47:35 UTC (rev 279779)
@@ -1,3 +1,45 @@
+2021-07-09  Alexander Mikhaylenko  <[email protected]>
+
+        [GTK] Touchscreen navigation swipe doesn't work when the page scrolls horizontally
+        https://bugs.webkit.org/show_bug.cgi?id=227691
+
+        Reviewed by Michael Catanzaro.
+
+        When the page scrolls horizontally, we have a separate code path for events that
+        WebCore didn't handle and which are considered safe to use to start a swipe
+        gesture. Unfortunately, that code relies on the NativeWebWheelEvents containing a
+        GdkEvent, which is only the case for actual scroll events, but not synthesized
+        scroll events on touchscreen, and the needed info (input source type and a proper
+        timestamp instead of the truncated one wallTimeForEventTime() produces) is not
+        stored in NativeWebWheelEvent.
+
+        While we don't have GdkEvents for every situation we synthesize wheel events in,
+        we do have them for touchscreen gestures. They aren't GdkScrollEvents, but that
+        isn't a problem - the only things we use that are specific to GdkScrollEvent are
+        scroll deltas and whether it's a scroll stop event, and that's also stored in
+        NativeWebWheelEvent, and we only need GdkEvent for the time and input source type,
+        where the event type doesn't really matter.
+
+        Since touch GdkEvents are controlled via event sequences rather than stop/propagate
+        return values, don't try and propagate them if web process has returned them: we've
+        already claimed their sequence before sending them to web process, so they will be
+        of no use to other widgets.
+
+        * Shared/NativeWebWheelEvent.h:
+        * Shared/gtk/NativeWebWheelEventGtk.cpp:
+        (WebKit::NativeWebWheelEvent::NativeWebWheelEvent):
+        Add a GdkEvent parameter to the remaining constructor.
+        * UIProcess/API/gtk/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::wheelEventWasNotHandledByWebCore):
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseZoomBegin):
+        (webkitWebViewBaseTouchDragBegin):
+        (webkitWebViewBaseTouchDragUpdate):
+        (webkitWebViewBaseTouchSwipe):
+        (webkitWebViewBaseSynthesizeWheelEvent):
+        Split into versions with and without a GdkEvent parameter.
+        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
+
 2021-07-08  Adam Mazander  <[email protected]>
 
         WebContent: Silence report of AppSupport denial

Modified: trunk/Source/WebKit/Shared/NativeWebWheelEvent.h (279778 => 279779)


--- trunk/Source/WebKit/Shared/NativeWebWheelEvent.h	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/Shared/NativeWebWheelEvent.h	2021-07-09 11:47:35 UTC (rev 279779)
@@ -61,7 +61,7 @@
     NativeWebWheelEvent(GdkEvent*);
     NativeWebWheelEvent(GdkEvent*, WebWheelEvent::Phase, WebWheelEvent::Phase momentumPhase);
     NativeWebWheelEvent(GdkEvent*, const WebCore::IntPoint&, const WebCore::FloatSize& wheelTicks);
-    NativeWebWheelEvent(const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, WebWheelEvent::Phase, WebWheelEvent::Phase momentumPhase);
+    NativeWebWheelEvent(GdkEvent*, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, WebWheelEvent::Phase, WebWheelEvent::Phase momentumPhase);
 #elif USE(LIBWPE)
     NativeWebWheelEvent(struct wpe_input_axis_event*, float deviceScaleFactor, WebWheelEvent::Phase, WebWheelEvent::Phase momentumPhase);
 #elif PLATFORM(WIN)

Modified: trunk/Source/WebKit/Shared/gtk/NativeWebWheelEventGtk.cpp (279778 => 279779)


--- trunk/Source/WebKit/Shared/gtk/NativeWebWheelEventGtk.cpp	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/Shared/gtk/NativeWebWheelEventGtk.cpp	2021-07-09 11:47:35 UTC (rev 279779)
@@ -49,8 +49,9 @@
 {
 }
 
-NativeWebWheelEvent::NativeWebWheelEvent(const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, WebWheelEvent::Phase phase, WebWheelEvent::Phase momentumPhase)
+NativeWebWheelEvent::NativeWebWheelEvent(GdkEvent *event, const WebCore::IntPoint& position, const WebCore::IntPoint& globalPosition, const WebCore::FloatSize& delta, const WebCore::FloatSize& wheelTicks, WebWheelEvent::Phase phase, WebWheelEvent::Phase momentumPhase)
     : WebWheelEvent(WebEvent::Wheel, position, globalPosition, delta, wheelTicks, phase, momentumPhase, WebWheelEvent::ScrollByPixelWheelEvent, false, { }, WallTime::now())
+    , m_nativeEvent(event ? gdk_event_copy(event) : nullptr)
 {
 }
 

Modified: trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp (279778 => 279779)


--- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp	2021-07-09 11:47:35 UTC (rev 279779)
@@ -424,9 +424,7 @@
 
     ViewGestureController* controller = webkitWebViewBaseViewGestureController(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
     if (controller && controller->isSwipeGestureEnabled()) {
-        double deltaX, deltaY;
-        gdk_event_get_scroll_deltas(event.nativeEvent(), &deltaX, &deltaY);
-        FloatSize delta(deltaX, deltaY);
+        FloatSize delta(-event.wheelTicks());
 
         int32_t eventTime = static_cast<int32_t>(gdk_event_get_time(event.nativeEvent()));
 
@@ -433,7 +431,7 @@
         GdkDevice* device = gdk_event_get_source_device(event.nativeEvent());
         GdkInputSource source = gdk_device_get_source(device);
 
-        bool isEnd = gdk_event_is_scroll_stop_event(event.nativeEvent()) ? true : false;
+        bool isEnd = event.phase() == WebWheelEvent::Phase::PhaseEnded;
 
         PlatformGtkScrollData scrollData = { .delta = delta, .eventTime = eventTime, .source = source, .isEnd = isEnd };
         controller->wheelEventWasNotHandledByWebCore(&scrollData);
@@ -440,6 +438,14 @@
         return;
     }
 
+    // Wheel events can have either scroll events or touch events attached to them.
+    // We only want to propagate scroll events; touch events are controlled via their
+    // event sequences and if we're scrolling with touch events, that sequence is
+    // already claimed and there's no point in propagating it.
+
+    if (gdk_event_get_event_type(event.nativeEvent()) != GDK_SCROLL)
+        return;
+
     webkitWebViewBaseForwardNextWheelEvent(WEBKIT_WEB_VIEW_BASE(m_viewWidget));
 
 #if USE(GTK4)

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (279778 => 279779)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp	2021-07-09 11:47:35 UTC (rev 279779)
@@ -1871,7 +1871,9 @@
     double x, y;
     gtk_gesture_get_bounding_box_center(gesture, &x, &y);
 
-    webkitWebViewBaseSynthesizeWheelEvent(webViewBase, 0, 0, x, y, WheelEventPhase::Began, WheelEventPhase::NoPhase);
+    auto* event = gtk_gesture_get_last_event(gesture, sequence);
+
+    webkitWebViewBaseSynthesizeWheelEvent(webViewBase, event, 0, 0, x, y, WheelEventPhase::Began, WheelEventPhase::NoPhase);
 }
 
 static void webkitWebViewBaseZoomChanged(WebKitWebViewBase* webViewBase, gdouble scale, GtkGesture* gesture)
@@ -1942,13 +1944,16 @@
     webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Release, button, buttons, x, y, modifiers, nPress, touchPointerEventType());
 }
 
-static void webkitWebViewBaseTouchDragBegin(WebKitWebViewBase* webViewBase, gdouble startX, gdouble startY, GtkGesture*)
+static void webkitWebViewBaseTouchDragBegin(WebKitWebViewBase* webViewBase, gdouble startX, gdouble startY, GtkGesture* gesture)
 {
     WebKitWebViewBasePrivate* priv = webViewBase->priv;
     priv->dragOffset.set(0, 0);
     priv->isBeingDragged = false;
 
-    webkitWebViewBaseSynthesizeWheelEvent(webViewBase, 0, 0, startX, startY, WheelEventPhase::Began, WheelEventPhase::NoPhase);
+    auto* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
+    auto* event = gtk_gesture_get_last_event(gesture, sequence);
+
+    webkitWebViewBaseSynthesizeWheelEvent(webViewBase, event, 0, 0, startX, startY, WheelEventPhase::Began, WheelEventPhase::NoPhase);
 }
 
 static void webkitWebViewBaseTouchDragUpdate(WebKitWebViewBase* webViewBase, double offsetX, double offsetY, GtkGesture* gesture)
@@ -1960,6 +1965,9 @@
     double x, y;
     gtk_gesture_drag_get_start_point(GTK_GESTURE_DRAG(gesture), &x, &y);
 
+    auto* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
+    auto* event = gtk_gesture_get_last_event(gesture, sequence);
+
     unsigned modifiers = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
     if (!priv->isBeingDragged) {
         if (!gtk_drag_check_threshold(GTK_WIDGET(webViewBase), 0, 0, static_cast<int>(offsetX), static_cast<int>(offsetY)))
@@ -1972,7 +1980,7 @@
             webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Motion, 0, 0, x, y, modifiers, 1, touchPointerEventType());
             webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Press, GDK_BUTTON_PRIMARY, 0, x, y, modifiers, 0, touchPointerEventType());
         } else
-            webkitWebViewBaseSynthesizeWheelEvent(webViewBase, 0, 0, x, y, WheelEventPhase::Began, WheelEventPhase::NoPhase);
+            webkitWebViewBaseSynthesizeWheelEvent(webViewBase, event, 0, 0, x, y, WheelEventPhase::Began, WheelEventPhase::NoPhase);
     }
 
     if (priv->isLongPressed)
@@ -1991,7 +1999,7 @@
                 return;
         }
 
-        webkitWebViewBaseSynthesizeWheelEvent(webViewBase, -deltaX, -deltaY, x, y, WheelEventPhase::Changed, WheelEventPhase::NoPhase);
+        webkitWebViewBaseSynthesizeWheelEvent(webViewBase, event, -deltaX, -deltaY, x, y, WheelEventPhase::Changed, WheelEventPhase::NoPhase);
     }
 }
 
@@ -2029,8 +2037,12 @@
         return;
 
     double x, y;
-    if (gtk_gesture_get_point(gesture, gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture)), &x, &y))
-        webkitWebViewBaseSynthesizeWheelEvent(webViewBase, -velocityX, -velocityY, x, y, WheelEventPhase::NoPhase, WheelEventPhase::Began);
+    if (gtk_gesture_get_point(gesture, gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture)), &x, &y)) {
+        auto* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
+        auto* event = gtk_gesture_get_last_event(gesture, sequence);
+
+        webkitWebViewBaseSynthesizeWheelEvent(webViewBase, event, -velocityX, -velocityY, x, y, WheelEventPhase::NoPhase, WheelEventPhase::Began);
+    }
 }
 
 static void webkitWebViewBaseConstructed(GObject* object)
@@ -3005,6 +3017,11 @@
 
 void webkitWebViewBaseSynthesizeWheelEvent(WebKitWebViewBase* webViewBase, double deltaX, double deltaY, int x, int y, WheelEventPhase phase, WheelEventPhase momentumPhase)
 {
+    webkitWebViewBaseSynthesizeWheelEvent(webViewBase, nullptr, deltaX, deltaY, x, y, phase, momentumPhase);
+}
+
+void webkitWebViewBaseSynthesizeWheelEvent(WebKitWebViewBase* webViewBase, const GdkEvent* event, double deltaX, double deltaY, int x, int y, WheelEventPhase phase, WheelEventPhase momentumPhase)
+{
     WebKitWebViewBasePrivate* priv = webViewBase->priv;
     if (priv->dialog)
         return;
@@ -3013,7 +3030,7 @@
     FloatSize delta(wheelTicks);
     delta.scale(static_cast<float>(Scrollbar::pixelsPerLineStep()));
 
-    priv->pageProxy->handleWheelEvent(NativeWebWheelEvent({ x, y }, widgetRootCoords(GTK_WIDGET(webViewBase), x, y),
+    priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(const_cast<GdkEvent*>(event), { x, y }, widgetRootCoords(GTK_WIDGET(webViewBase), x, y),
         delta, wheelTicks, toWebKitWheelEventPhase(phase), toWebKitWheelEventPhase(momentumPhase)));
 }
 

Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h (279778 => 279779)


--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h	2021-07-09 11:18:29 UTC (rev 279778)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h	2021-07-09 11:47:35 UTC (rev 279779)
@@ -38,6 +38,7 @@
 #include "WebInspectorUIProxy.h"
 #include "WebKitInputMethodContext.h"
 #include "WebKitWebViewBase.h"
+#include "WebKitWebViewBaseInternal.h"
 #include "WebPageProxy.h"
 #include <WebCore/DragActions.h>
 #include <WebCore/SelectionData.h>
@@ -113,6 +114,7 @@
 void webkitWebViewBaseSetInputMethodContext(WebKitWebViewBase*, WebKitInputMethodContext*);
 WebKitInputMethodContext* webkitWebViewBaseGetInputMethodContext(WebKitWebViewBase*);
 void webkitWebViewBaseSynthesizeCompositionKeyPress(WebKitWebViewBase*, const String& text, std::optional<Vector<WebCore::CompositionUnderline>>&&, std::optional<WebKit::EditingRange>&&);
+void webkitWebViewBaseSynthesizeWheelEvent(WebKitWebViewBase*, const GdkEvent*, double deltaX, double deltaY, int x, int y, WheelEventPhase, WheelEventPhase momentumPhase);
 
 void webkitWebViewBaseMakeBlank(WebKitWebViewBase*, bool);
 void webkitWebViewBasePageGrabbedTouch(WebKitWebViewBase*);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to