v147 · JavaScript · Device · Origin Trial
Compatibility Lab
Probe the event-driven Gamepad API contract, compare it with navigator.getGamepads() polling, and drive a synthetic input harness through button, axis, raw-input, deadzone, mapping, and fallback cases.
API contract probes
Synthetic input harness fallback
Input path
Button pressure
0.80
Axis value
0.45
Deadzone
0.12
Drive the adapter
Live readout 0 events
No gamepad connected. Use the harness or connect real hardware.
input events will appear here...
Last event payload
Input method comparison
Event-driven input IN DEVELOPMENT
Listens for
rawgamepadinputchange, gamepadbuttondown, gamepadbuttonup, gamepadbuttonchange, and gamepadaxismove on window. Events carry the gamepad index plus button or axis data, so games can respond to meaningful changes without scanning every frame.
rAF polling BASELINE FALLBACK
Calls
navigator.getGamepads() on a render tick, diffs button and axis arrays, applies a deadzone, and emits the same app-level actions. It works in current browsers but can miss sub-frame ordering and does work even when input has not changed.
Fallback pattern
const supportsEventDrivenGamepad =
"onrawgamepadinputchange" in window ||
"ongamepadbuttondown" in window ||
"ongamepadbuttonchange" in window ||
"ongamepadaxismove" in window;
function installGamepadAdapter({ onButton, onAxis, onBlocked }) {
if (supportsEventDrivenGamepad) {
addEventListener("gamepadbuttondown", (event) => onButton(event.gamepad.index, event.button, event.value));
addEventListener("gamepadbuttonup", (event) => onButton(event.gamepad.index, event.button, 0));
addEventListener("gamepadbuttonchange", (event) => onButton(event.gamepad.index, event.button, event.value));
addEventListener("gamepadaxismove", (event) => onAxis(event.gamepad.index, event.axis, event.value));
return "native";
}
if (typeof navigator.getGamepads !== "function") {
onBlocked("Gamepad API unavailable");
return "blocked";
}
requestAnimationFrame(function poll() {
for (const gamepad of navigator.getGamepads()) {
if (!gamepad) continue;
// Diff buttons and axes, apply deadzones, then call onButton/onAxis.
}
requestAnimationFrame(poll);
});
return "polling";
}
references
- ChromeStatus feature 5989275208253440
- Gamepad specification
- Button Visualizer — live hardware map with polling fallback
- Game Input Recorder — timestamped event stream comparison
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗