[libdazzle] transient-grab: be safer when releasing a grab



commit 3fe21e7359adc4f4f1af0a835d0b475adfffd622
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 30 13:04:43 2018 -0700

    transient-grab: be safer when releasing a grab
    
    We need to ensure that the grab does not disappear out from under us. We
    also want to make sure that we have ownership of the widgets during the
    processing of the events.
    
    This adds a new reference to self during the operation, and references all
    the potential widgets before doing notifications.

 src/panel/dzl-dock-transient-grab.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)
---
diff --git a/src/panel/dzl-dock-transient-grab.c b/src/panel/dzl-dock-transient-grab.c
index 9d37181..e856d13 100644
--- a/src/panel/dzl-dock-transient-grab.c
+++ b/src/panel/dzl-dock-transient-grab.c
@@ -260,23 +260,42 @@ dzl_dock_transient_grab_acquire (DzlDockTransientGrab *self)
 void
 dzl_dock_transient_grab_release (DzlDockTransientGrab *self)
 {
-  guint i;
+  g_autoptr(GPtrArray) matches = NULL;
 
   g_return_if_fail (DZL_IS_DOCK_TRANSIENT_GRAB (self));
   g_return_if_fail (self->acquired == TRUE);
+  g_return_if_fail (self->items != NULL);
 
-  for (i = 0; i < self->items->len; i++)
+  g_object_ref (self);
+
+  matches = g_ptr_array_new_full (self->items->len, g_object_unref);
+
+  /* Collect our matches and increment their reference count so that
+   * we can ensure they stick around while we notify our matches in
+   * the followup iteration.
+   */
+  for (guint i = 0; i < self->items->len; i++)
     {
       DzlDockItem *item = g_ptr_array_index (self->items, i);
 
       if (g_hash_table_contains (self->hidden, item))
-        {
-          DzlDockItem *parent = dzl_dock_item_get_parent (item);
+        g_ptr_array_add (matches, g_object_ref (item));
+    }
 
-          if (parent != NULL)
-            dzl_dock_item_set_child_visible (parent, item, FALSE);
-        }
+  /*
+   * Notify in reverse order to increase chances we don't collide with
+   * any state changing as we propagate.
+   */
+  for (guint i = matches->len; i > 0; i--)
+    {
+      DzlDockItem *item = g_ptr_array_index (matches, i - 1);
+      DzlDockItem *parent = dzl_dock_item_get_parent (item);
+
+      if (parent != NULL)
+        dzl_dock_item_set_child_visible (parent, item, FALSE);
     }
+
+  g_object_unref (self);
 }
 
 gboolean


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