From 48e516347587f6f9e21f3ba9616079521296888d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 22 Mar 2019 15:20:14 +0100 Subject: [PATCH 6/6] clipboard: implement CAP_CLIPBOARD_GRAB_SERIAL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- src/channel-main.c | 32 +++++++++++++++++++++++++++++++- src/spice-gtk-session.c | 1 - 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/channel-main.c b/src/channel-main.c index 8574ae6..0062593 100644 --- a/src/channel-main.c +++ b/src/channel-main.c @@ -111,6 +111,7 @@ struct _SpiceMainChannelPrivate { guint migrate_delayed_id; spice_migrate *migrate_data; int max_clipboard; + uint32_t clipboard_serial[256]; gboolean agent_volume_playback_sync; gboolean agent_volume_record_sync; @@ -223,6 +224,7 @@ static const char *agent_caps[] = { [ VD_AGENT_CAP_MONITORS_CONFIG_POSITION ] = "monitors config position", [ VD_AGENT_CAP_FILE_XFER_DISABLED ] = "file transfer disabled", [ VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB ] = "no release on re-grab", + [ VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL ] = "clipboard grab serial", }; #define NAME(_a, _i) ((_i) < SPICE_N_ELEMENTS(_a) ? (_a[(_i)] ?: "?") : "?") @@ -412,6 +414,7 @@ static void spice_main_channel_reset_agent(SpiceMainChannel *channel) spice_main_channel_reset_all_xfer_operations(channel); file_xfer_flushed(channel, FALSE); + memset(c->clipboard_serial, 0, sizeof(c->clipboard_serial)); } /* main or coroutine context */ @@ -1335,6 +1338,7 @@ static void agent_announce_caps(SpiceMainChannel *channel) VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG_POSITION); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB); + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL); agent_msg_queue(channel, VD_AGENT_ANNOUNCE_CAPABILITIES, size, caps); g_free(caps); @@ -1365,6 +1369,10 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection, return; } + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { + size += sizeof(uint32_t); + } + msg = g_alloca(size); memset(msg, 0, size); @@ -1372,7 +1380,13 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection, if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) { msg[0] = selection; - grab = (VDAgentClipboardGrab *)(msg + 4); + grab = (void *)grab + 4; + } + + if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { + guint32 *serial = (guint32 *)grab; + *serial = GUINT32_TO_LE(c->clipboard_serial[selection]++); + grab = (void *)grab + sizeof(uint32_t); } for (i = 0; i < ntypes; i++) { @@ -1974,6 +1988,7 @@ static void main_agent_handle_msg(SpiceChannel *channel, SpiceMainChannel *self = SPICE_MAIN_CHANNEL(channel); SpiceMainChannelPrivate *c = self->priv; guint8 selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD; + guint32 serial; g_return_if_fail(msg->protocol == VD_AGENT_PROTOCOL); @@ -2045,6 +2060,21 @@ static void main_agent_handle_msg(SpiceChannel *channel, case VD_AGENT_CLIPBOARD_GRAB: { gboolean ret; + + if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { + serial = GUINT32_FROM_LE(*((guint32 *)payload)); + payload = ((guint8*)payload) + sizeof(uint32_t); + msg->size -= sizeof(uint32_t); + + if (serial == c->clipboard_serial[selection]) { + c->clipboard_serial[selection]++; + } else { + CHANNEL_DEBUG(channel, "grab discard, serial:%u != c->serial:%u", + serial, c->clipboard_serial[selection]); + break; + } + } + g_coroutine_signal_emit(self, signals[SPICE_MAIN_CLIPBOARD_SELECTION_GRAB], 0, selection, (guint8*)payload, msg->size / sizeof(uint32_t), &ret); if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c index 34ae4a1..439199b 100644 --- a/src/spice-gtk-session.c +++ b/src/spice-gtk-session.c @@ -1116,7 +1116,6 @@ static gboolean clipboard_release_timeout(gpointer user_data) * * Workaround this problem by delaying the release event by 0.5 sec, * unless the no-release-on-regrab capability is present. - * FIXME: protocol change to solve the conflict and set client priority. */ #define CLIPBOARD_RELEASE_DELAY 500 /* ms */ -- 2.23.0