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:
@ -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);
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user