From 2e6a4ed20fbe962e3d2ad48e1fbbb1a4c3cadb55 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Thu, 23 Apr 2026 22:48:03 +0200 Subject: [PATCH] catch Bluetooth AVRCP media keys and route to mpv if running grabkeys() now iterates the full keymap and grabs every keycode that maps to each bound keysym, instead of relying on XKeysymToKeycode which returns only one. Bluetooth headsets (e.g. Jaybird X2 AVRCP) register as a second keyboard with their own keycodes for XF86AudioPlay/Next/Prev, so the single-keycode grab missed them. The media-key bindings now try pauseallmpv first (per-instance IPC control of any running mpv) and fall back to mpc when no mpv socket is reachable. --- config.h | 14 +++++++------- dwm.c | 23 ++++++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/config.h b/config.h index 1c4a5bd..76e4a62 100644 --- a/config.h +++ b/config.h @@ -266,13 +266,13 @@ static Key keys[] = { { 0, XF86XK_AudioMute, spawn, SHCMD("lmc mute; pkill -RTMIN+10 dwmblocks") }, { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("lmc up 5; pkill -RTMIN+10 dwmblocks") }, { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("lmc down 5; pkill -RTMIN+10 dwmblocks") }, - { 0, XF86XK_AudioPrev, spawn, SHCMD("mpc prev") }, - { 0, XF86XK_AudioNext, spawn, SHCMD("mpc next") }, - { 0, XF86XK_AudioPause, spawn, SHCMD("mpc pause") }, - { 0, XF86XK_AudioPlay, spawn, SHCMD("mpc toggle") }, - { 0, XF86XK_AudioStop, spawn, SHCMD("mpc stop") }, - { 0, XF86XK_AudioRewind, spawn, SHCMD("mpc seek -10") }, - { 0, XF86XK_AudioForward, spawn, SHCMD("mpc seek +10") }, + { 0, XF86XK_AudioPrev, spawn, SHCMD("pauseallmpv prev || mpc prev") }, + { 0, XF86XK_AudioNext, spawn, SHCMD("pauseallmpv next || mpc next") }, + { 0, XF86XK_AudioPause, spawn, SHCMD("pauseallmpv pause || mpc pause") }, + { 0, XF86XK_AudioPlay, spawn, SHCMD("pauseallmpv toggle || mpc toggle") }, + { 0, XF86XK_AudioStop, spawn, SHCMD("pauseallmpv stop || mpc stop") }, + { 0, XF86XK_AudioRewind, spawn, SHCMD("pauseallmpv seek-back || mpc seek -10") }, + { 0, XF86XK_AudioForward, spawn, SHCMD("pauseallmpv seek-fwd || mpc seek +10") }, { 0, XF86XK_AudioMedia, spawn, SHCMD("st -e ncmpcpp") }, { 0, XF86XK_Display, spawn, SHCMD("displayselect")}, diff --git a/dwm.c b/dwm.c index 17b9cb6..9ddb160 100644 --- a/dwm.c +++ b/dwm.c @@ -1037,16 +1037,25 @@ grabkeys(void) { updatenumlockmask(); { - unsigned int i, j; + unsigned int i, j, k; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - 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 | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + 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++) + if (keys[i].keysym == syms[(k - start) * skip]) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, k, + keys[i].mod | modifiers[j], + root, True, + GrabModeAsync, GrabModeAsync); + XFree(syms); } }