Backport clipboard-race patches for #1755038
This commit is contained in:
parent
9b912f4c8f
commit
56f7953ad2
77
0001-clipboard-do-not-release-between-client-grabs.patch
Normal file
77
0001-clipboard-do-not-release-between-client-grabs.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From 16b41429618985e4ab8c597fbd0c5cca5cf7b3e2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
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 <marcandre.lureau@redhat.com>
|
||||
---
|
||||
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
|
||||
|
167
0002-clipboard-do-not-release-between-remote-grabs.patch
Normal file
167
0002-clipboard-do-not-release-between-remote-grabs.patch
Normal file
@ -0,0 +1,167 @@
|
||||
From 271656ae32e756eacfcc522d1aaab9d7102b0ce7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
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 <marcandre.lureau@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,32 @@
|
||||
From c771229a978c69323869d4063228306dc41e15b4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jakub=20Jank=C5=AF?= <jjanku@redhat.com>
|
||||
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ů <jjanku@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -0,0 +1,79 @@
|
||||
From 31a44bfd0acc3ae18682ae19ff1c8a8101bc96f4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
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 <marcandre.lureau@redhat.com>
|
||||
---
|
||||
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
|
||||
|
33
0005-clipboard-pre-condition-on-selection-value-256.patch
Normal file
33
0005-clipboard-pre-condition-on-selection-value-256.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From 7bbf04e5484129037d29018352ab6d3333fddf05 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
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 <marcandre.lureau@redhat.com>
|
||||
---
|
||||
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
|
||||
|
121
0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch
Normal file
121
0006-clipboard-implement-CAP_CLIPBOARD_GRAB_SERIAL.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From 48e516347587f6f9e21f3ba9616079521296888d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
|
||||
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 <marcandre.lureau@redhat.com>
|
||||
---
|
||||
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
|
||||
|
@ -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 <awilliam@redhat.com> - 0.37-4
|
||||
- Backport clipboard-race patches for #1755038
|
||||
|
||||
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.37-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user