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




commit 6bf15e51980bb6e11e7503124f1ba0a86fab0f4a
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         | 42 +++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-stage-private.h |  4 ++++
 clutter/clutter/clutter-stage.c         | 23 ++++++++++++++----
 4 files changed, 71 insertions(+), 4 deletions(-)
---
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 415624e6e7..f9ae417485 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 */
 
@@ -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);
 }
 
 /**
@@ -5583,6 +5605,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);
@@ -19649,3 +19673,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-private.h b/clutter/clutter/clutter-stage-private.h
index e5e1c81fa4..a9fd17c1bb 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -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>
@@ -134,6 +135,9 @@ void clutter_stage_remove_device_entry (ClutterStage         *self,
                                         ClutterInputDevice   *device,
                                         ClutterEventSequence *sequence);
 
+void clutter_stage_unlink_grab (ClutterStage *self,
+                                ClutterGrab  *grab);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 2c483bc81e..bbd57d905f 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -3767,20 +3767,23 @@ clutter_stage_grab (ClutterStage *stage,
     priv->grabs->prev = grab;
 
   priv->grabs = 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->grabs != grab)
+    return;
 
-  priv = grab->stage->priv;
   prev = grab->prev;
   next = grab->next;
 
@@ -3796,6 +3799,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);
 }
 


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