On Wed, Nov 12, 2014 at 10:11 AM, Pavel Grunt <pgrunt@xxxxxxxxxx> wrote:
There is an issue to retake the grab with the same shortcut, after pressing alt-tab. It works only if pressed 2 times.
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.
There is an issue to retake the grab with the same shortcut, after pressing alt-tab. It works only if pressed 2 times.
It seems to be because the sequence is cancelled in check_for_grab_key(), I haven't investigated further.
https://bugs.freedesktop.org/show_bug.cgi?id=85331
---
v2:
- add missing 'release_keys(display)' calls
---
gtk/spice-widget-priv.h | 2 ++
gtk/spice-widget.c | 51 ++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 46 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..aca12fe 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,15 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
if (d->disable_inputs)
return true;
+ if (d->seq_pressed)
+ d->seq_pressed = FALSE;
You could set it unconditionaly
+
+ if (d->keyboard_grab_released) {
+ 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
looks good otherwise
--
Marc-André Lureau
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel