<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 12, 2014 at 10:11 AM, Pavel Grunt <span dir="ltr"><<a href="mailto:pgrunt@redhat.com" target="_blank">pgrunt@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This commit adds the ability to release the keyboard grab when<br>
the release keys (ctrl+alt) are pressed and released. It allows<br>
to use keyboard shortcuts (eg alt+tab, alt+f4) on the client.<br>
<br>
The keyboard is grabbed again when the release keys are pressed<br>
and released or when the mouse moves.<br>
<br></blockquote><div><br>There is an issue to retake the grab with the same shortcut, after pressing alt-tab. It works only if pressed 2 times.<br><br></div><div>It seems to be because the sequence is cancelled in check_for_grab_key(), I haven't investigated further.<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<a href="https://bugs.freedesktop.org/show_bug.cgi?id=85331" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=85331</a><br>
---<br>
v2:<br>
- add missing 'release_keys(display)' calls<br>
---<br>
gtk/spice-widget-priv.h | 2 ++<br>
gtk/spice-widget.c | 51 ++++++++++++++++++++++++++++++++++++++++++-------<br>
2 files changed, 46 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h<br>
index 9c38e2e..0e1f661 100644<br>
--- a/gtk/spice-widget-priv.h<br>
+++ b/gtk/spice-widget-priv.h<br>
@@ -109,6 +109,8 @@ struct _SpiceDisplayPrivate {<br>
guint key_delayed_id;<br>
SpiceGrabSequence *grabseq; /* the configured key sequence */<br>
gboolean *activeseq; /* the currently pressed keys */<br>
+ gboolean seq_pressed;<br>
+ gboolean keyboard_grab_released;<br>
gint mark;<br>
#ifdef WIN32<br>
HHOOK keyboard_hook;<br>
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c<br>
index ae11073..aca12fe 100644<br>
--- a/gtk/spice-widget.c<br>
+++ b/gtk/spice-widget.c<br>
@@ -719,6 +719,8 @@ static void try_keyboard_grab(SpiceDisplay *display)<br>
return;<br>
if (!d->mouse_have_pointer)<br>
return;<br>
+ if (d->keyboard_grab_released)<br>
+ return;<br>
<br>
g_return_if_fail(gtk_widget_is_focus(widget));<br>
<br>
@@ -1198,6 +1200,9 @@ static void send_key(SpiceDisplay *display, int scancode, SendKeyType type, gboo<br>
if (d->disable_inputs)<br>
return;<br>
<br>
+ if (d->keyboard_grab_released)<br>
+ return;<br>
+<br>
i = scancode / 32;<br>
b = scancode % 32;<br>
m = (1 << b);<br>
@@ -1259,7 +1264,8 @@ static void release_keys(SpiceDisplay *display)<br>
}<br>
}<br>
<br>
-static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval)<br>
+static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval,<br>
+ int check_type, int reset_type)<br>
{<br>
SpiceDisplayPrivate *d = display->priv;<br>
int i;<br>
@@ -1267,13 +1273,13 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval)<br>
if (!d->grabseq->nkeysyms)<br>
return FALSE;<br>
<br>
- if (type == GDK_KEY_PRESS) {<br>
- /* Record the new key press */<br>
+ if (type == check_type) {<br>
+ /* Record the new key */<br>
for (i = 0 ; i < d->grabseq->nkeysyms ; i++)<br>
if (d->grabseq->keysyms[i] == keyval)<br>
d->activeseq[i] = TRUE;<br>
<br>
- /* Return if any key is not pressed */<br>
+ /* Return if any key is missing */<br>
for (i = 0 ; i < d->grabseq->nkeysyms ; i++)<br>
if (d->activeseq[i] == FALSE)<br>
return FALSE;<br>
@@ -1281,9 +1287,10 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval)<br>
/* resets the whole grab sequence on success */<br>
memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms);<br>
return TRUE;<br>
- } else if (type == GDK_KEY_RELEASE) {<br>
- /* Any key release resets the whole grab sequence */<br>
+ } else if (type == reset_type) {<br>
+ /* reset key event type resets the whole grab sequence */<br>
memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms);<br>
+ d->seq_pressed = FALSE;<br>
return FALSE;<br>
} else<br>
g_warn_if_reached();<br>
@@ -1291,6 +1298,16 @@ static gboolean check_for_grab_key(SpiceDisplay *display, int type, int keyval)<br>
return FALSE;<br>
}<br>
<br>
+static gboolean check_for_grab_key_pressed(SpiceDisplay *display, int type, int keyval)<br>
+{<br>
+ return check_for_grab_key(display, type, keyval, GDK_KEY_PRESS, GDK_KEY_RELEASE);<br>
+}<br>
+<br>
+static gboolean check_for_grab_key_released(SpiceDisplay *display, int type, int keyval)<br>
+{<br>
+ return check_for_grab_key(display, type, keyval, GDK_KEY_RELEASE, GDK_KEY_PRESS);<br>
+}<br>
+<br>
static void update_display(SpiceDisplay *display)<br>
{<br>
#ifdef G_OS_WIN32<br>
@@ -1321,7 +1338,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)<br>
__FUNCTION__, key->type == GDK_KEY_PRESS ? "press" : "release",<br>
key->hardware_keycode, key->state, key->group, key->is_modifier);<br>
<br>
- if (check_for_grab_key(display, key->type, key->keyval)) {<br>
+ if (!d->seq_pressed && check_for_grab_key_pressed(display, key->type, key->keyval)) {<br>
g_signal_emit(widget, signals[SPICE_DISPLAY_GRAB_KEY_PRESSED], 0);<br>
<br>
if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) {<br>
@@ -1330,6 +1347,17 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)<br>
else<br>
try_mouse_grab(display);<br>
}<br>
+ d->seq_pressed = TRUE;<br>
+ } else if (d->seq_pressed && check_for_grab_key_released(display, key->type, key->keyval)) {<br>
+ release_keys(display);<br>
+ if (!d->keyboard_grab_released) {<br>
+ d->keyboard_grab_released = TRUE;<br>
+ try_keyboard_ungrab(display);<br>
+ } else {<br>
+ d->keyboard_grab_released = FALSE;<br>
+ try_keyboard_grab(display);<br>
+ }<br>
+ d->seq_pressed = FALSE;<br>
}<br>
<br>
if (!d->inputs)<br>
@@ -1562,6 +1590,15 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)<br>
if (d->disable_inputs)<br>
return true;<br>
<br>
+ if (d->seq_pressed)<br>
+ d->seq_pressed = FALSE;<br></blockquote><div><br></div><div>You could set it unconditionaly<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+ if (d->keyboard_grab_released) {<br>
+ d->keyboard_grab_released = FALSE;<br>
+ release_keys(display);<br>
+ try_keyboard_grab(display);<br>
+ }<br>
+<br>
spicex_transform_input (display, motion->x, motion->y, &x, &y);<br>
<br>
switch (d->mouse_mode) {<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.3<br>
<br>
_______________________________________________<br>
Spice-devel mailing list<br>
<a href="mailto:Spice-devel@lists.freedesktop.org">Spice-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/spice-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/spice-devel</a><br>
</font></span></blockquote></div><br><br clear="all"></div><div class="gmail_extra">looks good otherwise<br><br></div><div class="gmail_extra">-- <br><div class="gmail_signature">Marc-André Lureau</div>
</div></div>