Skip to content

Steam Controller support, controller test and visual binder - #733

Open
maxjivi05 wants to merge 5 commits into
WinNative-Emu:mainfrom
maxjivi05:feature/steam-controller
Open

Steam Controller support, controller test and visual binder#733
maxjivi05 wants to merge 5 commits into
WinNative-Emu:mainfrom
maxjivi05:feature/steam-controller

Conversation

@maxjivi05

Copy link
Copy Markdown
Contributor

Ports The412Banner's Steam Controller work from Bannerlator (https://github.com/The412Banner/Bannerlator, GPL-3.0) into WinNative.

A Steam Controller is not a gamepad out of the box: it presents as a keyboard and mouse, so Android never reports a controller and the normal InputDevice path cannot use it. SDL3's HIDAPI Steam drivers speak Valve's protocol over Bluetooth LE or USB instead. Only those drivers are enabled, so SDL never opens, claims or requests permission for any other controller, and every non-Valve pad keeps the untouched Android input path.

  • steamctrl/steam_controller_bridge.cpp: JNI bridge over SDL3's gamepad API
  • SteamControllerBackend: poll thread, 22-bit button model, trackpad mouse modes, back paddles and the "..." Quick Access button
  • WinHandler: SDL pads take ordinary player slots under a synthetic device id, shadow the Valve device Android also exposes, and rumble back through SDL
  • ControllerTestPanel: animated per-family pad art with live button glow, movable stick nubs that glow with deflection, metrics and the verified tally
  • VisualControllerBinder: tap a button on the pad art to rebind it, written to the same profile store the list editor uses
  • Settings card (off by default) and an in-game drawer entry

SDL3 3.4.16's official Android release AAR is vendored unmodified under vendor/maven/ and reached through prefab. Credits and the upstream commit history are in README.md and EMULATOR_CREDITS.md.

Ports The412Banner's Steam Controller work from Bannerlator
(https://github.com/The412Banner/Bannerlator, GPL-3.0) into WinNative.

A Steam Controller is not a gamepad out of the box: it presents as a keyboard
and mouse, so Android never reports a controller and the normal InputDevice
path cannot use it. SDL3's HIDAPI Steam drivers speak Valve's protocol over
Bluetooth LE or USB instead. Only those drivers are enabled, so SDL never
opens, claims or requests permission for any other controller, and every
non-Valve pad keeps the untouched Android input path.

- steamctrl/steam_controller_bridge.cpp: JNI bridge over SDL3's gamepad API
- SteamControllerBackend: poll thread, 22-bit button model, trackpad mouse
  modes, back paddles and the "..." Quick Access button
- WinHandler: SDL pads take ordinary player slots under a synthetic device id,
  shadow the Valve device Android also exposes, and rumble back through SDL
- ControllerTestPanel: animated per-family pad art with live button glow,
  movable stick nubs that glow with deflection, metrics and the verified tally
- VisualControllerBinder: tap a button on the pad art to rebind it, written to
  the same profile store the list editor uses
- Settings card (off by default) and an in-game drawer entry

SDL3 3.4.16's official Android release AAR is vendored unmodified under
vendor/maven/ and reached through prefab. Credits and the upstream commit
history are in README.md and EMULATOR_CREDITS.md.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

The app installed a default uncaught exception handler that logged and
returned, replacing Android's KillApplicationHandler. Any exception on the
main thread was logged, the stack unwound out of ActivityThread.main(), and
the process disappeared with no crash dialog and nothing in the crash
buffer. Chain to the platform handler so crashes are reported again.

publishUiState() runs from download callbacks and coroutine continuations
that can land after the fragment detaches; take the context once and bail
out instead of throwing from requireContext().

SteamControllerBackend: undo the partial SDL setup when start() fails, keep
the poll loop and the frame applier from throwing out of their threads, and
skip the HID manager release and SDL context reset when the poll thread has
not finished so teardown does not race native shutdown.

Do not start the backend once the display activity is destroyed.
In test mode the dialog window carries FLAG_NOT_FOCUSABLE so the host
activity keeps key focus and can forward controller events, which also means
the dialog never receives KEYCODE_BACK and dismissOnBackPress does nothing.
One Back press fell through to the settings shell and popped the whole stack
out to the library with the dialog still registered as open. Handle Back on
the host activity's dispatcher so the first press closes the dialog.

Container settings: remove the activity lifecycle observer on dismiss
instead of leaving one per open, shut the content sync executor down, catch
Throwable rather than Exception around the sync, and guard the main-thread
population callback so a failure there cannot take the process down.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant