[gtk-vnc] Release held keys upon grab_notify event



commit 3e9b8085b2990127977c75d6b66421f611c1676c
Author: Daniel P. Berrange <berrange redhat com>
Date:   Wed Jan 29 17:09:03 2014 +0000

    Release held keys upon grab_notify event
    
    gtk may propagate some press event up to the Spice display widget, but
    a widget may take focus and grab the release event, so the guest will
    keep seeing the key pressed.
    
    Releasing the keys when the grab is taken solves two menu-related bugs:
    
      https://bugzilla.redhat.com/show_bug.cgi?id=820829
      https://bugzilla.redhat.com/show_bug.cgi?id=924577
    
    This is based on a spice-gtk fix:
    
      http://lists.freedesktop.org/archives/spice-devel/2013-May/013351.html
    
    Signed-off-by: Daniel P. Berrange <berrange redhat com>

 src/vncdisplay.c |   26 ++++++++++++++++++++------
 1 files changed, 20 insertions(+), 6 deletions(-)
---
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index de3f3ef..259c352 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -979,15 +979,11 @@ static gboolean leave_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC
     return TRUE;
 }
 
-
-static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED)
+static void release_keys(VncDisplay *display)
 {
-    VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
+    VncDisplayPrivate *priv = display->priv;
     int i;
 
-    if (priv->conn == NULL || !vnc_connection_is_initialized(priv->conn))
-        return FALSE;
-
     for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
         /* We are currently pressed so... */
         if (priv->down_scancode[i] != 0) {
@@ -1001,10 +997,27 @@ static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSE
             priv->down_scancode[i] = 0;
         }
     }
+}
+
+static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED)
+{
+    VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
+
+    if (priv->conn == NULL || !vnc_connection_is_initialized(priv->conn))
+        return FALSE;
+
+    release_keys(VNC_DISPLAY(widget));
 
     return TRUE;
 }
 
+static void grab_notify(GtkWidget *widget, gboolean was_grabbed)
+{
+    if (was_grabbed == FALSE)
+       release_keys(VNC_DISPLAY(widget));
+}
+
+
 static void on_framebuffer_update(VncConnection *conn G_GNUC_UNUSED,
                                   int x, int y, int w, int h,
                                   gpointer opaque)
@@ -1815,6 +1828,7 @@ static void vnc_display_class_init(VncDisplayClass *klass)
     gtkwidget_class->enter_notify_event = enter_event;
     gtkwidget_class->leave_notify_event = leave_event;
     gtkwidget_class->focus_out_event = focus_event;
+    gtkwidget_class->grab_notify = grab_notify;
 
     object_class->finalize = vnc_display_finalize;
     object_class->get_property = vnc_display_get_property;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]