Skip to content

fix(gamepad-android): show real device name + type_hint on sokol-Android (#270) - #272

Merged
apotema merged 1 commit into
mainfrom
fix/270-android-gamepad-name-type-hint
Jun 11, 2026
Merged

apotema merged 1 commit into
mainfrom
fix/270-android-gamepad-name-type-hint

Conversation

@apotema

@apotema apotema commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Problem

The gamepad-android HUD showed Pad 9: Gamepad [unknown] for an Xbox controller, where desktop raylib showed Xbox Wireless Controller [xbox] (#270). Two independent bugs, one per repo:

  1. Name (this PR). examples/gamepad-android/scripts/connected_pads.nameFor still indexed the fixed entries array by the raw device id and returned a generic "Gamepad" for any id >= MAX_GAMEPADS. Android InputDevice ids are not dense 0..3 and routinely exceed 4 (e.g. 9). record/forget/typeHintFor were already migrated to a by-id lookup (findById) for labelle-engine#261 — nameFor was the one method left on the old slot-indexing, so the recorded real name was never surfaced. This is why desktop (ids 0..3) worked and Android (id 9) didn't.
  2. type_hint (core). Core's Android source never derived type_hint from the name. Fixed in labelle-core#31.

Fix (this PR)

Switch nameFor to findById, matching the other accessors, so the stored InputDevice.getName() shows for sparse ids. Add a host regression test covering a sparse id (9).

Tests

  • New host test in connected_pads.zig: record(9, "Xbox Wireless Controller", "xbox") → nameFor(9)/typeHintFor(9) resolve, unknown id falls back to "Gamepad"/"unknown", forget clears. Passes.
  • zig build-obj -target aarch64-linux-android examples/gamepad-android/scripts/connected_pads.zig: clean.
  • sokol backend host tests pass; the sokol_clib Android C-compile step fails only because the local env lacks the Android NDK sysroot (pre-existing, unrelated to this change — no backend Zig/C touched here).

Cross-repo dependency

The [xbox] type_hint half requires labelle-core#31 (derives type_hint from the name on the Android path). Merge core#31 first / repoint the core pin on its release; this PR's name fix is independently correct and testable. On-device verification on the test tablet is pending (main session).

Fixes #270. Refs labelle-core#31, #261, #248, #268, #269.

The gamepad-android demo's `connected_pads.nameFor` still indexed the
fixed `entries` array by the raw device id and returned a generic
"Gamepad" for any `id >= MAX_GAMEPADS`. Android `InputDevice` ids are not
dense 0..3 and routinely exceed 4 (e.g. 9), so the recorded real name was
never surfaced — the HUD showed `Pad 9: Gamepad [...]`. `record`,
`forget` and `typeHintFor` were already migrated to a by-id lookup
(`findById`) for labelle-engine#261; `nameFor` was the one method left
on the old slot-indexing.

Switch `nameFor` to `findById` so the stored `InputDevice.getName()`
shows for sparse ids, and add a host regression test covering a sparse
id (9). Combined with labelle-core deriving the type_hint, the HUD now
shows e.g. `Pad 9: Xbox Wireless Controller [xbox]`.

Note: the `[xbox]` type_hint half of this fix depends on the matching
labelle-core change (typeHintFromName on the Android path); see the
linked core PR. On-device verification on the test tablet is pending
(handled by the main session).

Fixes #270
@cursor

cursor Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Small demo-registry lookup fix with a targeted host test; no auth, persistence, or engine backend changes in this diff.

Overview
Fixes the gamepad-android HUD showing a generic Gamepad label for controllers whose Android InputDevice id is outside the dense 0..3 slot range (e.g. id 9).

nameFor no longer indexes entries by raw device id. It uses findById, like record, forget, and typeHintFor, so names recorded on connect are returned for sparse ids and out-of-bounds indexing is avoided. Fallback behavior for unknown or empty names is unchanged.

Adds a host regression test that records id 9, checks nameFor / typeHintFor, unknown-id fallbacks, and forget.

Reviewed by Cursor Bugbot for commit 5c4adbe. Bugbot is set up for automated code reviews on this repo. Configure here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request fixes a bug in nameFor where sparse Android device IDs exceeding MAX_GAMEPADS caused out-of-bounds indexing or missed entries, by switching to a lookup via findById. It also adds a test case to verify this fix. The reviewer identified a potential out-of-bounds read/panic in nameFor when a gamepad name is exactly NAME_CAP characters long, and suggested declaring the name field in the Entry struct as a sentinel-terminated array to resolve it.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +74 to +75
const e = findById(id) orelse return "Gamepad";
if (e.name_len == 0) return "Gamepad";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a potential out-of-bounds read/panic in nameFor if a gamepad name is exactly NAME_CAP (64) characters long.

When e.name_len == NAME_CAP, the expression e.name[0..e.name_len :0] (which is e.name[0..64 :0]) expects the sentinel 0 to be at e.name[64]. Since e.name is a standard array of size NAME_CAP ([64]u8), accessing index 64 is out of bounds and will trigger a runtime panic in safe build modes.

A clean and idiomatic way to fix this is to declare name in the Entry struct (line 27) as a sentinel-terminated array:

name: [NAME_CAP:0]u8 = [_:0]u8{0} ** NAME_CAP,

This ensures that e.name always has a sentinel at the end, making e.name[0..e.name_len :0] safe even when e.name_len == NAME_CAP.

@apotema
apotema merged commit acfd845 into main Jun 11, 2026
4 checks passed
@apotema
apotema deleted the fix/270-android-gamepad-name-type-hint branch June 11, 2026 17:15
apotema added a commit that referenced this pull request Jun 11, 2026
record() capped names at NAME_CAP, so name_len could equal NAME_CAP (64)
and nameFor's sentinel slice e.name[0..name_len :0] read index 64 of a
[64]u8 -> out-of-bounds panic. Cap record at NAME_CAP-1 (reserve the NUL)
and clamp in nameFor; add a buffer-filling regression test. (Re-do of a
#272-review fix that was lost to a detached-worktree push no-op.)
@apotema apotema mentioned this pull request Jun 12, 2026
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.

sokol/Android: gamepad name + type_hint not propagating to gamepad_connected event

1 participant