For some reason, I still need to press ctrl+alt two times to regain the grab. On Wed, Nov 19, 2014 at 1:39 PM, Pavel Grunt <pgrunt@xxxxxxxxxx> wrote: > This commit adds the ability to release the keyboard grab when > the release keys (ctrl+alt) are pressed and released. It allows > to use keyboard shortcuts (eg alt+tab, alt+f4) on the client. > > The keyboard is grabbed again when the release keys are pressed > and released or when the mouse moves. > > https://bugs.freedesktop.org/show_bug.cgi?id=85331 > --- > v3: > - don't grab when the keyboard doesn't have the focus > v2: > - add missing 'release_keys(display)' calls > --- > gtk/spice-widget-priv.h | 2 ++ > gtk/spice-widget.c | 50 ++++++++++++++++++++++++++++++++++++++++++------- > 2 files changed, 45 insertions(+), 7 deletions(-) > > diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h > index 9c38e2e..0e1f661 100644 > --- a/gtk/spice-widget-priv.h > +++ b/gtk/spice-widget-priv.h > @@ -109,6 +109,8 @@ struct _SpiceDisplayPrivate { > guint key_delayed_id; > SpiceGrabSequence *grabseq; /* the configured key sequence */ > gboolean *activeseq; /* the currently pressed keys */ > + gboolean seq_pressed; > + gboolean keyboard_grab_released; > gint mark; > #ifdef WIN32 > HHOOK keyboard_hook; > diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c > index ae11073..550d08d 100644 > --- a/gtk/spice-widget.c > +++ b/gtk/spice-widget.c > @@ -719,6 +719,8 @@ static void try_keyboard_grab(SpiceDisplay *display) > return; > if (!d->mouse_have_pointer) > return; > + if (d->keyboard_grab_released) > + return; > > g_return_if_fail(gtk_widget_is_focus(widget)); > > @@ -1198,6 +1200,9 @@ static void send_key(SpiceDisplay *display, int scancode, SendKeyType type, gboo > if (d->disable_inputs) > return; > > + if (d->keyboard_grab_released) > + return; > + > i = scancode / 32; > b = scancode % 32; > m = (1 << b); > @@ -1259,7 +1264,8 @@ static void release_keys(SpiceDisplay *display) > } > } > > -static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval) > +static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval, > + int check_type, int reset_type) > { > SpiceDisplayPrivate *d = display->priv; > int i; > @@ -1267,13 +1273,13 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval) > if (!d->grabseq->nkeysyms) > return FALSE; > > - if (type == GDK_KEY_PRESS) { > - /* Record the new key press */ > + if (type == check_type) { > + /* Record the new key */ > for (i = 0 ; i < d->grabseq->nkeysyms ; i++) > if (d->grabseq->keysyms[i] == keyval) > d->activeseq[i] = TRUE; > > - /* Return if any key is not pressed */ > + /* Return if any key is missing */ > for (i = 0 ; i < d->grabseq->nkeysyms ; i++) > if (d->activeseq[i] == FALSE) > return FALSE; > @@ -1281,9 +1287,10 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval) > /* resets the whole grab sequence on success */ > memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms); > return TRUE; > - } else if (type == GDK_KEY_RELEASE) { > - /* Any key release resets the whole grab sequence */ > + } else if (type == reset_type) { > + /* reset key event type resets the whole grab sequence */ > memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms); > + d->seq_pressed = FALSE; > return FALSE; > } else > g_warn_if_reached(); > @@ -1291,6 +1298,16 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval) > return FALSE; > } > > +static gboolean check_for_grab_key_pressed(SpiceDisplay *display, int type, int keyval) > +{ > + return check_for_grab_key(display, type, keyval, GDK_KEY_PRESS, GDK_KEY_RELEASE); > +} > + > +static gboolean check_for_grab_key_released(SpiceDisplay *display, int type, int keyval) > +{ > + return check_for_grab_key(display, type, keyval, GDK_KEY_RELEASE, GDK_KEY_PRESS); > +} > + > static void update_display(SpiceDisplay *display) > { > #ifdef G_OS_WIN32 > @@ -1321,7 +1338,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key) > __FUNCTION__, key->type == GDK_KEY_PRESS ? "press" : "release", > key->hardware_keycode, key->state, key->group, key->is_modifier); > > - if (check_for_grab_key(display, key->type, key->keyval)) { > + if (!d->seq_pressed && check_for_grab_key_pressed(display, key->type, key->keyval)) { > g_signal_emit(widget, signals[SPICE_DISPLAY_GRAB_KEY_PRESSED], 0); > > if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) { > @@ -1330,6 +1347,17 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key) > else > try_mouse_grab(display); > } > + d->seq_pressed = TRUE; > + } else if (d->seq_pressed && check_for_grab_key_released(display, key->type, key->keyval)) { > + release_keys(display); > + if (!d->keyboard_grab_released) { > + d->keyboard_grab_released = TRUE; > + try_keyboard_ungrab(display); > + } else { > + d->keyboard_grab_released = FALSE; > + try_keyboard_grab(display); > + } > + d->seq_pressed = FALSE; > } > > if (!d->inputs) > @@ -1562,6 +1590,14 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion) > if (d->disable_inputs) > return true; > > + d->seq_pressed = FALSE; > + > + if (d->keyboard_grab_released && d->keyboard_have_focus) { > + d->keyboard_grab_released = FALSE; > + release_keys(display); > + try_keyboard_grab(display); > + } > + > spicex_transform_input (display, motion->x, motion->y, &x, &y); > > switch (d->mouse_mode) { > -- > 1.9.3 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel -- Marc-André Lureau _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel