[mutter/wip/carlosg/grabs-pt1: 11/16] clutter: Carry accounting of grabs in the ClutterActors holding them




commit 88f8aa9e2e7ffad3cf8af8b54618ff6fe6cc699d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Oct 28 14:04:58 2021 +0200

    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.

 clutter/clutter/clutter-actor-private.h |  6 +++++
 clutter/clutter/clutter-actor.c         | 41 +++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-stage.c         |  4 ++++
 3 files changed, 51 insertions(+)
---
diff --git a/clutter/clutter/clutter-actor-private.h b/clutter/clutter/clutter-actor-private.h
index a803166ace..764705447d 100644
--- a/clutter/clutter/clutter-actor-private.h
+++ b/clutter/clutter/clutter-actor-private.h
@@ -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__ */
diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c
index 0c625ec9e3..ad7ca44fc5 100644
--- a/clutter/clutter/clutter-actor.c
+++ b/clutter/clutter/clutter-actor.c
@@ -801,6 +801,7 @@ struct _ClutterActorPrivate
   gulong layout_changed_id;
 
   GList *stage_views;
+  GList *grabs;
 
   /* bitfields: KEEP AT THE END */
 
@@ -1679,6 +1680,25 @@ clutter_actor_real_unmap (ClutterActor *self)
     maybe_unset_key_focus (self);
 }
 
+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_ungrab().
+   */
+  while (priv->grabs)
+    clutter_ungrab (CLUTTER_STAGE (stage), priv->grabs->data);
+}
+
 /**
  * clutter_actor_unmap:
  * @self: A #ClutterActor
@@ -1710,6 +1730,7 @@ clutter_actor_unmap (ClutterActor *self)
     return;
 
   clutter_actor_update_map_state (self, MAP_STATE_MAKE_UNMAPPED);
+  clutter_actor_clear_grabs (self);
 }
 
 static void
@@ -5582,6 +5603,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);
@@ -19621,3 +19644,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);
+}
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 7c980e5fa4..7da944ede9 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -3754,11 +3754,14 @@ clutter_grab (ClutterStage *stage,
   ClutterStagePrivate *priv = stage->priv;
   ClutterGrab *grab = g_new0 (ClutterGrab, 1);
 
+  g_return_val_if_fail (CLUTTER_ACTOR_IS_MAPPED (actor), NULL);
+
   grab->actor = actor;
   grab->prev = NULL;
   grab->next = priv->grabs;
 
   priv->grabs = grab;
+  clutter_actor_attach_grab (actor, grab);
   clutter_stage_notify_grab (stage, grab, grab->next);
 
   return grab;
@@ -3787,6 +3790,7 @@ clutter_ungrab (ClutterStage *stage,
       clutter_stage_notify_grab (stage, next, grab);
     }
 
+  clutter_actor_detach_grab (grab->actor, grab);
   g_free (grab);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]