summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-11-15 16:27:04 +0100
committerHans de Goede <hdegoede@redhat.com>2011-11-21 15:30:38 +0100
commit40cae5011adb79489f7425f02c4c660623fe2b7a (patch)
treeb84e2cadae3d7542b8c197e2b90a9e1553f3f8d1
parent2161b5464fa8ad995ce6116f78aacb4c2389af55 (diff)
downloadspice-gtk-40cae5011adb79489f7425f02c4c660623fe2b7a.tar.gz
spice-gtk-40cae5011adb79489f7425f02c4c660623fe2b7a.tar.xz
spice-gtk-40cae5011adb79489f7425f02c4c660623fe2b7a.zip
Release our keyboard grab when we're going to invoke the usb acl helper
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@redhat.com>
-rw-r--r--gtk/channel-usbredir.c4
-rw-r--r--gtk/spice-session-priv.h4
-rw-r--r--gtk/spice-session.c25
-rw-r--r--gtk/spice-widget-priv.h1
-rw-r--r--gtk/spice-widget.c22
5 files changed, 56 insertions, 0 deletions
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 767e68c..9479b6b 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", 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", 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)