[libdazzle] menu-button: handle destruction races better



commit 385473263e0df737c69c02e4f924aee51be3f3f9
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 10 16:51:58 2017 -0700

    menu-button: handle destruction races better
    
    We are insensitive when we have no models, so we can get away
    with holding onto old menu items until the new mode is set.
    That makes it convenient to handle the GtkWidget.destroy case.

 src/menus/dzl-menu-button-section.c |   25 ++++++-------------------
 src/menus/dzl-menu-button.c         |   18 +++++++++---------
 2 files changed, 15 insertions(+), 28 deletions(-)
---
diff --git a/src/menus/dzl-menu-button-section.c b/src/menus/dzl-menu-button-section.c
index 9278508..9dec193 100644
--- a/src/menus/dzl-menu-button-section.c
+++ b/src/menus/dzl-menu-button-section.c
@@ -106,23 +106,15 @@ dzl_menu_button_section_bind (DzlMenuButtonSection *self,
   g_assert (G_IS_MENU_MODEL (menu));
   g_assert (DZL_IS_SIGNAL_GROUP (menu_signals));
 
-  n_items = g_menu_model_get_n_items (menu);
-  dzl_menu_button_section_items_changed (self, 0, 0, n_items, menu);
-}
-
-static void
-dzl_menu_button_section_unbind (DzlMenuButtonSection *self,
-                                DzlSignalGroup       *menu_signals)
-{
-  g_assert (DZL_IS_MENU_BUTTON_SECTION (self));
-  g_assert (DZL_IS_SIGNAL_GROUP (menu_signals));
-
-  if (gtk_widget_in_destruction (GTK_WIDGET (self)))
-    return;
-
+  /* Remove on bind instead of unbind to avoid data races
+   * when destroying the widget.
+   */
   gtk_container_foreach (GTK_CONTAINER (self->items_box),
                          (GtkCallback) gtk_widget_destroy,
                          NULL);
+
+  n_items = g_menu_model_get_n_items (menu);
+  dzl_menu_button_section_items_changed (self, 0, 0, n_items, menu);
 }
 
 static void
@@ -234,11 +226,6 @@ dzl_menu_button_section_init (DzlMenuButtonSection *self)
                             G_CALLBACK (dzl_menu_button_section_bind),
                             self);
 
-  g_signal_connect_swapped (self->menu_signals,
-                            "unbind",
-                            G_CALLBACK (dzl_menu_button_section_unbind),
-                            self);
-
   dzl_signal_group_connect_swapped (self->menu_signals,
                                     "items-changed",
                                     G_CALLBACK (dzl_menu_button_section_items_changed),
diff --git a/src/menus/dzl-menu-button.c b/src/menus/dzl-menu-button.c
index ce81635..ec00eac 100644
--- a/src/menus/dzl-menu-button.c
+++ b/src/menus/dzl-menu-button.c
@@ -156,12 +156,21 @@ dzl_menu_button_menu_signals_bind (DzlMenuButton  *self,
                                    GMenuModel     *menu,
                                    DzlSignalGroup *menu_signals)
 {
+  DzlMenuButtonPrivate *priv = dzl_menu_button_get_instance_private (self);
   guint n_items;
 
   g_assert (DZL_IS_MENU_BUTTON (self));
   g_assert (G_IS_MENU_MODEL (menu));
   g_assert (DZL_IS_SIGNAL_GROUP (menu_signals));
 
+  /* Clear on bind instead of unbind to avoid data races.
+   * We already are insensitive when unbound, so this should
+   * be a fine solution.
+   */
+  gtk_container_foreach (GTK_CONTAINER (priv->popover_box),
+                         (GtkCallback) gtk_widget_destroy,
+                         NULL);
+
   n_items = g_menu_model_get_n_items (menu);
   dzl_menu_button_items_changed (self, 0, 0, n_items, menu);
 
@@ -172,18 +181,9 @@ static void
 dzl_menu_button_menu_signals_unbind (DzlMenuButton  *self,
                                      DzlSignalGroup *menu_signals)
 {
-  DzlMenuButtonPrivate *priv = dzl_menu_button_get_instance_private (self);
-
   g_assert (DZL_IS_MENU_BUTTON (self));
   g_assert (DZL_IS_SIGNAL_GROUP (menu_signals));
 
-  if (gtk_widget_in_destruction (GTK_WIDGET (self)))
-    return;
-
-  gtk_container_foreach (GTK_CONTAINER (priv->popover_box),
-                         (GtkCallback) gtk_widget_destroy,
-                         NULL);
-
   gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
 }
 


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