[Spice-devel] [PATCH spice-gtk 1/3] clipboard: accept grab only from the side with keyboard focus

Jakub Janků jjanku at redhat.com
Thu Feb 28 19:12:42 UTC 2019

If two grab messages in opposite directions "meet" on their way
to their destinations, we end up in a state when both spice-gtk
and spice-vdagent think that the other component can provide
clipboard data. As a consequence of this, neither of them can.

This is a bug in the spice-protocol. To mitigate the issue,
accept grab only from the side that currently has keyboard focus,
this means:
(1) spice-gtk has focus ==>
    * accept grabs from vdagent,
    * ignore grabs from other apps running in the host
(2) spice-gtk doesn't have focus ==>
    * accept grabs from other apps running in the host
    * ignore grabs from vdagent

The check in clipboard_owner_change() is X11-specific,
because on Wayland, spice-gtk is first notified about the
owner-change once it gains focus.

The check in clipboard_grab() can be generic.
Note that on Wayland, calling gtk_clipboard_set_with_owner()
while not having focus doesn't have any effect anyway,
only focused clients can set clipboard.

With this patch, the race can still occur around the time
when focus changes (rare, but possible), on X11 as well as Wayland.

Related: https://gitlab.freedesktop.org/spice/spice-gtk/issues/82
Related: https://bugzilla.redhat.com/show_bug.cgi?id=1594876

Signed-off-by: Jakub Janků <jjanku at redhat.com>

Victor, half of this patch is basically yours,
so feel free to add signed-off or something,
in the case this gets upstream :)

 src/spice-gtk-session.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
index b48f92a..7b7370c 100644
--- a/src/spice-gtk-session.c
+++ b/src/spice-gtk-session.c
@@ -680,6 +680,13 @@ static void clipboard_owner_change(GtkClipboard        *clipboard,
         s->clip_hasdata[selection] = FALSE;
+    if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
+        spice_gtk_session_get_keyboard_has_focus(self)) {
+        SPICE_DEBUG("%s: spice-gtk has keyboard focus, "
+                    "ignoring grab from other app", __FUNCTION__);
+        return;
+    }
     s->clip_hasdata[selection] = TRUE;
@@ -823,6 +830,12 @@ static gboolean clipboard_grab(SpiceMainChannel *main, guint selection,
     cb = get_clipboard_from_selection(s, selection);
     g_return_val_if_fail(cb != NULL, FALSE);
+    if (!spice_gtk_session_get_keyboard_has_focus(self)) {
+        SPICE_DEBUG("%s: spice-gtk doesn't have keyboard focus, "
+                    "ignoring grab from guest agent", __FUNCTION__);
+        return FALSE;
+    }
     for (n = 0; n < ntypes; ++n) {
         found = FALSE;
         for (m = 0; m < SPICE_N_ELEMENTS(atom2agent); m++) {

More information about the Spice-devel mailing list