[Spice-devel] [PATCH spice-gtk] RFC: populate all clipboards

Marc-André Lureau marcandre.lureau at gmail.com
Thu Feb 20 07:15:51 PST 2014


Some users want all the clipboards to be populated when doing copy.  I
wonder if there isn't a better solution than to have this hack in
spice-gtk, in particular, if a small X daemon/tools could do that
automatically? That would be a cleaner and more future-proof approach
imho.

Nevertheless, this is a proof of concept, when setting
SPICE_CLIPBOARD_FILL_ALL=1, all implemented clipboards will be
populated by spice-gtk.

https://bugzilla.redhat.com/show_bug.cgi?id=967077
---
 gtk/channel-main.c      | 74 ++++++++++++++++++++++++++++++++++++++++++++-----
 gtk/spice-gtk-session.c |  3 +-
 gtk/spice-util-priv.h   |  3 ++
 3 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index d44ac23..c83233e 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -107,6 +107,8 @@ struct _SpiceMainChannelPrivate  {
     guint                       migrate_delayed_id;
     spice_migrate               *migrate_data;
     int                         max_clipboard;
+    gint                        last_selection;
+    gint                        last_selection_request;
 };
 
 struct spice_migrate {
@@ -229,6 +231,8 @@ static void spice_main_channel_init(SpiceMainChannel *channel)
     c = channel->priv = SPICE_MAIN_CHANNEL_GET_PRIVATE(channel);
     c->agent_msg_queue = g_queue_new();
     c->file_xfer_tasks = g_hash_table_new(g_direct_hash, g_direct_equal);
+    c->last_selection = -1;
+    c->last_selection_request = -1;
 
     spice_main_channel_reset_capabilties(SPICE_CHANNEL(channel));
 }
@@ -1306,6 +1310,11 @@ static void agent_clipboard_notify(SpiceMainChannel *self, guint selection,
     size_t msgsize;
     gint max_clipboard = spice_main_get_max_clipboard(self);
 
+    if (c->last_selection_request != -1) {
+        selection = c->last_selection_request;
+        c->last_selection_request = -1;
+    }
+
     g_return_if_fail(c->agent_connected);
     g_return_if_fail(test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
     g_return_if_fail(max_clipboard == -1 || size < max_clipboard);
@@ -1916,6 +1925,10 @@ static void main_agent_handle_msg(SpiceChannel *channel,
     case VD_AGENT_CLIPBOARD:
     {
         VDAgentClipboard *cb = payload;
+
+        if (g_getenv("SPICE_CLIPBOARD_FILL_ALL"))
+            selection = c->last_selection;
+
         emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION, selection,
                           cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
 
@@ -1927,17 +1940,38 @@ static void main_agent_handle_msg(SpiceChannel *channel,
     case VD_AGENT_CLIPBOARD_GRAB:
     {
         gboolean ret;
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
-                          (guint8*)payload, msg->size / sizeof(uint32_t), &ret);
-        if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
+
+        if (g_getenv("SPICE_CLIPBOARD_FILL_ALL")) {
+            c->last_selection = selection;
+
+            for (selection = 0; selection <= CLIPBOARD_ALL; selection++) {
+                emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
+                                  (guint8*)payload, msg->size / sizeof(uint32_t), &ret);
+            }
+
             emit_main_context(self, SPICE_MAIN_CLIPBOARD_GRAB,
                               payload, msg->size / sizeof(uint32_t), &ret);
+        } else {
+            emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
+                              (guint8*)payload, msg->size / sizeof(uint32_t), &ret);
+
+            if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
+                emit_main_context(self, SPICE_MAIN_CLIPBOARD_GRAB,
+                                  payload, msg->size / sizeof(uint32_t), &ret);
+        }
         break;
     }
     case VD_AGENT_CLIPBOARD_REQUEST:
     {
         gboolean ret;
         VDAgentClipboardRequest *req = payload;
+
+        if (g_getenv("SPICE_CLIPBOARD_FILL_ALL")) {
+            g_return_if_fail(c->last_selection_request == -1);
+            c->last_selection_request = selection;
+            selection = c->last_selection;
+        }
+
         emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, selection,
                           req->type, &ret);
 
@@ -1948,10 +1982,19 @@ static void main_agent_handle_msg(SpiceChannel *channel,
     }
     case VD_AGENT_CLIPBOARD_RELEASE:
     {
-        emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
+        if (g_getenv("SPICE_CLIPBOARD_FILL_ALL")) {
+            for (selection = 0; selection <= CLIPBOARD_ALL; selection++) {
+                emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
+            }
 
-        if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
             emit_main_context(self, SPICE_MAIN_CLIPBOARD_RELEASE);
+        } else {
+            emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
+
+            if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
+                emit_main_context(self, SPICE_MAIN_CLIPBOARD_RELEASE);
+        }
+
         break;
     }
     case VD_AGENT_REPLY:
@@ -2580,8 +2623,15 @@ void spice_main_clipboard_selection_grab(SpiceMainChannel *channel, guint select
 {
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
+    SpiceMainChannelPrivate *c = channel->priv;
 
-    agent_clipboard_grab(channel, selection, types, ntypes);
+    if (g_getenv("SPICE_CLIPBOARD_FILL_ALL")) {
+        c->last_selection = selection;
+        for (selection = 0; selection <= CLIPBOARD_ALL; selection++)
+            agent_clipboard_grab(channel, selection, types, ntypes);
+    } else {
+        agent_clipboard_grab(channel, selection, types, ntypes);
+    }
     spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
 }
 
@@ -2619,7 +2669,13 @@ void spice_main_clipboard_selection_release(SpiceMainChannel *channel, guint sel
     if (!c->agent_connected)
         return;
 
-    agent_clipboard_release(channel, selection);
+    if (g_getenv("SPICE_CLIPBOARD_FILL_ALL")) {
+        for (selection = 0; selection <= CLIPBOARD_ALL; selection++)
+            agent_clipboard_release(channel, selection);
+    } else {
+        agent_clipboard_release(channel, selection);
+    }
+
     spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
 }
 
@@ -2693,6 +2749,10 @@ void spice_main_clipboard_selection_request(SpiceMainChannel *channel, guint sel
 {
     g_return_if_fail(channel != NULL);
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
+    SpiceMainChannelPrivate *c = channel->priv;
+
+    if (g_getenv("SPICE_CLIPBOARD_FILL_ALL"))
+        selection = c->last_selection;
 
     agent_clipboard_request(channel, selection, type);
     spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 44a8844..f5a72cb 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -563,7 +563,8 @@ static void clipboard_got_from_guest(SpiceMainChannel *main, guint selection,
     SpiceGtkSessionPrivate *s = ri->self->priv;
     gchar *conv = NULL;
 
-    g_return_if_fail(selection == ri->selection);
+    if (!g_getenv("SPICE_CLIPBOARD_FILL_ALL"))
+        g_return_if_fail(selection == ri->selection);
 
     SPICE_DEBUG("clipboard got data");
 
diff --git a/gtk/spice-util-priv.h b/gtk/spice-util-priv.h
index c0ea8d9..843fc33 100644
--- a/gtk/spice-util-priv.h
+++ b/gtk/spice-util-priv.h
@@ -47,6 +47,9 @@ void spice_mono_edge_highlight(unsigned width, unsigned hight,
 #define STATIC_MUTEX_UNLOCK(m)  g_static_mutex_unlock(&(m))
 #endif
 
+/* all currently supported clipboards by spice-gtk */
+#define CLIPBOARD_ALL (VD_AGENT_CLIPBOARD_SELECTION_PRIMARY)
+
 G_END_DECLS
 
 #endif /* SPICE_UTIL_PRIV_H */
-- 
1.8.5.3



More information about the Spice-devel mailing list