From 4457be688da16811d2e558519b566b2605de346d Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 9 Jul 2015 19:18:09 +0200 Subject: [PATCH] gtkgesture: Handle touchpad events These will be mutually exclusive with touch events, so it won't be possible to trigger gestures through mixed input and whatnot. The accounting of touchpad events is slightly different, there will be a single internal PointData struct, stored in the hashtable with the NULL event sequence/key (same than pointer events in this regard), just that the events stored will be GdkEventTouchpad*, so will hold information about all fingers at once. But this difference is just internal, the GtkGesture API doesn't make explicit assumptions about the number of points (the closest to a per-point query API is gtk_gesture_get_sequences()). All signals emitted just contain the last changed GdkEventSequence, and API takes GdkEventSequences, so everything is consistent with sequence=NULL for touchpad events. --- gtk/gtkgesture.c | 87 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/gtk/gtkgesture.c b/gtk/gtkgesture.c index 04c169e1aa..53be0c6075 100644 --- a/gtk/gtkgesture.c +++ b/gtk/gtkgesture.c @@ -152,6 +152,7 @@ struct _GtkGesturePrivate GList *group_link; guint n_points; guint recognized : 1; + guint touchpad : 1; }; static guint signals[N_SIGNALS] = { 0 }; @@ -222,6 +223,42 @@ gtk_gesture_finalize (GObject *object) G_OBJECT_CLASS (gtk_gesture_parent_class)->finalize (object); } +static guint +_gtk_gesture_get_n_touchpad_points (GtkGesture *gesture, + gboolean only_active) +{ + GtkGesturePrivate *priv; + PointData *data; + + priv = gtk_gesture_get_instance_private (gesture); + + if (!priv->touchpad) + return 0; + + data = g_hash_table_lookup (priv->points, NULL); + + if (!data) + return 0; + + if (only_active && + (data->state == GTK_EVENT_SEQUENCE_DENIED || + (data->event->type == GDK_TOUCHPAD_SWIPE && + data->event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_END) || + (data->event->type == GDK_TOUCHPAD_PINCH && + data->event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END))) + return 0; + + switch (data->event->type) + { + case GDK_TOUCHPAD_SWIPE: + return data->event->touchpad_swipe.n_fingers; + case GDK_TOUCHPAD_PINCH: + return data->event->touchpad_pinch.n_fingers; + default: + return 0; + } +} + static guint _gtk_gesture_get_n_touch_points (GtkGesture *gesture, gboolean only_active) @@ -252,7 +289,14 @@ static guint _gtk_gesture_get_n_physical_points (GtkGesture *gesture, gboolean only_active) { - return _gtk_gesture_get_n_touch_points (gesture, only_active); + GtkGesturePrivate *priv; + + priv = gtk_gesture_get_instance_private (gesture); + + if (priv->touchpad) + return _gtk_gesture_get_n_touchpad_points (gesture, only_active); + else + return _gtk_gesture_get_n_touch_points (gesture, only_active); } static gboolean @@ -428,7 +472,7 @@ _gtk_gesture_update_point (GtkGesture *gesture, GdkWindow *widget_window; GtkGesturePrivate *priv; GdkDevice *device; - gboolean existed; + gboolean existed, touchpad; PointData *data; if (!gdk_event_get_coords (event, NULL, NULL)) @@ -445,6 +489,8 @@ _gtk_gesture_update_point (GtkGesture *gesture, if (!widget_window) return FALSE; + touchpad = EVENT_IS_TOUCHPAD_GESTURE (event); + if (add) { /* If the event happens with the wrong device, or @@ -456,6 +502,12 @@ _gtk_gesture_update_point (GtkGesture *gesture, return FALSE; if (priv->user_window && priv->user_window != widget_window) return FALSE; + + /* Make touchpad and touchscreen gestures mutually exclusive */ + if (touchpad && g_hash_table_size (priv->points) > 0) + return FALSE; + else if (!touchpad && priv->touchpad) + return FALSE; } else if (!priv->device || !priv->window) return FALSE; @@ -474,6 +526,7 @@ _gtk_gesture_update_point (GtkGesture *gesture, { priv->window = widget_window; priv->device = device; + priv->touchpad = touchpad; } data = g_new0 (PointData, 1); @@ -511,6 +564,7 @@ _gtk_gesture_check_empty (GtkGesture *gesture) { priv->window = NULL; priv->device = NULL; + priv->touchpad = FALSE; } } @@ -609,7 +663,11 @@ gtk_gesture_handle_event (GtkEventController *controller, priv->last_sequence = sequence; if (event->type == GDK_BUTTON_PRESS || - event->type == GDK_TOUCH_BEGIN) + event->type == GDK_TOUCH_BEGIN || + (event->type == GDK_TOUCHPAD_SWIPE && + event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN) || + (event->type == GDK_TOUCHPAD_PINCH && + event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)) { if (_gtk_gesture_update_point (gesture, event, TRUE)) { @@ -639,7 +697,11 @@ gtk_gesture_handle_event (GtkEventController *controller, } } else if (event->type == GDK_BUTTON_RELEASE || - event->type == GDK_TOUCH_END) + event->type == GDK_TOUCH_END || + (event->type == GDK_TOUCHPAD_SWIPE && + event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_END) || + (event->type == GDK_TOUCHPAD_PINCH && + event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_END)) { if (_gtk_gesture_update_point (gesture, event, FALSE)) { @@ -651,7 +713,11 @@ gtk_gesture_handle_event (GtkEventController *controller, } } else if (event->type == GDK_MOTION_NOTIFY || - event->type == GDK_TOUCH_UPDATE) + event->type == GDK_TOUCH_UPDATE || + (event->type == GDK_TOUCHPAD_SWIPE && + event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE) || + (event->type == GDK_TOUCHPAD_PINCH && + event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_UPDATE)) { if (event->type == GDK_MOTION_NOTIFY) { @@ -668,7 +734,16 @@ gtk_gesture_handle_event (GtkEventController *controller, } else if (event->type == GDK_TOUCH_CANCEL) { - _gtk_gesture_cancel_sequence (gesture, sequence); + if (!priv->touchpad) + _gtk_gesture_cancel_sequence (gesture, sequence); + } + else if ((event->type == GDK_TOUCHPAD_SWIPE && + event->touchpad_swipe.phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL) || + (event->type == GDK_TOUCHPAD_PINCH && + event->touchpad_pinch.phase == GDK_TOUCHPAD_GESTURE_PHASE_CANCEL)) + { + if (priv->touchpad) + _gtk_gesture_cancel_sequence (gesture, sequence); } else if (event->type == GDK_GRAB_BROKEN) {