1
0
Fork 0

clutter: Add API to create inactive ClutterGrabs, and activate them explicitly

This gives greater control to the callers on the place where a grab is being
activated, this may make a difference in the handling of crossing events
triggered through it, e.g. by having callers rely on having already obtained
a ClutterGrab prior to handling the resulting effects.

The "input only" grab has also been turned inactive by default, in order to
to have the ClutterGrab pointer available for checks at the MetaWaylandEventHandler
focus changing methods triggered through grab activation.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3463
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3747>
This commit is contained in:
Carlos Garnacho 2024-05-11 11:59:13 +02:00
parent 5ba364a947
commit 8e5f3a1f83
5 changed files with 69 additions and 14 deletions

View file

@ -36,6 +36,9 @@
CLUTTER_EXPORT
G_DECLARE_FINAL_TYPE (ClutterGrab, clutter_grab, CLUTTER, GRAB, GObject)
CLUTTER_EXPORT
void clutter_grab_activate (ClutterGrab *grab);
CLUTTER_EXPORT
void clutter_grab_dismiss (ClutterGrab *grab);

View file

@ -3834,18 +3834,45 @@ clutter_stage_grab_full (ClutterStage *stage,
ClutterActor *actor,
gboolean owns_actor)
{
ClutterStagePrivate *priv;
ClutterGrab *grab;
gboolean was_grabbed;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
g_return_val_if_fail (stage ==
(ClutterStage *) _clutter_actor_get_stage_internal (actor),
NULL);
return clutter_grab_new (stage, actor, owns_actor);
}
/**
* clutter_grab_activate:
* @grab: a `ClutterGrab`
*
* Activates a grab onto its assigned actor. Events will be propagated as
* usual inside its hierarchy. Activating an already active grab will have
* no side effects.
*
* This method is necessary for grabs obtained through
* [method@Stage.grab_inactive]. Grabs obtained through [method@Stage.grab]
* will be activated implicitly.
*
* to undo the effects of this function, call [method@Grab.dismiss].
**/
void
clutter_grab_activate (ClutterGrab *grab)
{
ClutterStage *stage;
ClutterStagePrivate *priv;
gboolean was_grabbed;
g_return_if_fail (CLUTTER_IS_GRAB (grab));
stage = grab->stage;
priv = clutter_stage_get_instance_private (stage);
/* This grab is already active */
if (grab->prev || grab->next || priv->topmost_grab == grab)
return;
if (!priv->topmost_grab)
{
ClutterContext *context;
@ -3858,8 +3885,6 @@ clutter_stage_grab_full (ClutterStage *stage,
clutter_seat_grab (seat, clutter_get_current_event_time ());
}
grab = clutter_grab_new (stage, actor, owns_actor);
grab->prev = NULL;
grab->next = priv->topmost_grab;
@ -3880,10 +3905,10 @@ clutter_stage_grab_full (ClutterStage *stage,
CLUTTER_NOTE (GRABS,
"[grab=%p] Attached seat grab (n_grabs: %u) on actor: %s",
grab, n_grabs, _clutter_actor_get_debug_name (actor));
grab, n_grabs, _clutter_actor_get_debug_name (grab->actor));
}
clutter_actor_attach_grab (actor, grab);
clutter_actor_attach_grab (grab->actor, grab);
clutter_stage_notify_grab (stage, grab, grab->next);
if (was_grabbed != !!priv->topmost_grab)
@ -3891,8 +3916,6 @@ clutter_stage_grab_full (ClutterStage *stage,
if (grab->next)
clutter_grab_notify (grab->next);
return grab;
}
/**
@ -3909,6 +3932,28 @@ clutter_stage_grab_full (ClutterStage *stage,
ClutterGrab *
clutter_stage_grab (ClutterStage *stage,
ClutterActor *actor)
{
ClutterGrab *grab;
grab = clutter_stage_grab_full (stage, actor, FALSE);
clutter_grab_activate (grab);
return grab;
}
/**
* clutter_stage_grab_inactive:
* @stage: The #ClutterStage
* @actor: The actor that will grab input
*
* Creates an inactive grab. The grab will become effective
* after [method@Grab.activate].
*
* Returns: (transfer full): an opaque #ClutterGrab handle
**/
ClutterGrab *
clutter_stage_grab_inactive (ClutterStage *stage,
ClutterActor *actor)
{
return clutter_stage_grab_full (stage, actor, FALSE);
}

View file

@ -223,6 +223,10 @@ CLUTTER_EXPORT
ClutterGrab * clutter_stage_grab (ClutterStage *stage,
ClutterActor *actor);
CLUTTER_EXPORT
ClutterGrab * clutter_stage_grab_inactive (ClutterStage *stage,
ClutterActor *actor);
CLUTTER_EXPORT
ClutterActor * clutter_stage_get_grab_actor (ClutterStage *stage);

View file

@ -628,6 +628,7 @@ grab_input_only (void)
grab = clutter_stage_grab_input_only (CLUTTER_STAGE (data.stage),
handle_input_only_event,
data.events, NULL);
clutter_grab_activate (grab);
event_log_compare ((EventLog *) &grab1_log, data.events);
clutter_virtual_input_device_notify_button (pointer,

View file

@ -303,6 +303,8 @@ meta_wayland_input_attach_event_handler (MetaWaylandInput *input,
grab_handle_event,
input,
NULL);
clutter_grab_activate (input->grab);
g_signal_connect_swapped (input->grab, "notify::revoked",
G_CALLBACK (on_grab_revocation_change),
input);