diff options
author | Ray Strode <rstrode@redhat.com> | 2021-10-06 22:03:46 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2021-10-07 09:26:27 -0400 |
commit | 57ffff35496f14d1712945dea83e7e3e0f74323b (patch) | |
tree | ab9cad9da7bcefce0069a4b0fd1097673fb47e07 | |
parent | 867db93043dd3c93d8ccb6cb197d4a3687d3a5e5 (diff) | |
download | mutter-57ffff35496f14d1712945dea83e7e3e0f74323b.tar.gz |
clutter-gester-action: Cancel gesture when a device gets grabbedwip/halfline/gesture-osk-fix
If an actor takes a grab on an input device, that's a good indicator
that the user expects input to be handled solely by the actor and
any gestures that are taking place aren't meant for the stage.
At the moment, the gesture code has no insight into when a grab
gets taken, though. If a grab does get taken it missed out on the
motion and button release events that have now been redirected to
the actor.
Those missed events can confuse the event processing code into thinking
the user is doing a multi-press gesture, when the user is actually just
e.g., doing a series of clicks.
This commit addresses the problem by installing an event filter that
can see the events before they're delivered to the grabbed actor.
The filter checkes if a device a grabbed, and if so cancels any
in-flight gestures that are currently getting processed.
-rw-r--r-- | clutter/clutter/clutter-gesture-action.c | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/clutter/clutter/clutter-gesture-action.c b/clutter/clutter/clutter-gesture-action.c index f938a549a..008668f97 100644 --- a/clutter/clutter/clutter-gesture-action.c +++ b/clutter/clutter/clutter-gesture-action.c @@ -120,6 +120,7 @@ struct _ClutterGestureActionPrivate gulong actor_capture_id; gulong stage_capture_id; + guint event_filter_id; ClutterGestureTriggerEdge edge; float distance_x, distance_y; @@ -312,6 +313,7 @@ cancel_gesture (ClutterGestureAction *action) priv->in_gesture = FALSE; + g_clear_handle_id (&priv->event_filter_id, clutter_event_remove_filter); g_clear_signal_handler (&priv->stage_capture_id, priv->stage); actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); @@ -354,6 +356,26 @@ begin_gesture (ClutterGestureAction *action, } static gboolean +event_filter_cb (const ClutterEvent *event, + ClutterGestureAction *action) +{ + ClutterInputDevice *device = NULL; + ClutterActor *grabbed_actor; + + device = clutter_event_get_device (event); + + if (device == NULL) + return CLUTTER_EVENT_PROPAGATE; + + grabbed_actor = clutter_input_device_get_grabbed_actor (device); + + if (grabbed_actor != NULL) + cancel_gesture (action); + + return CLUTTER_EVENT_PROPAGATE; +} + +static gboolean stage_captured_event_cb (ClutterActor *stage, ClutterEvent *event, ClutterGestureAction *action) @@ -383,21 +405,7 @@ stage_captured_event_cb (ClutterActor *stage, switch (clutter_event_type (event)) { case CLUTTER_MOTION: - { - ClutterModifierType mods = clutter_event_get_state (event); - - /* we might miss a button-release event in case of grabs, - * so we need to check whether the button is still down - * during a motion event - */ - if (!(mods & CLUTTER_BUTTON1_MASK)) - { - cancel_gesture (action); - return CLUTTER_EVENT_PROPAGATE; - } - } /* Follow same code path as a touch event update */ - case CLUTTER_TOUCH_UPDATE: if (!priv->in_gesture) { @@ -482,7 +490,10 @@ stage_captured_event_cb (ClutterActor *stage, } if (priv->points->len == 0) - g_clear_signal_handler (&priv->stage_capture_id, priv->stage); + { + g_clear_handle_id (&priv->event_filter_id, clutter_event_remove_filter); + g_clear_signal_handler (&priv->stage_capture_id, priv->stage); + } return CLUTTER_EVENT_PROPAGATE; } @@ -508,6 +519,12 @@ actor_captured_event_cb (ClutterActor *actor, if (priv->stage == NULL) priv->stage = clutter_actor_get_stage (actor); + if (priv->event_filter_id == 0) + priv->event_filter_id = clutter_event_add_filter (priv->stage, + (ClutterEventFilterFunc) event_filter_cb, + NULL, + action); + if (priv->stage_capture_id == 0) priv->stage_capture_id = g_signal_connect_after (priv->stage, "captured-event", @@ -542,12 +559,11 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta, priv->actor_capture_id = 0; } - if (priv->stage_capture_id != 0) + if (priv->stage != NULL) { - if (priv->stage != NULL) - g_clear_signal_handler (&priv->stage_capture_id, priv->stage); + g_clear_handle_id (&priv->event_filter_id, clutter_event_remove_filter); + g_clear_signal_handler (&priv->stage_capture_id, priv->stage); - priv->stage_capture_id = 0; priv->stage = NULL; } |