diff --git a/0001-mime-actions-Group-files-depending-on-the-opening-ap.patch b/0001-mime-actions-Group-files-depending-on-the-opening-ap.patch new file mode 100644 index 0000000..060bedf --- /dev/null +++ b/0001-mime-actions-Group-files-depending-on-the-opening-ap.patch @@ -0,0 +1,621 @@ +From 873939e8222a778e8f9855944483cb1ee1cb984b Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 6 Feb 2020 15:04:31 +0100 +Subject: [PATCH] mime-actions: Group files depending on the opening app + +Reinstate the old behaviour which used to look at the files to open, +group them by handling application, and pass a single call to each +application with all the files it could handle. + +For the common case where it's a single application handling all the +files, as is usual for handling media files (images, videos, music, +etc.), it changes the launching behaviour from: +application.bin foo.mp3 +application.bin foo2.mp3 +application.bin foo3.mp3 +to: +application.bin foo.mp3 foo2.mp3 foo3.mp3 + +This however impacts the behaviour of nautilus launching applications +when inside a Flatpak sandbox, as it cannot enumerate and launch +applications itself. As the Flatpak sandbox is a development tool, and +for the sake of expediency, we reverted to the old code path. + +Revert "mime-actions: launch default uri handlers when activating files" + +This reverts commit f5206a6daf0991d91e885a28bb66795a8ae12a41. + +Closes: #117 +--- + src/nautilus-mime-actions.c | 268 +++++++++++++++++++++++--------- + src/nautilus-program-choosing.c | 188 +++------------------- + src/nautilus-program-choosing.h | 7 - + 3 files changed, 211 insertions(+), 252 deletions(-) + +diff --git a/src/nautilus-mime-actions.c b/src/nautilus-mime-actions.c +index 26468c597..4a49828a8 100644 +--- a/src/nautilus-mime-actions.c ++++ b/src/nautilus-mime-actions.c +@@ -61,6 +61,12 @@ typedef struct + char *uri; + } LaunchLocation; + ++typedef struct ++{ ++ GAppInfo *application; ++ GList *uris; ++} ApplicationLaunchParameters; ++ + typedef struct + { + NautilusWindowSlot *slot; +@@ -80,13 +86,6 @@ typedef struct + gboolean user_confirmation; + } ActivateParameters; + +-typedef struct +-{ +- ActivateParameters *activation_params; +- GQueue *uris; +- GQueue *unhandled_uris; +-} ApplicationLaunchParameters; +- + /* Microsoft mime types at https://blogs.msdn.microsoft.com/vsofficedeveloper/2008/05/08/office-2007-file-format-mime-types-for-http-content-streaming-2/ */ + struct + { +@@ -345,19 +344,27 @@ launch_locations_from_file_list (GList *list) + } + + static ApplicationLaunchParameters * +-application_launch_parameters_new (ActivateParameters *activation_params, +- GQueue *uris) ++application_launch_parameters_new (GAppInfo *application, ++ GList *uris) + { + ApplicationLaunchParameters *result; + + result = g_new0 (ApplicationLaunchParameters, 1); +- result->activation_params = activation_params; +- result->uris = uris; +- result->unhandled_uris = g_queue_new (); ++ result->application = g_object_ref (application); ++ result->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL); + + return result; + } + ++static void ++application_launch_parameters_free (ApplicationLaunchParameters *parameters) ++{ ++ g_object_unref (parameters->application); ++ g_list_free_full (parameters->uris, g_free); ++ ++ g_free (parameters); ++} ++ + static gboolean + nautilus_mime_actions_check_if_required_attributes_ready (NautilusFile *file) + { +@@ -792,6 +799,114 @@ nautilus_mime_file_opens_in_external_app (NautilusFile *file) + return (activation_action == ACTIVATION_ACTION_OPEN_IN_APPLICATION); + } + ++ ++static unsigned int ++mime_application_hash (GAppInfo *app) ++{ ++ const char *id; ++ ++ id = g_app_info_get_id (app); ++ ++ if (id == NULL) ++ { ++ return GPOINTER_TO_UINT (app); ++ } ++ ++ return g_str_hash (id); ++} ++ ++static void ++list_to_parameters_foreach (GAppInfo *application, ++ GList *uris, ++ GList **ret) ++{ ++ ApplicationLaunchParameters *parameters; ++ ++ uris = g_list_reverse (uris); ++ ++ parameters = application_launch_parameters_new ++ (application, uris); ++ *ret = g_list_prepend (*ret, parameters); ++} ++ ++ ++/** ++ * make_activation_parameters ++ * ++ * Construct a list of ApplicationLaunchParameters from a list of NautilusFiles, ++ * where files that have the same default application are put into the same ++ * launch parameter, and others are put into the unhandled_files list. ++ * ++ * @files: Files to use for construction. ++ * @unhandled_files: Files without any default application will be put here. ++ * ++ * Return value: Newly allocated list of ApplicationLaunchParameters. ++ **/ ++static GList * ++make_activation_parameters (GList *uris, ++ GList **unhandled_uris) ++{ ++ GList *ret, *l, *app_uris; ++ NautilusFile *file; ++ GAppInfo *app, *old_app; ++ GHashTable *app_table; ++ char *uri; ++ ++ ret = NULL; ++ *unhandled_uris = NULL; ++ ++ app_table = g_hash_table_new_full ++ ((GHashFunc) mime_application_hash, ++ (GEqualFunc) g_app_info_equal, ++ (GDestroyNotify) g_object_unref, ++ (GDestroyNotify) g_list_free); ++ ++ for (l = uris; l != NULL; l = l->next) ++ { ++ uri = l->data; ++ file = nautilus_file_get_by_uri (uri); ++ ++ app = nautilus_mime_get_default_application_for_file (file); ++ if (app != NULL) ++ { ++ app_uris = NULL; ++ ++ if (g_hash_table_lookup_extended (app_table, app, ++ (gpointer *) &old_app, ++ (gpointer *) &app_uris)) ++ { ++ g_hash_table_steal (app_table, old_app); ++ ++ app_uris = g_list_prepend (app_uris, uri); ++ ++ g_object_unref (app); ++ app = old_app; ++ } ++ else ++ { ++ app_uris = g_list_prepend (NULL, uri); ++ } ++ ++ g_hash_table_insert (app_table, app, app_uris); ++ } ++ else ++ { ++ *unhandled_uris = g_list_prepend (*unhandled_uris, uri); ++ } ++ nautilus_file_unref (file); ++ } ++ ++ g_hash_table_foreach (app_table, ++ (GHFunc) list_to_parameters_foreach, ++ &ret); ++ ++ g_hash_table_destroy (app_table); ++ ++ *unhandled_uris = g_list_reverse (*unhandled_uris); ++ ++ return g_list_reverse (ret); ++} ++ + static gboolean + file_was_cancelled (NautilusFile *file) + { +@@ -843,16 +958,6 @@ activation_parameters_free (ActivateParameters *parameters) + g_free (parameters); + } + +-static void +-application_launch_parameters_free (ApplicationLaunchParameters *parameters) +-{ +- g_queue_free (parameters->unhandled_uris); +- g_queue_free (parameters->uris); +- activation_parameters_free (parameters->activation_params); +- +- g_free (parameters); +-} +- + static void + cancel_activate_callback (gpointer callback_data) + { +@@ -1369,55 +1474,22 @@ out: + show_unhandled_type_error (parameters_install); + } + +-static void +-on_launch_default_for_uri (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- ApplicationLaunchParameters *params; +- ActivateParameters *activation_params; +- char *uri; +- gboolean sandboxed; +- GError *error = NULL; +- +- params = user_data; +- activation_params = params->activation_params; +- uri = g_queue_pop_head (params->uris); +- sandboxed = g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS); +- +- nautilus_launch_default_for_uri_finish (res, &error); +- if (!sandboxed && error != NULL && error->code != G_IO_ERROR_CANCELLED) +- { +- g_queue_push_tail (params->unhandled_uris, uri); +- } +- +- if (!g_queue_is_empty (params->uris)) +- { +- nautilus_launch_default_for_uri_async (g_queue_peek_head (params->uris), +- activation_params->parent_window, +- activation_params->cancellable, +- on_launch_default_for_uri, +- params); +- } +- else +- { +- while ((uri = g_queue_pop_head (params->unhandled_uris)) != NULL) +- { +- application_unhandled_uri (activation_params, uri); +- } +- +- application_launch_parameters_free (params); +- } +-} +- + static void + activate_files (ActivateParameters *parameters) + { + NautilusFile *file; + NautilusWindowOpenFlags flags; ++ g_autoptr (GList) open_in_app_parameters = NULL; ++ g_autoptr (GList) unhandled_open_in_app_uris = NULL; ++ ApplicationLaunchParameters *one_parameters; + int count; + g_autofree char *old_working_dir = NULL; + GdkScreen *screen; ++ gint num_apps; ++ gint num_unhandled; ++ gint num_files; ++ gboolean open_files; ++ g_autoptr (GQueue) launch_desktop_files = NULL; + g_autoptr (GQueue) launch_files = NULL; + g_autoptr (GQueue) launch_in_terminal_files = NULL; + g_autoptr (GQueue) open_in_app_uris = NULL; +@@ -1612,26 +1684,68 @@ activate_files (ActivateParameters *parameters) + } + } + +- if (g_queue_is_empty (open_in_app_uris)) ++ if (open_in_app_uris != NULL) + { +- activation_parameters_free (parameters); ++ open_in_app_parameters = make_activation_parameters (g_queue_peek_head_link (open_in_app_uris), ++ &unhandled_open_in_app_uris); + } +- else ++ ++ num_apps = g_list_length (open_in_app_parameters); ++ num_unhandled = g_list_length (unhandled_open_in_app_uris); ++ num_files = g_queue_get_length (open_in_app_uris); ++ open_files = TRUE; ++ ++ if (g_queue_is_empty (open_in_app_uris) && ++ (!parameters->user_confirmation || ++ num_files + num_unhandled > SILENT_OPEN_LIMIT) && ++ num_apps > 1) + { +- const char *uri; +- ApplicationLaunchParameters *params; ++ GtkDialog *dialog; ++ char *prompt; ++ g_autofree char *detail = NULL; ++ int response; + +- uri = g_queue_peek_head (open_in_app_uris); +- params = application_launch_parameters_new (parameters, +- g_queue_copy (open_in_app_uris)); ++ pause_activation_timed_cancel (parameters); + +- gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri); +- nautilus_launch_default_for_uri_async (uri, +- parameters->parent_window, +- parameters->cancellable, +- on_launch_default_for_uri, +- params); ++ prompt = _("Are you sure you want to open all files?"); ++ detail = g_strdup_printf (ngettext ("This will open %d separate application.", ++ "This will open %d separate applications.", num_apps), num_apps); ++ dialog = eel_show_yes_no_dialog (prompt, detail, ++ _("_OK"), _("_Cancel"), ++ parameters->parent_window); ++ response = gtk_dialog_run (dialog); ++ gtk_widget_destroy (GTK_WIDGET (dialog)); ++ ++ unpause_activation_timed_cancel (parameters); ++ ++ if (response != GTK_RESPONSE_YES) ++ { ++ open_files = FALSE; ++ } ++ } ++ ++ if (open_files) ++ { ++ for (l = open_in_app_parameters; l != NULL; l = l->next) ++ { ++ one_parameters = l->data; ++ ++ nautilus_launch_application_by_uri (one_parameters->application, ++ one_parameters->uris, ++ parameters->parent_window); ++ application_launch_parameters_free (one_parameters); ++ } ++ ++ for (l = unhandled_open_in_app_uris; l != NULL; l = l->next) ++ { ++ char *uri = l->data; ++ ++ /* this does not block */ ++ application_unhandled_uri (parameters, uri); ++ } + } ++ ++ activation_parameters_free (parameters); + } + + static void +diff --git a/src/nautilus-program-choosing.c b/src/nautilus-program-choosing.c +index 47362a3f7..35a4ab73f 100644 +--- a/src/nautilus-program-choosing.c ++++ b/src/nautilus-program-choosing.c +@@ -126,32 +126,6 @@ nautilus_launch_application (GAppInfo *application, + g_list_free_full (uris, g_free); + } + +-static GdkAppLaunchContext * +-get_launch_context (GtkWindow *parent_window) +-{ +- GdkDisplay *display; +- GdkAppLaunchContext *launch_context; +- +- if (parent_window != NULL) +- { +- display = gtk_widget_get_display (GTK_WIDGET (parent_window)); +- } +- else +- { +- display = gdk_display_get_default (); +- } +- +- launch_context = gdk_display_get_app_launch_context (display); +- +- if (parent_window != NULL) +- { +- gdk_app_launch_context_set_screen (launch_context, +- gtk_window_get_screen (parent_window)); +- } +- +- return launch_context; +-} +- + void + nautilus_launch_application_by_uri (GAppInfo *application, + GList *uris, +@@ -163,7 +137,8 @@ nautilus_launch_application_by_uri (GAppInfo *application, + NautilusFile *file; + gboolean result; + GError *error; +- g_autoptr (GdkAppLaunchContext) launch_context = NULL; ++ GdkDisplay *display; ++ GdkAppLaunchContext *launch_context; + NautilusIconInfo *icon; + int count, total; + +@@ -186,7 +161,22 @@ nautilus_launch_application_by_uri (GAppInfo *application, + } + locations = g_list_reverse (locations); + +- launch_context = get_launch_context (parent_window); ++ if (parent_window != NULL) ++ { ++ display = gtk_widget_get_display (GTK_WIDGET (parent_window)); ++ } ++ else ++ { ++ display = gdk_display_get_default (); ++ } ++ ++ launch_context = gdk_display_get_app_launch_context (display); ++ ++ if (parent_window != NULL) ++ { ++ gdk_app_launch_context_set_screen (launch_context, ++ gtk_window_get_screen (parent_window)); ++ } + + file = nautilus_file_get_by_uri (uris->data); + icon = nautilus_file_get_icon (file, +@@ -222,6 +212,8 @@ nautilus_launch_application_by_uri (GAppInfo *application, + &error); + } + ++ g_object_unref (launch_context); ++ + if (result) + { + for (l = uris; l != NULL; l = l->next) +@@ -480,144 +472,4 @@ nautilus_launch_desktop_file (GdkScreen *screen, + g_object_unref (app_info); + } + +-/* HAX +- * +- * TODO: remove everything below once it’s doable from GTK+. +- * +- * Context: https://bugzilla.gnome.org/show_bug.cgi?id=781132 and +- * https://bugzilla.gnome.org/show_bug.cgi?id=779312 +- * +- * In a sandboxed environment, this is needed to able to get the actual +- * result of the operation, since gtk_show_uri_on_window () neither blocks +- * nor returns a useful value. +- */ +- +-static void +-on_launch_default_for_uri (GObject *source, +- GAsyncResult *result, +- gpointer data) +-{ +- GTask *task; +- NautilusWindow *window; +- gboolean success; +- GError *error = NULL; +- +- task = data; +- window = g_task_get_source_object (task); +- +- success = g_app_info_launch_default_for_uri_finish (result, &error); +- +- if (window) +- { +- nautilus_window_unexport_handle (window); +- } +- +- if (success) +- { +- g_task_return_boolean (task, success); +- } +- else +- { +- g_task_return_error (task, error); +- } +- +- /* Reffed in the call to nautilus_window_export_handle */ +- g_object_unref (task); +-} +- +-static void +-on_window_handle_export (NautilusWindow *window, +- const char *handle_str, +- guint xid, +- gpointer user_data) +-{ +- GTask *task = user_data; +- GAppLaunchContext *context = g_task_get_task_data (task); +- const char *uri; +- +- uri = g_object_get_data (G_OBJECT (context), "uri"); +- +- g_app_launch_context_setenv (context, "PARENT_WINDOW_ID", handle_str); +- +- g_app_info_launch_default_for_uri_async (uri, +- context, +- g_task_get_cancellable (task), +- on_launch_default_for_uri, +- task); +-} +- +-static void +-launch_default_for_uri_thread_func (GTask *task, +- gpointer source_object, +- gpointer task_data, +- GCancellable *cancellable) +-{ +- GAppLaunchContext *launch_context; +- const char *uri; +- gboolean success; +- GError *error = NULL; +- +- launch_context = task_data; +- uri = g_object_get_data (G_OBJECT (launch_context), "uri"); +- success = g_app_info_launch_default_for_uri (uri, launch_context, &error); +- +- if (success) +- { +- g_task_return_boolean (task, success); +- } +- else +- { +- g_task_return_error (task, error); +- } +-} +- +-void +-nautilus_launch_default_for_uri_async (const char *uri, +- GtkWindow *parent_window, +- GCancellable *cancellable, +- GAsyncReadyCallback callback, +- gpointer callback_data) +-{ +- g_autoptr (GdkAppLaunchContext) launch_context = NULL; +- g_autoptr (GTask) task = NULL; +- +- g_return_if_fail (uri != NULL); +- +- launch_context = get_launch_context (parent_window); +- task = g_task_new (parent_window, cancellable, callback, callback_data); +- +- gdk_app_launch_context_set_timestamp (launch_context, GDK_CURRENT_TIME); +- +- g_object_set_data_full (G_OBJECT (launch_context), +- "uri", g_strdup (uri), g_free); +- g_task_set_task_data (task, +- g_object_ref (launch_context), g_object_unref); +- +- if (parent_window != NULL) +- { +- gboolean handle_exported; +- +- handle_exported = nautilus_window_export_handle (NAUTILUS_WINDOW (parent_window), +- on_window_handle_export, +- g_object_ref (task)); +- +- if (handle_exported) +- { +- /* Launching will now be handled from the callback */ +- return; +- } +- } +- +- g_task_run_in_thread (task, launch_default_for_uri_thread_func); +-} +- +-gboolean +-nautilus_launch_default_for_uri_finish (GAsyncResult *result, +- GError **error) +-{ +- g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE); +- +- return g_task_propagate_boolean (G_TASK (result), error); +-} +- + /* END OF HAX */ +diff --git a/src/nautilus-program-choosing.h b/src/nautilus-program-choosing.h +index 51881ff17..a402b79a2 100644 +--- a/src/nautilus-program-choosing.h ++++ b/src/nautilus-program-choosing.h +@@ -51,10 +51,3 @@ void nautilus_launch_desktop_file (GdkScreen + const char *desktop_file_uri, + const GList *parameter_uris, + GtkWindow *parent_window); +-void nautilus_launch_default_for_uri_async (const char *uri, +- GtkWindow *parent_window, +- GCancellable *cancellable, +- GAsyncReadyCallback callback, +- gpointer callback_data); +-gboolean nautilus_launch_default_for_uri_finish (GAsyncResult *result, +- GError **error); +\ No newline at end of file +-- +GitLab + diff --git a/nautilus-3.33.90.tar.xz b/nautilus-3.33.90.tar.xz deleted file mode 100644 index 11e2317..0000000 Binary files a/nautilus-3.33.90.tar.xz and /dev/null differ diff --git a/nautilus-3.38.2.tar.xz b/nautilus-3.38.2.tar.xz new file mode 100644 index 0000000..0ef99d6 Binary files /dev/null and b/nautilus-3.38.2.tar.xz differ diff --git a/nautilus.spec b/nautilus.spec index b499840..3330129 100644 --- a/nautilus.spec +++ b/nautilus.spec @@ -1,16 +1,18 @@ Name: nautilus -Version: 3.33.90 -Release: 3 +Version: 3.38.2 +Release: 1 Summary: Default file manager for GNOME License: GPLv3+ and LGPLv2+ URL: https://wiki.gnome.org/Apps/Nautilus -Source0: https://download.gnome.org/sources/%{name}/3.33/%{name}-%{version}.tar.xz +Source0: https://download.gnome.org/sources/%{name}/3.38/%{name}-%{version}.tar.xz + +Patch0: 0001-mime-actions-Group-files-depending-on-the-opening-ap.patch BuildRequires: desktop-file-utils gcc gettext gtk-doc meson libgexiv2-devel glib2-devel gnome-autoar-devel gnome-desktop3-devel BuildRequires: gobject-introspection-devel gsettings-desktop-schemas-devel gtk3-devel libseccomp-devel libselinux-devel libxslt -BuildRequires: libxml2-devel tracker-devel libX11-devel /usr/bin/appstream-util pkgconfig(gstreamer-pbutils-1.0) pkgconfig(gstreamer-tag-1.0) git +BuildRequires: libxml2-devel tracker3-devel libX11-devel /usr/bin/appstream-util pkgconfig(gstreamer-pbutils-1.0) pkgconfig(gstreamer-tag-1.0) -Requires: glib2 gsettings-desktop-schemas gtk3 gvfs tracker-miners +Requires: glib2 gsettings-desktop-schemas gtk3 gvfs tracker3-miners Provides: %{name}-extensions Obsoletes: %{name}-extensions @@ -47,7 +49,6 @@ sed -i '/-Werror/d' meson.build %check appstream-util validate-relax --nonet $RPM_BUILD_ROOT%{_datadir}/metainfo/org.gnome.Nautilus.appdata.xml desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/*.desktop -make test %ldconfig_scriptlets @@ -64,6 +65,8 @@ make test %{_datadir}/applications/* %{_datadir}/icons/hicolor/* %{_datadir}/glib-2.0/* +%{_datadir}/nautilus/* +%{_datadir}/tracker3/* %files devel %defattr(-,root,root) @@ -79,6 +82,10 @@ make test %{_datadir}/metainfo/* %changelog +* Mon Jun 7 2021 weijin deng - 3.38.2-1 +- Upgrade to 3.38.2 +- Add a patch that can launch default uri handlers when activating files + * Sat Dec 28 2019 Jiangping Hu - 3.33.90-3 - Type:bugfix - Id:NA