78 lines
3.2 KiB
Diff
78 lines
3.2 KiB
Diff
|
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
|
||
|
|