diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 6736e4d5c..bbe7a2116 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -3668,6 +3668,7 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage, { gboolean pointer_in_grab, pointer_in_old_grab; gboolean implicit_grab_cancelled = FALSE; + unsigned int implicit_grab_n_removed = 0, implicit_grab_n_remaining = 0; ClutterEventType event_type = CLUTTER_NOTHING; ClutterActor *topmost, *deepmost; @@ -3688,9 +3689,6 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage, ClutterInputDevice *device = entry->device; ClutterEventSequence *sequence = entry->sequence; unsigned int i; - unsigned int n_removed = 0; - - implicit_grab_cancelled = TRUE; for (i = 0; i < entry->event_emission_chain->len; i++) { @@ -3702,11 +3700,11 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage, if (!clutter_actor_contains (grab_actor, receiver->actor)) { g_clear_object (&receiver->actor); - n_removed++; + implicit_grab_n_removed++; } else { - implicit_grab_cancelled = FALSE; + implicit_grab_n_remaining++; } } else if (receiver->action) @@ -3720,23 +3718,27 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage, device, sequence); g_clear_object (&receiver->action); - n_removed++; + implicit_grab_n_removed++; } else { - implicit_grab_cancelled = FALSE; + implicit_grab_n_remaining++; } } } - if (n_removed > 0) - { - CLUTTER_NOTE (GRABS, - "[grab=%p device=%p sequence=%p implicit_grab_cancelled=%d] " - "Cancelled %u actors and actions on implicit grab due to new seat grab", - stage->priv->topmost_grab, device, sequence, implicit_grab_cancelled, - n_removed); - } + /* Seat grabs win over implicit grabs, so we default to cancel the ongoing + * implicit grab. If the seat grab contains one or more actors from + * the implicit grab though, the implicit grab remains in effect. + */ + implicit_grab_cancelled = implicit_grab_n_remaining == 0; + + CLUTTER_NOTE (GRABS, + "[grab=%p device=%p sequence=%p implicit_grab_cancelled=%d] " + "Cancelled %u actors and actions (%u remaining) on implicit " + "grab due to new seat grab", + stage->priv->topmost_grab, device, sequence, implicit_grab_cancelled, + implicit_grab_n_removed, implicit_grab_n_remaining); } /* Equate NULL actors to the stage here, to ease calculations further down. */ @@ -3747,7 +3749,8 @@ clutter_stage_notify_grab_on_pointer_entry (ClutterStage *stage, if (grab_actor == old_grab_actor) { - g_assert (!implicit_grab_cancelled); + g_assert ((implicit_grab_n_removed == 0 && implicit_grab_n_remaining == 0) || + !implicit_grab_cancelled); return; }