[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