1
0
Fork 0

clutter: Carry accounting of grabs in the ClutterActors holding them

And make it required that actors must be mapped to hold a grab. These
grabs will be automatically undone when the actor is unmapped.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2068>
This commit is contained in:
Carlos Garnacho 2021-10-28 14:04:58 +02:00 committed by Marge Bot
parent 2e94efddc9
commit 1713f791cb
4 changed files with 71 additions and 4 deletions

View file

@ -23,6 +23,7 @@
#define __CLUTTER_ACTOR_PRIVATE_H__
#include <clutter/clutter-actor.h>
#include <clutter/clutter-grab.h>
G_BEGIN_DECLS
@ -272,6 +273,11 @@ gboolean clutter_actor_get_redraw_clip (ClutterActor *self,
ClutterPaintVolume *dst_old_pv,
ClutterPaintVolume *dst_new_pv);
void clutter_actor_attach_grab (ClutterActor *actor,
ClutterGrab *grab);
void clutter_actor_detach_grab (ClutterActor *actor,
ClutterGrab *grab);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */

View file

@ -801,6 +801,7 @@ struct _ClutterActorPrivate
gulong layout_changed_id;
GList *stage_views;
GList *grabs;
/* bitfields: KEEP AT THE END */
@ -1633,6 +1634,25 @@ maybe_unset_key_focus (ClutterActor *self)
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL);
}
static void
clutter_actor_clear_grabs (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
ClutterActor *stage;
if (!priv->grabs)
return;
stage = _clutter_actor_get_stage_internal (self);
g_assert (stage != NULL);
/* Undo every grab that the actor may hold, priv->grabs
* will be updated internally in clutter_stage_unlink_grab().
*/
while (priv->grabs)
clutter_stage_unlink_grab (CLUTTER_STAGE (stage), priv->grabs->data);
}
static void
clutter_actor_real_unmap (ClutterActor *self)
{
@ -1678,6 +1698,8 @@ clutter_actor_real_unmap (ClutterActor *self)
/* relinquish keyboard focus if we were unmapped while owning it */
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
maybe_unset_key_focus (self);
clutter_actor_clear_grabs (self);
}
/**
@ -5586,6 +5608,8 @@ clutter_actor_finalize (GObject *object)
_clutter_actor_get_debug_name ((ClutterActor *) object),
g_type_name (G_OBJECT_TYPE (object)));
/* No new grabs should have happened after unmapping */
g_assert (priv->grabs == NULL);
g_free (priv->name);
g_free (priv->debug_name);
@ -19684,3 +19708,21 @@ clutter_actor_get_redraw_clip (ClutterActor *self,
return TRUE;
}
void
clutter_actor_attach_grab (ClutterActor *self,
ClutterGrab *grab)
{
ClutterActorPrivate *priv = self->priv;
priv->grabs = g_list_prepend (priv->grabs, grab);
}
void
clutter_actor_detach_grab (ClutterActor *self,
ClutterGrab *grab)
{
ClutterActorPrivate *priv = self->priv;
priv->grabs = g_list_remove (priv->grabs, grab);
}

View file

@ -22,6 +22,7 @@
#ifndef __CLUTTER_STAGE_PRIVATE_H__
#define __CLUTTER_STAGE_PRIVATE_H__
#include <clutter/clutter-grab.h>
#include <clutter/clutter-stage-window.h>
#include <clutter/clutter-stage.h>
#include <clutter/clutter-input-device.h>
@ -149,6 +150,9 @@ ClutterActor * clutter_stage_pick_and_update_device (ClutterStage *s
graphene_point_t point,
uint32_t time_ms);
void clutter_stage_unlink_grab (ClutterStage *self,
ClutterGrab *grab);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View file

@ -3873,20 +3873,23 @@ clutter_stage_grab (ClutterStage *stage,
priv->topmost_grab->prev = grab;
priv->topmost_grab = grab;
clutter_actor_attach_grab (actor, grab);
clutter_stage_notify_grab (stage, grab, grab->next);
return grab;
}
void
clutter_grab_dismiss (ClutterGrab *grab)
clutter_stage_unlink_grab (ClutterStage *stage,
ClutterGrab *grab)
{
ClutterStagePrivate *priv;
ClutterStagePrivate *priv = stage->priv;
ClutterGrab *prev, *next;
g_return_if_fail (grab != NULL);
/* This grab is already detached */
if (!grab->prev && !grab->next && priv->topmost_grab != grab)
return;
priv = grab->stage->priv;
prev = grab->prev;
next = grab->next;
@ -3903,6 +3906,18 @@ clutter_grab_dismiss (ClutterGrab *grab)
clutter_stage_notify_grab (stage, next, grab);
}
clutter_actor_detach_grab (grab->actor, grab);
grab->next = NULL;
grab->prev = NULL;
}
void
clutter_grab_dismiss (ClutterGrab *grab)
{
g_return_if_fail (grab != NULL);
clutter_stage_unlink_grab (grab->stage, grab);
g_free (grab);
}