Skip to content

fix: Correct inverted Android stick Y axis and map the RX/RY right stick - #129

Merged
spydon merged 1 commit into
mainfrom
fix/android-axis-inversion-and-missing-axes
Aug 25, 2026
Merged

fix: Correct inverted Android stick Y axis and map the RX/RY right stick#129
spydon merged 1 commit into
mainfrom
fix/android-axis-inversion-and-missing-axes

Conversation

@spydon

@spydon spydon commented Aug 25, 2026

Copy link
Copy Markdown
Member

Follow-up to #128, which fixed the same double inversion for the d-pad hat axis but left the analog sticks inconsistent with it. Also closes the second symptom reported in #123.

Stick Y axis was double inverted

gamepads_android's EventListener registers AXIS_Y, AXIS_RZ and AXIS_RY with invert = true, so a physical stick-up already arrives in Dart as +1.0. AndroidMapping.normalizeAxis negated it a second time:

if (axis == GamepadAxis.leftStickY || axis == GamepadAxis.rightStickY) {
  return [NormalizedAxis(axis, -value)];
}

The result was leftStickY = -1.0 for up on Android, while the same gesture gives +1.0 on iOS, macOS and Web. That contradicts the convention documented on GamepadAxis and PlatformMapping ("Left/Down = -1, Right/Up = +1"), so cross-platform game code moved the player in opposite directions.

After #128 the file also argued both ways: "EventListener already inverted it" for the hat axis, and the opposite three lines above for the sticks.

RX/RY right stick events were dropped

EventListener reports AXIS_RX and AXIS_RY (added in #111 for non-Xbox layouts such as the DJI RC Pro), but they were missing from _axisMap. Unmatched analog keys fall through to normalizeDpadAxis, which returns const [] for anything that is not a hat axis, so those events were discarded. On a DJI RC Pro the right stick produced no normalized events at all.

Both are mapped to rightStickX/rightStickY, the same aliasing pattern already used for AXIS_BRAKE/AXIS_GAS.

Guarding the cross-package invariant

AndroidMapping's correctness depends on the invert = true flags staying in the separately versioned Kotlin plugin, and until now the only trace of that was a comment on the Dart side. EventListener.kt is the more obvious place for a contributor to "fix" against Android's documentation, and doing so would silently re-invert everything without a single test failing, since the tests only exercise the Dart half. Added a counterpart comment next to supportedAxes pointing back at the Dart mapping.

AXIS_WHEEL is still reported by EventListener and still unmapped, since there is no matching GamepadAxis. It stays available through the raw event API.

Changes

  • packages/gamepads/lib/src/mappings/android_mapping.dart
  • packages/gamepads/lib/src/mappings/platform_mapping.dart, the Y-axis contract no longer lists Android as a platform that must negate
  • packages/gamepads_android/.../EventListener.kt, comment only
  • packages/gamepads/test/mappings_test.dart, stick assertions corrected, new RX/RY test
  • packages/gamepads/test/gamepad_normalizer_test.dart, the AXIS_Y test asserted the buggy -1.0

Verification

melos analyze is clean, dart format reports no changes, and all 80 tests in packages/gamepads pass. Hardware confirmation on a physical Android device is still worth doing before release.

https://claude.ai/code/session_019aEP4Np5vqDw5BkgGYyHe7

Follow-up to #128, which fixed the same double inversion for the d-pad
hat axis.

gamepads_android's EventListener already inverts AXIS_Y, AXIS_RZ and
AXIS_RY, so a physical stick-up reaches Dart as +1.0. AndroidMapping
negated it a second time and emitted leftStickY = -1.0 for up, the
opposite of every other platform and of the documented convention.

AXIS_RX and AXIS_RY were reported by EventListener but missing from the
axis map, so they fell through to normalizeDpadAxis and were dropped.
Controllers that report the right stick on RX/RY, such as the DJI RC
Pro, emitted no normalized right stick events at all.

Claude-Session: https://claude.ai/code/session_019aEP4Np5vqDw5BkgGYyHe7
@spydon
spydon merged commit 18c1886 into main Aug 25, 2026
8 checks passed
@spydon
spydon deleted the fix/android-axis-inversion-and-missing-axes branch August 25, 2026 09:03
spydon added a commit that referenced this pull request Aug 25, 2026
…8.4.0 (#130)

## Description

Removes the `+x` build numbers from all package versions and updates
melos to `^8.4.0`.

Every `+x` version was the currently published one on pub.dev, so plain
stripping would have produced versions that sort lower than what is
published. Each package got a patch bump instead, with the build number
dropped:

| Package | Before | After |
|---|---|---|
| gamepads_android | 0.1.8+2 | 0.1.9 |
| gamepads_darwin | 0.1.2+4 | 0.1.3 |
| gamepads_ios | 0.1.3+3 | 0.1.4 |
| gamepads_web | 0.1.1+1 | 0.1.2 |
| gamepads_windows | 0.3.0+1 | 0.3.1 |
| gamepads | 0.1.10+5 | 0.1.11 |
| flutter_gamepads | 0.1.11+4 | 0.1.12 |

Internal dependency constraints and changelogs were generated with
`melos version` from the unreleased commits (#125 to #129).
`gamepads_web` and `gamepads_windows` had no unreleased changes and are
only bumped to drop the suffix.

Melos 8.x bumps the patch version for fixes and dependency updates on
0.x packages and only keeps a build number when the current version
already has one, so with these clean versions no `+x` will be
reintroduced by future `melos version` runs. 8.4.0 is the latest release
and requires `sdk: ^3.9.0`, which matches the workspace minimum.

## Checklist

- [x] The title of my PR starts with a [Conventional Commit] prefix
(`fix:`, `feat:`, `docs:` etc).
- [x] I have read the [Contributor Guide] and followed the process
outlined for submitting PRs.
- [x] I have updated/added tests for ALL new/updated/fixed
functionality.
- [x] I have updated/added relevant documentation in `docs` and added
dartdoc comments with `///`.
- [x] I have updated/added relevant examples in `examples`.

## Breaking Change

- [ ] Yes, this is a breaking change.
- [x] No, this is *not* a breaking change.

https://claude.ai/code/session_01ECm9j87ohzVbQSagq7qe8M

[Conventional Commit]: https://conventionalcommits.org
[Contributor Guide]:
https://github.com/flame-engine/gamepads/blob/main/CONTRIBUTING.md
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.

2 participants