Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (277171 => 277172)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2021-05-07 12:31:26 UTC (rev 277171)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2021-05-07 14:55:50 UTC (rev 277172)
@@ -316,11 +316,9 @@
std::unique_ptr<DropTarget> dropTarget;
#endif
-#if !USE(GTK4)
- std::unique_ptr<GestureController> gestureController;
+ GtkGesture* touchGestureGroup;
std::unique_ptr<ViewGestureController> viewGestureController;
bool isBackForwardNavigationGestureEnabled { false };
-#endif
#if GTK_CHECK_VERSION(3, 24, 0)
GtkWidget* emojiChooser;
@@ -328,6 +326,14 @@
RunLoop::Timer<WebKitWebViewBasePrivate> releaseEmojiChooserTimer;
#endif
+ // Touch gestures state
+ double initialZoomScale;
+ IntPoint initialZoomPoint;
+ FloatPoint dragOffset;
+ bool isLongPressed;
+ bool isBeingDragged;
+ bool pageGrabbedTouch;
+
std::unique_ptr<PointerLockManager> pointerLockManager;
};
@@ -746,11 +752,23 @@
if (!drawingArea)
return;
+ auto* pageSnapshot = gtk_snapshot_new();
if (!webViewBase->priv->isBlank) {
ASSERT(drawingArea->isInAcceleratedCompositingMode());
- webViewBase->priv->acceleratedBackingStore->snapshot(snapshot);
+ webViewBase->priv->acceleratedBackingStore->snapshot(pageSnapshot);
}
+ if (auto* pageRenderNode = gtk_snapshot_free_to_node(pageSnapshot)) {
+ bool showingNavigationSnapshot = webViewBase->priv->pageProxy->isShowingNavigationGestureSnapshot();
+ auto* controller = webkitWebViewBaseViewGestureController(webViewBase);
+ if (showingNavigationSnapshot && controller)
+ controller->snapshot(snapshot, pageRenderNode);
+ else
+ gtk_snapshot_append_node(snapshot, pageRenderNode);
+
+ gsk_render_node_unref(pageRenderNode);
+ }
+
if (webViewBase->priv->inspectorView)
gtk_widget_snapshot_child(widget, webViewBase->priv->inspectorView, snapshot);
@@ -1157,6 +1175,9 @@
if (priv->dialog)
return GDK_EVENT_STOP;
+ if (gdk_device_get_source(gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event))) == GDK_SOURCE_TOUCHSCREEN)
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->button_press_event(widget, event);
+
webkitWebViewBaseHandleMouseEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
return GDK_EVENT_STOP;
@@ -1169,6 +1190,8 @@
if (priv->dialog)
return GDK_EVENT_STOP;
+ if (gdk_device_get_source(gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event))) == GDK_SOURCE_TOUCHSCREEN)
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->button_release_event(widget, event);
webkitWebViewBaseHandleMouseEvent(webViewBase, reinterpret_cast<GdkEvent*>(event));
@@ -1179,6 +1202,8 @@
#if USE(GTK4)
static void webkitWebViewBaseButtonPressed(WebKitWebViewBase* webViewBase, int clickCount, double x, double y, GtkGesture* gesture)
{
+ if (gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture)))
+ return;
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->dialog)
return;
@@ -1202,6 +1227,8 @@
static void webkitWebViewBaseButtonReleased(WebKitWebViewBase* webViewBase, int clickCount, double x, double y, GtkGesture* gesture)
{
+ if (gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture)))
+ return;
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->dialog)
return;
@@ -1234,8 +1261,15 @@
static void webkitWebViewBaseHandleWheelEvent(WebKitWebViewBase* webViewBase, GdkEvent* event, Optional<WebWheelEvent::Phase> phase = WTF::nullopt, Optional<WebWheelEvent::Phase> momentum = WTF::nullopt)
{
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webViewBase);
- if (controller && controller->isSwipeGestureEnabled() && controller->handleScrollWheelEvent(reinterpret_cast<GdkEventScroll*>(event)))
- return;
+ if (controller && controller->isSwipeGestureEnabled()) {
+ double deltaX;
+ gdk_event_get_scroll_deltas(event, &deltaX, nullptr);
+ bool isEnd = gdk_event_is_scroll_stop_event(event) ? true : false;
+ int32_t eventTime = static_cast<int32_t>(gdk_event_get_time(event));
+ PlatformGtkScrollData scrollData = { .delta = deltaX, .eventTime = eventTime, .isTouch = false, .isEnd = isEnd };
+ if (controller->handleScrollWheelEvent(&scrollData))
+ return;
+ }
WebKitWebViewBasePrivate* priv = webViewBase->priv;
ASSERT(!priv->dialog);
@@ -1283,14 +1317,23 @@
#endif
#if USE(GTK4)
-static gboolean webkitWebViewBaseScroll(WebKitWebViewBase* webViewBase, double deltaX, double deltaY, GtkEventController* controller)
+static gboolean webkitWebViewBaseScroll(WebKitWebViewBase* webViewBase, double deltaX, double deltaY, GtkEventController* eventController)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->dialog)
return GDK_EVENT_PROPAGATE;
- auto* event = gtk_event_controller_get_current_event(controller);
+ auto* event = gtk_event_controller_get_current_event(eventController);
+ ViewGestureController* controller = webkitWebViewBaseViewGestureController(webViewBase);
+ if (controller && controller->isSwipeGestureEnabled()) {
+ bool isEnd = gdk_scroll_event_is_stop(event) ? true : false;
+ int32_t eventTime = static_cast<int32_t>(gtk_event_controller_get_current_event_time(eventController));
+ PlatformGtkScrollData scrollData = { .delta = deltaX, .eventTime = eventTime, .isTouch = false, .isEnd = isEnd };
+ if (controller->handleScrollWheelEvent(&scrollData))
+ return GDK_EVENT_STOP;
+ }
+
if (shouldInvertDirectionForScrollEvent(priv->mouseIsOverScrollbar, gdk_event_get_modifier_state(event) & GDK_SHIFT_MASK))
std::swap(deltaX, deltaY);
@@ -1330,6 +1373,9 @@
return widgetClass->motion_notify_event ? widgetClass->motion_notify_event(widget, event) : GDK_EVENT_PROPAGATE;
}
+ if (gdk_device_get_source(gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event))) == GDK_SOURCE_TOUCHSCREEN)
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->motion_notify_event(widget, event);
+
if (priv->pointerLockManager) {
double x, y;
gdk_event_get_root_coords(reinterpret_cast<GdkEvent*>(event), &x, &y);
@@ -1453,11 +1499,16 @@
}
#endif
-#if ENABLE(TOUCH_EVENTS) && !USE(GTK4)
-static void appendTouchEvent(Vector<WebPlatformTouchPoint>& touchPoints, const GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
+#if ENABLE(TOUCH_EVENTS)
+static void appendTouchEvent(GtkWidget* webViewBase, Vector<WebPlatformTouchPoint>& touchPoints, GdkEvent* event, WebPlatformTouchPoint::TouchPointState state)
{
gdouble x, y;
gdk_event_get_coords(event, &x, &y);
+#if USE(GTK4)
+ // Events in GTK4 are given in native surface coordinates
+ gtk_widget_translate_coordinates(GTK_WIDGET(gtk_widget_get_native(webViewBase)),
+ webViewBase, x, y, &x, &y);
+#endif
gdouble xRoot, yRoot;
gdk_event_get_root_coords(event, &xRoot, &yRoot);
@@ -1466,12 +1517,12 @@
touchPoints.uncheckedAppend(WebPlatformTouchPoint(identifier, state, IntPoint(xRoot, yRoot), IntPoint(x, y)));
}
-static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(const GdkEvent* current, const GdkEvent* event)
+static inline WebPlatformTouchPoint::TouchPointState touchPointStateForEvents(GdkEvent* current, GdkEvent* event)
{
if (gdk_event_get_event_sequence(current) != gdk_event_get_event_sequence(event))
return WebPlatformTouchPoint::TouchStationary;
- switch (current->type) {
+ switch (gdk_event_get_event_type(event)) {
case GDK_TOUCH_UPDATE:
return WebPlatformTouchPoint::TouchMoved;
case GDK_TOUCH_BEGIN:
@@ -1492,15 +1543,20 @@
bool touchEnd = (type == GDK_TOUCH_END) || (type == GDK_TOUCH_CANCEL);
touchPoints.reserveInitialCapacity(touchEnd ? priv->touchEvents.size() + 1 : priv->touchEvents.size());
+ GtkWidget* widget = GTK_WIDGET(webViewBase);
for (const auto& it : priv->touchEvents)
- appendTouchEvent(touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
+ appendTouchEvent(widget, touchPoints, it.value.get(), touchPointStateForEvents(it.value.get(), event));
// Touch was already removed from the TouchEventsMap, add it here.
if (touchEnd)
- appendTouchEvent(touchPoints, event, WebPlatformTouchPoint::TouchReleased);
+ appendTouchEvent(widget, touchPoints, event, WebPlatformTouchPoint::TouchReleased);
}
+#if USE(GTK4)
+static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEvent* event)
+#else
static gboolean webkitWebViewBaseTouchEvent(GtkWidget* widget, GdkEventTouch* event)
+#endif
{
WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
WebKitWebViewBasePrivate* priv = webViewBase->priv;
@@ -1514,6 +1570,8 @@
GdkEventType type = gdk_event_get_event_type(touchEvent);
switch (type) {
case GDK_TOUCH_BEGIN: {
+ if (priv->touchEvents.isEmpty())
+ priv->pageGrabbedTouch = false;
ASSERT(!priv->touchEvents.contains(sequence));
GUniquePtr<GdkEvent> event(gdk_event_copy(touchEvent));
priv->touchEvents.add(sequence, WTFMove(event));
@@ -1532,7 +1590,10 @@
priv->touchEvents.remove(sequence);
break;
default:
- break;
+#if !USE(GTK4)
+ ASSERT_NOT_REACHED();
+#endif
+ return GDK_EVENT_PROPAGATE;
}
Vector<WebPlatformTouchPoint> touchPoints;
@@ -1539,142 +1600,16 @@
webkitWebViewBaseGetTouchPointsForEvent(webViewBase, touchEvent, touchPoints);
priv->pageProxy->handleTouchEvent(NativeWebTouchEvent(reinterpret_cast<GdkEvent*>(event), WTFMove(touchPoints)));
- return GDK_EVENT_STOP;
+#if USE(GTK4)
+ return GDK_EVENT_PROPAGATE;
+#else
+ return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->touch_event(widget, event);
+#endif
}
#endif // ENABLE(TOUCH_EVENTS)
-#if !USE(GTK4)
-class TouchGestureController final : public GestureControllerClient {
- WTF_MAKE_FAST_ALLOCATED;
-
-public:
- explicit TouchGestureController(WebKitWebViewBase* webViewBase)
- : m_webView(webViewBase)
- {
- }
-
-private:
- static GUniquePtr<GdkEvent> createScrollEvent(GdkEventTouch* event, const FloatPoint& point, const FloatPoint& delta, bool isStop = false)
- {
- GUniquePtr<GdkEvent> scrollEvent(gdk_event_new(GDK_SCROLL));
- scrollEvent->scroll.time = event->time;
- scrollEvent->scroll.x = point.x();
- scrollEvent->scroll.y = point.y();
- scrollEvent->scroll.x_root = event->x_root;
- scrollEvent->scroll.y_root = event->y_root;
- scrollEvent->scroll.direction = GDK_SCROLL_SMOOTH;
- scrollEvent->scroll.delta_x = delta.x();
- scrollEvent->scroll.delta_y = delta.y();
- scrollEvent->scroll.state = event->state;
- scrollEvent->scroll.is_stop = isStop;
- scrollEvent->scroll.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
- auto* touchEvent = reinterpret_cast<GdkEvent*>(event);
- gdk_event_set_screen(scrollEvent.get(), gdk_event_get_screen(touchEvent));
- gdk_event_set_device(scrollEvent.get(), gdk_event_get_device(touchEvent));
- gdk_event_set_source_device(scrollEvent.get(), gdk_event_get_source_device(touchEvent));
- return scrollEvent;
- }
-
- void simulateMouseClick(GdkEventTouch* event, unsigned button)
- {
- GUniquePtr<GdkEvent> pointerEvent(gdk_event_new(GDK_MOTION_NOTIFY));
- pointerEvent->motion.time = event->time;
- pointerEvent->motion.x = event->x;
- pointerEvent->motion.y = event->y;
- pointerEvent->motion.x_root = event->x_root;
- pointerEvent->motion.y_root = event->y_root;
- pointerEvent->motion.state = event->state;
- pointerEvent->motion.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
- auto* touchEvent = reinterpret_cast<GdkEvent*>(event);
- gdk_event_set_screen(pointerEvent.get(), gdk_event_get_screen(touchEvent));
- gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
- gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
- webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
-
- pointerEvent.reset(gdk_event_new(GDK_BUTTON_PRESS));
- pointerEvent->button.button = button;
- pointerEvent->button.time = event->time;
- pointerEvent->button.x = event->x;
- pointerEvent->button.y = event->y;
- pointerEvent->button.x_root = event->x_root;
- pointerEvent->button.y_root = event->y_root;
- pointerEvent->button.window = event->window ? GDK_WINDOW(g_object_ref(event->window)) : nullptr;
- gdk_event_set_screen(pointerEvent.get(), gdk_event_get_screen(touchEvent));
- gdk_event_set_device(pointerEvent.get(), gdk_event_get_device(touchEvent));
- gdk_event_set_source_device(pointerEvent.get(), gdk_event_get_source_device(touchEvent));
- webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
-
- pointerEvent->type = GDK_BUTTON_RELEASE;
- webkitWebViewBaseHandleMouseEvent(m_webView, pointerEvent.get());
- }
-
- void tap(GdkEventTouch* event) final
- {
- simulateMouseClick(event, GDK_BUTTON_PRIMARY);
- }
-
- void startDrag(GdkEventTouch* event, const FloatPoint& startPoint) final
- {
- GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, startPoint, { });
- webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseBegan);
- }
-
- void drag(GdkEventTouch* event, const FloatPoint& point, const FloatPoint& delta) final
- {
- GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, point, delta);
- webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseChanged);
- }
-
- void cancelDrag() final
- {
- if (auto* controller = webkitWebViewBaseViewGestureController(m_webView))
- controller->cancelSwipe();
- }
-
- void swipe(GdkEventTouch* event, const FloatPoint& velocity) final
- {
- double x, y;
- gdk_event_get_coords(reinterpret_cast<GdkEvent*>(event), &x, &y);
- GUniquePtr<GdkEvent> scrollEvent = createScrollEvent(event, FloatPoint::narrowPrecision(x, y), velocity, true);
- webkitWebViewBaseHandleWheelEvent(m_webView, scrollEvent.get(), WebWheelEvent::Phase::PhaseNone, WebWheelEvent::Phase::PhaseBegan);
- }
-
- void startZoom(const IntPoint& center, double& initialScale, IntPoint& initialPoint) final
- {
- auto* page = m_webView->priv->pageProxy.get();
- ASSERT(page);
- initialScale = page->pageScaleFactor();
- page->getCenterForZoomGesture(center, initialPoint);
- }
-
- void zoom(double scale, const IntPoint& origin) final
- {
- auto* page = m_webView->priv->pageProxy.get();
- ASSERT(page);
-
- page->scalePage(scale, origin);
- }
-
- void longPress(GdkEventTouch* event) final
- {
- simulateMouseClick(event, GDK_BUTTON_SECONDARY);
- }
-
- WebKitWebViewBase* m_webView;
-};
-
-GestureController& webkitWebViewBaseGestureController(WebKitWebViewBase* webViewBase)
-{
- WebKitWebViewBasePrivate* priv = webViewBase->priv;
- if (!priv->gestureController)
- priv->gestureController = makeUnique<GestureController>(GTK_WIDGET(webViewBase), makeUnique<TouchGestureController>(webViewBase));
- return *priv->gestureController;
-}
-#endif
-
void webkitWebViewBaseSetEnableBackForwardNavigationGesture(WebKitWebViewBase* webViewBase, bool enabled)
{
-#if !USE(GTK4)
WebKitWebViewBasePrivate* priv = webViewBase->priv;
priv->isBackForwardNavigationGestureEnabled = enabled;
@@ -1682,22 +1617,17 @@
controller->setSwipeGestureEnabled(enabled);
priv->pageProxy->setShouldRecordNavigationSnapshots(enabled);
-#endif
}
-#if !USE(GTK4)
ViewGestureController* webkitWebViewBaseViewGestureController(WebKitWebViewBase* webViewBase)
{
return webViewBase->priv->viewGestureController.get();
}
-#endif
bool webkitWebViewBaseBeginBackSwipeForTesting(WebKitWebViewBase* webViewBase)
{
-#if !USE(GTK4)
if (auto* gestureController = webkitWebViewBaseViewGestureController(webViewBase))
return gestureController->beginSimulatedSwipeInDirectionForTesting(ViewGestureController::SwipeDirection::Back);
-#endif
return FALSE;
}
@@ -1704,10 +1634,8 @@
bool webkitWebViewBaseCompleteBackSwipeForTesting(WebKitWebViewBase* webViewBase)
{
-#if !USE(GTK4)
if (auto* gestureController = webkitWebViewBaseViewGestureController(webViewBase))
return gestureController->completeSimulatedSwipeInDirectionForTesting(ViewGestureController::SwipeDirection::Back);
-#endif
return FALSE;
}
@@ -1736,13 +1664,6 @@
}
#if !USE(GTK4)
-static gboolean webkitWebViewBaseEvent(GtkWidget* widget, GdkEvent* event)
-{
- if (gdk_event_get_event_type(event) == GDK_TOUCHPAD_PINCH)
- webkitWebViewBaseGestureController(WEBKIT_WEB_VIEW_BASE(widget)).handleEvent(event);
- return GDK_EVENT_PROPAGATE;
-}
-
static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget)
{
WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
@@ -1924,6 +1845,158 @@
return GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->focus(widget, direction);
}
+static void webkitWebViewBaseZoomBegin(WebKitWebViewBase* webViewBase, GdkEventSequence* sequence, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ priv->initialZoomScale = priv->pageProxy->pageScaleFactor();
+
+ double x, y;
+ gtk_gesture_get_bounding_box_center(gesture, &x, &y);
+ priv->pageProxy->getCenterForZoomGesture(IntPoint(x, y), priv->initialZoomPoint);
+}
+
+static void webkitWebViewBaseZoomChanged(WebKitWebViewBase* webViewBase, gdouble scale, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->pageGrabbedTouch)
+ return;
+
+ gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_CLAIMED);
+
+ auto pageScale = clampTo<double>(priv->initialZoomScale * scale, 1, 3);
+
+ FloatPoint scaledZoomCenter(priv->initialZoomPoint);
+ scaledZoomCenter.scale(pageScale);
+
+ double x, y;
+ gtk_gesture_get_bounding_box_center(gesture, &x, &y);
+ FloatPoint viewPoint = FloatPoint(x, y);
+
+ priv->pageProxy->scalePage(pageScale, WebCore::roundedIntPoint(FloatPoint(scaledZoomCenter - viewPoint)));
+}
+
+static void webkitWebViewBaseTouchLongPress(WebKitWebViewBase* webViewBase, gdouble x, gdouble y, GtkGesture*)
+{
+ webViewBase->priv->isLongPressed = true;
+}
+
+static void webkitWebViewBaseTouchPress(WebKitWebViewBase* webViewBase, int nPress, double x, double y, GtkGesture*)
+{
+ webViewBase->priv->isLongPressed = false;
+}
+
+static void webkitWebViewBaseTouchRelease(WebKitWebViewBase* webViewBase, int nPress, double x, double y, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->pageGrabbedTouch)
+ return;
+ if (priv->isBeingDragged)
+ return;
+
+ unsigned button;
+ unsigned buttons;
+ if (priv->isLongPressed) {
+ button = GDK_BUTTON_SECONDARY;
+ buttons = GDK_BUTTON3_MASK;
+ } else {
+ button = GDK_BUTTON_PRIMARY;
+ buttons = GDK_BUTTON1_MASK;
+ }
+
+ unsigned modifiers = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
+ webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Motion, 0, 0, x, y, modifiers, nPress, touchPointerEventType());
+ webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Press, button, 0, x, y, modifiers, nPress, touchPointerEventType());
+ webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Release, button, buttons, x, y, modifiers, nPress, touchPointerEventType());
+}
+
+static void webkitWebViewBaseTouchDragBegin(WebKitWebViewBase* webViewBase, gdouble startX, gdouble startY, GtkGesture*)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ priv->dragOffset.set(0, 0);
+ priv->isBeingDragged = false;
+}
+
+static void webkitWebViewBaseTouchDragUpdate(WebKitWebViewBase* webViewBase, double offsetX, double offsetY, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->pageGrabbedTouch)
+ return;
+
+ double x, y;
+ gtk_gesture_drag_get_start_point(GTK_GESTURE_DRAG(gesture), &x, &y);
+
+ 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)))
+ return;
+ priv->isBeingDragged = true;
+ gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_CLAIMED);
+
+ if (priv->isLongPressed) {
+ // Drag after long press forwards emulated mouse events (for e.g. text selection)
+ 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);
+ }
+
+ if (priv->isLongPressed)
+ webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Motion, GDK_BUTTON_PRIMARY, GDK_BUTTON1_MASK, x + offsetX, y + offsetY, modifiers, 0, touchPointerEventType());
+ else {
+ double deltaX = (priv->dragOffset.x() - offsetX) / Scrollbar::pixelsPerLineStep();
+ double deltaY = (priv->dragOffset.y() - offsetY) / Scrollbar::pixelsPerLineStep();
+ priv->dragOffset.set(offsetX, offsetY);
+
+ ViewGestureController* controller = webkitWebViewBaseViewGestureController(webViewBase);
+ if (controller && controller->isSwipeGestureEnabled()) {
+ int32_t eventTime = static_cast<int32_t>(gtk_event_controller_get_current_event_time(GTK_EVENT_CONTROLLER(gesture)));
+ PlatformGtkScrollData scrollData = { .delta = deltaX, .eventTime = eventTime, .isTouch = true, .isEnd = false };
+ if (controller->handleScrollWheelEvent(&scrollData))
+ return;
+ }
+
+ webkitWebViewBaseSynthesizeWheelEvent(webViewBase, -deltaX, -deltaY, x, y, WheelEventPhase::Changed, WheelEventPhase::NoPhase);
+ }
+}
+
+static void webkitWebViewBaseTouchDragEnd(WebKitWebViewBase* webViewBase, gdouble offsetX, gdouble offsetY, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->pageGrabbedTouch)
+ return;
+
+ if (priv->isLongPressed) {
+ double x, y;
+ gtk_gesture_drag_get_start_point(GTK_GESTURE_DRAG(gesture), &x, &y);
+ unsigned modifiers = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
+ webkitWebViewBaseSynthesizeMouseEvent(webViewBase, MouseEventType::Release, GDK_BUTTON_PRIMARY, GDK_BUTTON1_MASK, x + offsetX, y + offsetY, modifiers, 0, touchPointerEventType());
+ } else {
+ ViewGestureController* controller = webkitWebViewBaseViewGestureController(webViewBase);
+ if (controller && controller->isSwipeGestureEnabled()) {
+ int32_t eventTime = static_cast<int32_t>(gtk_event_controller_get_current_event_time(GTK_EVENT_CONTROLLER(gesture)));
+ PlatformGtkScrollData scrollData = { .delta = 0, .eventTime = eventTime, .isTouch = false, .isEnd = true };
+ controller->handleScrollWheelEvent(&scrollData);
+ }
+ }
+}
+
+static void webkitWebViewBaseTouchDragCancel(WebKitWebViewBase* webViewBase, GdkEventSequence*, GtkGesture*)
+{
+ if (auto* controller = webkitWebViewBaseViewGestureController(webViewBase))
+ controller->cancelSwipe();
+}
+
+static void webkitWebViewBaseTouchSwipe(WebKitWebViewBase* webViewBase, gdouble velocityX, gdouble velocityY, GtkGesture* gesture)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (priv->pageGrabbedTouch || !priv->isBeingDragged || priv->isLongPressed)
+ 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);
+}
+
static void webkitWebViewBaseConstructed(GObject* object)
{
G_OBJECT_CLASS(webkit_web_view_base_parent_class)->constructed(object);
@@ -1961,12 +2034,77 @@
g_signal_connect_object(controller, "key-released", G_CALLBACK(webkitWebViewBaseKeyReleased), viewWidget, G_CONNECT_SWAPPED);
gtk_widget_add_controller(viewWidget, controller);
+ controller = gtk_event_controller_legacy_new();
+ gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(controller), GTK_PHASE_TARGET);
+ g_signal_connect_object(controller, "event", G_CALLBACK(webkitWebViewBaseTouchEvent), viewWidget, G_CONNECT_SWAPPED);
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(controller));
+
auto* gesture = gtk_gesture_click_new();
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 0);
+ gtk_gesture_single_set_exclusive(GTK_GESTURE_SINGLE(gesture), TRUE);
g_signal_connect_object(gesture, "pressed", G_CALLBACK(webkitWebViewBaseButtonPressed), viewWidget, G_CONNECT_SWAPPED);
g_signal_connect_object(gesture, "released", G_CALLBACK(webkitWebViewBaseButtonReleased), viewWidget, G_CONNECT_SWAPPED);
gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(gesture));
#endif
+
+ // Touch gestures
+#if USE(GTK4)
+ priv->touchGestureGroup = gtk_gesture_zoom_new();
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(priv->touchGestureGroup));
+#else
+ priv->touchGestureGroup = gtk_gesture_zoom_new(viewWidget);
+ g_object_set_data_full(G_OBJECT(viewWidget), "wk-view-zoom-gesture", priv->touchGestureGroup, g_object_unref);
+#endif
+ g_signal_connect_object(priv->touchGestureGroup, "begin", G_CALLBACK(webkitWebViewBaseZoomBegin), viewWidget, G_CONNECT_SWAPPED);
+ g_signal_connect_object(priv->touchGestureGroup, "scale-changed", G_CALLBACK(webkitWebViewBaseZoomChanged), viewWidget, G_CONNECT_SWAPPED);
+
+#if USE(GTK4)
+ gesture = gtk_gesture_long_press_new();
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(gesture));
+#else
+ auto* gesture = gtk_gesture_long_press_new(viewWidget);
+ g_object_set_data_full(G_OBJECT(viewWidget), "wk-view-long-press-gesture", gesture, g_object_unref);
+#endif
+ gtk_gesture_group(gesture, priv->touchGestureGroup);
+ gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(gesture), TRUE);
+ g_signal_connect_object(gesture, "pressed", G_CALLBACK(webkitWebViewBaseTouchLongPress), viewWidget, G_CONNECT_SWAPPED);
+
+#if USE(GTK4)
+ gesture = gtk_gesture_click_new();
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(gesture));
+#else
+ gesture = gtk_gesture_multi_press_new(viewWidget);
+ g_object_set_data_full(G_OBJECT(viewWidget), "wk-view-multi-press-gesture", gesture, g_object_unref);
+#endif
+ gtk_gesture_group(gesture, priv->touchGestureGroup);
+ gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(gesture), TRUE);
+ g_signal_connect_object(gesture, "pressed", G_CALLBACK(webkitWebViewBaseTouchPress), viewWidget, G_CONNECT_SWAPPED);
+ g_signal_connect_object(gesture, "released", G_CALLBACK(webkitWebViewBaseTouchRelease), viewWidget, G_CONNECT_SWAPPED);
+
+#if USE(GTK4)
+ gesture = gtk_gesture_drag_new();
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(gesture));
+#else
+ gesture = gtk_gesture_drag_new(viewWidget);
+ g_object_set_data_full(G_OBJECT(viewWidget), "wk-view-drag-gesture", gesture, g_object_unref);
+#endif
+ gtk_gesture_group(gesture, priv->touchGestureGroup);
+ gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(gesture), TRUE);
+ g_signal_connect_object(gesture, "drag-begin", G_CALLBACK(webkitWebViewBaseTouchDragBegin), viewWidget, G_CONNECT_SWAPPED);
+ g_signal_connect_object(gesture, "drag-update", G_CALLBACK(webkitWebViewBaseTouchDragUpdate), viewWidget, G_CONNECT_SWAPPED);
+ g_signal_connect_object(gesture, "drag-end", G_CALLBACK(webkitWebViewBaseTouchDragEnd), viewWidget, G_CONNECT_SWAPPED);
+ g_signal_connect_object(gesture, "cancel", G_CALLBACK(webkitWebViewBaseTouchDragCancel), viewWidget, G_CONNECT_SWAPPED);
+
+#if USE(GTK4)
+ gesture = gtk_gesture_swipe_new();
+ gtk_widget_add_controller(viewWidget, GTK_EVENT_CONTROLLER(gesture));
+#else
+ gesture = gtk_gesture_swipe_new(viewWidget);
+ g_object_set_data_full(G_OBJECT(viewWidget), "wk-view-swipe-gesture", gesture, g_object_unref);
+#endif
+ gtk_gesture_group(gesture, priv->touchGestureGroup);
+ gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(gesture), TRUE);
+ g_signal_connect_object(gesture, "swipe", G_CALLBACK(webkitWebViewBaseTouchSwipe), viewWidget, G_CONNECT_SWAPPED);
}
static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebViewBaseClass)
@@ -2009,7 +2147,6 @@
#endif
widgetClass->query_tooltip = webkitWebViewBaseQueryTooltip;
#if !USE(GTK4)
- widgetClass->event = webkitWebViewBaseEvent;
widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
#endif
#if USE(GTK4)
@@ -2298,18 +2435,14 @@
void webkitWebViewBaseWillSwapWebProcess(WebKitWebViewBase* webkitWebViewBase)
{
-#if !USE(GTK4)
WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv;
if (priv->viewGestureController)
priv->viewGestureController->disconnectFromProcess();
-#endif
}
void webkitWebViewBaseDidExitWebProcess(WebKitWebViewBase* webkitWebViewBase)
{
-#if !USE(GTK4)
webkitWebViewBase->priv->viewGestureController = nullptr;
-#endif
}
void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
@@ -2322,7 +2455,6 @@
auto* drawingArea = static_cast<DrawingAreaProxyCoordinatedGraphics*>(priv->pageProxy->drawingArea());
priv->acceleratedBackingStore->update(drawingArea->layerTreeContext());
}
-#if !USE(GTK4)
if (priv->viewGestureController)
priv->viewGestureController->connectToProcess();
else {
@@ -2329,7 +2461,6 @@
priv->viewGestureController = makeUnique<WebKit::ViewGestureController>(*priv->pageProxy);
priv->viewGestureController->setSwipeGestureEnabled(priv->isBackForwardNavigationGestureEnabled);
}
-#endif
}
void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
@@ -2364,56 +2495,44 @@
void webkitWebViewBaseDidStartProvisionalLoadForMainFrame(WebKitWebViewBase* webkitWebViewBase)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
controller->didStartProvisionalLoadForMainFrame();
-#endif
}
void webkitWebViewBaseDidFirstVisuallyNonEmptyLayoutForMainFrame(WebKitWebViewBase* webkitWebViewBase)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
controller->didFirstVisuallyNonEmptyLayoutForMainFrame();
-#endif
}
void webkitWebViewBaseDidFinishNavigation(WebKitWebViewBase* webkitWebViewBase, API::Navigation* navigation)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
controller->didFinishNavigation(navigation);
-#endif
}
void webkitWebViewBaseDidFailNavigation(WebKitWebViewBase* webkitWebViewBase, API::Navigation* navigation)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
controller->didFailNavigation(navigation);
-#endif
}
void webkitWebViewBaseDidSameDocumentNavigationForMainFrame(WebKitWebViewBase* webkitWebViewBase, SameDocumentNavigationType type)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
controller->didSameDocumentNavigationForMainFrame(type);
-#endif
}
void webkitWebViewBaseDidRestoreScrollPosition(WebKitWebViewBase* webkitWebViewBase)
{
-#if !USE(GTK4)
ViewGestureController* controller = webkitWebViewBaseViewGestureController(webkitWebViewBase);
if (controller && controller->isSwipeGestureEnabled())
webkitWebViewBase->priv->viewGestureController->didRestoreScrollPosition();
-#endif
}
#if GTK_CHECK_VERSION(3, 24, 0)
@@ -2792,3 +2911,10 @@
priv->isBlank = makeBlank;
gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
}
+
+void webkitWebViewBasePageGrabbedTouch(WebKitWebViewBase* webViewBase)
+{
+ WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ priv->pageGrabbedTouch = true;
+ gtk_gesture_set_state(priv->touchGestureGroup, GTK_EVENT_SEQUENCE_DENIED);
+}
Deleted: trunk/Source/WebKit/UIProcess/gtk/GestureController.cpp (277171 => 277172)
--- trunk/Source/WebKit/UIProcess/gtk/GestureController.cpp 2021-05-07 12:31:26 UTC (rev 277171)
+++ trunk/Source/WebKit/UIProcess/gtk/GestureController.cpp 2021-05-07 14:55:50 UTC (rev 277172)
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- *
- * 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 "GestureController.h"
-
-#if !USE(GTK4)
-
-#include <WebCore/Scrollbar.h>
-#include <gtk/gtk.h>
-
-namespace WebKit {
-using namespace WebCore;
-
-static const double maximumZoom = 3.0;
-
-GestureController::GestureController(GtkWidget* widget, std::unique_ptr<GestureControllerClient>&& client)
- : m_client(WTFMove(client))
- , m_dragGesture(widget, *m_client)
- , m_swipeGesture(widget, *m_client)
- , m_zoomGesture(widget, *m_client)
- , m_longpressGesture(widget, *m_client)
-{
-}
-
-bool GestureController::handleEvent(GdkEvent* event)
-{
- bool wasProcessingGestures = isProcessingGestures();
- bool touchEnd;
- m_dragGesture.handleEvent(event);
- m_swipeGesture.handleEvent(event);
- m_zoomGesture.handleEvent(event);
- m_longpressGesture.handleEvent(event);
- touchEnd = (gdk_event_get_event_type(event) == GDK_TOUCH_END) || (gdk_event_get_event_type(event) == GDK_TOUCH_CANCEL);
- return touchEnd ? wasProcessingGestures : isProcessingGestures();
-}
-
-bool GestureController::isProcessingGestures() const
-{
- return m_dragGesture.isActive() || m_swipeGesture.isActive() || m_zoomGesture.isActive() || m_longpressGesture.isActive();
-}
-
-GestureController::Gesture::Gesture(GtkGesture* gesture, GestureControllerClient& client)
- : m_gesture(adoptGRef(gesture))
- , m_client(client)
-{
- gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(m_gesture.get()), GTK_PHASE_NONE);
-}
-
-void GestureController::Gesture::reset()
-{
- gtk_event_controller_reset(GTK_EVENT_CONTROLLER(m_gesture.get()));
-}
-
-bool GestureController::Gesture::isActive() const
-{
- return gtk_gesture_is_active(m_gesture.get());
-}
-
-void GestureController::Gesture::handleEvent(GdkEvent* event)
-{
- gtk_event_controller_handle_event(GTK_EVENT_CONTROLLER(m_gesture.get()), event);
-}
-
-void GestureController::DragGesture::startDrag(GdkEvent* event)
-{
- ASSERT(!m_inDrag);
- m_client.startDrag(reinterpret_cast<GdkEventTouch*>(event), m_start);
-}
-
-void GestureController::DragGesture::handleDrag(GdkEvent* event, double x, double y)
-{
- ASSERT(m_inDrag);
- m_client.drag(reinterpret_cast<GdkEventTouch*>(event), m_start,
- FloatPoint::narrowPrecision((m_offset.x() - x) / Scrollbar::pixelsPerLineStep(), (m_offset.y() - y) / Scrollbar::pixelsPerLineStep()));
-}
-
-void GestureController::DragGesture::cancelDrag()
-{
- ASSERT(m_inDrag);
- m_client.cancelDrag();
-}
-
-void GestureController::DragGesture::handleTap(GdkEvent* event)
-{
- ASSERT(!m_inDrag);
- m_client.tap(reinterpret_cast<GdkEventTouch*>(event));
-}
-
-void GestureController::DragGesture::begin(DragGesture* dragGesture, double x, double y, GtkGesture* gesture)
-{
- GdkEventSequence* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
- gtk_gesture_set_sequence_state(gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
- dragGesture->m_inDrag = false;
- dragGesture->m_start.set(x, y);
- dragGesture->m_offset.set(0, 0);
-
- GtkWidget* widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
- unsigned delay;
- g_object_get(gtk_widget_get_settings(widget), "gtk-long-press-time", &delay, nullptr);
- dragGesture->m_longPressTimeout.startOneShot(1_ms * delay);
- dragGesture->startDrag(const_cast<GdkEvent*>(gtk_gesture_get_last_event(gesture, sequence)));
-}
-
-void GestureController::DragGesture::update(DragGesture* dragGesture, double x, double y, GtkGesture* gesture)
-{
- GdkEventSequence* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
- gtk_gesture_set_sequence_state(gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
-
- GtkWidget* widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
- if (!dragGesture->m_inDrag && gtk_drag_check_threshold(widget, dragGesture->m_start.x(), dragGesture->m_start.y(), dragGesture->m_start.x() + x, dragGesture->m_start.y() + y)) {
- dragGesture->m_inDrag = true;
- dragGesture->m_longPressTimeout.stop();
- }
-
- if (dragGesture->m_inDrag)
- dragGesture->handleDrag(const_cast<GdkEvent*>(gtk_gesture_get_last_event(gesture, sequence)), x, y);
- dragGesture->m_offset.set(x, y);
-}
-
-void GestureController::DragGesture::end(DragGesture* dragGesture, GdkEventSequence* sequence, GtkGesture* gesture)
-{
- dragGesture->m_longPressTimeout.stop();
- if (!gtk_gesture_handles_sequence(gesture, sequence)) {
- gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_DENIED);
- return;
- }
- if (!dragGesture->m_inDrag) {
- dragGesture->handleTap(const_cast<GdkEvent*>(gtk_gesture_get_last_event(gesture, sequence)));
- gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_DENIED);
- }
-}
-
-void GestureController::DragGesture::cancel(DragGesture* dragGesture, GdkEventSequence* sequence, GtkGesture* gesture)
-{
- dragGesture->m_longPressTimeout.stop();
- dragGesture->cancelDrag();
-}
-
-void GestureController::DragGesture::longPressFired()
-{
- m_inDrag = true;
-}
-
-GestureController::DragGesture::DragGesture(GtkWidget* widget, GestureControllerClient& client)
- : Gesture(gtk_gesture_drag_new(widget), client)
- , m_longPressTimeout(RunLoop::main(), this, &GestureController::DragGesture::longPressFired)
-{
- gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(m_gesture.get()), TRUE);
- g_signal_connect_swapped(m_gesture.get(), "drag-begin", G_CALLBACK(begin), this);
- g_signal_connect_swapped(m_gesture.get(), "drag-update", G_CALLBACK(update), this);
- g_signal_connect_swapped(m_gesture.get(), "end", G_CALLBACK(end), this);
- g_signal_connect_swapped(m_gesture.get(), "cancel", G_CALLBACK(cancel), this);
-}
-
-void GestureController::SwipeGesture::startMomentumScroll(GdkEvent* event, double velocityX, double velocityY)
-{
- m_client.swipe(reinterpret_cast<GdkEventTouch*>(event), FloatPoint::narrowPrecision(velocityX, velocityY));
-}
-
-void GestureController::SwipeGesture::swipe(SwipeGesture* swipeGesture, double velocityX, double velocityY, GtkGesture* gesture)
-{
- GdkEventSequence* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
- if (!gtk_gesture_handles_sequence(gesture, sequence))
- return;
-
- gtk_gesture_set_sequence_state(gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
-
- swipeGesture->startMomentumScroll(const_cast<GdkEvent*>(gtk_gesture_get_last_event(gesture, sequence)), velocityX, velocityY);
-}
-
-GestureController::SwipeGesture::SwipeGesture(GtkWidget* widget, GestureControllerClient& client)
- : Gesture(gtk_gesture_swipe_new(widget), client)
-{
- gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(m_gesture.get()), TRUE);
- g_signal_connect_swapped(m_gesture.get(), "swipe", G_CALLBACK(swipe), this);
-}
-
-void GestureController::ZoomGesture::begin(ZoomGesture* zoomGesture, GdkEventSequence*, GtkGesture* gesture)
-{
- gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_CLAIMED);
- zoomGesture->startZoom();
-}
-
-IntPoint GestureController::ZoomGesture::center() const
-{
- double x, y;
- gtk_gesture_get_bounding_box_center(m_gesture.get(), &x, &y);
- return IntPoint(x, y);
-}
-
-void GestureController::ZoomGesture::startZoom()
-{
- m_client.startZoom(center(), m_initialScale, m_initialPoint);
-}
-
-void GestureController::ZoomGesture::handleZoom()
-{
- FloatPoint scaledZoomCenter(m_initialPoint);
- scaledZoomCenter.scale(m_scale);
-
- m_client.zoom(m_scale, WebCore::roundedIntPoint(FloatPoint(scaledZoomCenter - m_viewPoint)));
-}
-
-void GestureController::ZoomGesture::scaleChanged(ZoomGesture* zoomGesture, double scale, GtkGesture*)
-{
- zoomGesture->m_scale = zoomGesture->m_initialScale * scale;
- if (zoomGesture->m_scale < 1.0)
- zoomGesture->m_scale = 1.0;
- if (zoomGesture->m_scale > maximumZoom)
- zoomGesture->m_scale = maximumZoom;
-
- zoomGesture->m_viewPoint = zoomGesture->center();
-
- if (zoomGesture->m_idle.isActive())
- return;
-
- zoomGesture->m_idle.startOneShot(0_s);
-}
-
-GestureController::ZoomGesture::ZoomGesture(GtkWidget* widget, GestureControllerClient& client)
- : Gesture(gtk_gesture_zoom_new(widget), client)
- , m_idle(RunLoop::main(), this, &GestureController::ZoomGesture::handleZoom)
-{
- g_signal_connect_swapped(m_gesture.get(), "begin", G_CALLBACK(begin), this);
- g_signal_connect_swapped(m_gesture.get(), "scale-changed", G_CALLBACK(scaleChanged), this);
-}
-
-void GestureController::LongPressGesture::longPressed(GdkEvent* event)
-{
- m_client.longPress(reinterpret_cast<GdkEventTouch*>(event));
-}
-
-void GestureController::LongPressGesture::pressed(LongPressGesture* longpressGesture, double x, double y, GtkGesture* gesture)
-{
- GdkEventSequence* sequence = gtk_gesture_single_get_current_sequence(GTK_GESTURE_SINGLE(gesture));
- if (!gtk_gesture_handles_sequence(gesture, sequence))
- return;
-
- gtk_gesture_set_sequence_state(gesture, sequence, GTK_EVENT_SEQUENCE_CLAIMED);
-
- longpressGesture->longPressed(const_cast<GdkEvent*>(gtk_gesture_get_last_event(gesture, sequence)));
-}
-
-GestureController::LongPressGesture::LongPressGesture(GtkWidget* widget, GestureControllerClient& client)
- : Gesture(gtk_gesture_long_press_new(widget), client)
-{
- gtk_gesture_single_set_touch_only(GTK_GESTURE_SINGLE(m_gesture.get()), TRUE);
- g_signal_connect_swapped(m_gesture.get(), "pressed", G_CALLBACK(pressed), this);
-}
-
-} // namespace WebKit
-
-#endif
Modified: trunk/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp (277171 => 277172)
--- trunk/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp 2021-05-07 12:31:26 UTC (rev 277171)
+++ trunk/Source/WebKit/UIProcess/gtk/ViewGestureControllerGtk.cpp 2021-05-07 14:55:50 UTC (rev 277172)
@@ -48,9 +48,9 @@
static const double swipeCancelArea = 0.5;
static const double swipeCancelVelocityThreshold = 0.4;
-static bool isEventStop(GdkEventScroll* event)
+static bool isEventStop(PlatformGtkScrollData* event)
{
- return gdk_event_is_scroll_stop_event(reinterpret_cast<GdkEvent*>(event));
+ return event->isEnd;
}
void ViewGestureController::platformTeardown()
@@ -58,45 +58,34 @@
cancelSwipe();
}
-bool ViewGestureController::PendingSwipeTracker::scrollEventCanStartSwipe(GdkEventScroll*)
+bool ViewGestureController::PendingSwipeTracker::scrollEventCanStartSwipe(PlatformGtkScrollData*)
{
return true;
}
-bool ViewGestureController::PendingSwipeTracker::scrollEventCanEndSwipe(GdkEventScroll* event)
+bool ViewGestureController::PendingSwipeTracker::scrollEventCanEndSwipe(PlatformGtkScrollData* event)
{
return isEventStop(event);
}
-bool ViewGestureController::PendingSwipeTracker::scrollEventCanInfluenceSwipe(GdkEventScroll* event)
+bool ViewGestureController::PendingSwipeTracker::scrollEventCanInfluenceSwipe(PlatformGtkScrollData* event)
{
- GdkDevice* device = gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event));
- GdkInputSource source = gdk_device_get_source(device);
-
- bool isDeviceAllowed = source == GDK_SOURCE_TOUCHPAD || source == GDK_SOURCE_TOUCHSCREEN || m_viewGestureController.m_isSimulatedSwipe;
-
- return gdk_event_get_scroll_deltas(reinterpret_cast<GdkEvent*>(event), nullptr, nullptr) && isDeviceAllowed;
+ return true;
}
-static bool isTouchEvent(GdkEventScroll* event)
+static bool isTouchEvent(PlatformGtkScrollData* event)
{
- GdkDevice* device = gdk_event_get_source_device(reinterpret_cast<GdkEvent*>(event));
- GdkInputSource source = gdk_device_get_source(device);
-
- return source == GDK_SOURCE_TOUCHSCREEN;
+ return event->isTouch;
}
-FloatSize ViewGestureController::PendingSwipeTracker::scrollEventGetScrollingDeltas(GdkEventScroll* event)
+FloatSize ViewGestureController::PendingSwipeTracker::scrollEventGetScrollingDeltas(PlatformGtkScrollData* event)
{
double multiplier = isTouchEvent(event) ? Scrollbar::pixelsPerLineStep() : gtkScrollDeltaMultiplier;
- double xDelta, yDelta;
- gdk_event_get_scroll_deltas(reinterpret_cast<GdkEvent*>(event), &xDelta, &yDelta);
-
- // GdkEventScroll deltas are inverted compared to NSEvent, so invert them again
- return -FloatSize(xDelta, yDelta) * multiplier;
+ // GTK deltas are inverted compared to NSEvent, so invert them again
+ return -FloatSize(event->delta, 0) * multiplier;
}
-bool ViewGestureController::handleScrollWheelEvent(GdkEventScroll* event)
+bool ViewGestureController::handleScrollWheelEvent(PlatformGtkScrollData* event)
{
return m_swipeProgressTracker.handleEvent(event) || m_pendingSwipeTracker.handleEvent(event);
}
@@ -146,7 +135,7 @@
m_cancelled = false;
}
-bool ViewGestureController::SwipeProgressTracker::handleEvent(GdkEventScroll* event)
+bool ViewGestureController::SwipeProgressTracker::handleEvent(PlatformGtkScrollData* event)
{
// Don't allow scrolling while the next page is loading
if (m_state == State::Finishing)
@@ -175,9 +164,8 @@
return false;
}
- uint32_t eventTime = gdk_event_get_time(reinterpret_cast<GdkEvent*>(event));
- double eventDeltaX;
- gdk_event_get_scroll_deltas(reinterpret_cast<GdkEvent*>(event), &eventDeltaX, nullptr);
+ uint32_t eventTime = event->eventTime;
+ double eventDeltaX = event->delta;
double deltaX = -eventDeltaX;
if (isTouchEvent(event)) {
@@ -281,6 +269,7 @@
m_viewGestureController.endSwipeGesture(m_targetItem.get(), m_cancelled);
}
+#if !USE(GTK4)
GRefPtr<GtkStyleContext> ViewGestureController::createStyleContext(const char* name)
{
bool isRTL = m_webPageProxy.userInterfaceLayoutDirection() == WebCore::UserInterfaceLayoutDirection::RTL;
@@ -320,6 +309,7 @@
return width;
}
+#endif
void ViewGestureController::beginSwipeGesture(WebBackForwardListItem* targetItem, SwipeDirection direction)
{
@@ -346,6 +336,7 @@
}
}
+#if !USE(GTK4)
if (!m_currentSwipeSnapshotPattern) {
GdkRGBA color;
auto* context = gtk_widget_get_style_context(m_webPageProxy.viewWidget());
@@ -382,6 +373,7 @@
m_swipeOutlineSize = elementWidth(context.get());
if (m_swipeOutlineSize)
m_swipeOutlinePattern = createElementPattern(context.get(), m_swipeOutlineSize, size.height(), scale);
+#endif
}
void ViewGestureController::handleSwipeGesture(WebBackForwardListItem*, double, SwipeDirection)
@@ -399,6 +391,49 @@
}
}
+#if USE(GTK4)
+void ViewGestureController::snapshot(GtkSnapshot* snapshot, GskRenderNode* pageRenderNode)
+{
+ bool swipingLeft = isPhysicallySwipingLeft(m_swipeProgressTracker.direction());
+ bool swipingBack = m_swipeProgressTracker.direction() == SwipeDirection::Back;
+ bool isRTL = m_webPageProxy.userInterfaceLayoutDirection() == WebCore::UserInterfaceLayoutDirection::RTL;
+ float progress = m_swipeProgressTracker.progress();
+
+ auto size = m_webPageProxy.drawingArea()->size();
+ int width = size.width();
+ int height = size.height();
+ double scale = m_webPageProxy.deviceScaleFactor();
+
+ double swipingLayerOffset = (swipingLeft ? 0 : width) + floor(width * progress * scale) / scale;
+
+ double dimmingProgress = swipingLeft ? 1 - progress : -progress;
+ if (isRTL) {
+ dimmingProgress = 1 - dimmingProgress;
+ swipingLayerOffset = -(width - swipingLayerOffset);
+ }
+
+ gtk_snapshot_save(snapshot);
+
+ graphene_point_t translation = { static_cast<float>(swipingLayerOffset), 0 };
+ if (!swipingBack) {
+ gtk_snapshot_append_node(snapshot, pageRenderNode);
+ gtk_snapshot_translate(snapshot, &translation);
+ }
+
+ graphene_rect_t rect = { 0, 0, (float)width, (float)height };
+ auto* cr = gtk_snapshot_append_cairo(snapshot, &rect);
+ cairo_set_source(cr, m_currentSwipeSnapshotPattern.get());
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_fill(cr);
+
+ if (swipingBack) {
+ gtk_snapshot_translate(snapshot, &translation);
+ gtk_snapshot_append_node(snapshot, pageRenderNode);
+ }
+
+ gtk_snapshot_restore(snapshot);
+}
+#else
void ViewGestureController::draw(cairo_t* cr, cairo_pattern_t* pageGroup)
{
bool swipingLeft = isPhysicallySwipingLeft(m_swipeProgressTracker.direction());
@@ -489,6 +524,7 @@
cairo_restore(cr);
}
+#endif
void ViewGestureController::removeSwipeSnapshot()
{
@@ -518,37 +554,6 @@
m_swipeProgressTracker.reset();
}
-static GUniquePtr<GdkEvent> createScrollEvent(GtkWidget* widget, double xDelta, double yDelta)
-{
- GdkWindow* window = gtk_widget_get_window(widget);
-
- int x, y;
- gdk_window_get_root_origin(window, &x, &y);
-
- int width = gdk_window_get_width(window);
- int height = gdk_window_get_height(window);
-
- GUniquePtr<GdkEvent> event(gdk_event_new(GDK_SCROLL));
- event->scroll.time = GDK_CURRENT_TIME;
- event->scroll.x = width / 2;
- event->scroll.y = height / 2;
- event->scroll.x_root = x + width / 2;
- event->scroll.y_root = y + height / 2;
- event->scroll.direction = GDK_SCROLL_SMOOTH;
- event->scroll.delta_x = xDelta;
- event->scroll.delta_y = yDelta;
- event->scroll.state = 0;
- event->scroll.is_stop = !xDelta && !yDelta;
- event->scroll.window = GDK_WINDOW(g_object_ref(window));
- gdk_event_set_screen(event.get(), gdk_window_get_screen(window));
-
- GdkDevice* pointer = gdk_seat_get_pointer(gdk_display_get_default_seat(gdk_window_get_display(window)));
- gdk_event_set_device(event.get(), pointer);
- gdk_event_set_source_device(event.get(), pointer);
-
- return event;
-}
-
bool ViewGestureController::beginSimulatedSwipeInDirectionForTesting(SwipeDirection direction)
{
if (!canSwipeInDirection(direction))
@@ -561,8 +566,8 @@
if (isPhysicallySwipingLeft(direction))
delta = -delta;
- GUniquePtr<GdkEvent> event = createScrollEvent(m_webPageProxy.viewWidget(), delta, 0);
- gtk_widget_event(m_webPageProxy.viewWidget(), event.get());
+ PlatformGtkScrollData scrollData = { .delta = delta, .eventTime = GDK_CURRENT_TIME, .isTouch = false, .isEnd = false };
+ handleScrollWheelEvent(&scrollData);
return true;
}
@@ -569,9 +574,8 @@
bool ViewGestureController::completeSimulatedSwipeInDirectionForTesting(SwipeDirection)
{
- GUniquePtr<GdkEvent> event = createScrollEvent(m_webPageProxy.viewWidget(), 0, 0);
- gtk_widget_event(m_webPageProxy.viewWidget(), event.get());
-
+ PlatformGtkScrollData scrollData = { .delta = 0, .eventTime = GDK_CURRENT_TIME, .isTouch = false, .isEnd = true };
+ handleScrollWheelEvent(&scrollData);
m_isSimulatedSwipe = false;
return true;