[Spice-devel] [PATCH spice-gtk 8/8] Release our keyboard grab when we're going to invoke the usb acl helper

Hans de Goede hdegoede at redhat.com
Wed Nov 16 09:49:51 PST 2011


The usb acl helper asks policykit, which may want to interact with the
user through the policykit agent, which wants to grab the keyboard, if
we then have the keyboard grabbed, the agent says authentication has failed,
policykit rejects the helper opening up the acl and usbredir won't work.

Unfortunately the only way to work around this is to temporarily release our
own keyboard grab, not pretty but as discussed on irc, this is the "best"
solution.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 gtk/channel-usbredir.c   |    4 ++++
 gtk/spice-session-priv.h |    4 ++++
 gtk/spice-session.c      |   25 +++++++++++++++++++++++++
 gtk/spice-widget-priv.h  |    1 +
 gtk/spice-widget.c       |   22 ++++++++++++++++++++++
 5 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 767e68c..e9a4e58 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -227,6 +227,8 @@ static void spice_usbredir_channel_open_acl_cb(
 
     spice_usb_acl_helper_close_acl(priv->acl_helper);
     g_clear_object(&priv->acl_helper);
+    g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
+                 "inhibit-keyboard-grab", (gboolean)FALSE, NULL);
 
     g_simple_async_result_complete_in_idle(priv->result);
     g_clear_object(&priv->result);
@@ -268,6 +270,8 @@ void spice_usbredir_channel_connect_async(SpiceUsbredirChannel *channel,
         priv->result = result;
         priv->state = STATE_WAITING_FOR_ACL_HELPER;
         priv->acl_helper = spice_usb_acl_helper_new();
+        g_object_set(spice_channel_get_session(SPICE_CHANNEL(channel)),
+                     "inhibit-keyboard-grab", (gboolean)TRUE, NULL);
         spice_usb_acl_helper_open_acl(priv->acl_helper,
                                       g_usb_device_get_bus(device),
                                       g_usb_device_get_address(device),
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index 8f10407..963735b 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -59,6 +59,10 @@ struct _SpiceSessionPrivate {
     /* whether to enable USB redirection */
     gboolean          usbredir;
 
+    /* Set when a usbredir channel has requested the keyboard grab to be
+       temporarily released (because it is going to invoke policykit) */
+    gboolean          inhibit_keyboard_grab;
+
     GStrv             disable_effects;
     gint              color_depth;
 
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 8fd98c1..3366b58 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -96,6 +96,7 @@ enum {
     PROP_SMARTCARD_CERTIFICATES,
     PROP_SMARTCARD_DB,
     PROP_USBREDIR,
+    PROP_INHIBIT_KEYBOARD_GRAB,
     PROP_DISABLE_EFFECTS,
     PROP_COLOR_DEPTH,
 };
@@ -360,6 +361,9 @@ static void spice_session_get_property(GObject    *gobject,
     case PROP_USBREDIR:
         g_value_set_boolean(value, s->usbredir);
         break;
+    case PROP_INHIBIT_KEYBOARD_GRAB:
+        g_value_set_boolean(value, s->inhibit_keyboard_grab);
+        break;
     case PROP_DISABLE_EFFECTS:
         g_value_set_boxed(value, s->disable_effects);
         break;
@@ -452,6 +456,9 @@ static void spice_session_set_property(GObject      *gobject,
     case PROP_USBREDIR:
         s->usbredir = g_value_get_boolean(value);
         break;
+    case PROP_INHIBIT_KEYBOARD_GRAB:
+        s->inhibit_keyboard_grab = g_value_get_boolean(value);
+        break;
     case PROP_DISABLE_EFFECTS:
         g_strfreev(s->disable_effects);
         s->disable_effects = g_value_dup_boxed(value);
@@ -798,6 +805,24 @@ static void spice_session_class_init(SpiceSessionClass *klass)
                           G_PARAM_STATIC_STRINGS));
 
     /**
+     * SpiceSession::inhibit-keyboard-grab
+     *
+     * This boolean is set by the usbredir channel to indicate to #SpiceDisplay
+     * that the keyboard grab should be temporarily released, because it is
+     * going to invoke policykit. It will get reset when the usbredir channel
+     * is done with polickit.
+     *
+     * Since: 0.8
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_INHIBIT_KEYBOARD_GRAB,
+         g_param_spec_boolean("inhibit-keyboard-grab",
+                        "Inhibit Keyboard Grab",
+                        "Request that SpiceDisplays don't grab the keyboard",
+                        FALSE,
+                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    /**
      * SpiceSession::channel-new:
      * @session: the session that emitted the signal
      * @channel: the new #SpiceChannel
diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h
index a5791a4..a86168d 100644
--- a/gtk/spice-widget-priv.h
+++ b/gtk/spice-widget-priv.h
@@ -46,6 +46,7 @@ struct _SpiceDisplayPrivate {
 
     /* options */
     bool                    keyboard_grab_enable;
+    gboolean                keyboard_grab_inhibit;
     bool                    mouse_grab_enable;
     bool                    resize_guest_enable;
 
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index cec9aaa..f095130 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -222,6 +222,22 @@ static void gtk_session_property_changed(GObject    *gobject,
     g_object_notify(G_OBJECT(display), g_param_spec_get_name(pspec));
 }
 
+static void session_inhibit_keyboard_grab_changed(GObject    *gobject,
+                                                  GParamSpec *pspec,
+                                                  gpointer    user_data)
+{
+    SpiceDisplay *display = user_data;
+    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
+
+    g_object_get(d->session, "inhibit-keyboard-grab",
+                 &d->keyboard_grab_inhibit, NULL);
+    if (d->keyboard_grab_inhibit) {
+        try_keyboard_ungrab(display);
+    } else {
+        try_keyboard_grab(display);
+    }
+}
+
 static void spice_display_dispose(GObject *obj)
 {
     SpiceDisplay *display = SPICE_DISPLAY(obj);
@@ -330,6 +346,10 @@ spice_display_constructor(GType                  gtype,
     g_signal_connect(d->gtk_session, "notify::auto-clipboard",
                      G_CALLBACK(gtk_session_property_changed), display);
 
+    g_signal_connect(d->session, "notify::inhibit-keyboard-grab",
+                     G_CALLBACK(session_inhibit_keyboard_grab_changed),
+                     display);
+
     return obj;
 }
 
@@ -414,6 +434,8 @@ static void try_keyboard_grab(SpiceDisplay *display)
     if (d->keyboard_grab_active)
         return;
 
+    if (d->keyboard_grab_inhibit)
+        return;
     if (!d->keyboard_grab_enable)
         return;
     if (!d->keyboard_have_focus)
-- 
1.7.7.3



More information about the Spice-devel mailing list