Phase 1 of controller-support epic: labelle-toolkit/labelle-engine#609
Goal
sokol gamepad sources for desktop Linux (evdev + libudev) and wasm (HTML5 Gamepad API), so a sokol build has controller detection — and on Linux, better reconnection than raylib.
Context
sokol has no gamepad layer on any platform. Unlike Android, on desktop Linux an app can open /dev/input/event* directly (subject to permissions), and on the web the Gamepad API is pollable. These plug into the Phase 0 comptime fallback (only compiled in when the backend declares no pollGamepadEvents).
Scope
Linux (evdev + libudev):
- libudev monitor for add/remove →
GamepadEvents into the ring buffer; enumerate existing /dev/input/event* at startup.
- Derive a stable
guid from the device input_id (vendor/product/version + phys) — gives correct reconnection (raylib can't).
- Permissions: on
EACCES, surface via describeGamepads unavailable_reason + a one-time log hint (input group / udev rule). Ship a sample 99-labelle-gamepads.rules (uaccess) and document Flatpak --device=input.
- Filter duplicate js*/event* nodes and non-gamepad devices (accelerometers etc.).
wasm (HTML5 Gamepad API):
5. gamepadconnected/gamepaddisconnected events → ring buffer; gamepad.id → name, index → slot.
Acceptance criteria
Non-goals
- Semantic button/axis mapping (the SDL_GameControllerDB problem) is Phase 3. This issue is detection + identity.
Phase 1 of controller-support epic: labelle-toolkit/labelle-engine#609
Goal
sokol gamepad sources for desktop Linux (evdev + libudev) and wasm (HTML5 Gamepad API), so a sokol build has controller detection — and on Linux, better reconnection than raylib.
Context
sokol has no gamepad layer on any platform. Unlike Android, on desktop Linux an app can open
/dev/input/event*directly (subject to permissions), and on the web the Gamepad API is pollable. These plug into the Phase 0 comptime fallback (only compiled in when the backend declares nopollGamepadEvents).Scope
Linux (evdev + libudev):
GamepadEvents into the ring buffer; enumerate existing/dev/input/event*at startup.guidfrom the deviceinput_id(vendor/product/version + phys) — gives correct reconnection (raylib can't).EACCES, surface viadescribeGamepadsunavailable_reason+ a one-time log hint (input group / udev rule). Ship a sample99-labelle-gamepads.rules(uaccess) and document Flatpak--device=input.wasm (HTML5 Gamepad API):
5.
gamepadconnected/gamepaddisconnectedevents → ring buffer;gamepad.id→name, index →slot.Acceptance criteria
input_idguid; permission failure produces a clear diagnostic, not silence.Non-goals