From 98a074417fb9ac157c32d637123b6eaae19239f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Tue, 29 Jun 2021 13:13:20 +0200 Subject: 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. --- src/event.c | 23 ++++++------------- src/key.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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); } /**************************************************************************** diff --git a/src/key.c b/src/key.c index d5c6b4f..f14ad62 100644 --- a/src/key.c +++ b/src/key.c @@ -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; +} + diff --git a/src/key.h b/src/key.h index 05e8083..985d7bc 100644 --- a/src/key.h +++ b/src/key.h @@ -58,5 +58,7 @@ void ShowKeyMenu(const XKeyEvent *event); void ValidateKeys(); +int Switching(const XKeyEvent *event); + #endif -- cgit v1.2.3