diff options
author | John Ankarström <john@ankarstrom.se> | 2021-06-29 13:13:20 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2021-06-29 13:13:20 +0200 |
commit | 98a074417fb9ac157c32d637123b6eaae19239f9 (patch) | |
tree | 583236741d6fdae64fb5a82eb6f7cb4394da844a | |
parent | 5ff9125db3a7f8f545cbfb5f7bf452c8b0db4d41 (diff) | |
download | jwm-98a074417fb9ac157c32d637123b6eaae19239f9.tar.gz |
Handle modifiers when window switching
Before this patch, releasing Shift would end the switch, even if
the Shift key was part of the prevstacked key binding.
This patch fixes that. It ranks the modifiers, so that Shift can
act as an "alternate" modifier for all modifiers, Alt for all keys
but Shift, Ctrl for all keys but Alt and Shift and so forth. The
Hyper key cannot act as an "alternate" modifier for any modifier.
It is a bit complex, but hopefully intuitive.
-rw-r--r-- | src/event.c | 23 | ||||
-rw-r--r-- | src/key.c | 74 | ||||
-rw-r--r-- | src/key.h | 2 |
3 files changed, 83 insertions, 16 deletions
diff --git a/src/event.c b/src/event.c index 8850665..05218d8 100644 --- a/src/event.c +++ b/src/event.c @@ -452,24 +452,15 @@ void HandleKeyPress(const XKeyEvent *event) { ****************************************************************************/ void HandleKeyRelease(const XKeyEvent *event) { ClientNode *np; - KeyType key; - key = GetKey(event); + if(!switching || Switching(event)) + return; - switch(key & 0xFF) { - case KEY_NEXT: - case KEY_PREV: - case KEY_NEXT_STACKED: - case KEY_PREV_STACKED: - break; - default: - if(switching) { - switching = 0; - np = GetActiveClient(); - if (np) RaiseClient(np); - JXUngrabKeyboard(display, CurrentTime); - } - } + /* End window switching */ + switching = 0; + np = GetActiveClient(); + if (np) RaiseClient(np); + JXUngrabKeyboard(display, CurrentTime); } /**************************************************************************** @@ -455,3 +455,77 @@ void ValidateKeys() { } +/** Return true if the key event matches any switching key or its modifiers. */ +int Switching(const XKeyEvent *event) { + KeyNode *np; + KeySym keysym; + KeyType key; + unsigned int mask; + + /* Match key bindings for switching windows */ + key = GetKey(event); + switch(key & 0xFF) { + case KEY_NEXT: + case KEY_PREV: + case KEY_NEXT_STACKED: + case KEY_PREV_STACKED: + return 1; + } + + /* Get modifiers of those key bindings */ + mask = 0; + for(np = bindings; np; np = np->next) { + switch(np->key & 0xFF) { + case KEY_NEXT: + case KEY_PREV: + case KEY_NEXT_STACKED: + case KEY_PREV_STACKED: + mask |= np->mask; + } + } + + /* Match (prioritized) modifier */ + keysym = XLookupKeysym((XKeyEvent*)event, 0); + switch(keysym) { + case XK_Hyper_L: + case XK_Hyper_R: + return mask & MASK_HYPER + && !(mask & MASK_SUPER) + && !(mask & MASK_META) + && !(mask & MASK_ALT) + && !(mask & MASK_CTRL) + && !(mask & MASK_SHIFT); + case XK_Super_L: + case XK_Super_R: + return mask & MASK_SUPER + && !(mask & MASK_META) + && !(mask & MASK_ALT) + && !(mask & MASK_CTRL) + && !(mask & MASK_SHIFT); + case XK_Meta_L: + case XK_Meta_R: + return mask & MASK_META + && !(mask & MASK_ALT) + && !(mask & MASK_CTRL) + && !(mask & MASK_SHIFT); + case XK_Alt_L: + case XK_Alt_R: + return mask & MASK_ALT + && !(mask & MASK_CTRL) + && !(mask & MASK_SHIFT); + case XK_Control_L: + case XK_Control_R: + return mask & MASK_CTRL + && !(mask & MASK_SHIFT); + case XK_Shift_L: + case XK_Shift_R: + return mask & MASK_SHIFT + && (mask & MASK_SUPER + || mask & MASK_META + || mask & MASK_ALT + || mask & MASK_CTRL); + } + + return 0; +} + @@ -58,5 +58,7 @@ void ShowKeyMenu(const XKeyEvent *event); void ValidateKeys(); +int Switching(const XKeyEvent *event); + #endif |