diff --git a/0001-clipboard-do-not-release-between-client-grabs.patch b/0001-clipboard-do-not-release-between-client-grabs.patch new file mode 100644 index 0000000..c32f23f --- /dev/null +++ b/0001-clipboard-do-not-release-between-client-grabs.patch @@ -0,0 +1,77 @@ +From 16b41429618985e4ab8c597fbd0c5cca5cf7b3e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 21 Mar 2019 13:21:33 +0100 +Subject: [PATCH 1/6] clipboard: do not release between client grabs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +On the client side, whenever the grab owner changes (and the clipboard +was previously grabbed), spice-gtk sends a clipboard release followed +immediately by a new grab. But some clipboard managers on the remote +side react to clipboard release events by taking a clipboard grab, +presumably to avoid empty clipboards. + +The two grabs, coming from the client and from the remote sides, will +race in both directions, which may confuse the client & remote side, +as both believe the other side is the current grab owner, and thus +further clipboard data requests are likely to fail. + +Let's avoid sending a release event when re-grabing. + +The race described above may still happen in other rare circunstances, +and will require a protocol change. To avoid the conflict, a discussed +solution could use a clipboard serial number. + +Tested with current linux & windows vdagent. Looking at earlier +version of the code, it doesn't seem like subsequent grabs will be +treated as an error. + +Signed-off-by: Marc-André Lureau +--- + src/spice-gtk-session.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c +index 60399d0..cb00fa5 100644 +--- a/src/spice-gtk-session.c ++++ b/src/spice-gtk-session.c +@@ -577,8 +577,7 @@ static void clipboard_get_targets(GtkClipboard *clipboard, + g_return_if_fail(selection != -1); + + if (s->clip_grabbed[selection]) { +- SPICE_DEBUG("Clipboard is already grabbed, ignoring %d atoms", n_atoms); +- return; ++ SPICE_DEBUG("Clipboard is already grabbed, re-grab: %d atoms", n_atoms); + } + + /* Set all Atoms that matches our current protocol implementation */ +@@ -660,18 +659,14 @@ static void clipboard_owner_change(GtkClipboard *clipboard, + return; + } + +- /* In case we sent a grab to the agent, we need to release it now as +- * previous clipboard data should not be reachable anymore */ +- if (s->clip_grabbed[selection]) { +- s->clip_grabbed[selection] = FALSE; +- if (spice_main_channel_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) { +- spice_main_channel_clipboard_selection_release(s->main, selection); +- } +- } +- +- /* We are mostly interested when owner has changed in which case +- * we would like to let agent know about new clipboard data. */ + if (event->reason != GDK_OWNER_CHANGE_NEW_OWNER) { ++ if (s->clip_grabbed[selection]) { ++ /* grab was sent to the agent, so release it */ ++ s->clip_grabbed[selection] = FALSE; ++ if (spice_main_channel_agent_test_capability(s->main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) { ++ spice_main_channel_clipboard_selection_release(s->main, selection); ++ } ++ } + s->clip_hasdata[selection] = FALSE; + return; + } +-- +2.23.0 + diff --git a/0002-clipboard-do-not-release-between-remote-grabs.patch b/0002-clipboard-do-not-release-between-remote-grabs.patch new file mode 100644 index 0000000..a69bef5 --- /dev/null +++ b/0002-clipboard-do-not-release-between-remote-grabs.patch @@ -0,0 +1,167 @@ +From 271656ae32e756eacfcc522d1aaab9d7102b0ce7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 21 Mar 2019 13:21:34 +0100 +Subject: [PATCH 2/6] clipboard: do not release between remote grabs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Delay the release events for 0.5 sec. If no further grab comes in, +then release the grab. Otherwise, let's skip the release. This avoids +some races with clipboard managers. + +Related to: +https://gitlab.freedesktop.org/spice/spice-gtk/issues/82 + +Signed-off-by: Marc-André Lureau +--- + src/spice-gtk-session.c | 80 ++++++++++++++++++++++++++++++++++++----- + 1 file changed, 72 insertions(+), 8 deletions(-) + +diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c +index cb00fa5..79385a4 100644 +--- a/src/spice-gtk-session.c ++++ b/src/spice-gtk-session.c +@@ -59,6 +59,7 @@ struct _SpiceGtkSessionPrivate { + gboolean clip_hasdata[CLIPBOARD_LAST]; + gboolean clip_grabbed[CLIPBOARD_LAST]; + gboolean clipboard_by_guest[CLIPBOARD_LAST]; ++ guint clipboard_release_delay[CLIPBOARD_LAST]; + /* auto-usbredir related */ + gboolean auto_usbredir_enable; + int auto_usbredir_reqs; +@@ -95,6 +96,7 @@ struct _SpiceGtkSessionPrivate { + + /* ------------------------------------------------------------------ */ + /* Prototypes for private functions */ ++static void clipboard_release(SpiceGtkSession *self, guint selection); + static void clipboard_owner_change(GtkClipboard *clipboard, + GdkEventOwnerChange *event, + gpointer user_data); +@@ -255,6 +257,23 @@ static void spice_gtk_session_dispose(GObject *gobject) + G_OBJECT_CLASS(spice_gtk_session_parent_class)->dispose(gobject); + } + ++static void clipboard_release_delay_remove(SpiceGtkSession *self, guint selection, ++ gboolean release_if_delayed) ++{ ++ SpiceGtkSessionPrivate *s = self->priv; ++ ++ if (!s->clipboard_release_delay[selection]) ++ return; ++ ++ if (release_if_delayed) { ++ SPICE_DEBUG("delayed clipboard release, sel:%u", selection); ++ clipboard_release(self, selection); ++ } ++ ++ g_source_remove(s->clipboard_release_delay[selection]); ++ s->clipboard_release_delay[selection] = 0; ++} ++ + static void spice_gtk_session_finalize(GObject *gobject) + { + SpiceGtkSession *self = SPICE_GTK_SESSION(gobject); +@@ -264,6 +283,7 @@ static void spice_gtk_session_finalize(GObject *gobject) + /* release stuff */ + for (i = 0; i < CLIPBOARD_LAST; ++i) { + g_clear_pointer(&s->clip_targets[i], g_free); ++ clipboard_release_delay_remove(self, i, true); + } + + /* Chain up to the parent class */ +@@ -823,6 +843,8 @@ static gboolean clipboard_grab(SpiceMainChannel *main, guint selection, + int m, n; + int num_targets = 0; + ++ clipboard_release_delay_remove(self, selection, false); ++ + cb = get_clipboard_from_selection(s, selection); + g_return_val_if_fail(cb != NULL, FALSE); + +@@ -1052,17 +1074,12 @@ static gboolean clipboard_request(SpiceMainChannel *main, guint selection, + return TRUE; + } + +-static void clipboard_release(SpiceMainChannel *main, guint selection, +- gpointer user_data) ++static void clipboard_release(SpiceGtkSession *self, guint selection) + { +- g_return_if_fail(SPICE_IS_GTK_SESSION(user_data)); +- +- SpiceGtkSession *self = user_data; + SpiceGtkSessionPrivate *s = self->priv; + GtkClipboard* clipboard = get_clipboard_from_selection(s, selection); + +- if (!clipboard) +- return; ++ g_return_if_fail(clipboard != NULL); + + s->nclip_targets[selection] = 0; + +@@ -1072,6 +1089,53 @@ static void clipboard_release(SpiceMainChannel *main, guint selection, + s->clipboard_by_guest[selection] = FALSE; + } + ++typedef struct SpiceGtkClipboardRelease { ++ SpiceGtkSession *self; ++ guint selection; ++} SpiceGtkClipboardRelease; ++ ++static gboolean clipboard_release_timeout(gpointer user_data) ++{ ++ SpiceGtkClipboardRelease *rel = user_data; ++ ++ clipboard_release_delay_remove(rel->self, rel->selection, true); ++ ++ return G_SOURCE_REMOVE; ++} ++ ++/* ++ * The agents send release between two grabs. This may trigger ++ * clipboard managers trying to grab the clipboard. We end up with two ++ * sides, client and remote, racing for the clipboard grab, and ++ * believing each other is the owner. ++ * ++ * Workaround this problem by delaying the release event by 0.5 sec. ++ * FIXME: protocol change to solve the conflict and set client priority. ++ */ ++#define CLIPBOARD_RELEASE_DELAY 500 /* ms */ ++ ++static void clipboard_release_delay(SpiceMainChannel *main, guint selection, ++ gpointer user_data) ++{ ++ SpiceGtkSession *self = SPICE_GTK_SESSION(user_data); ++ SpiceGtkSessionPrivate *s = self->priv; ++ GtkClipboard* clipboard = get_clipboard_from_selection(s, selection); ++ SpiceGtkClipboardRelease *rel; ++ ++ if (!clipboard) ++ return; ++ ++ clipboard_release_delay_remove(self, selection, true); ++ ++ rel = g_new0(SpiceGtkClipboardRelease, 1); ++ rel->self = self; ++ rel->selection = selection; ++ s->clipboard_release_delay[selection] = ++ g_timeout_add_full(G_PRIORITY_DEFAULT, CLIPBOARD_RELEASE_DELAY, ++ clipboard_release_timeout, rel, g_free); ++ ++} ++ + static void channel_new(SpiceSession *session, SpiceChannel *channel, + gpointer user_data) + { +@@ -1088,7 +1152,7 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel, + g_signal_connect(channel, "main-clipboard-selection-request", + G_CALLBACK(clipboard_request), self); + g_signal_connect(channel, "main-clipboard-selection-release", +- G_CALLBACK(clipboard_release), self); ++ G_CALLBACK(clipboard_release_delay), self); + } + if (SPICE_IS_INPUTS_CHANNEL(channel)) { + spice_g_signal_connect_object(channel, "inputs-modifiers", +-- +2.23.0 + diff --git a/0003-fixup-clipboard-do-not-release-between-remote-grabs.patch b/0003-fixup-clipboard-do-not-release-between-remote-grabs.patch new file mode 100644 index 0000000..1d9fa10 --- /dev/null +++ b/0003-fixup-clipboard-do-not-release-between-remote-grabs.patch @@ -0,0 +1,32 @@ +From c771229a978c69323869d4063228306dc41e15b4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jakub=20Jank=C5=AF?= +Date: Mon, 30 Sep 2019 18:44:05 +0200 +Subject: [PATCH 3/6] fixup! clipboard: do not release between remote grabs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jakub Janků +--- + src/spice-gtk-session.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c +index 79385a4..cbfe3bf 100644 +--- a/src/spice-gtk-session.c ++++ b/src/spice-gtk-session.c +@@ -782,6 +782,11 @@ static void clipboard_get(GtkClipboard *clipboard, + g_return_if_fail(info < SPICE_N_ELEMENTS(atom2agent)); + g_return_if_fail(s->main != NULL); + ++ if (s->clipboard_release_delay[selection]) { ++ SPICE_DEBUG("not requesting data from guest during delayed release"); ++ return; ++ } ++ + ri.selection_data = selection_data; + ri.info = info; + ri.loop = g_main_loop_new(NULL, FALSE); +-- +2.23.0 + diff --git a/0004-clipboard-do-not-delay-release-if-agent-has-no-relea.patch b/0004-clipboard-do-not-delay-release-if-agent-has-no-relea.patch new file mode 100644 index 0000000..bc49a48 --- /dev/null +++ b/0004-clipboard-do-not-delay-release-if-agent-has-no-relea.patch @@ -0,0 +1,79 @@ +From 31a44bfd0acc3ae18682ae19ff1c8a8101bc96f4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 15:20:12 +0100 +Subject: [PATCH 4/6] clipboard: do not delay release if agent has "no release + on regrab" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Marc-André Lureau +--- + meson.build | 2 +- + src/channel-main.c | 2 ++ + src/spice-gtk-session.c | 9 ++++++++- + 3 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/meson.build b/meson.build +index 171a3f6..b89a15b 100644 +--- a/meson.build ++++ b/meson.build +@@ -81,7 +81,7 @@ endforeach + # + # check for mandatory dependencies + # +-spice_protocol_version='>= 0.12.15' ++spice_protocol_version='>= 0.14.1' + + glib_version = '2.46' + glib_version_info = '>= @0@'.format(glib_version) +diff --git a/src/channel-main.c b/src/channel-main.c +index 4305dcd..adf6bab 100644 +--- a/src/channel-main.c ++++ b/src/channel-main.c +@@ -222,6 +222,7 @@ static const char *agent_caps[] = { + [ VD_AGENT_CAP_AUDIO_VOLUME_SYNC ] = "volume-sync", + [ 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", + }; + #define NAME(_a, _i) ((_i) < SPICE_N_ELEMENTS(_a) ? (_a[(_i)] ?: "?") : "?") + +@@ -1333,6 +1334,7 @@ static void agent_announce_caps(SpiceMainChannel *channel) + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION); + 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); + + agent_msg_queue(channel, VD_AGENT_ANNOUNCE_CAPABILITIES, size, caps); + g_free(caps); +diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c +index cbfe3bf..34ae4a1 100644 +--- a/src/spice-gtk-session.c ++++ b/src/spice-gtk-session.c +@@ -1114,7 +1114,8 @@ static gboolean clipboard_release_timeout(gpointer user_data) + * sides, client and remote, racing for the clipboard grab, and + * believing each other is the owner. + * +- * Workaround this problem by delaying the release event by 0.5 sec. ++ * 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 */ +@@ -1132,6 +1133,12 @@ static void clipboard_release_delay(SpiceMainChannel *main, guint selection, + + clipboard_release_delay_remove(self, selection, true); + ++ if (spice_main_channel_agent_test_capability(s->main, ++ VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB)) { ++ clipboard_release(self, selection); ++ return; ++ } ++ + rel = g_new0(SpiceGtkClipboardRelease, 1); + rel->self = self; + rel->selection = selection; +-- +2.23.0 + diff --git a/0005-clipboard-pre-condition-on-selection-value-256.patch b/0005-clipboard-pre-condition-on-selection-value-256.patch new file mode 100644 index 0000000..de707fe --- /dev/null +++ b/0005-clipboard-pre-condition-on-selection-value-256.patch @@ -0,0 +1,33 @@ +From 7bbf04e5484129037d29018352ab6d3333fddf05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Fri, 22 Mar 2019 15:20:13 +0100 +Subject: [PATCH 5/6] clipboard: pre-condition on selection value < 256 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The protocol uses a u8 for the selection value. Make sure the given +argument value fits there, or throw a critical. + +The other places seem to use u8 variables already. + +Signed-off-by: Marc-André Lureau +--- + src/channel-main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/channel-main.c b/src/channel-main.c +index adf6bab..8574ae6 100644 +--- a/src/channel-main.c ++++ b/src/channel-main.c +@@ -1354,6 +1354,7 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection, + if (!c->agent_connected) + return; + ++ g_return_if_fail(selection < 256); + g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); + + size = sizeof(VDAgentClipboardGrab) + sizeof(uint32_t) * ntypes; +-- +2.23.0 + diff --git a/0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch b/0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch new file mode 100644 index 0000000..dd18732 --- /dev/null +++ b/0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch @@ -0,0 +1,121 @@ +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 + diff --git a/spice-gtk.spec b/spice-gtk.spec index bf9fea2..0584acb 100644 --- a/spice-gtk.spec +++ b/spice-gtk.spec @@ -2,7 +2,7 @@ Name: spice-gtk Version: 0.37 -Release: 3%{?dist} +Release: 4%{?dist} Summary: A GTK+ widget for SPICE clients License: LGPLv2+ @@ -13,6 +13,16 @@ Source1: https://www.spice-space.org/download/gtk/%{name}-%{version}%{?_v Source2: victortoso-E37A484F.keyring Patch0001: 0001-vmcstream-Fix-buffer-overflow-sending-data-to-task.patch +# clipboard-race patches: together with patches for spice-protocol +# and spice-gtk these fix problems interacting with mutter's new +# clipboard manager +# https://bugzilla.redhat.com/show_bug.cgi?id=1755038 +Patch0002: 0001-clipboard-do-not-release-between-client-grabs.patch +Patch0003: 0002-clipboard-do-not-release-between-remote-grabs.patch +Patch0004: 0003-fixup-clipboard-do-not-release-between-remote-grabs.patch +Patch0005: 0004-clipboard-do-not-delay-release-if-agent-has-no-relea.patch +Patch0006: 0005-clipboard-pre-condition-on-selection-value-256.patch +Patch0007: 0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch BuildRequires: git-core BuildRequires: meson @@ -194,6 +204,9 @@ gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} %{_bindir}/spicy-stats %changelog +* Fri Oct 04 2019 Adam Williamson - 0.37-4 +- Backport clipboard-race patches for #1755038 + * Fri Jul 26 2019 Fedora Release Engineering - 0.37-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild