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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel