summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Fergeau <cfergeau@redhat.com>2016-08-10 12:04:30 +0200
committerChristophe Fergeau <cfergeau@redhat.com>2016-09-01 12:51:58 +0200
commit7b0de6217670e0f668aff2949fba174ed3cc0b50 (patch)
tree842350db86016486471ff1a6a18dfb605ba6da1e
parentb0a2ff4f205e39f87e9b54d658a27d415ee3d055 (diff)
clipboard: Use gtk_clipboard_request_text for text data
Currently, when the agent asks us for VD_AGENT_CLIPBOARD_UTF8_TEXT data, spice-gtk looks up for the first X11 target which would provide it with UTF8_TEXT data, and uses that for the clipboard request. This means we will use UTF8_STRING as the target for gtk_clipboard_request_contents(). However, some applications who can copy and paste text do not necessarily support the UTF8_STRING target. This is the case for Motif applications which support the STRING target however. It turns out gtk+ also provides a gtk_clipboard_request_text() method which will try several targets (UTF8_TEXT, COMPOUND_TEXT, TEXT), and will ensure the returned string is UTF-8, so we can use that when the agent asks us for some text data. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1348624
-rw-r--r--src/spice-gtk-session.c67
1 files changed, 52 insertions, 15 deletions
diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
index fb7630d..7b75117 100644
--- a/src/spice-gtk-session.c
+++ b/src/spice-gtk-session.c
@@ -953,6 +953,40 @@ static char *fixup_clipboard_text(SpiceGtkSession *self, const char *text, int *
return conv;
}
+static void clipboard_received_text_cb(GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer user_data)
+{
+ WeakRef *weakref = user_data;
+ SpiceGtkSession *self = (SpiceGtkSession*)weakref->object;
+ char *conv = NULL;
+ int len = 0;
+ int selection;
+
+ weak_unref(weakref);
+
+ if (self == NULL)
+ return;
+
+ g_return_if_fail(SPICE_IS_GTK_SESSION(self));
+
+ selection = get_selection_from_clipboard(self->priv, clipboard);
+ g_return_if_fail(selection != -1);
+
+ len = strlen(text);
+ if (!check_clipboard_size_limits(self, len)) {
+ return;
+ }
+
+ /* gtk+ internal utf8 newline is always LF, even on windows */
+ conv = fixup_clipboard_text(self, text, &len);
+
+ spice_main_clipboard_selection_notify(self->priv->main, selection,
+ VD_AGENT_CLIPBOARD_UTF8_TEXT,
+ (guchar *)(conv ?: text), len);
+ g_free(conv);
+}
+
static void clipboard_received_cb(GtkClipboard *clipboard,
GtkSelectionData *selection_data,
gpointer user_data)
@@ -998,16 +1032,14 @@ static void clipboard_received_cb(GtkClipboard *clipboard,
}
const guchar *data = gtk_selection_data_get_data(selection_data);
- gpointer conv = NULL;
- /* gtk+ internal utf8 newline is always LF, even on windows */
- if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
- conv = fixup_clipboard_text(self, (gchar *)data, &len);
- }
+ /* text should be handled through clipboard_received_text_cb(), not
+ * clipboard_received_cb().
+ */
+ g_warn_if_fail(type != VD_AGENT_CLIPBOARD_UTF8_TEXT);
spice_main_clipboard_selection_notify(s->main, selection, type,
- conv ?: data, len);
- g_free(conv);
+ data, len);
}
static gboolean clipboard_request(SpiceMainChannel *main, guint selection,
@@ -1030,16 +1062,21 @@ static gboolean clipboard_request(SpiceMainChannel *main, guint selection,
cb = get_clipboard_from_selection(s, selection);
g_return_val_if_fail(cb != NULL, FALSE);
- for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
- if (atom2agent[m].vdagent == type)
- break;
- }
+ if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
+ gtk_clipboard_request_text(cb, clipboard_received_text_cb,
+ weak_ref(G_OBJECT(self)));
+ } else {
+ for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {
+ if (atom2agent[m].vdagent == type)
+ break;
+ }
- g_return_val_if_fail(m < SPICE_N_ELEMENTS(atom2agent), FALSE);
+ g_return_val_if_fail(m < SPICE_N_ELEMENTS(atom2agent), FALSE);
- atom = gdk_atom_intern_static_string(atom2agent[m].xatom);
- gtk_clipboard_request_contents(cb, atom, clipboard_received_cb,
- weak_ref(G_OBJECT(self)));
+ atom = gdk_atom_intern_static_string(atom2agent[m].xatom);
+ gtk_clipboard_request_contents(cb, atom, clipboard_received_cb,
+ weak_ref(G_OBJECT(self)));
+ }
return TRUE;
}