[libdazzle/libdazzle-3-26] prefs: track destruction state of pref widgets
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle/libdazzle-3-26] prefs: track destruction state of pref widgets
- Date: Mon, 25 Sep 2017 06:48:51 +0000 (UTC)
commit 1253e4c714d700a268695f12f58fe47c57acdf22
Author: Christian Hergert <chergert redhat com>
Date: Sun Sep 24 23:46:06 2017 -0700
prefs: track destruction state of pref widgets
We want to be sure we don't call gtk_widget_destroy() on
something that is already in the destruction process. Also,
we want to ensure that we aren't holding onto pointers to
widgets after they've been destroyed.
This avoids that by using an indirection structure that allows
us to zero out the widget field on GtkWidget::destroy.
src/prefs/dzl-preferences-view.c | 77 ++++++++++++++++++++++++++++++-------
1 files changed, 62 insertions(+), 15 deletions(-)
---
diff --git a/src/prefs/dzl-preferences-view.c b/src/prefs/dzl-preferences-view.c
index 494c04f..48791c4 100644
--- a/src/prefs/dzl-preferences-view.c
+++ b/src/prefs/dzl-preferences-view.c
@@ -44,6 +44,13 @@ typedef struct
guint last_widget_id;
} DzlPreferencesViewPrivate;
+typedef struct
+{
+ GtkWidget *widget;
+ gulong handler;
+ guint id;
+} TrackedWidget;
+
static void dzl_preferences_iface_init (DzlPreferencesInterface *iface);
G_DEFINE_TYPE_WITH_CODE (DzlPreferencesView, dzl_preferences_view, GTK_TYPE_BIN,
@@ -51,6 +58,39 @@ G_DEFINE_TYPE_WITH_CODE (DzlPreferencesView, dzl_preferences_view, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (DZL_TYPE_PREFERENCES, dzl_preferences_iface_init))
static void
+tracked_widget_free (gpointer data)
+{
+ TrackedWidget *tracked = data;
+
+ if (tracked->widget != NULL)
+ g_signal_handler_disconnect (tracked->widget, tracked->handler);
+ g_slice_free (TrackedWidget, tracked);
+}
+
+static void
+dzl_preferences_view_track (DzlPreferencesView *self,
+ guint id,
+ GtkWidget *widget)
+{
+ DzlPreferencesViewPrivate *priv = dzl_preferences_view_get_instance_private (self);
+ TrackedWidget *tracked;
+
+ g_assert (DZL_IS_PREFERENCES_VIEW (self));
+ g_assert (id > 0);
+ g_assert (GTK_IS_WIDGET (widget));
+
+ tracked = g_slice_new0 (TrackedWidget);
+ tracked->widget = widget;
+ tracked->id = id;
+ tracked->handler = g_signal_connect (widget,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &tracked->widget);
+
+ g_hash_table_insert (priv->widgets, GUINT_TO_POINTER (id), tracked);
+}
+
+static void
dzl_preferences_view_refilter_cb (GtkWidget *widget,
gpointer user_data)
{
@@ -269,7 +309,8 @@ dzl_preferences_view_init (DzlPreferencesView *self)
G_CONNECT_SWAPPED);
priv->pages = g_sequence_new (NULL);
- priv->widgets = g_hash_table_new (g_direct_hash, g_direct_equal);
+ priv->widgets = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, tracked_widget_free);
priv->actions = G_ACTION_GROUP (g_simple_action_group_new ());
g_action_map_add_action_entries (G_ACTION_MAP (priv->actions),
@@ -476,7 +517,7 @@ dzl_preferences_view_add_radio (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (widget));
widget_id = ++priv->last_widget_id;
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -553,7 +594,7 @@ dzl_preferences_view_add_switch (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (widget));
widget_id = ++priv->last_widget_id;
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -616,7 +657,7 @@ dzl_preferences_view_add_spin_button (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (widget));
widget_id = ++priv->last_widget_id;
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -674,7 +715,7 @@ dzl_preferences_view_add_font_button (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (widget));
widget_id = ++priv->last_widget_id;
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -738,7 +779,7 @@ dzl_preferences_view_add_file_chooser (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (widget));
widget_id = ++priv->last_widget_id;
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -797,7 +838,7 @@ dzl_preferences_view_add_custom (DzlPreferences *preferences,
dzl_preferences_group_add (group, GTK_WIDGET (container));
- g_hash_table_insert (priv->widgets, GINT_TO_POINTER (widget_id), widget);
+ dzl_preferences_view_track (self, widget_id, GTK_WIDGET (widget));
return widget_id;
}
@@ -808,20 +849,25 @@ dzl_preferences_view_remove_id (DzlPreferences *preferences,
{
DzlPreferencesView *self = (DzlPreferencesView *)preferences;
DzlPreferencesViewPrivate *priv = dzl_preferences_view_get_instance_private (self);
- GtkWidget *widget;
+ TrackedWidget *tracked;
g_assert (DZL_IS_PREFERENCES_VIEW (self));
g_assert (widget_id);
- widget = g_hash_table_lookup (priv->widgets, GINT_TO_POINTER (widget_id));
- if (widget != NULL)
+ tracked = g_hash_table_lookup (priv->widgets, GUINT_TO_POINTER (widget_id));
+
+ if (tracked != NULL)
{
- if (g_hash_table_remove (priv->widgets, GINT_TO_POINTER (widget_id)))
+ GtkWidget *widget = tracked->widget;
+
+ g_hash_table_remove (priv->widgets, GUINT_TO_POINTER (widget_id));
+
+ if (widget != NULL && !gtk_widget_in_destruction (widget))
{
GtkWidget *parent = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
/* in case we added our own row ancestor, destroy it */
- if (parent != NULL)
+ if (parent != NULL && !gtk_widget_in_destruction (parent))
gtk_widget_destroy (parent);
else
gtk_widget_destroy (widget);
@@ -830,8 +876,6 @@ dzl_preferences_view_remove_id (DzlPreferences *preferences,
}
}
- g_warning ("No Preferences widget with number %i could be found and thus removed.", widget_id);
-
return FALSE;
}
@@ -874,10 +918,13 @@ dzl_preferences_view_get_widget (DzlPreferences *preferences,
{
DzlPreferencesView *self = (DzlPreferencesView *)preferences;
DzlPreferencesViewPrivate *priv = dzl_preferences_view_get_instance_private (self);
+ TrackedWidget *tracked;
g_assert (DZL_IS_PREFERENCES_VIEW (self));
- return g_hash_table_lookup (priv->widgets, GINT_TO_POINTER (widget_id));
+ tracked = g_hash_table_lookup (priv->widgets, GINT_TO_POINTER (widget_id));
+
+ return tracked ? tracked->widget : NULL;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]