[Spice-devel] [PATCH spice-gtk v3] Release keyboard grab using keyboard shortcut
Marc-André Lureau
marcandre.lureau at gmail.com
Fri Nov 21 01:58:03 PST 2014
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 at redhat.com> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
--
Marc-André Lureau
More information about the Spice-devel
mailing list