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.
This commit is contained in:
2026-04-23 22:48:03 +02:00
parent aad610d178
commit 2e6a4ed20f
2 changed files with 23 additions and 14 deletions
+7 -7
View File
@@ -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")},
+16 -7
View File
@@ -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);
}
}