[Spice-devel] [PATCH spice-gtk 1/2] clipboard: do not release between client grabs
Marc-André Lureau
marcandre.lureau at gmail.com
Sun Mar 24 18:25:51 UTC 2019
Hi
On Sun, Mar 24, 2019 at 6:50 PM Jakub Janku <jjanku at redhat.com> wrote:
>
> Hi,
>
> On Thu, Mar 21, 2019 at 1:21 PM <marcandre.lureau at redhat.com> wrote:
> >
> > From: Marc-André Lureau <marcandre.lureau at redhat.com>
> >
> > 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 at 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 b48f92a..0e748b6 100644
> > --- a/src/spice-gtk-session.c
> > +++ b/src/spice-gtk-session.c
> > @@ -569,8 +569,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 */
> > @@ -652,18 +651,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);
> > - }
> > - }
>
> If event->owner is NULL, the clipboard is empty at the moment and this
> function exits without requesting the new targets. So in this case, we
> should still send release to the agent, otherwise the guest might
> think that clipboard data can be provided while the clipboard in the
> client is empty for a long time. Pasting data in the guest would
> result into an invalid request being sent to spice-gtk.
This is going into undocumented territories. But if what you say is
true in commit 9af2c481b74077ab7d6cb9d4bf589f9855a302f5, then yes,
client should probably release the clipboard.
I don't quite understand why gtk+ would allow NEW_OWNER, with owner ==
NULL and empty clipboard. It sounds more like a bug to me.
Would this be enough ?
diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
index 5b2c27c..3dbcae6 100644
--- a/src/spice-gtk-session.c
+++ b/src/spice-gtk-session.c
@@ -671,7 +671,11 @@ static void clipboard_owner_change(GtkClipboard
*clipboard,
return;
}
- if (event->reason != GDK_OWNER_CHANGE_NEW_OWNER) {
+ if (event->reason != GDK_OWNER_CHANGE_NEW_OWNER ||
+#ifdef GDK_WINDOWING_X11
+ (!event->owner && GDK_IS_X11_DISPLAY(gdk_display_get_default()))
+#endif
+ ) {
if (s->clip_grabbed[selection]) {
/* grab was sent to the agent, so release it */
s->clip_grabbed[selection] = FALSE;
@@ -690,13 +694,6 @@ static void clipboard_owner_change(GtkClipboard
*clipboard,
s->clipboard_by_guest[selection] = FALSE;
-#ifdef GDK_WINDOWING_X11
- if (!event->owner && GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
- s->clip_hasdata[selection] = FALSE;
- return;
- }
-#endif
-
> > -
> > - /* 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.21.0.4.g36eb1cb9cf
> >
>
> Regards,
> Jakub
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
--
Marc-André Lureau
More information about the Spice-devel
mailing list