From 965a1fb9dcd468b9fc0b87279f3a4a33b6bd635c Mon Sep 17 00:00:00 2001 From: Carlos Soriano Date: Tue, 7 Aug 2018 12:40:42 +0200 Subject: [PATCH 06/11] properties-window: Keep alive properties window if called through DBus The properties window can be used from within Nautilus, and therefore a dialog window makes sense, or from outside Nautilus, such as the FileManager dbus free desktop standard. In the later, used for integration with things like desktop icons extensions, we need to keep the application alive since GApplication would close the application if no application window is alive after a timeout. To fix this, this work makes the window hint a regular window if used from those cases. --- src/nautilus-files-view.c | 6 +- src/nautilus-freedesktop-dbus.c | 10 ++- src/nautilus-pathbar.c | 3 +- src/nautilus-properties-window.c | 106 ++++++++++++++++++++++--------- src/nautilus-properties-window.h | 10 ++- src/nautilus-window.c | 3 +- 6 files changed, 101 insertions(+), 37 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 8aff33e25..5395390e7 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -2435,14 +2435,16 @@ action_properties (GSimpleAction *action, { files = g_list_append (NULL, nautilus_file_ref (priv->directory_as_file)); - nautilus_properties_window_present (files, GTK_WIDGET (view), NULL); + nautilus_properties_window_present (files, GTK_WIDGET (view), NULL, + NULL, NULL); nautilus_file_list_free (files); } } else { - nautilus_properties_window_present (selection, GTK_WIDGET (view), NULL); + nautilus_properties_window_present (selection, GTK_WIDGET (view), NULL, + NULL, NULL); } } diff --git a/src/nautilus-freedesktop-dbus.c b/src/nautilus-freedesktop-dbus.c index c4657aba3..b88809908 100644 --- a/src/nautilus-freedesktop-dbus.c +++ b/src/nautilus-freedesktop-dbus.c @@ -114,6 +114,12 @@ skeleton_handle_show_folders_cb (NautilusFreedesktopFileManager1 *object, return TRUE; } +static void +properties_window_on_finished (gpointer user_data) +{ + g_application_release (g_application_get_default ()); +} + static gboolean skeleton_handle_show_item_properties_cb (NautilusFreedesktopFileManager1 *object, GDBusMethodInvocation *invocation, @@ -133,7 +139,9 @@ skeleton_handle_show_item_properties_cb (NautilusFreedesktopFileManager1 *object files = g_list_reverse (files); - nautilus_properties_window_present (files, NULL, startup_id); + g_application_hold (g_application_get_default ()); + nautilus_properties_window_present (files, NULL, startup_id, + properties_window_on_finished, NULL); nautilus_file_list_free (files); diff --git a/src/nautilus-pathbar.c b/src/nautilus-pathbar.c index 630b8ed33..ea3d2b53f 100644 --- a/src/nautilus-pathbar.c +++ b/src/nautilus-pathbar.c @@ -211,7 +211,8 @@ action_pathbar_properties (GSimpleAction *action, files = g_list_append (NULL, nautilus_file_ref (priv->context_menu_file)); - nautilus_properties_window_present (files, GTK_WIDGET (self), NULL); + nautilus_properties_window_present (files, GTK_WIDGET (self), NULL, NULL, + NULL); nautilus_file_list_free (files); } diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c index 8bd335a07..5405435cd 100644 --- a/src/nautilus-properties-window.c +++ b/src/nautilus-properties-window.c @@ -152,6 +152,9 @@ typedef struct char *startup_id; char *pending_key; GHashTable *pending_files; + NautilusPropertiesWindowCallback callback; + gpointer callback_data; + NautilusPropertiesWindow *window; } StartupData; /* drag and drop definitions */ @@ -197,8 +200,6 @@ static void is_directory_ready_callback (NautilusFile *file, gpointer data); static void cancel_group_change_callback (GroupChange *change); static void cancel_owner_change_callback (OwnerChange *change); -static void parent_widget_destroyed_callback (GtkWidget *widget, - gpointer callback_data); static void select_image_button_callback (GtkWidget *widget, NautilusPropertiesWindow *properties_window); static void set_icon (const char *icon_path, @@ -4811,12 +4812,15 @@ get_pending_key (GList *file_list) } static StartupData * -startup_data_new (GList *original_files, - GList *target_files, - const char *pending_key, - GtkWidget *parent_widget, - GtkWindow *parent_window, - const char *startup_id) +startup_data_new (GList *original_files, + GList *target_files, + const char *pending_key, + GtkWidget *parent_widget, + GtkWindow *parent_window, + const char *startup_id, + NautilusPropertiesWindowCallback callback, + gpointer callback_data, + NautilusPropertiesWindow *window) { StartupData *data; GList *l; @@ -4830,6 +4834,9 @@ startup_data_new (GList *original_files, data->pending_key = g_strdup (pending_key); data->pending_files = g_hash_table_new (g_direct_hash, g_direct_equal); + data->callback = callback; + data->callback_data = callback_data; + data->window = window; for (l = data->target_files; l != NULL; l = l->next) { @@ -5149,7 +5156,7 @@ remove_window (NautilusPropertiesWindow *window) } } -static GtkWindow * +static NautilusPropertiesWindow * get_existing_window (GList *file_list) { if (!file_list->next) @@ -5160,10 +5167,28 @@ get_existing_window (GList *file_list) return NULL; } +static void +properties_window_finish (StartupData *data) +{ + if (data->parent_widget != NULL) + { + g_signal_handlers_disconnect_by_data (data->parent_widget, + data); + } + if (data->window != NULL) + { + g_signal_handlers_disconnect_by_data (data->window, + data); + } + + remove_pending (data, TRUE, TRUE, FALSE); + startup_data_free (data); +} + static void cancel_create_properties_window_callback (gpointer callback_data) { - remove_pending ((StartupData *) callback_data, TRUE, FALSE, TRUE); + properties_window_finish ((StartupData *) callback_data); } static void @@ -5172,7 +5197,7 @@ parent_widget_destroyed_callback (GtkWidget *widget, { g_assert (widget == ((StartupData *) callback_data)->parent_widget); - remove_pending ((StartupData *) callback_data, TRUE, TRUE, FALSE); + properties_window_finish ((StartupData *) callback_data); } static void @@ -5203,16 +5228,24 @@ remove_pending (StartupData *startup_data, eel_timed_wait_stop (cancel_create_properties_window_callback, startup_data); } - if (cancel_destroy_handler && startup_data->parent_widget) + g_hash_table_remove (pending_lists, startup_data->pending_key); +} + +static gboolean +widget_on_destroy (GtkWidget *widget, + gpointer user_data) +{ + StartupData *data = (StartupData *) user_data; + + + if (data->callback != NULL) { - g_signal_handlers_disconnect_by_func (startup_data->parent_widget, - G_CALLBACK (parent_widget_destroyed_callback), - startup_data); + data->callback (data->callback_data); } - g_hash_table_remove (pending_lists, startup_data->pending_key); + properties_window_finish (data); - startup_data_free (startup_data); + return GDK_EVENT_PROPAGATE; } static void @@ -5232,29 +5265,34 @@ is_directory_ready_callback (NautilusFile *file, new_window = create_properties_window (startup_data); add_window (new_window); + startup_data->window = new_window; remove_pending (startup_data, FALSE, TRUE, TRUE); gtk_window_present (GTK_WINDOW (new_window)); + g_signal_connect(GTK_WIDGET (new_window), "destroy", + G_CALLBACK (widget_on_destroy), startup_data); } } - void -nautilus_properties_window_present (GList *original_files, - GtkWidget *parent_widget, - const gchar *startup_id) +nautilus_properties_window_present (GList *original_files, + GtkWidget *parent_widget, + const gchar *startup_id, + NautilusPropertiesWindowCallback callback, + gpointer callback_data) { GList *l, *next; - GtkWidget *parent_window; + GtkWindow *parent_window; StartupData *startup_data; GList *target_files; - GtkWindow *existing_window; + NautilusPropertiesWindow *existing_window; char *pending_key; g_return_if_fail (original_files != NULL); g_return_if_fail (parent_widget == NULL || GTK_IS_WIDGET (parent_widget)); + /* Create the hash tables first time through. */ if (windows == NULL) { @@ -5272,15 +5310,19 @@ nautilus_properties_window_present (GList *original_files, { if (parent_widget) { - gtk_window_set_screen (existing_window, + gtk_window_set_screen (GTK_WINDOW (existing_window), gtk_widget_get_screen (parent_widget)); } else if (startup_id) { - gtk_window_set_startup_id (existing_window, startup_id); + gtk_window_set_startup_id (GTK_WINDOW (existing_window), startup_id); } - gtk_window_present (existing_window); + gtk_window_present (GTK_WINDOW (existing_window)); + startup_data = startup_data_new (NULL, NULL, NULL, NULL, NULL, NULL, + callback, callback_data, existing_window); + g_signal_connect(GTK_WIDGET (existing_window), "destroy", + G_CALLBACK (widget_on_destroy), startup_data); return; } @@ -5290,6 +5332,9 @@ nautilus_properties_window_present (GList *original_files, /* Look to see if we're already waiting for a window for this file. */ if (g_hash_table_lookup (pending_lists, pending_key) != NULL) { + /* FIXME: No callback is done if this happen. In practice, it's a quite + * corner case + */ return; } @@ -5297,7 +5342,7 @@ nautilus_properties_window_present (GList *original_files, if (parent_widget) { - parent_window = gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW); + parent_window = GTK_WINDOW (gtk_widget_get_ancestor (parent_widget, GTK_TYPE_WINDOW)); } else { @@ -5308,8 +5353,11 @@ nautilus_properties_window_present (GList *original_files, target_files, pending_key, parent_widget, - GTK_WINDOW (parent_window), - startup_id); + parent_window, + startup_id, + callback, + callback_data, + NULL); nautilus_file_list_free (target_files); g_free (pending_key); diff --git a/src/nautilus-properties-window.h b/src/nautilus-properties-window.h index 9eff54c4e..e8d6a90e9 100644 --- a/src/nautilus-properties-window.h +++ b/src/nautilus-properties-window.h @@ -59,8 +59,12 @@ typedef struct NautilusPropertiesWindowClass NautilusPropertiesWindowClass; GType nautilus_properties_window_get_type (void); -void nautilus_properties_window_present (GList *files, - GtkWidget *parent_widget, - const gchar *startup_id); +typedef void (* NautilusPropertiesWindowCallback) (gpointer callback_data); + +void nautilus_properties_window_present (GList *files, + GtkWidget *parent_widget, + const gchar *startup_id, + NautilusPropertiesWindowCallback callback, + gpointer callback_data); #endif /* NAUTILUS_PROPERTIES_WINDOW_H */ diff --git a/src/nautilus-window.c b/src/nautilus-window.c index 41c4623be..a6ee4d489 100644 --- a/src/nautilus-window.c +++ b/src/nautilus-window.c @@ -1309,7 +1309,8 @@ action_properties (GSimpleAction *action, file = nautilus_file_get (priv->selected_file); list = g_list_append (NULL, file); - nautilus_properties_window_present (list, GTK_WIDGET (window), NULL); + nautilus_properties_window_present (list, GTK_WIDGET (window), NULL, NULL, + NULL); nautilus_file_list_free (list); g_clear_object (&priv->selected_file); -- 2.17.1