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.

Availability: ChromeStatus currently lists this feature as in development. A browser that lacks the new events should still show a clean fallback path and keep the polling adapter usable.

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

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗