summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntónio Fernandes <antoniof@gnome.org>2020-07-18 22:01:20 +0100
committerOndrej Holy <oholy@redhat.com>2020-09-07 08:28:58 +0000
commit7768f7b54937f0a99a909224d90812b793dc1f46 (patch)
treeb4e4679f34202131ee520052c39dc443a767d2d5
parent831203e9512b29900e8095c91332b49bbbf97047 (diff)
downloadnautilus-revert-text-only-clipboard.tar.gz
Revert "clipboard: Use text based clipboard only"revert-text-only-clipboard
After removing the non-default "icons on desktop" functionality from nautilus, a gnome-shell extension was created as a substitute. This extension needed to interoperate with nautilus for file operations, but its access to clipboard was limited to plain text, so, in order to ensure interoperation, nautilus had to use plain text clipboard only. However, this temporary regression resulted in implementation details leaking into the text clipboard, instead of a plain file path. But now St.Clipboard can handle any type of clipboard content[1], the extension will be able to handle any clipboard type, so we can finally fix this regression on our side. This reverts commit 1f77023b5769c773dd9261e5294c0738bf6a3115 and its fixup commit be53569b339b4494647758a9afa0fdd30184455b Fixes https://gitlab.gnome.org/GNOME/nautilus/-/issues/634 [1] GNOME/gnome-shell@ec367623
-rw-r--r--src/nautilus-canvas-view.c13
-rw-r--r--src/nautilus-clipboard.c116
-rw-r--r--src/nautilus-clipboard.h5
-rw-r--r--src/nautilus-files-view.c113
-rw-r--r--src/nautilus-list-view.c13
5 files changed, 153 insertions, 107 deletions
diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c
index 4b3197bd7..09a72be6b 100644
--- a/src/nautilus-canvas-view.c
+++ b/src/nautilus-canvas-view.c
@@ -528,9 +528,9 @@ nautilus_canvas_view_begin_loading (NautilusFilesView *view)
}
static void
-on_clipboard_contents_received (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer user_data)
+on_clipboard_contents_received (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer user_data)
{
NautilusCanvasView *canvas_view;
@@ -569,9 +569,10 @@ static void
update_clipboard_status (NautilusCanvasView *view)
{
g_object_ref (view); /* Need to keep the object alive until we get the reply */
- gtk_clipboard_request_text (nautilus_clipboard_get (GTK_WIDGET (view)),
- on_clipboard_contents_received,
- view);
+ gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
+ nautilus_clipboard_get_atom (),
+ on_clipboard_contents_received,
+ view);
}
static void
diff --git a/src/nautilus-clipboard.c b/src/nautilus-clipboard.c
index fb7e96d4b..02bf05497 100644
--- a/src/nautilus-clipboard.c
+++ b/src/nautilus-clipboard.c
@@ -33,6 +33,8 @@
#include <gtk/gtk.h>
#include <string.h>
+static GdkAtom copied_files_atom;
+
typedef struct
{
gboolean cut;
@@ -40,31 +42,21 @@ typedef struct
} ClipboardInfo;
static GList *
-convert_selection_data_to_str_list (const gchar *data)
+convert_lines_to_str_list (char **lines)
{
- g_auto (GStrv) lines = NULL;
- guint number_of_lines;
+ int i;
GList *result;
- lines = g_strsplit (data, "\n", 0);
- number_of_lines = g_strv_length (lines);
- if (number_of_lines == 0)
+ if (lines[0] == NULL)
{
- /* An empty string will result in g_strsplit() returning an empty
- * array, so, naturally, 0 - 1 = UINT_MAX and we read all sorts
- * of invalid memory.
- */
return NULL;
}
- result = NULL;
- /* Also, this skips the last line, since it would be an
- * empty string from the split */
- for (guint i = 0; i < number_of_lines - 1; i++)
+ result = NULL;
+ for (i = 0; lines[i] != NULL; i++)
{
result = g_list_prepend (result, g_strdup (lines[i]));
}
-
return g_list_reverse (result);
}
@@ -85,8 +77,7 @@ convert_file_list_to_string (ClipboardInfo *info,
}
else
{
- uris = g_string_new ("x-special/nautilus-clipboard\n");
- g_string_append (uris, info->cut ? "cut\n" : "copy\n");
+ uris = g_string_new (info->cut ? "cut" : "copy");
}
for (i = 0, l = info->files; l != NULL; l = l->next, i++)
@@ -109,12 +100,16 @@ convert_file_list_to_string (ClipboardInfo *info,
g_string_append (uris, uri);
}
- g_string_append_c (uris, '\n');
+ /* skip newline for last element */
+ if (i + 1 < g_list_length (info->files))
+ {
+ g_string_append_c (uris, '\n');
+ }
}
else
{
- g_string_append (uris, uri);
g_string_append_c (uris, '\n');
+ g_string_append (uris, uri);
}
g_free (uri);
@@ -125,60 +120,43 @@ convert_file_list_to_string (ClipboardInfo *info,
}
static GList *
-get_item_list_from_selection_data (const gchar *selection_data)
+get_item_list_from_selection_data (GtkSelectionData *selection_data)
{
- GList *items = NULL;
+ GList *items;
+ char **lines;
- if (selection_data != NULL)
+ if (gtk_selection_data_get_data_type (selection_data) != copied_files_atom
+ || gtk_selection_data_get_length (selection_data) <= 0)
+ {
+ items = NULL;
+ }
+ else
{
- gboolean valid_data = TRUE;
+ gchar *data;
/* Not sure why it's legal to assume there's an extra byte
* past the end of the selection data that it's safe to write
* to. But gtk_editable_selection_received does this, so I
* think it is OK.
*/
- items = convert_selection_data_to_str_list (selection_data);
- if (items == NULL || g_strcmp0 (items->data, "x-special/nautilus-clipboard") != 0)
- {
- valid_data = FALSE;
- }
- else if (items->next == NULL)
- {
- valid_data = FALSE;
- }
- else if (g_strcmp0 (items->next->data, "cut") != 0 &&
- g_strcmp0 (items->next->data, "copy") != 0)
- {
- valid_data = FALSE;
- }
-
- if (!valid_data)
- {
- g_list_free_full (items, g_free);
- items = NULL;
- }
+ data = (gchar *) gtk_selection_data_get_data (selection_data);
+ data[gtk_selection_data_get_length (selection_data)] = '\0';
+ lines = g_strsplit (data, "\n", 0);
+ items = convert_lines_to_str_list (lines);
+ g_strfreev (lines);
}
return items;
}
-gboolean
-nautilus_clipboard_is_data_valid_from_selection_data (const gchar *selection_data)
-{
- return nautilus_clipboard_get_uri_list_from_selection_data (selection_data) != NULL;
-}
-
GList *
-nautilus_clipboard_get_uri_list_from_selection_data (const gchar *selection_data)
+nautilus_clipboard_get_uri_list_from_selection_data (GtkSelectionData *selection_data)
{
GList *items;
items = get_item_list_from_selection_data (selection_data);
if (items)
{
- /* Line 0 is x-special/nautilus-clipboard. */
- items = g_list_remove (items, items->data);
- /* Line 1 is "cut" or "copy", so uris start at line 2. */
+ /* Line 0 is "cut" or "copy", so uris start at line 1. */
items = g_list_remove (items, items->data);
}
@@ -196,12 +174,13 @@ void
nautilus_clipboard_clear_if_colliding_uris (GtkWidget *widget,
const GList *item_uris)
{
- g_autofree gchar *data = NULL;
+ GtkSelectionData *data;
GList *clipboard_item_uris, *l;
gboolean collision;
collision = FALSE;
- data = gtk_clipboard_wait_for_text (nautilus_clipboard_get (widget));
+ data = gtk_clipboard_wait_for_contents (nautilus_clipboard_get (widget),
+ copied_files_atom);
if (data == NULL)
{
return;
@@ -231,14 +210,14 @@ nautilus_clipboard_clear_if_colliding_uris (GtkWidget *widget,
}
gboolean
-nautilus_clipboard_is_cut_from_selection_data (const gchar *selection_data)
+nautilus_clipboard_is_cut_from_selection_data (GtkSelectionData *selection_data)
{
GList *items;
gboolean is_cut_from_selection_data;
items = get_item_list_from_selection_data (selection_data);
is_cut_from_selection_data = items != NULL &&
- g_strcmp0 ((gchar *) items->next->data, "cut") == 0;
+ g_strcmp0 ((gchar *) items->data, "cut") == 0;
g_list_free_full (items, g_free);
@@ -283,10 +262,19 @@ on_get_clipboard (GtkClipboard *clipboard,
char *str;
gsize len;
- str = convert_file_list_to_string (clipboard_info, FALSE, &len);
+ str = convert_file_list_to_string (clipboard_info, TRUE, &len);
gtk_selection_data_set_text (selection_data, str, len);
g_free (str);
}
+ else if (target == copied_files_atom)
+ {
+ char *str;
+ gsize len;
+
+ str = convert_file_list_to_string (clipboard_info, FALSE, &len);
+ gtk_selection_data_set (selection_data, copied_files_atom, 8, (guchar *) str, len);
+ g_free (str);
+ }
}
static void
@@ -315,6 +303,7 @@ nautilus_clipboard_prepare_for_files (GtkClipboard *clipboard,
clipboard_info->files = nautilus_file_list_copy (files);
target_list = gtk_target_list_new (NULL, 0);
+ gtk_target_list_add (target_list, copied_files_atom, 0, 0);
gtk_target_list_add_uri_targets (target_list, 0);
gtk_target_list_add_text_targets (target_list, 0);
@@ -327,3 +316,14 @@ nautilus_clipboard_prepare_for_files (GtkClipboard *clipboard,
clipboard_info);
gtk_target_table_free (targets, n_targets);
}
+
+GdkAtom
+nautilus_clipboard_get_atom (void)
+{
+ if (!copied_files_atom)
+ {
+ copied_files_atom = gdk_atom_intern_static_string ("x-special/gnome-copied-files");
+ }
+
+ return copied_files_atom;
+}
diff --git a/src/nautilus-clipboard.h b/src/nautilus-clipboard.h
index 61810c154..1dd26d7c2 100644
--- a/src/nautilus-clipboard.h
+++ b/src/nautilus-clipboard.h
@@ -27,10 +27,9 @@
void nautilus_clipboard_clear_if_colliding_uris (GtkWidget *widget,
const GList *item_uris);
GtkClipboard* nautilus_clipboard_get (GtkWidget *widget);
-GList* nautilus_clipboard_get_uri_list_from_selection_data (const gchar *selection_data);
-gboolean nautilus_clipboard_is_cut_from_selection_data (const gchar *selection_data);
+GList* nautilus_clipboard_get_uri_list_from_selection_data (GtkSelectionData *selection_data);
+gboolean nautilus_clipboard_is_cut_from_selection_data (GtkSelectionData *selection_data);
void nautilus_clipboard_prepare_for_files (GtkClipboard *clipboard,
GList *files,
gboolean cut);
GdkAtom nautilus_clipboard_get_atom (void);
-gboolean nautilus_clipboard_is_data_valid_from_selection_data (const gchar *selection_data);
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index b22bd8408..f5c6c9342 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -2638,7 +2638,7 @@ action_open_item_new_window (GSimpleAction *action,
static void
handle_clipboard_data (NautilusFilesView *view,
- const gchar *selection_data,
+ GtkSelectionData *selection_data,
char *destination_uri,
GdkDragAction action)
{
@@ -2663,7 +2663,7 @@ handle_clipboard_data (NautilusFilesView *view,
static void
paste_clipboard_data (NautilusFilesView *view,
- const gchar *selection_data,
+ GtkSelectionData *selection_data,
char *destination_uri)
{
GdkDragAction action;
@@ -2681,9 +2681,9 @@ paste_clipboard_data (NautilusFilesView *view,
}
static void
-paste_clipboard_text_received_callback (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer data)
+paste_clipboard_received_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
{
NautilusFilesView *view;
NautilusFilesViewPrivate *priv;
@@ -2715,10 +2715,10 @@ paste_files (NautilusFilesView *view)
* is in the callback.
*/
g_object_ref (view);
-
- gtk_clipboard_request_text (clipboard,
- paste_clipboard_text_received_callback,
- view);
+ gtk_clipboard_request_contents (clipboard,
+ nautilus_clipboard_get_atom (),
+ paste_clipboard_received_callback,
+ view);
}
static void
@@ -2756,9 +2756,9 @@ action_paste_files_accel (GSimpleAction *action,
}
static void
-create_links_clipboard_received_callback (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer data)
+create_links_clipboard_received_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
{
NautilusFilesView *view;
NautilusFilesViewPrivate *priv;
@@ -2791,9 +2791,10 @@ action_create_links (GSimpleAction *action,
view = NAUTILUS_FILES_VIEW (user_data);
g_object_ref (view);
- gtk_clipboard_request_text (nautilus_clipboard_get (GTK_WIDGET (view)),
- create_links_clipboard_received_callback,
- view);
+ gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
+ nautilus_clipboard_get_atom (),
+ create_links_clipboard_received_callback,
+ view);
}
static void
@@ -6222,9 +6223,9 @@ typedef struct
} PasteIntoData;
static void
-paste_into_clipboard_received_callback (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer callback_data)
+paste_into_clipboard_received_callback (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer callback_data)
{
NautilusFilesViewPrivate *priv;
PasteIntoData *data;
@@ -6264,9 +6265,10 @@ paste_into (NautilusFilesView *view,
data->view = g_object_ref (view);
data->target = nautilus_file_ref (target);
- gtk_clipboard_request_text (nautilus_clipboard_get (GTK_WIDGET (view)),
- paste_into_clipboard_received_callback,
- data);
+ gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
+ nautilus_clipboard_get_atom (),
+ paste_into_clipboard_received_callback,
+ data);
}
static void
@@ -7141,9 +7143,9 @@ can_paste_into_file (NautilusFile *file)
}
static void
-on_clipboard_contents_received (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer user_data)
+on_clipboard_contents_received (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer user_data)
{
NautilusFilesViewPrivate *priv;
NautilusFilesView *view;
@@ -7153,7 +7155,6 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
gboolean selection_contains_recent;
gboolean selection_contains_starred;
GAction *action;
- gboolean is_data_valid;
view = NAUTILUS_FILES_VIEW (user_data);
priv = nautilus_files_view_get_instance_private (view);
@@ -7166,7 +7167,6 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
return;
}
- is_data_valid = nautilus_clipboard_is_data_valid_from_selection_data (selection_data);
settings_show_create_link = g_settings_get_boolean (nautilus_preferences,
NAUTILUS_PREFERENCES_SHOW_CREATE_LINK);
is_read_only = nautilus_files_view_is_read_only (view);
@@ -7174,7 +7174,7 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
selection_contains_starred = showing_starred_directory (view);
can_link_from_copied_files = !nautilus_clipboard_is_cut_from_selection_data (selection_data) &&
!selection_contains_recent && !selection_contains_starred &&
- !is_read_only && selection_data != NULL;
+ !is_read_only && gtk_selection_data_get_length (selection_data) > 0;
action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
"create-link");
@@ -7182,25 +7182,62 @@ on_clipboard_contents_received (GtkClipboard *clipboard,
can_link_from_copied_files &&
settings_show_create_link);
+ g_object_unref (view);
+}
+
+static void
+on_clipboard_targets_received (GtkClipboard *clipboard,
+ GdkAtom *targets,
+ int n_targets,
+ gpointer user_data)
+{
+ NautilusFilesViewPrivate *priv;
+ NautilusFilesView *view;
+ gboolean is_data_copied;
+ int i;
+ GAction *action;
+
+ view = NAUTILUS_FILES_VIEW (user_data);
+ priv = nautilus_files_view_get_instance_private (view);
+ is_data_copied = FALSE;
+
+ if (priv->slot == NULL ||
+ !priv->active)
+ {
+ /* We've been destroyed or became inactive since call */
+ g_object_unref (view);
+ return;
+ }
+
+ if (targets)
+ {
+ for (i = 0; i < n_targets; i++)
+ {
+ if (targets[i] == nautilus_clipboard_get_atom ())
+ {
+ is_data_copied = TRUE;
+ }
+ }
+ }
+
action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
"paste");
/* Take into account if the action was previously disabled for other reasons,
* like the directory not being writabble */
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
- is_data_valid && g_action_get_enabled (action));
+ is_data_copied && g_action_get_enabled (action));
action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
"paste-into");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
- is_data_valid && g_action_get_enabled (action));
+ is_data_copied && g_action_get_enabled (action));
action = g_action_map_lookup_action (G_ACTION_MAP (priv->view_action_group),
"create-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
- is_data_valid && g_action_get_enabled (action));
-
+ is_data_copied && g_action_get_enabled (action));
g_object_unref (view);
}
@@ -7748,10 +7785,18 @@ real_update_actions_state (NautilusFilesView *view)
!selection_contains_starred &&
priv->templates_present);
+ /* Actions that are related to the clipboard need request, request the data
+ * and update them once we have the data */
+ g_object_ref (view); /* Need to keep the object alive until we get the reply */
+ gtk_clipboard_request_targets (nautilus_clipboard_get (GTK_WIDGET (view)),
+ on_clipboard_targets_received,
+ view);
+
g_object_ref (view); /* Need to keep the object alive until we get the reply */
- gtk_clipboard_request_text (nautilus_clipboard_get (GTK_WIDGET (view)),
- on_clipboard_contents_received,
- view);
+ gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
+ nautilus_clipboard_get_atom (),
+ on_clipboard_contents_received,
+ view);
action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group),
"select-all");
diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c
index e30fb6389..d4b0763a8 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -3839,9 +3839,9 @@ list_view_scroll_to_file (NautilusFilesView *view,
}
static void
-on_clipboard_contents_received (GtkClipboard *clipboard,
- const gchar *selection_data,
- gpointer user_data)
+on_clipboard_contents_received (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer user_data)
{
NautilusListView *view = NAUTILUS_LIST_VIEW (user_data);
@@ -3876,9 +3876,10 @@ static void
update_clipboard_status (NautilusListView *view)
{
g_object_ref (view); /* Need to keep the object alive until we get the reply */
- gtk_clipboard_request_text (nautilus_clipboard_get (GTK_WIDGET (view)),
- on_clipboard_contents_received,
- view);
+ gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)),
+ nautilus_clipboard_get_atom (),
+ on_clipboard_contents_received,
+ view);
}
static void