Skip to content

Commit 2b0b6c9

Browse files
authored
fix: ignore gamepads that are masked by steam input to prevent dublicated inputs (#3470)
Fixes #989
1 parent 484d4cb commit 2b0b6c9

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

src/frontend/helpers/gamepad.ts

+47-1
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,59 @@ export const initGamepad = () => {
300300
}
301301
}
302302

303+
/**
304+
* Returns true, if the vendor ID is from valve, else false.
305+
*
306+
* @param gamepad
307+
*/
308+
function isValveGamepad(gamepad: Gamepad | null) {
309+
return gamepad && gamepad.id.includes('Vendor: 28de')
310+
}
311+
312+
/**
313+
* Returns gamepads that are from valve
314+
* - virtual gamepads through Steam Input
315+
* - real gamepads like Steam Deck or Steam Controller
316+
*
317+
* @param gamepads
318+
*/
319+
function filterValveGamepads(gamepads: (Gamepad | null)[]) {
320+
return gamepads.filter(isValveGamepad)
321+
}
322+
323+
/**
324+
* Returns true, if the gamepad is masked through Steam Input.
325+
* Checks if the timestamp of the gamepad is nearly identical of one of the valve gamepads.
326+
* There is a threshold of 10, because the timestamps differ from time to time.
327+
*
328+
* Attention: Without filtering masked gamepads, you have 2 button presses at the same time.
329+
*
330+
* @param valveGamepads
331+
* @param gamepad
332+
*/
333+
function isMaskedGamepad(
334+
valveGamepads: (Gamepad | null)[],
335+
gamepad: Gamepad
336+
) {
337+
return valveGamepads.find(
338+
(valveGamepad) =>
339+
valveGamepad &&
340+
Math.abs(valveGamepad.timestamp - gamepad.timestamp) <= 10
341+
)
342+
}
343+
344+
function isValidGamepad(gamepads: (Gamepad | null)[], gamepad: Gamepad) {
345+
const valveGamepads = filterValveGamepads(gamepads)
346+
return isValveGamepad(gamepad) || !isMaskedGamepad(valveGamepads, gamepad)
347+
}
348+
303349
// check all the buttons and axes every frame
304350
function updateStatus() {
305351
const gamepads = navigator.getGamepads()
306352

307353
controllers.forEach((index) => {
308354
const controller = gamepads[index]
309-
if (!controller) return
355+
if (!controller || !isValidGamepad(gamepads, controller)) return
310356

311357
// logState(index)
312358

0 commit comments

Comments
 (0)