From 80d6735ffc328137fdc366b777fe65b0bf09ab02 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 24 Jun 2014 19:08:51 +0200 Subject: [PATCH] gesture: Consume the event triggering ::begin if reset within the handler If the event triggers GtkGesture::begin, and the handler ends up resetting the gesture (say, due to taking a grab somewhere else within the handler), still take the event as "managed", as it actually triggered recognition, even if just to end abruptly. https://bugzilla.gnome.org/show_bug.cgi?id=731711 --- gtk/gtkgesture.c | 53 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/gtk/gtkgesture.c b/gtk/gtkgesture.c index c7526299bc..dae458ddbb 100644 --- a/gtk/gtkgesture.c +++ b/gtk/gtkgesture.c @@ -287,21 +287,29 @@ _gtk_gesture_do_check (GtkGesture *gesture) } static gboolean -_gtk_gesture_check_recognized (GtkGesture *gesture, - GdkEventSequence *sequence) +_gtk_gesture_has_matching_touchpoints (GtkGesture *gesture) { GtkGesturePrivate *priv = gtk_gesture_get_instance_private (gesture); guint current_n_points; current_n_points = _gtk_gesture_effective_n_points (gesture); - if (priv->recognized && - (current_n_points != priv->n_points || - g_hash_table_size (priv->points) != priv->n_points)) + return (current_n_points == priv->n_points && + g_hash_table_size (priv->points) == priv->n_points); +} + +static gboolean +_gtk_gesture_check_recognized (GtkGesture *gesture, + GdkEventSequence *sequence) +{ + GtkGesturePrivate *priv = gtk_gesture_get_instance_private (gesture); + gboolean has_matching_touchpoints; + + has_matching_touchpoints = _gtk_gesture_has_matching_touchpoints (gesture); + + if (priv->recognized && !has_matching_touchpoints) _gtk_gesture_set_recognized (gesture, FALSE, sequence); - else if (!priv->recognized && - current_n_points == priv->n_points && - g_hash_table_size (priv->points) == priv->n_points && + else if (!priv->recognized && has_matching_touchpoints && _gtk_gesture_do_check (gesture)) _gtk_gesture_set_recognized (gesture, TRUE, sequence); @@ -576,16 +584,31 @@ gtk_gesture_handle_event (GtkEventController *controller, { case GDK_BUTTON_PRESS: case GDK_TOUCH_BEGIN: - if (_gtk_gesture_update_point (gesture, event, TRUE) && - _gtk_gesture_check_recognized (gesture, sequence)) + if (_gtk_gesture_update_point (gesture, event, TRUE)) { - PointData *data; + gboolean triggered_recognition; - data = g_hash_table_lookup (priv->points, sequence); + triggered_recognition = + !was_recognized && _gtk_gesture_has_matching_touchpoints (gesture); - /* If the sequence was claimed early, the press event will be consumed */ - if (gtk_gesture_get_sequence_state (gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED) - data->press_handled = TRUE; + if (_gtk_gesture_check_recognized (gesture, sequence)) + { + PointData *data; + + data = g_hash_table_lookup (priv->points, sequence); + + /* If the sequence was claimed early, the press event will be consumed */ + if (gtk_gesture_get_sequence_state (gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED) + data->press_handled = TRUE; + } + else if (triggered_recognition && g_hash_table_size (priv->points) == 0) + { + /* Recognition was triggered, but the gesture reset during + * ::begin emission. Still, recognition was strictly triggered, + * so the event should be consumed. + */ + return TRUE; + } } break;