feat(gamepad): multi-controller support on the native plane
Host was already built for 16 pads; the blocker was every client hard-coding pad 0. This lands the host-side + reference-client contract: - input.rs: new wire kinds GamepadArrival=14 (declares a pad's type: code=GamepadPref byte, flags=pad) and GamepadRemove=13 (flags=seq<<24|pad, shares the snapshot seq space via encode/decode_gamepad_remove). - pf-client-core/gamepad.rs: reworked from a single `open` pad to a slots: Vec<Slot> model — every forwarded controller gets a stable lowest-free wire index held for its lifetime, per-slot held/axis/touch/ rumble state, GamepadArrival on open + GamepadRemove on close, and feedback routed back per wire index. Automatic forwards all real pads; a pin forces single-player. - punktfunk1.rs: replaced the single-session PadBackend enum with a Pads router — per-pad kinds[]/owner[] arrays, lazily-created per-kind managers, pure route_decision keeping a live device in its manager across a kind change (no ghost/dup). Input thread seq-gates GamepadRemove (clears the pad_mask bit, resets rumble) and applies GamepadArrival kinds. - inject linux/windows backends: add the two new no-op InputKind arms. Native/session + default-Windows clients (both spawn punktfunk-session) inherit this. 57 core + 33 client-core + 272 host tests green; clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -425,7 +425,11 @@ impl InputInjector for KwinFakeInjector {
|
||||
self.fake.touch_frame();
|
||||
}
|
||||
// Gamepads are injected through uinput, not the compositor.
|
||||
InputKind::GamepadState | InputKind::GamepadButton | InputKind::GamepadAxis => {}
|
||||
InputKind::GamepadState
|
||||
| InputKind::GamepadButton
|
||||
| InputKind::GamepadAxis
|
||||
| InputKind::GamepadRemove
|
||||
| InputKind::GamepadArrival => {}
|
||||
}
|
||||
// Surface protocol errors / disconnects, then push the batch to the compositor.
|
||||
self.queue
|
||||
|
||||
@@ -404,6 +404,8 @@ fn kind_bit(kind: InputKind) -> u32 {
|
||||
InputKind::GamepadButton => 10,
|
||||
InputKind::GamepadAxis => 11,
|
||||
InputKind::GamepadState => 12,
|
||||
InputKind::GamepadRemove => 13,
|
||||
InputKind::GamepadArrival => 14,
|
||||
};
|
||||
1 << i
|
||||
}
|
||||
@@ -546,7 +548,11 @@ impl EiState {
|
||||
InputKind::TouchDown | InputKind::TouchMove | InputKind::TouchUp => {
|
||||
DeviceCapability::Touch
|
||||
}
|
||||
InputKind::GamepadState | InputKind::GamepadButton | InputKind::GamepadAxis => return, // uinput path (later)
|
||||
InputKind::GamepadState
|
||||
| InputKind::GamepadButton
|
||||
| InputKind::GamepadAxis
|
||||
| InputKind::GamepadRemove
|
||||
| InputKind::GamepadArrival => return, // uinput path (later)
|
||||
};
|
||||
self.injected += 1;
|
||||
let n = self.injected;
|
||||
@@ -693,9 +699,11 @@ impl EiState {
|
||||
Some(t) => t.up(ev.code),
|
||||
None => emitted = false,
|
||||
},
|
||||
InputKind::GamepadState | InputKind::GamepadButton | InputKind::GamepadAxis => {
|
||||
emitted = false
|
||||
}
|
||||
InputKind::GamepadState
|
||||
| InputKind::GamepadButton
|
||||
| InputKind::GamepadAxis
|
||||
| InputKind::GamepadRemove
|
||||
| InputKind::GamepadArrival => emitted = false,
|
||||
}
|
||||
|
||||
if emitted {
|
||||
|
||||
@@ -254,7 +254,11 @@ impl InputInjector for WlrootsInjector {
|
||||
tracing::debug!(vk = event.code, "unmapped VK keycode — dropped");
|
||||
}
|
||||
}
|
||||
InputKind::GamepadState | InputKind::GamepadButton | InputKind::GamepadAxis => {} // not yet injected
|
||||
InputKind::GamepadState
|
||||
| InputKind::GamepadButton
|
||||
| InputKind::GamepadAxis
|
||||
| InputKind::GamepadRemove
|
||||
| InputKind::GamepadArrival => {} // not yet injected
|
||||
// wlroots has no virtual-touch protocol wired here; touch is the libei path only.
|
||||
InputKind::TouchDown | InputKind::TouchMove | InputKind::TouchUp => {}
|
||||
}
|
||||
|
||||
@@ -301,6 +301,8 @@ impl InputInjector for SendInputInjector {
|
||||
InputKind::GamepadButton
|
||||
| InputKind::GamepadAxis
|
||||
| InputKind::GamepadState
|
||||
| InputKind::GamepadRemove
|
||||
| InputKind::GamepadArrival
|
||||
| InputKind::TouchDown
|
||||
| InputKind::TouchMove
|
||||
| InputKind::TouchUp => Ok(()),
|
||||
|
||||
Reference in New Issue
Block a user