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
- trunk/Source/WebKit/ChangeLog
- trunk/Source/WebKit/Shared/NativeWebWheelEvent.h
- trunk/Source/WebKit/Shared/gtk/NativeWebWheelEventGtk.cpp
- trunk/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp
- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
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
