Skip to content

feat: Gyro mouse aiming#875

Closed
unbelievableflavour wants to merge 1 commit intoutkarshdalal:masterfrom
unbelievableflavour:gyro-aiming
Closed

feat: Gyro mouse aiming#875
unbelievableflavour wants to merge 1 commit intoutkarshdalal:masterfrom
unbelievableflavour:gyro-aiming

Conversation

@unbelievableflavour
Copy link
Copy Markdown
Contributor

@unbelievableflavour unbelievableflavour commented Mar 16, 2026

Currently only supports mouse. Controller is a pain in the ass. So let's just start with this.

  • Adds a toggle in the overlay which can enable gyro mouse aiming
  • Adds a setting to the container config allowing to set gyro mouse aiming sensitivity.

Summary by cubic

Adds gyroscope-powered mouse aiming with a Quick Menu toggle and a per-container sensitivity (25%–200%) applied on launch. Localizes the new UI and highlights the toggle in the Quick Menu.

  • New Features
    • Quick Menu: “Gyro aiming” toggle with accent highlight; state saved per container, restored on launch, and captures gyro_aiming_toggled.
    • Controller: “Gyro sensitivity” (25%–200%); persisted per container and applied at startup.
    • Implementation: GyroAimingHelper converts gyro data to relative mouse deltas with sensitivity scaling, per-frame clamping, rotation handling, and sub-pixel accumulation; integrated into TouchpadView (enable/disable and sensitivity), works in relative and desktop pointer modes, auto-stops on detach, and initialized by XServerScreen on start.

Written for commit fa25b83. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Gyro-based mouse aiming: quick-menu toggle, per-session persistence, and live application to the touchpad.
    • Adjustable gyro sensitivity: new setting in controller options that updates immediately when changed.
  • Localization

    • Added gyro-related UI texts (label, sensitivity name and description) across many locales (15+ languages).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds gyro-based mouse aiming: quick-menu action/item, controller UI for selecting gyro sensitivity, persisted per-container sensitivity, a GyroAimingHelper sensor bridge, TouchpadView integration to inject deltas, XServerScreen wiring for toggles and persistence, and localized strings across many locales.

Changes

Cohort / File(s) Summary
Quick Menu & Controller UI
app/src/main/java/app/gamenative/ui/component/QuickMenu.kt, app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
Introduces QuickMenuAction.GYRO_AIMING and adds a gyro-aiming quick-menu item; adds a ControllerTab SettingsListDropdown for selecting predefined gyro sensitivity multipliers and persists selection to container config.
XServerScreen wiring
app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
Handles GYRO_AIMING quick-menu action (toggle, persist to container extras, emit analytics) and initializes TouchpadView gyro enabled state and sensitivity from container extras on view creation.
Container persistence
app/src/main/java/com/winlator/container/ContainerData.kt, app/src/main/java/app/gamenative/utils/ContainerUtils.kt
Adds gyroSensitivity: Float to ContainerData and mapSaver; reads/writes gyroSensitivity via container extras with parsing and clamping to [0.25f, 2f].
Gyro sensor helper
app/src/main/java/com/winlator/widget/GyroAimingHelper.java
New SensorEventListener-based helper converting gyroscope angular velocity to integer mouse deltas with start/stop lifecycle, sensitivity control, rotation remapping, fractional accumulation, and main-thread listener callbacks.
Touchpad integration
app/src/main/java/com/winlator/widget/TouchpadView.java
Adds gyro-aiming fields and APIs (setGyroAimingEnabled, setGyroSensitivity, isGyroAimingEnabled), ensures gyro disabled on detach, routes gyro deltas into XServer or relative mouse path, and logs state changes.
Localization
app/src/main/res/values/.../strings.xml (multiple files, e.g. values/, values-de/, values-es/, values-zh-rCN/, values-zh-rTW/, etc.)
Adds gyro_aiming, gyro_sensitivity, and gyro_sensitivity_description strings across English and many localized resource files.

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as QuickMenu UI
    participant XServer as XServerScreen
    participant Container as Container
    participant TPView as TouchpadView
    participant Gyro as GyroAimingHelper
    participant Sensor as Gyro Sensor

    User->>UI: toggle "Gyro Aiming"
    UI->>XServer: dispatch QuickMenuAction.GYRO_AIMING
    XServer->>Container: saveData(gyroAiming=true)
    XServer->>TPView: setGyroAimingEnabled(true)
    TPView->>Gyro: create & start()
    Gyro->>Sensor: registerListener()
    Sensor-->>Gyro: onSensorChanged(event)
    Gyro->>Gyro: compute & accumulate deltas
    Gyro-->>TPView: onMouseDelta(dx,dy)
    TPView->>XServer: injectRelativeMouseMovement(dx,dy)
    XServer-->>User: cursor moves
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I twitched my whiskers, felt a spin,
tiny gyro hops nudged the tin,
angles turned to pixel hops,
deltas danced and target drops,
a rabbit cheers — the crosshair wins!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description is partially complete but lacks key template sections including a recording/GIF and incomplete checklist items. Add a recording or GIF demonstrating the gyro aiming toggle and sensitivity settings, and complete all checklist items by marking them as done or explaining why they cannot be completed.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Gyro mouse aiming' directly and clearly summarizes the main change: adding gyroscope-based aiming functionality mapped to mouse movement, which is the primary objective across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@unbelievableflavour unbelievableflavour marked this pull request as ready for review March 16, 2026 00:25
@unbelievableflavour unbelievableflavour changed the title Gyro aiming Gyro mouse aiming Mar 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
app/src/main/java/com/winlator/container/ContainerData.kt (1)

221-221: Clamp restored gyroSensitivity to the same supported bounds.
Line 221 restores the value but does not enforce the [0.25f, 2f] range used elsewhere, so malformed saved state can leak invalid values into runtime state.

♻️ Proposed fix
-                    gyroSensitivity = (savedMap["gyroSensitivity"] as? Float) ?: (savedMap["gyroSensitivity"] as? Double)?.toFloat() ?: 1f,
+                    gyroSensitivity =
+                        (
+                            (savedMap["gyroSensitivity"] as? Float)
+                                ?: (savedMap["gyroSensitivity"] as? Double)?.toFloat()
+                                ?: 1f
+                        ).coerceIn(0.25f, 2f),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/winlator/container/ContainerData.kt` at line 221,
Restore gyroSensitivity from savedMap but clamp it into the supported bounds
[0.25f, 2f]; locate the assignment that reads gyroSensitivity =
(savedMap["gyroSensitivity"] as? Float) ?: (savedMap["gyroSensitivity"] as?
Double)?.toFloat() ?: 1f and wrap the parsed value with a clamp (e.g., use
Kotlin's coerceIn on the parsed Float) so any malformed or out-of-range saved
values are constrained to 0.25f..2f before storing in the
ContainerData.gyroSensitivity field.
app/src/main/java/app/gamenative/ui/component/QuickMenu.kt (1)

590-593: Make active rows use active text color as well.

At Line 590-593, active-but-not-focused items keep default label color, which makes active state less consistent than the icon treatment.

🎨 Suggested tweak
         Text(
             text = stringResource(item.labelResId),
             style = MaterialTheme.typography.bodyLarge,
             color = when {
                 !isEnabled -> MaterialTheme.colorScheme.onSurface.copy(alpha = disabledAlpha)
-                isFocused -> accentColor
+                isFocused || isActive -> accentColor
                 else -> MaterialTheme.colorScheme.onSurface
             },
             modifier = Modifier.weight(1f)
         )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt` around lines 590
- 593, The text color assignment for rows is missing the active-but-not-focused
case; in the color = when { ... } block currently checking isEnabled and
isFocused, add a branch that returns accentColor for the active/selected state
(e.g., check your active flag such as isActive or isSelected) so active rows use
accentColor like the icon does; keep the disabledAlpha branch and the fallback
to MaterialTheme.colorScheme.onSurface unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt`:
- Around line 977-978: The gyro is enabled via
PluviaApp.touchpadView?.setGyroAimingEnabled(...) before the X server WinHandler
is assigned (getxServer().winHandler = WinHandler(...)), risking a callback
calling xServer.getWinHandler().mouseEvent(...) when null; move the WinHandler
initialization (the getxServer().winHandler = WinHandler(...) call) to occur
before calling PluviaApp.touchpadView?.setGyroAimingEnabled(...) so the handler
is always assigned before gyro callbacks can run, ensuring
TouchpadView.setGyroAimingEnabled() cannot trigger mouseEvent on a null handler.

In `@app/src/main/java/com/winlator/widget/GyroAimingHelper.java`:
- Around line 71-80: stop() currently only unregisters the sensor but does not
cancel already posted main-thread callbacks, so queued runnables can still
execute and move the cursor after disable; update stop() in GyroAimingHelper to
(1) set running = false, (2) remove any pending callbacks from the main thread
handler (e.g., call mainHandler.removeCallbacks(someRunnable) and/or
mainHandler.removeCallbacksAndMessages(null)), and (3) ensure the runnable(s)
that update cursor check the running flag at the start and return early if
false; apply the same cancellation/check to the other stop/pause block
referenced around lines 123-126 so no queued deltas execute after stop().
- Around line 125-126: The per-sample debug log call Timber.d("GyroAiming: delta
dx=%d dy=%d", fix, fiy) inside the gyro delta emitter in GyroAimingHelper is on
the input hot path and must be removed or gated; either delete the call or
replace it with a cheap sampling guard (e.g., only log when a lightweight
counter % N == 0 or when BuildConfig.DEBUG is true) so that the high-frequency
lambda/callback that emits deltas doesn't log every event and flood/slow the
system.

In `@app/src/main/java/com/winlator/widget/TouchpadView.java`:
- Around line 1310-1345: The field gyroAimingEnabled is set to true before
actually starting the gyro helper so isGyroAimingEnabled() can report true even
if start() fails; change setGyroAimingEnabled(boolean) so you only mark
gyroAimingEnabled = true after a successful gyroAimingHelper.start() (or catch
failures from start() and revert gyroAimingEnabled to false and log the error),
and/or make isGyroAimingEnabled() return the real running state by checking
gyroAimingHelper != null && gyroAimingHelper.isRunning() (or add an isRunning()
on GyroAimingHelper) instead of relying solely on the boolean flag. Ensure to
update references to gyroAimingEnabled/gyroAimingHelper in setGyroSensitivity
and shutdown paths accordingly.

---

Nitpick comments:
In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt`:
- Around line 590-593: The text color assignment for rows is missing the
active-but-not-focused case; in the color = when { ... } block currently
checking isEnabled and isFocused, add a branch that returns accentColor for the
active/selected state (e.g., check your active flag such as isActive or
isSelected) so active rows use accentColor like the icon does; keep the
disabledAlpha branch and the fallback to MaterialTheme.colorScheme.onSurface
unchanged.

In `@app/src/main/java/com/winlator/container/ContainerData.kt`:
- Line 221: Restore gyroSensitivity from savedMap but clamp it into the
supported bounds [0.25f, 2f]; locate the assignment that reads gyroSensitivity =
(savedMap["gyroSensitivity"] as? Float) ?: (savedMap["gyroSensitivity"] as?
Double)?.toFloat() ?: 1f and wrap the parsed value with a clamp (e.g., use
Kotlin's coerceIn on the parsed Float) so any malformed or out-of-range saved
values are constrained to 0.25f..2f before storing in the
ContainerData.gyroSensitivity field.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 773fdc2c-3cf9-4363-91fd-9664358f2dc9

📥 Commits

Reviewing files that changed from the base of the PR and between 3ed0380 and 7ace2fc.

📒 Files selected for processing (22)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/java/com/winlator/widget/GyroAimingHelper.java
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/java/com/winlator/winhandler/WinHandler.java
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/winlator/winhandler/WinHandler.java

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 22 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/main/java/com/winlator/widget/GyroAimingHelper.java">

<violation number="1" location="app/src/main/java/com/winlator/widget/GyroAimingHelper.java:104">
P2: Gyroscope axes are not remapped for device orientation, causing inverted/swapped controls when device orientation differs from natural orientation</violation>
</file>

<file name="app/src/main/java/com/winlator/widget/TouchpadView.java">

<violation number="1" location="app/src/main/java/com/winlator/widget/TouchpadView.java:1317">
P2: Race condition: gyro callback lacks gyroAimingEnabled guard, allowing queued sensor events to inject mouse movement after feature is disabled</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@unbelievableflavour unbelievableflavour moved this to In Progress in Open Source Mar 16, 2026
@unbelievableflavour unbelievableflavour moved this from In Progress to PR Needs Review in Open Source Mar 16, 2026
Copy link
Copy Markdown
Contributor

@phobos665 phobos665 left a comment

Choose a reason for hiding this comment

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

Overall it seems pretty sensible.

Does it work seemlessly also with gamepad inputs at the same time?

@unbelievableflavour
Copy link
Copy Markdown
Contributor Author

Overall it seems pretty sensible.

Does it work seemlessly also with gamepad inputs at the same time?

That depends on how a game registers gamepads.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt (1)

1357-1358: ⚠️ Potential issue | 🟠 Major

Initialize WinHandler before enabling gyro callbacks.

Line 1358 enables gyro aiming before winHandler is assigned at Line 1380, leaving a small callback window with unsafe ordering.

🔧 Proposed fix
-                PluviaApp.touchpadView?.setGyroSensitivity(container.getExtra("gyroSensitivity", "1").toFloatOrNull()?.coerceIn(0.25f, 2f) ?: 1f)
-                PluviaApp.touchpadView?.setGyroAimingEnabled(container.getExtra("gyroAiming", "false") == "true")
+                PluviaApp.touchpadView?.setGyroSensitivity(
+                    container.getExtra("gyroSensitivity", "1").toFloatOrNull()?.coerceIn(0.25f, 2f) ?: 1f
+                )
@@
                 getxServer().winHandler = WinHandler(getxServer(), this)
+                PluviaApp.touchpadView?.setGyroAimingEnabled(container.getExtra("gyroAiming", "false") == "true")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt` around
lines 1357 - 1358, The gyro aiming is enabled via
PluviaApp.touchpadView.setGyroAimingEnabled(...) before winHandler is assigned,
creating a race; move the initialization/assignment of winHandler (the variable
or property named winHandler in XServerScreen) to occur before calling
setGyroAimingEnabled and setGyroSensitivity, or defer enabling gyro callbacks
until after winHandler is fully constructed/assigned (e.g., check winHandler !=
null or call an initialization method on winHandler first). Update the code
paths around the calls to PluviaApp.touchpadView.setGyroSensitivity(...) and
PluviaApp.touchpadView.setGyroAimingEnabled(...) so they execute only after the
winHandler assignment is complete.
🧹 Nitpick comments (1)
app/src/main/java/com/winlator/container/ContainerData.kt (1)

221-221: Clamp restored sensitivity to the supported runtime range.

Line 221 restores numeric types safely, but it can still accept out-of-range values from stale/corrupt state. Clamping here keeps behavior consistent with the rest of the gyro settings flow.

♻️ Proposed hardening
-                    gyroSensitivity = (savedMap["gyroSensitivity"] as? Float) ?: (savedMap["gyroSensitivity"] as? Double)?.toFloat() ?: 1f,
+                    gyroSensitivity = (
+                        (savedMap["gyroSensitivity"] as? Float)
+                            ?: (savedMap["gyroSensitivity"] as? Double)?.toFloat()
+                            ?: 1f
+                        ).coerceIn(0.25f, 2f),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/winlator/container/ContainerData.kt` at line 221, The
restored gyroSensitivity value in ContainerData (gyroSensitivity property)
should be clamped to the supported runtime range to avoid accepting
stale/corrupt out-of-range values; replace the current restore expression with
one that computes the Float as now (using the savedMap cast chain) and then
calls .coerceIn(GYRO_SENSITIVITY_MIN, GYRO_SENSITIVITY_MAX), adding
GYRO_SENSITIVITY_MIN and GYRO_SENSITIVITY_MAX constants (e.g., in ContainerData
companion object or an existing config place) if they don't exist so the value
is constrained to the same runtime limits used elsewhere in the gyro settings
flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/com/winlator/widget/GyroAimingHelper.java`:
- Around line 71-73: The code sets the field running = true before confirming
sensor registration; change the start logic in GyroAimingHelper (the running
field and isRunning()) to first call sensorManager.registerListener(this, gyro,
SENSOR_DELAY_US), capture its boolean result, and only set running = true when
registration returns true; if registration fails, leave running false and log an
error via Timber (including gyro.getName()) and return/throw as appropriate so
callers can retry or handle failure.

---

Duplicate comments:
In `@app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt`:
- Around line 1357-1358: The gyro aiming is enabled via
PluviaApp.touchpadView.setGyroAimingEnabled(...) before winHandler is assigned,
creating a race; move the initialization/assignment of winHandler (the variable
or property named winHandler in XServerScreen) to occur before calling
setGyroAimingEnabled and setGyroSensitivity, or defer enabling gyro callbacks
until after winHandler is fully constructed/assigned (e.g., check winHandler !=
null or call an initialization method on winHandler first). Update the code
paths around the calls to PluviaApp.touchpadView.setGyroSensitivity(...) and
PluviaApp.touchpadView.setGyroAimingEnabled(...) so they execute only after the
winHandler assignment is complete.

---

Nitpick comments:
In `@app/src/main/java/com/winlator/container/ContainerData.kt`:
- Line 221: The restored gyroSensitivity value in ContainerData (gyroSensitivity
property) should be clamped to the supported runtime range to avoid accepting
stale/corrupt out-of-range values; replace the current restore expression with
one that computes the Float as now (using the savedMap cast chain) and then
calls .coerceIn(GYRO_SENSITIVITY_MIN, GYRO_SENSITIVITY_MAX), adding
GYRO_SENSITIVITY_MIN and GYRO_SENSITIVITY_MAX constants (e.g., in ContainerData
companion object or an existing config place) if they don't exist so the value
is constrained to the same runtime limits used elsewhere in the gyro settings
flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7ebdac61-1e72-4def-b169-c94a06764858

📥 Commits

Reviewing files that changed from the base of the PR and between 7ace2fc and 0374434.

📒 Files selected for processing (21)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/java/com/winlator/widget/GyroAimingHelper.java
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
✅ Files skipped from review due to trivial changes (13)
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-it/strings.xml
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
  • app/src/main/java/com/winlator/widget/TouchpadView.java

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt (1)

4-8: Remove unused imports.

The imports padding, Modifier, and dp (lines 4, 6–7) are unused in this file. Only abs from line 8 is used in the gyro sensitivity calculation on line 111.

Proposed cleanup
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.dp
 import kotlin.math.abs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt` around
lines 4 - 8, In ControllerTab.kt the imports
androidx.compose.foundation.layout.padding, androidx.compose.ui.Modifier, and
androidx.compose.ui.unit.dp are unused and should be removed; keep
kotlin.math.abs which is used by the gyro sensitivity calculation in the
ControllerTab implementation (the code computing gyro sensitivity uses abs).
Remove the three unused import lines to clean up the file and avoid
unused-import warnings.
app/src/main/java/com/winlator/widget/GyroAimingHelper.java (1)

80-91: Make stop() fully idempotent for partial-start states.

At Line 81, early return skips cleanup when running is false. If startup partially initialized fields before failing, stop() won’t clear them. Consider always clearing callbacks/references and only gating unregister by prior running state.

♻️ Proposed refactor
 public void stop() {
-    if (!running) return;
-    running = false;
+    final boolean wasRunning = running;
+    running = false;
     mainHandler.removeCallbacksAndMessages(null);
-    if (sensorManager != null && gyro != null) {
+    if (wasRunning && sensorManager != null && gyro != null) {
         sensorManager.unregisterListener(this, gyro);
     }
     sensorManager = null;
     displayManager = null;
     gyro = null;
     Timber.d("GyroAiming: stopped");
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/winlator/widget/GyroAimingHelper.java` around lines 80
- 91, Make stop() fully idempotent: capture current running state (e.g., boolean
wasRunning = running), then immediately set running = false; always call
mainHandler.removeCallbacksAndMessages(null) and clear
displayManager/sensorManager/gyro references to null; only call
sensorManager.unregisterListener(this, gyro) when wasRunning is true and
sensorManager != null and gyro != null to avoid attempting unregister for
partial-start states; keep the final Timber.d("GyroAiming: stopped") log.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt`:
- Around line 4-8: In ControllerTab.kt the imports
androidx.compose.foundation.layout.padding, androidx.compose.ui.Modifier, and
androidx.compose.ui.unit.dp are unused and should be removed; keep
kotlin.math.abs which is used by the gyro sensitivity calculation in the
ControllerTab implementation (the code computing gyro sensitivity uses abs).
Remove the three unused import lines to clean up the file and avoid
unused-import warnings.

In `@app/src/main/java/com/winlator/widget/GyroAimingHelper.java`:
- Around line 80-91: Make stop() fully idempotent: capture current running state
(e.g., boolean wasRunning = running), then immediately set running = false;
always call mainHandler.removeCallbacksAndMessages(null) and clear
displayManager/sensorManager/gyro references to null; only call
sensorManager.unregisterListener(this, gyro) when wasRunning is true and
sensorManager != null and gyro != null to avoid attempting unregister for
partial-start states; keep the final Timber.d("GyroAiming: stopped") log.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5abd9d90-32ac-446e-96c9-4b1a6166410a

📥 Commits

Reviewing files that changed from the base of the PR and between 0374434 and 95a08a2.

📒 Files selected for processing (21)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/java/com/winlator/widget/GyroAimingHelper.java
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
✅ Files skipped from review due to trivial changes (11)
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-ru/strings.xml
🚧 Files skipped from review as they are similar to previous changes (7)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-da/strings.xml
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt

@unbelievableflavour unbelievableflavour force-pushed the gyro-aiming branch 2 times, most recently from 1ff1e57 to 52d2ac1 Compare March 30, 2026 11:31
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt (1)

112-112: Prefer locale-aware percent formatting for dropdown labels.

"${(it * 100).toInt()}%" is readable, but using locale-aware formatting will better support non-English numeral/percent conventions.

Suggested refactor
+import java.text.NumberFormat
...
+    val percentFormatter = remember { NumberFormat.getPercentInstance().apply { maximumFractionDigits = 0 } }
...
-            items = GYRO_SENSITIVITY_VALUES.map { "${(it * 100).toInt()}%" },
+            items = GYRO_SENSITIVITY_VALUES.map { percentFormatter.format(it.toDouble()) },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt` at
line 112, Replace the manual string interpolation for dropdown labels with a
locale-aware percent formatter: create a NumberFormat via
NumberFormat.getPercentInstance(Locale.getDefault()) (optionally set
maximum/minimum fraction digits to 0) and use it to format each value in
GYRO_SENSITIVITY_VALUES when assigning items (the mapping that currently uses
"${(it * 100).toInt()}%").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt`:
- Line 112: Replace the manual string interpolation for dropdown labels with a
locale-aware percent formatter: create a NumberFormat via
NumberFormat.getPercentInstance(Locale.getDefault()) (optionally set
maximum/minimum fraction digits to 0) and use it to format each value in
GYRO_SENSITIVITY_VALUES when assigning items (the mapping that currently uses
"${(it * 100).toInt()}%").

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 953e9836-9162-4812-a00e-7022272127a0

📥 Commits

Reviewing files that changed from the base of the PR and between 1ff1e57 and 52d2ac1.

📒 Files selected for processing (21)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ControllerTab.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/java/com/winlator/widget/GyroAimingHelper.java
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
✅ Files skipped from review due to trivial changes (15)
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/java/com/winlator/widget/TouchpadView.java
  • app/src/main/java/com/winlator/widget/GyroAimingHelper.java
🚧 Files skipped from review as they are similar to previous changes (5)
  • app/src/main/java/com/winlator/container/ContainerData.kt
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/java/app/gamenative/utils/ContainerUtils.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/res/values-uk/strings.xml

@unbelievableflavour unbelievableflavour changed the title Gyro mouse aiming feat: Gyro mouse aiming Apr 8, 2026
@unbelievableflavour
Copy link
Copy Markdown
Contributor Author

Drafting this again since I might have a nicer solution that works with controllers. So more of a gamenative focused solution.

@unbelievableflavour
Copy link
Copy Markdown
Contributor Author

Closed in favour of #1173

@github-project-automation github-project-automation bot moved this from PR Needs Review to Done in Open Source Apr 10, 2026
@unbelievableflavour unbelievableflavour deleted the gyro-aiming branch April 12, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants