aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-06-29 13:13:20 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-06-29 13:13:20 +0200
commit98a074417fb9ac157c32d637123b6eaae19239f9 (patch)
tree583236741d6fdae64fb5a82eb6f7cb4394da844a /src
parent5ff9125db3a7f8f545cbfb5f7bf452c8b0db4d41 (diff)
downloadjwm-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.
Diffstat (limited to 'src')
-rw-r--r--src/event.c23
-rw-r--r--src/key.c74
-rw-r--r--src/key.h2
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