[Spice-devel] [PATCH spice-gtk v4] Release keyboard grab using keyboard shortcut

Marc-André Lureau marcandre.lureau at gmail.com
Mon Nov 24 06:07:37 PST 2014


It works now, ack

On Mon, Nov 24, 2014 at 8:24 AM, 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
> ---
> v4:
>  - when 'focus in' clear activeseq, because it can wrongly contain keys that were pressed
>    but missed the event they were released
> 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      | 52 ++++++++++++++++++++++++++++++++++++++++++-------
>  2 files changed, 47 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..87d2bb0 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)
> @@ -1457,6 +1485,8 @@ static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UN
>      release_keys(display);
>      if (!d->disable_inputs)
>          spice_gtk_session_sync_keyboard_modifiers(d->gtk_session);
> +    if (d->keyboard_grab_released)
> +        memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms);
>      update_keyboard_focus(display, true);
>      try_keyboard_grab(display);
>      update_display(display);
> @@ -1562,6 +1592,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