diff options
author | Christophe Fergeau <cfergeau@redhat.com> | 2016-08-10 12:04:30 +0200 |
---|---|---|
committer | Christophe Fergeau <cfergeau@redhat.com> | 2016-09-01 12:51:58 +0200 |
commit | 7b0de6217670e0f668aff2949fba174ed3cc0b50 (patch) | |
tree | 842350db86016486471ff1a6a18dfb605ba6da1e | |
parent | b0a2ff4f205e39f87e9b54d658a27d415ee3d055 (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.c | 67 |
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; } |