From 0c4c6fe58c45d28b406146fc67c5cafc9e4df580 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath <2+defunkt@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:56:47 -0700 Subject: [PATCH] gamepad support --- app/src/js/gamepad.ts | 64 +++++++++++++++++++++++++++++++++++++++++++ app/src/js/main.ts | 2 ++ 2 files changed, 66 insertions(+) create mode 100644 app/src/js/gamepad.ts diff --git a/app/src/js/gamepad.ts b/app/src/js/gamepad.ts new file mode 100644 index 0000000..ac589e4 --- /dev/null +++ b/app/src/js/gamepad.ts @@ -0,0 +1,64 @@ +//// +// Support for gamepads. +// Maps incoming gamepad button presses to keyboard buttons. +// + +const BUTTONS = [ + "A", "B", "X", "Y", + "LB", "RB", "LT", "RT", + "Select", "Start", + "LStick", "RStick", + "DPad Up", "DPad Down", "DPad Left", "DPad Right" +] + +const BUTTONS_TO_KEYS: Record = { + 0: "z", // A → Z + 1: "x", // B → X + 2: "c", // X → C + 3: "v", // Y → V + 12: "ArrowUp", + 13: "ArrowDown", + 14: "ArrowLeft", + 15: "ArrowRight", + 9: "Enter", // Start + 8: "Escape" // Select +} + +const activePads = new Set() +const prevState: Record = {} + +export function initGamepad() { + window.addEventListener("gamepadconnected", e => { + console.log("Gamepad connected:", e.gamepad) + activePads.add(e.gamepad.index) + requestAnimationFrame(handleGamepad) + }) + + window.addEventListener("gamepaddisconnected", e => { + console.log("Gamepad disconnected:", e.gamepad) + activePads.delete(e.gamepad.index) + }) +} + +function handleGamepad() { + const pads = navigator.getGamepads() + for (const gp of pads) { + if (!gp) continue + if (!prevState[gp.index]) prevState[gp.index] = gp.buttons.map(() => false) + + gp.buttons.forEach((btn, i) => { + const was = prevState[gp.index]![i] + const is = btn.pressed + if (was !== is) { + const key = BUTTONS_TO_KEYS[i] + if (key) { + const type = is ? "keydown" : "keyup" + window.dispatchEvent(new KeyboardEvent(type, { code: key, key })) + } + prevState[gp.index]![i] = is + } + }) + } + + requestAnimationFrame(handleGamepad) +} \ No newline at end of file diff --git a/app/src/js/main.ts b/app/src/js/main.ts index a2901af..df2c49c 100644 --- a/app/src/js/main.ts +++ b/app/src/js/main.ts @@ -2,6 +2,7 @@ import { initCompletion } from "./completion.js" import { initCursor } from "./cursor.js" import { initEditor } from "./editor.js" import { initFocus } from "./focus.js" +import { initGamepad } from "./gamepad.js" import { initHistory } from "./history.js" import { initHyperlink } from "./hyperlink.js" import { initInput } from "./input.js" @@ -13,6 +14,7 @@ initCompletion() initCursor() initFocus() initEditor() +initGamepad() initHistory() initHyperlink() initInput()