Blame SOURCES/0003-Only-trigger-grab-sequence-upon-release.patch

09badb
From afc46d8f3ba54c0a3b536d1ce05b3f8b4743cf17 Mon Sep 17 00:00:00 2001
09badb
From: "Daniel P. Berrange" <berrange@redhat.com>
09badb
Date: Fri, 13 Sep 2013 14:22:17 +0100
09badb
Subject: [PATCH] Only trigger grab sequence upon release
09badb
09badb
For
09badb
09badb
  https://bugzilla.redhat.com/show_bug.cgi?id=1007877
09badb
09badb
GTK-VNC uses the keyboard shortcut ctrl+alt to toggle inside/outside
09badb
the VM (aka release pointer). Now Gnome uses ctrl+alt+arrow_key to
09badb
switch virtual desktops. So these two shortcuts collide and gtk-vnc
09badb
will grab the key presses as soon as ctrl+alt is pressed and toogle
09badb
inside/outside the VM, which makes switching desktops impossible.
09badb
09badb
The solution is to only trigger the grab sequence when the user
09badb
releases the key. So if they press Ctrl+alt and then release it,
09badb
we trigger, but if they press Ctrl+alt+left-arrow we don't trigger
09badb
09badb
https://bugzilla.gnome.org/show_bug.cgi?id=685257
09badb
09badb
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
09badb
(cherry picked from commit af4fc65182f8a51d81fab2d7e46bc4a11a9da452)
09badb
---
09badb
 src/vncdisplay.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
09badb
 1 file changed, 41 insertions(+), 9 deletions(-)
09badb
09badb
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
09badb
index 37de008..51a6b0f 100644
09badb
--- a/src/vncdisplay.c
09badb
+++ b/src/vncdisplay.c
09badb
@@ -80,6 +80,7 @@ struct _VncDisplayPrivate
09badb
     size_t keycode_maplen;
09badb
     const guint16 *keycode_map;
09badb
 
09badb
+    gboolean vncgrabpending; /* Key sequence detected, waiting for release */
09badb
     VncGrabSequence *vncgrabseq; /* the configured key sequence */
09badb
     gboolean *vncactiveseq; /* the currently pressed keys */
09badb
 };
09badb
@@ -784,6 +785,17 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
09badb
 }
09badb
 
09badb
 
09badb
+/*
09badb
+ * Lets say the grab sequence of Ctrl_L + Alt_L
09badb
+ *
09badb
+ * We first need to detect when both Ctrl_L and Alt_L are pressed.
09badb
+ * When this happens we are "primed" to tigger.
09badb
+ *
09badb
+ * If any further key is pressed though, we unprime ourselves
09badb
+ *
09badb
+ * If any key is released while we are primed, then we
09badb
+ * trigger.
09badb
+ */ 
09badb
 static gboolean check_for_grab_key(GtkWidget *widget, int type, int keyval)
09badb
 {
09badb
     VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
09badb
@@ -793,23 +805,42 @@ static gboolean check_for_grab_key(GtkWidget *widget, int type, int keyval)
09badb
         return FALSE;
09badb
 
09badb
     if (type == GDK_KEY_RELEASE) {
09badb
+        gboolean active = priv->vncgrabpending;
09badb
         /* Any key release resets the whole grab sequence */
09badb
         memset(priv->vncactiveseq, 0,
09badb
                sizeof(gboolean)*priv->vncgrabseq->nkeysyms);
09badb
-
09badb
-        return FALSE;
09badb
+        priv->vncgrabpending = FALSE;
09badb
+        return active;
09badb
     } else {
09badb
+        gboolean setone = FALSE;
09badb
+
09badb
         /* Record the new key press */
09badb
-        for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++)
09badb
-            if (priv->vncgrabseq->keysyms[i] == keyval)
09badb
+        for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++) {
09badb
+            if (priv->vncgrabseq->keysyms[i] == keyval) {
09badb
                 priv->vncactiveseq[i] = TRUE;
09badb
+                setone = TRUE;
09badb
+            }
09badb
+        }
09badb
 
09badb
-        /* Return if any key is not pressed */
09badb
-        for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++)
09badb
-            if (priv->vncactiveseq[i] == FALSE)
09badb
-                return FALSE;
09badb
+        if (setone) {
09badb
+            /* Return if any key is not pressed */
09badb
+            for (i = 0 ; i < priv->vncgrabseq->nkeysyms ; i++)
09badb
+                if (priv->vncactiveseq[i] == FALSE)
09badb
+                    return FALSE;
09badb
 
09badb
-        return TRUE;
09badb
+            /* All keys in grab seq are pressed, so prime
09badb
+             * to trigger on release
09badb
+             */
09badb
+            priv->vncgrabpending = TRUE;
09badb
+        } else {
09badb
+            /* Key not in grab seq, so must reset any pending
09badb
+             * grab keys we have */
09badb
+            memset(priv->vncactiveseq, 0,
09badb
+                   sizeof(gboolean)*priv->vncgrabseq->nkeysyms);
09badb
+            priv->vncgrabpending = FALSE;
09badb
+        }
09badb
+
09badb
+        return FALSE;
09badb
     }
09badb
 }
09badb
 
09badb
@@ -2238,6 +2269,7 @@ void vnc_display_set_pointer_grab(VncDisplay *obj, gboolean enable)
09badb
  */
09badb
 void vnc_display_set_grab_keys(VncDisplay *obj, VncGrabSequence *seq)
09badb
 {
09badb
+    obj->priv->vncgrabpending = FALSE;
09badb
     if (obj->priv->vncgrabseq) {
09badb
         vnc_grab_sequence_free(obj->priv->vncgrabseq);
09badb
         g_free(obj->priv->vncactiveseq);