summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntónio Fernandes <antoniof@gnome.org>2020-07-18 22:01:20 +0100
committerAntónio Fernandes <antoniojpfernandes@gmail.com>2021-03-07 11:12:20 +0000
commit2045f662f26891f5bb8c7ab0a7763227fe5fdf78 (patch)
tree8e1660cc592e7911159af8eb6d4a30d08294f790
parent7834de2671356f7074940644c149b81bd655a3b1 (diff)
downloadnautilus-2045f662f26891f5bb8c7ab0a7763227fe5fdf78.tar.gz
Revert "clipboard: Use text based clipboard only"
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 144deb06b..c4e747e3c 100644
--- a/src/nautilus-canvas-view.c
+++ b/src/nautilus-canvas-view.c
@@ -540,9 +540,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;
@@ -581,9 +581,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 9282e96ca..250c37264 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -2643,7 +2643,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)
{
@@ -2668,7 +2668,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;
@@ -2686,9 +2686,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;
@@ -2720,10 +2720,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
@@ -2761,9 +2761,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;
@@ -2796,9 +2796,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
@@ -6182,9 +6183,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;
@@ -6224,9 +6225,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
@@ -7235,9 +7237,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;
@@ -7247,7 +7249,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);
@@ -7260,7 +7261,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);
@@ -7268,7 +7268,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");
@@ -7276,25 +7276,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);
}
@@ -7845,10 +7882,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 63e54d11c..e3c0b81f6 100644
--- a/src/nautilus-list-view.c
+++ b/src/nautilus-list-view.c
@@ -3845,9 +3845,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);
@@ -3882,9 +3882,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