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));
|
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
|
static void
|
||||||
cleanup_context (GtkInspectorClassesList *cl)
|
cleanup_context (GtkInspectorClassesList *cl)
|
||||||
{
|
{
|
||||||
if (cl->priv->context)
|
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);
|
||||||
gtk_list_store_clear (cl->priv->model);
|
|
||||||
cl->priv->context = NULL;
|
cl->priv->context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cl->priv->model)
|
||||||
|
gtk_list_store_clear (cl->priv->model);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
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));
|
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);
|
hash_context = get_hash_context (cl);
|
||||||
if (hash_context)
|
if (hash_context)
|
||||||
@ -290,10 +293,23 @@ gtk_inspector_classes_list_set_object (GtkInspectorClassesList *cl,
|
|||||||
read_classes_from_style_context (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
|
static void
|
||||||
gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass)
|
gtk_inspector_classes_list_class_init (GtkInspectorClassesListClass *klass)
|
||||||
{
|
{
|
||||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (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_set_template_from_resource (widget_class, "/org/gtk/inspector/classes-list.ui");
|
||||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);
|
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorClassesList, model);
|
||||||
|
|||||||
@ -67,6 +67,9 @@ struct _GtkInspectorCssEditorPrivate
|
|||||||
guint timeout;
|
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)
|
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorCssEditor, gtk_inspector_css_editor, GTK_TYPE_BOX)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -333,6 +336,30 @@ create_provider (GtkInspectorCssEditor *ce)
|
|||||||
G_CALLBACK (show_parsing_error), 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
|
static void
|
||||||
gtk_inspector_css_editor_init (GtkInspectorCssEditor *ce)
|
gtk_inspector_css_editor_init (GtkInspectorCssEditor *ce)
|
||||||
{
|
{
|
||||||
@ -398,6 +425,16 @@ finalize (GObject *object)
|
|||||||
if (ce->priv->timeout != 0)
|
if (ce->priv->timeout != 0)
|
||||||
g_source_remove (ce->priv->timeout);
|
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);
|
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
|
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;
|
GtkInspectorCssEditor *ce = data;
|
||||||
|
|
||||||
@ -447,7 +484,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
|
|||||||
|
|
||||||
if (ce->priv->context)
|
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));
|
text = get_current_text (GTK_TEXT_BUFFER (ce->priv->text));
|
||||||
g_object_set_data_full (G_OBJECT (ce->priv->context),
|
g_object_set_data_full (G_OBJECT (ce->priv->context),
|
||||||
GTK_INSPECTOR_CSS_EDITOR_TEXT,
|
GTK_INSPECTOR_CSS_EDITOR_TEXT,
|
||||||
@ -472,7 +509,7 @@ gtk_inspector_css_editor_set_object (GtkInspectorCssEditor *ce,
|
|||||||
set_initial_text (ce);
|
set_initial_text (ce);
|
||||||
disable_toggled (ce->priv->disable_button, 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:
|
// vim: set et sw=2 ts=2:
|
||||||
|
|||||||
@ -391,14 +391,14 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl,
|
|||||||
g_free (props);
|
g_free (props);
|
||||||
|
|
||||||
if (GTK_IS_WIDGET (object))
|
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 */
|
/* Listen for updates */
|
||||||
pl->priv->notify_handler_id =
|
pl->priv->notify_handler_id =
|
||||||
g_signal_connect (object,
|
g_signal_connect_object (object,
|
||||||
pl->priv->child_properties ? "child-notify" : "notify",
|
pl->priv->child_properties ? "child-notify" : "notify",
|
||||||
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
|
G_CALLBACK (gtk_inspector_prop_list_prop_changed_cb),
|
||||||
pl);
|
pl, 0);
|
||||||
|
|
||||||
gtk_widget_show (GTK_WIDGET (pl));
|
gtk_widget_show (GTK_WIDGET (pl));
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ typedef struct
|
|||||||
} ObjectData;
|
} ObjectData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_dead_object (gpointer data, GObject *dead_object)
|
gtk_widget_tree_remove_dead_object (gpointer data, GObject *dead_object)
|
||||||
{
|
{
|
||||||
ObjectData *od = data;
|
ObjectData *od = data;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ object_data_free (gpointer data)
|
|||||||
gtk_tree_row_reference_free (od->row);
|
gtk_tree_row_reference_free (od->row);
|
||||||
|
|
||||||
if (od->object)
|
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);
|
g_free (od);
|
||||||
}
|
}
|
||||||
@ -333,7 +333,7 @@ gtk_inspector_widget_tree_append_object (GtkInspectorWidgetTree *wt,
|
|||||||
gtk_tree_path_free (path);
|
gtk_tree_path_free (path);
|
||||||
|
|
||||||
g_hash_table_insert (wt->priv->iters, object, od);
|
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);
|
g_free (address);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user