grabkeys: Avoid missing events when a keysym maps to multiple keycodes - dwm - … | |
git clone git://git.suckless.org/dwm | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 89f9905714c1c1b2e8b09986dfbeca15b68d8af8 | |
parent ba56fe9fea0a28d8184a727a987836a0903e2682 | |
Author: Chris Down <[email protected]> | |
Date: Wed, 7 Dec 2022 14:55:08 +0000 | |
grabkeys: Avoid missing events when a keysym maps to multiple keycodes | |
It's not uncommon for one keysym to map to multiple keycodes. For | |
example, the "play" button on my keyboard sends keycode 172, but my | |
bluetooth headphones send keycode 208, both of which map back to | |
XF86AudioPlay: | |
% xmodmap -pke | grep XF86AudioPlay | |
keycode 172 = XF86AudioPlay XF86AudioPause XF86AudioPlay XF86AudioPause | |
keycode 208 = XF86AudioPlay NoSymbol XF86AudioPlay | |
keycode 215 = XF86AudioPlay NoSymbol XF86AudioPlay | |
This is a problem because the current code only grabs a single one of | |
these keycodes, which means that events for any other keycode also | |
mapping to the bound keysym will not be handled by dwm. In my case, this | |
means that binding XF86AudioPlay does the right thing and correctly | |
handles my keyboard's keys, but does nothing on my headphones. I'm not | |
the only person affected by this, there are other reports[0]. | |
In order to fix this, we look at the mappings between keycodes and | |
keysyms at grabkeys() time and pick out all matching keycodes rather | |
than just the first one. The keypress() side of this doesn't need any | |
changes because the keycode gets converted back to a canonical keysym | |
before any action is taken. | |
0: https://github.com/cdown/dwm/issues/11 | |
Diffstat: | |
M dwm.c | 24 +++++++++++++++++------- | |
1 file changed, 17 insertions(+), 7 deletions(-) | |
--- | |
diff --git a/dwm.c b/dwm.c | |
@@ -955,16 +955,26 @@ grabkeys(void) | |
{ | |
updatenumlockmask(); | |
{ | |
- unsigned int i, j; | |
+ unsigned int i, j, k; | |
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlock… | |
- KeyCode code; | |
+ int start, end, skip; | |
+ KeySym *syms; | |
XUngrabKey(dpy, AnyKey, AnyModifier, root); | |
- for (i = 0; i < LENGTH(keys); i++) | |
- if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) | |
- for (j = 0; j < LENGTH(modifiers); j++) | |
- XGrabKey(dpy, code, keys[i].mod | modi… | |
- True, GrabModeAsync, GrabModeA… | |
+ XDisplayKeycodes(dpy, &start, &end); | |
+ syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); | |
+ if (!syms) | |
+ return; | |
+ for (k = start; k <= end; k++) | |
+ for (i = 0; i < LENGTH(keys); i++) | |
+ /* skip modifier codes, we do that ourselves */ | |
+ if (keys[i].keysym == syms[(k - start) * skip]) | |
+ for (j = 0; j < LENGTH(modifiers); j++) | |
+ XGrabKey(dpy, k, | |
+ keys[i].mod | modifie… | |
+ root, True, | |
+ GrabModeAsync, GrabMo… | |
+ XFree(syms); | |
} | |
} | |