Capture hotkeys through XInput2, as TeamSpeak does

The bundled TS3 Linux binary dlopens libX11 and libXi and drives
XIQueryVersion/XISelectEvents/XGetEventData — XInput2 raw events, with no
trace of the RECORD extension anywhere in its tree. That is the better
choice for us too: XInput2 is core input, present on any remotely modern
server, where RECORD is a debugging extension that is sometimes disabled
or left out of the build. Both are passive, so the keystroke still
reaches the focused window either way.

XRecordInputHook stays as the fallback behind it. Raw events also explain
why TS3's hotkeys work under KWin's Wayland session despite it using no
Wayland API at all: it runs on Xwayland, and KWin's legacy X11 app
support forwards the keys.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 18:33:32 +00:00
parent 7e4b9671fe
commit edc8a0ca3a
4 changed files with 377 additions and 14 deletions

View File

@@ -94,10 +94,15 @@ frontend supplies its own UI and audio backend while reusing `core` unchanged.
actions. Actions this client does not implement are listed but greyed out.
- Push-to-talk is one of those hotkeys; the button in **Options → Voice Activation**
edits that binding.
- Capture uses X11's RECORD extension, which needs no privileges and does not swallow
the keystroke. On Wayland the X server never sees keys aimed at other applications,
so the client falls back to reading `/dev/input/event*` — for which your user has to
be in the `input` group. The Hotkeys tab says which backend is in use, or why none is.
- Capture uses **XInput2 raw events**, as TeamSpeak's own Linux client does: no
privileges needed and the keystroke is not swallowed. X11's RECORD extension is kept
as a fallback for servers without XInput2.
- On Wayland the hooks run inside Xwayland, so they see every X11 application, and keys
aimed at native Wayland windows only where the compositor forwards them — under KWin
that is *System Settings → Window Management → Legacy X11 App Support*, which is why
TeamSpeak's hotkeys work there. Where it forwards nothing, the client reads
`/dev/input/event*` instead, for which your user has to be in the `input` group.
The Hotkeys tab says which backend is in use, or why none is.
### Notification sounds
- **Sound packs** in TeamSpeak's own format: a folder of waves plus a `settings.ini`
@@ -198,7 +203,8 @@ desktop/ com.ts3client.audio.desktop + com.ts3client.hotkey.desktop
├── WavSoundPlayer sound-pack playback: decode, resample and mix on one line
├── JavaSoundAudioBackend wires the above into the core AudioBackend
└── hotkey.desktop
├── XRecordInputHook global key/button capture via X11's RECORD extension
├── XInput2InputHook global key/button capture via XInput2 raw events
├── XRecordInputHook the same via X11's RECORD extension, as a fallback
├── EvdevInputHook /dev/input fallback for Wayland sessions
└── DesktopInputHooks picks the backend that suits the session