Improve handling of <Super>key combinations
When we get a press of the overlay key, and then another key is pressed, first try to handle the combination as a global keybinding. If that fails, call XAllowEvents(..., ReplayKeyboard, ...) to let it be handled by our per-window keybindings or by the application. This requires restructuring things to call XAllowEvents a bit later so we can pass the right mode. https://bugzilla.gnome.org/show_bug.cgi?id=624869
This commit is contained in:
parent
b369c75e1b
commit
12f71c9795
@ -1250,31 +1250,6 @@ primary_modifier_still_pressed (MetaDisplay *display,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
process_overlay_key (MetaDisplay *display,
|
|
||||||
MetaScreen *Screen,
|
|
||||||
XEvent *event,
|
|
||||||
KeySym keysym)
|
|
||||||
{
|
|
||||||
if (event->xkey.keycode != display->overlay_key_combo.keycode)
|
|
||||||
{
|
|
||||||
display->overlay_key_only_pressed = FALSE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event->xkey.type == KeyPress)
|
|
||||||
{
|
|
||||||
display->overlay_key_only_pressed = TRUE;
|
|
||||||
}
|
|
||||||
else if (event->xkey.type == KeyRelease && display->overlay_key_only_pressed)
|
|
||||||
{
|
|
||||||
display->overlay_key_only_pressed = FALSE;
|
|
||||||
meta_display_overlay_key_activate (display);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
invoke_handler (MetaDisplay *display,
|
invoke_handler (MetaDisplay *display,
|
||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
@ -1380,6 +1355,73 @@ process_event (MetaKeyBinding *bindings,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
process_overlay_key (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
XEvent *event,
|
||||||
|
KeySym keysym)
|
||||||
|
{
|
||||||
|
if (display->overlay_key_only_pressed)
|
||||||
|
{
|
||||||
|
if (event->xkey.keycode != display->overlay_key_combo.keycode)
|
||||||
|
{
|
||||||
|
display->overlay_key_only_pressed = FALSE;
|
||||||
|
|
||||||
|
/* OK, the user hit modifier+key rather than pressing and
|
||||||
|
* releasing the ovelay key. We want to handle the key
|
||||||
|
* sequence "normally". Unfortunately, using
|
||||||
|
* XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
|
||||||
|
* work, since global keybindings won't be activated ("this
|
||||||
|
* time, however, the function ignores any passive grabs at
|
||||||
|
* above (toward the root of) the grab_window of the grab
|
||||||
|
* just released.") So, we first explicitly check for one of
|
||||||
|
* our global keybindings, and if not found, we then replay
|
||||||
|
* the event. Other clients with global grabs will be out of
|
||||||
|
* luck.
|
||||||
|
*/
|
||||||
|
if (process_event (display->key_bindings,
|
||||||
|
display->n_key_bindings,
|
||||||
|
display, screen, NULL, event, keysym,
|
||||||
|
FALSE))
|
||||||
|
{
|
||||||
|
/* As normally, after we've handled a global key
|
||||||
|
* binding, we unfreeze the keyboard but keep the grab
|
||||||
|
* (this is important for something like cycling
|
||||||
|
* windows */
|
||||||
|
XAllowEvents (display->xdisplay, AsyncKeyboard, event->xkey.time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Replay the event so it gets delivered to our
|
||||||
|
* per-window key bindings or to the application */
|
||||||
|
XAllowEvents (display->xdisplay, ReplayKeyboard, event->xkey.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event->xkey.type == KeyRelease)
|
||||||
|
{
|
||||||
|
display->overlay_key_only_pressed = FALSE;
|
||||||
|
/* We want to unfreeze events, but keep the grab so that if the user
|
||||||
|
* starts typing into the overlay we get all the keys */
|
||||||
|
XAllowEvents (display->xdisplay, AsyncKeyboard, event->xkey.time);
|
||||||
|
meta_display_overlay_key_activate (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (event->xkey.type == KeyPress &&
|
||||||
|
event->xkey.keycode == display->overlay_key_combo.keycode)
|
||||||
|
{
|
||||||
|
display->overlay_key_only_pressed = TRUE;
|
||||||
|
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
|
||||||
|
* on the next event if it's not the release of the overlay key */
|
||||||
|
XAllowEvents (display->xdisplay, SyncKeyboard, event->xkey.time);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle a key event. May be called recursively: some key events cause
|
/* Handle a key event. May be called recursively: some key events cause
|
||||||
* grabs to be ended and then need to be processed again in their own
|
* grabs to be ended and then need to be processed again in their own
|
||||||
* right. This cannot cause infinite recursion because we never call
|
* right. This cannot cause infinite recursion because we never call
|
||||||
@ -1406,11 +1448,19 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
const char *str;
|
const char *str;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
|
|
||||||
XAllowEvents (display->xdisplay,
|
|
||||||
all_bindings_disabled ? ReplayKeyboard : AsyncKeyboard,
|
|
||||||
event->xkey.time);
|
|
||||||
if (all_bindings_disabled)
|
if (all_bindings_disabled)
|
||||||
return FALSE;
|
{
|
||||||
|
/* In this mode, we try to pretend we don't have grabs, so we
|
||||||
|
* immediately replay events and drop the grab. (This still
|
||||||
|
* messes up global passive grabs from other clients.) The
|
||||||
|
* FALSE return here is a little suspect, but we don't really
|
||||||
|
* know if we'll see the event again or not, and it's pretty
|
||||||
|
* poorly defined how this mode is supposed to interact with
|
||||||
|
* plugins.
|
||||||
|
*/
|
||||||
|
XAllowEvents (display->xdisplay, ReplayKeyboard, event->xkey.time);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* if key event was on root window, we have a shortcut */
|
/* if key event was on root window, we have a shortcut */
|
||||||
screen = meta_display_screen_for_root (display, event->xkey.window);
|
screen = meta_display_screen_for_root (display, event->xkey.window);
|
||||||
@ -1440,8 +1490,17 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
str ? str : "none", event->xkey.state,
|
str ? str : "none", event->xkey.state,
|
||||||
window ? window->desc : "(no window)");
|
window ? window->desc : "(no window)");
|
||||||
|
|
||||||
keep_grab = TRUE;
|
|
||||||
all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed;
|
all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed;
|
||||||
|
if (!all_keys_grabbed)
|
||||||
|
{
|
||||||
|
handled = process_overlay_key (display, screen, event, keysym);
|
||||||
|
if (handled)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
XAllowEvents (display->xdisplay, AsyncKeyboard, event->xkey.time);
|
||||||
|
|
||||||
|
keep_grab = TRUE;
|
||||||
if (all_keys_grabbed)
|
if (all_keys_grabbed)
|
||||||
{
|
{
|
||||||
if (display->grab_op == META_GRAB_OP_NONE)
|
if (display->grab_op == META_GRAB_OP_NONE)
|
||||||
@ -1527,10 +1586,6 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
handled = process_overlay_key (display, screen, event, keysym);
|
|
||||||
if (handled)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* Do the normal keybindings */
|
/* Do the normal keybindings */
|
||||||
return process_event (display->key_bindings,
|
return process_event (display->key_bindings,
|
||||||
display->n_key_bindings,
|
display->n_key_bindings,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user