feat(gamepad): Gamepad API for iOS, Android and Windows - #159
Merged
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
New @nativescript/canvas-gamepad package: navigator.getGamepads() plus gamepadconnected/gamepaddisconnected, standard mapping, up to 4 pads. Native code writes controller state into one shared Float32Array as input arrives; getGamepads() reads it in TS, so polling makes no native calls on iOS/Android and one per frame on Windows. - iOS/tvOS/visionOS: GameController GCExtendedGamepad (ObjC) - Android: KeyEvent/MotionEvent taken at the activity's Window.Callback - Windows: Windows.Gaming.Input poller (crates/canvas-gamepad-napi) - canvas-polyfill: getGamepads() and window events use the package when installed; events go through the iOS runtime's own EventTarget
triniwiz
force-pushed
the
feat/gamepad
branch
from
September 28, 2026 07:45
953f731 to
5fc1f6e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #139
Adds the Gamepad API as a new package,
@nativescript/canvas-gamepad.navigator.getGamepads()was a stub returning[], so games built on Phaser, Pixi, Three or Babylon could not use controllers.How it works
Games call
getGamepads()every frame, so polling must not cross into native code. The native side writes each controller's state into one JS-ownedFloat32Arraywhenever input arrives, the same pattern as the canvas bounds buffer.getGamepads()and theGamepadobjects are plain TS reading that memory.timestamponly when something changed.Gamepadobjects are updated in place between calls, as in Firefox.vibrationActuatorisnullfor now.Platforms
NSCGamepadManager, ObjC): GameController connect/disconnect notifications. EachGCExtendedGamepad'svalueChangedHandlerrewrites its slot. The Siri Remote (micro gamepad) is ignored and keeps its keyboard mapping inNSCCanvas.NSCGamepadManager, Java):InputManagerdevice listener for connect/disconnect. Stick and button events are taken at the activity'sWindow.Callback, because joystick events only reach the focused view. Only events from tracked controllers are consumed, and only after JS starts monitoring, so B stays Back for apps that never use the API. D-pad hats and analog triggers are detected per device.crates/canvas-gamepad-napi→canvasgamepad.node):Windows.Gaming.Inputcan only be polled, sogetGamepads()makes onepoll(buffer)call per frame.GamepadAdded/GamepadRemovedare re-posted to JS through a threadsafe function.make windows-gamepadbuilds it.canvas-polyfill
navigator.getGamepads()andgamepadconnected/gamepaddisconnecteduse the package when it is installed, and fall back to[]otherwise. Nothing starts until a page polls or adds a gamepad listener.addEventListener/dispatchEvent, so the polyfill'sglobal.emitternever reacheswindowlisteners there. Gamepad events are dispatched throughglobal.dispatchEventwhen it exists, and through the emitter otherwise.resize.tscallsemitter.emit, whichObservabledoes not have, so that event is probably not delivered either. Not changed here.Testing
node --test 'packages/canvas-gamepad/__test__/*.test.mjs': 7 tests for the buffer reader, connect/disconnect events and polling.gamepadconnectedreacheswindow, and the newcanvas-gamepaddemo page renders it at 60 fps.getGamepads()plus reading every axis and button: about 320–380 ns per frame.canvas-gamepad-napipassescargo checkand clippy forx86_64-pc-windows-msvc.--demo=canvas-gamepad/--es demo canvas-gamepad) logsGAMEPAD|lines for these.