feat(host): fold Steam Deck to DualSense on Windows; split-pad touch + pad clicks
A Deck client asking for 'steamdeck' on a Windows host resolved to Xbox360, whose apply_rich is a no-op — gyro and both trackpads silently discarded. Windows already ships a full DualSense backend (UMDF driver, touchpad + motion, wire units 1:1), so pick_gamepad now folds SteamDeck -> DualSense there. The three near-identical DualSense-family appliers (Linux UHID, Windows DualSense, Windows DS4) are hoisted into one shared dualsense_proto::DsState::apply_rich, with two mapping upgrades for Steam dual-pad clients everywhere: * the Deck's two pads SPLIT the single DualSense touchpad — left pad -> contact 0 on the left half, right pad -> contact 1 on the right half — mirroring the physical thumb layout and the split-pad zones games and Steam Input already use (the left pad was previously dropped outright) * TouchpadEx pad clicks now press the touchpad-click button (persisted in DsState::touch_click, OR-ed in by both serializers; previously dropped by every DualSense-family backend, Linux included) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,7 @@ impl DualShock4WindowsManager {
|
||||
s.touch = prev.touch;
|
||||
s.gyro = prev.gyro;
|
||||
s.accel = prev.accel;
|
||||
s.touch_click = prev.touch_click;
|
||||
self.state[idx] = s;
|
||||
self.write(idx);
|
||||
}
|
||||
@@ -224,46 +225,9 @@ impl DualShock4WindowsManager {
|
||||
if idx >= MAX_PADS || self.pads[idx].is_none() {
|
||||
return;
|
||||
}
|
||||
match rich {
|
||||
RichInput::Touchpad {
|
||||
finger,
|
||||
active,
|
||||
x,
|
||||
y,
|
||||
..
|
||||
} => {
|
||||
let slot = (finger as usize).min(1);
|
||||
let t = &mut self.state[idx].touch[slot];
|
||||
t.active = active;
|
||||
t.id = slot as u8;
|
||||
t.x = ((x as u32 * (DS4_TOUCH_W - 1) as u32) / u16::MAX as u32) as u16;
|
||||
t.y = ((y as u32 * (DS4_TOUCH_H - 1) as u32) / u16::MAX as u32) as u16;
|
||||
}
|
||||
RichInput::Motion { gyro, accel, .. } => {
|
||||
self.state[idx].gyro = gyro;
|
||||
self.state[idx].accel = accel;
|
||||
}
|
||||
RichInput::TouchpadEx {
|
||||
surface,
|
||||
finger,
|
||||
touch,
|
||||
x,
|
||||
y,
|
||||
..
|
||||
} => {
|
||||
// A Steam right/single pad maps onto the one DS4 touchpad (signed centre-0 →
|
||||
// 0..=65535); surface 1 (the Steam left pad) has no DS4 equivalent.
|
||||
if surface != 1 {
|
||||
let slot = (finger as usize).min(1);
|
||||
let n = |v: i16| ((v as i32) + 32768) as u32;
|
||||
let t = &mut self.state[idx].touch[slot];
|
||||
t.active = touch;
|
||||
t.id = slot as u8;
|
||||
t.x = (n(x) * (DS4_TOUCH_W - 1) as u32 / u16::MAX as u32) as u16;
|
||||
t.y = (n(y) * (DS4_TOUCH_H - 1) as u32 / u16::MAX as u32) as u16;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The shared DualSense-family mapping (dualsense_proto::DsState::apply_rich): Steam
|
||||
// dual pads split the one touchpad left/right, pad clicks ride touch_click.
|
||||
self.state[idx].apply_rich(rich, DS4_TOUCH_W, DS4_TOUCH_H);
|
||||
self.write(idx);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user