From 09b093291801fdf02ec5f0d76f1d7abb9363e7ba Mon Sep 17 00:00:00 2001 From: Ernestas Kulik Date: Sat, 26 May 2018 16:35:22 +0300 Subject: [PATCH] toolbar: Fix window slot handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling _set_window_slot() in the window slot weak ref notification callback isn’t a good idea, given that most of the stuff being cleaned up there is done automagically, and results in runtime warnings or potentially a segfault when removing a property binding. This commit split nautilus_toolbar_set_window_slot(), so that property bindings aren’t removed if called from the weak reference notification function. Additionally, the same notification functions nulls out the icon property binding, fixing the same thing happening in dispose(). Fixes https://gitlab.gnome.org/GNOME/nautilus/issues/441 --- src/nautilus-toolbar.c | 141 +++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 61 deletions(-) diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c index 0d7a29556..fa7e56d4c 100644 --- a/src/nautilus-toolbar.c +++ b/src/nautilus-toolbar.c @@ -125,7 +125,9 @@ static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; G_DEFINE_TYPE (NautilusToolbar, nautilus_toolbar, GTK_TYPE_HEADER_BAR); -static void update_operations (NautilusToolbar *self); +static void nautilus_toolbar_set_window_slot_real (NautilusToolbar *self, + NautilusWindowSlot *slot); +static void update_operations (NautilusToolbar *self); static void toolbar_update_appearance (NautilusToolbar *self) @@ -1013,9 +1015,16 @@ static void on_window_slot_destroyed (gpointer data, GObject *where_the_object_was) { - NautilusToolbar *self = NAUTILUS_TOOLBAR (data); + NautilusToolbar *self; - nautilus_toolbar_set_window_slot (self, NULL); + self = NAUTILUS_TOOLBAR (data); + + /* The window slot was finalized, and the binding has already been removed. + * Null it here, so that dispose() does not trip over itself when removing it. + */ + self->icon_binding = NULL; + + nautilus_toolbar_set_window_slot_real (self, NULL); } static void @@ -1343,74 +1352,84 @@ nautilus_toolbar_view_toggle_icon_transform_to (GBinding *binding, return TRUE; } +/* Called from on_window_slot_destroyed(), since bindings and signal handlers + * are automatically removed once the slot goes away. + */ +static void +nautilus_toolbar_set_window_slot_real (NautilusToolbar *self, + NautilusWindowSlot *slot) +{ + g_autoptr (GList) children = NULL; + + self->window_slot = slot; + + if (self->window_slot != NULL) + { + g_object_weak_ref (G_OBJECT (self->window_slot), + on_window_slot_destroyed, + self); + + self->icon_binding = g_object_bind_property_full (self->window_slot, "icon", + self->view_toggle_icon, "gicon", + G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE, + (GBindingTransformFunc) nautilus_toolbar_view_toggle_icon_transform_to, + NULL, + self, + NULL); + + on_slot_toolbar_menu_sections_changed (self, NULL, self->window_slot); + g_signal_connect_swapped (self->window_slot, "notify::toolbar-menu-sections", + G_CALLBACK (on_slot_toolbar_menu_sections_changed), self); + g_signal_connect_swapped (self->window_slot, "notify::extensions-background-menu", + G_CALLBACK (slot_on_extensions_background_menu_changed), self); + g_signal_connect_swapped (self->window_slot, "notify::templates-menu", + G_CALLBACK (slot_on_templates_menu_changed), self); + g_signal_connect_swapped (self->window_slot, "notify::searching", + G_CALLBACK (toolbar_update_appearance), self); + + } + + children = gtk_container_get_children (GTK_CONTAINER (self->search_container)); + if (children != NULL) + { + gtk_container_remove (GTK_CONTAINER (self->search_container), + children->data); + } + + if (self->window_slot != NULL) + { + gtk_container_add (GTK_CONTAINER (self->search_container), + GTK_WIDGET (nautilus_window_slot_get_query_editor (self->window_slot))); + } + + toolbar_update_appearance (self); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]); +} + void nautilus_toolbar_set_window_slot (NautilusToolbar *self, NautilusWindowSlot *window_slot) { g_return_if_fail (NAUTILUS_IS_TOOLBAR (self)); + g_return_if_fail (window_slot == NULL || NAUTILUS_IS_WINDOW_SLOT (window_slot)); + + if (self->window_slot == window_slot) + { + return; + } g_clear_pointer (&self->icon_binding, g_binding_unbind); - if (self->window_slot != window_slot) + disconnect_toolbar_menu_sections_change_handler (self); + if (self->window_slot != NULL) { - GList *children; - - disconnect_toolbar_menu_sections_change_handler (self); - if (self->window_slot != NULL) - { - g_signal_handlers_disconnect_by_data (self->window_slot, self); - g_object_weak_unref (G_OBJECT (self->window_slot), - on_window_slot_destroyed, self); - self->window_slot = NULL; - } - - self->window_slot = window_slot; - - if (self->window_slot) - { - g_object_weak_ref (G_OBJECT (self->window_slot), - on_window_slot_destroyed, - self); - - self->icon_binding = g_object_bind_property_full (self->window_slot, "icon", - self->view_toggle_icon, "gicon", - G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE, - (GBindingTransformFunc) nautilus_toolbar_view_toggle_icon_transform_to, - NULL, - self, - NULL); - - on_slot_toolbar_menu_sections_changed (self, NULL, self->window_slot); - g_signal_connect_swapped (self->window_slot, "notify::toolbar-menu-sections", - G_CALLBACK (on_slot_toolbar_menu_sections_changed), self); - g_signal_connect_swapped (self->window_slot, "notify::extensions-background-menu", - G_CALLBACK (slot_on_extensions_background_menu_changed), self); - g_signal_connect_swapped (self->window_slot, "notify::templates-menu", - G_CALLBACK (slot_on_templates_menu_changed), self); - g_signal_connect_swapped (window_slot, "notify::searching", - G_CALLBACK (toolbar_update_appearance), self); - - } - - children = gtk_container_get_children (GTK_CONTAINER (self->search_container)); - if (children != NULL) - { - gtk_container_remove (GTK_CONTAINER (self->search_container), - children->data); - } - - if (self->window_slot != NULL) - { - GTK_WIDGET (nautilus_window_slot_get_query_editor (self->window_slot)); - GTK_CONTAINER (self->search_container); - gtk_container_add (GTK_CONTAINER (self->search_container), - GTK_WIDGET (nautilus_window_slot_get_query_editor (self->window_slot))); - } - - toolbar_update_appearance (self); - - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]); + g_signal_handlers_disconnect_by_data (self->window_slot, self); + g_object_weak_unref (G_OBJECT (self->window_slot), + on_window_slot_destroyed, self); } + + nautilus_toolbar_set_window_slot_real (self, window_slot); } gboolean