inspector: life-cycle fixes

When closing the inspector before the main window, we must take
care to sever all signal connections and weak refs, otherwise
things will go bad when the window is closed later.
This commit is contained in:
Matthias Clasen 2014-09-25 23:05:15 -04:00
parent ed5f6d4333
commit 1041f93f7f
4 changed files with 70 additions and 17 deletions

View File

@ -225,20 +225,23 @@ gtk_inspector_classes_list_init (GtkInspectorClassesList *cl)
gtk_widget_init_template (GTK_WIDGET (cl));
}
static void remove_dead_object (gpointer data, GObject *dead_object);
static void gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object);
static void
cleanup_context (GtkInspectorClassesList *cl)
{
if (cl->priv->context)
g_object_weak_unref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
{
g_object_weak_unref (G_OBJECT (cl->priv->context),gtk_inspector_classes_list_remove_dead_object, cl);
cl->priv->context = NULL;
}
gtk_list_store_clear (cl->priv->model);
cl->priv->context = NULL;
if (cl->priv->model)
gtk_list_store_clear (cl->priv->model);
}
static void
remove_dead_object (gpointer data, GObject *dead_object)
gtk_inspector_classes_list_remove_dead_object (gpointer data, GObject *dead_object)
{
GtkInspectorClassesList *cl = data;
@ -267,7 +270,7 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl,
cl->priv->context = gtk_widget_get_style_context (GTK_WIDGET (object));
g_object_weak_ref (G_OBJECT (cl->priv->context), remove_dead_object, cl);
g_object_weak_ref (G_OBJECT (cl->priv->context), gtk_inspector_classes_list_remove_dead_object, cl);
hash_context = get_hash_context (cl);
if (hash_context)
@ -290,10 +293,23 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl,
read_classes_from_style_context (cl);
}
static void
gtk_inspector_classes_list_finalize (GObject *object)
{
GtkInspectorClassesList *cl = GTK_INSPECTOR_CLASSES_LIST (object);
cleanup_context (cl);
G_OBJECT_CLASS (gtk_inspector_classes_list_parent_class)->finalize (object);
}
static void
gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_inspector_classes_list_finalize;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui");
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);

View File

@ -67,6 +67,9 @@ struct _GtkInspectorCssEditorPrivate
guint timeout;
};
static void gtk_inspector_css_editor_remove_dead_object (gpointer data,
GObject *dead_object);
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssEditor, gtk_inspector_css_editor, GTK_TYPE_BOX)
static void
@ -333,6 +336,30 @@ create_provider (GtkInspectorCssEditor *ce)
G_CALLBACK (show_parsing_error), ce);
}
static void
destroy_provider (GtkInspectorCssEditor *ce)
{
if (ce->priv->global)
{
gtk_style_context_remove_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (ce->priv->provider));
g_object_unref (ce->priv->provider);
ce->priv->provider = NULL;
}
else if (ce->priv->context)
{
GtkStyleProvider *provider;
provider = g_object_get_data (G_OBJECT (ce->priv->context),
GTK_INSPECTOR_CSS_EDITOR_PROVIDER);
gtk_style_context_remove_provider (ce->priv->context, provider);
g_object_set_data (G_OBJECT (ce->priv->context),
GTK_INSPECTOR_CSS_EDITOR_PROVIDER,
NULL);
}
}
static void
gtk_inspector_css_editor_init (GtkInspectorCssEditor *ce)
{
@ -398,6 +425,16 @@ finalize (GObject *object)
if (ce->priv->timeout != 0)
g_source_remove (ce->priv->timeout);
destroy_provider (ce);
if (ce->priv->context)
{
g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
g_object_set_data (G_OBJECT (ce->priv->context),
GTK_INSPECTOR_CSS_EDITOR_TEXT,
NULL);
ce->priv->context = NULL;
}
G_OBJECT_CLASS (gtk_inspector_css_editor_parent_class)->finalize (object);
}
@ -427,7 +464,7 @@ gtk_inspector_css_editor_class_init (GtkInspectorCssEditorClass *klass)
}
static void
remove_dead_object (gpointer data, GObject *dead_object)
gtk_inspector_css_editor_remove_dead_object (gpointer data, GObject *dead_object)
{
GtkInspectorCssEditor *ce = data;
@ -447,7 +484,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
if (ce->priv->context)
{
g_object_weak_unref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
g_object_weak_unref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text));
g_object_set_data_full (G_OBJECT (ce->priv->context),
GTK_INSPECTOR_CSS_EDITOR_TEXT,
@ -472,7 +509,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
set_initial_text (ce);
disable_toggled (ce->priv->disable_button, ce);
g_object_weak_ref (G_OBJECT (ce->priv->context), remove_dead_object, ce);
g_object_weak_ref (G_OBJECT (ce->priv->context), gtk_inspector_css_editor_remove_dead_object, ce);
}
// vim: set et sw=2 ts=2:

View File

@ -391,14 +391,14 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
g_free (props);
if (GTK_IS_WIDGET (object))
g_signal_connect_swapped (object, "destroy", G_CALLBACK (cleanup_object), pl);
g_signal_connect_object (object, "destroy", G_CALLBACK (cleanup_object), pl, G_CONNECT_SWAPPED);
/* Listen for updates */
pl->priv->notify_handler_id =
g_signal_connect (object,
pl->priv->child_properties ? "child-notify" : "notify",
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
pl);
g_signal_connect_object (object,
pl->priv->child_properties ? "child-notify" : "notify",
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
pl, 0);
gtk_widget_show (GTK_WIDGET (pl));

View File

@ -88,7 +88,7 @@ typedef struct
} ObjectData;
static void
remove_dead_object (gpointer data, GObject *dead_object)
gtk_widget_tree_remove_dead_object (gpointer data, GObject *dead_object)
{
ObjectData *od = data;
@ -113,7 +113,7 @@ object_data_free (gpointer data)
gtk_tree_row_reference_free (od->row);
if (od->object)
g_object_weak_unref (od->object, remove_dead_object, od);
g_object_weak_unref (od->object, gtk_widget_tree_remove_dead_object, od);
g_free (od);
}
@ -333,7 +333,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
gtk_tree_path_free (path);
g_hash_table_insert (wt->priv->iters, object, od);
g_object_weak_ref (object, remove_dead_object, od);
g_object_weak_ref (object, gtk_widget_tree_remove_dead_object, od);
g_free (address);