+ nautilus-3.35.90-2

Fix launching multiple files at once
This commit is contained in:
Bastien Nocera 2020-02-06 15:11:38 +01:00
parent 551f80ce87
commit 6539af8439
2 changed files with 611 additions and 2 deletions

View File

@ -0,0 +1,601 @@
From 759cbb3a7b6d633b55f367a913c1f7b5abb380bd Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Thu, 6 Feb 2020 15:04:31 +0100
Subject: [PATCH] Revert "mime-actions: launch default uri handlers when
activating files"
This reverts commit f5206a6daf0991d91e885a28bb66795a8ae12a41.
---
src/nautilus-mime-actions.c | 268 +++++++++++++++++++++++---------
src/nautilus-program-choosing.c | 190 +++-------------------
src/nautilus-program-choosing.h | 7 -
3 files changed, 211 insertions(+), 254 deletions(-)
diff --git a/src/nautilus-mime-actions.c b/src/nautilus-mime-actions.c
index 316066d4c..e629e60ee 100644
--- a/src/nautilus-mime-actions.c
+++ b/src/nautilus-mime-actions.c
@@ -64,6 +64,12 @@ typedef struct
char *uri;
} LaunchLocation;
+typedef struct
+{
+ GAppInfo *application;
+ GList *uris;
+} ApplicationLaunchParameters;
+
typedef struct
{
NautilusWindowSlot *slot;
@@ -83,13 +89,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
{
@@ -348,19 +347,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)
{
@@ -794,6 +801,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)
{
@@ -845,16 +960,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)
{
@@ -1384,55 +1489,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;
@@ -1627,26 +1699,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 047a78c2b..0b56c71bf 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)
@@ -479,145 +471,3 @@ nautilus_launch_desktop_file (GdkScreen *screen,
g_object_unref (context);
g_object_unref (app_info);
}
-
-/* HAX
- *
- * TODO: remove everything below once its 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
--
2.24.1

View File

@ -3,7 +3,7 @@
Name: nautilus Name: nautilus
Version: 3.35.90 Version: 3.35.90
Release: 1%{?dist} Release: 2%{?dist}
Summary: File manager for GNOME Summary: File manager for GNOME
License: GPLv3+ License: GPLv3+
@ -15,6 +15,7 @@ BuildRequires: gcc
BuildRequires: gettext BuildRequires: gettext
BuildRequires: gtk-doc BuildRequires: gtk-doc
BuildRequires: meson BuildRequires: meson
BuildRequires: git
BuildRequires: pkgconfig(gexiv2) BuildRequires: pkgconfig(gexiv2)
BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version} BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version}
BuildRequires: pkgconfig(gnome-autoar-0) BuildRequires: pkgconfig(gnome-autoar-0)
@ -44,6 +45,9 @@ Requires: tracker-miners
# libtotem-properties-page.so was shipped in totem-nautilus before # libtotem-properties-page.so was shipped in totem-nautilus before
Conflicts: totem-nautilus < 1:3.31.91 Conflicts: totem-nautilus < 1:3.31.91
# https://gitlab.gnome.org/GNOME/nautilus/issues/117#note_496825
Patch0: 0001-Revert-mime-actions-launch-default-uri-handlers-when.patch
%description %description
Nautilus is the file manager and graphical shell for the GNOME desktop Nautilus is the file manager and graphical shell for the GNOME desktop
that makes it easy to manage your files and the rest of your system. that makes it easy to manage your files and the rest of your system.
@ -69,7 +73,7 @@ This package provides libraries and header files needed
for developing nautilus extensions. for developing nautilus extensions.
%prep %prep
%autosetup -p1 %autosetup -p1 -S git
# Remove -Werror from compiler flags # Remove -Werror from compiler flags
sed -i '/-Werror/d' meson.build sed -i '/-Werror/d' meson.build
@ -132,6 +136,10 @@ desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/*.desktop
%doc %{_datadir}/gtk-doc/html/libnautilus-extension/ %doc %{_datadir}/gtk-doc/html/libnautilus-extension/
%changelog %changelog
* Thu Feb 06 2020 Bastien Nocera <bnocera@redhat.com> - 3.35.90-2
+ nautilus-3.35.90-2
- Fix launching multiple files at once
* Sun Feb 02 2020 Kalev Lember <klember@redhat.com> - 3.35.90-1 * Sun Feb 02 2020 Kalev Lember <klember@redhat.com> - 3.35.90-1
- Update to 3.35.90 - Update to 3.35.90