Skip to content

Fix/sensitivity redo#100

Open
Rozerxshashank wants to merge 4 commits intoAOSSIE-Org:mainfrom
Rozerxshashank:fix/sensitivity-redo
Open

Fix/sensitivity redo#100
Rozerxshashank wants to merge 4 commits intoAOSSIE-Org:mainfrom
Rozerxshashank:fix/sensitivity-redo

Conversation

@Rozerxshashank
Copy link
Contributor

@Rozerxshashank Rozerxshashank commented Feb 16, 2026

Fixes: #52

This PR resolves the "double-sensitivity" bug by consolidating sensitivity and inversion logic entirely on the client-side. It also fixes a server-side precision issue where fractional movements from the client were being ignored or incorrectly scaled on Windows.

Changes:

Client-Side Move: Moved mouseSensitivity and mouseInvert from server-config.json to client-side localStorage.

This prevents the server from interfering with user-specific gesture preferences.
Input Precision: Updated InputHandler.ts to use Math.round() for all physical movements, scrolls, and zooms.

This ensures that scaled deltas from the client are correctly translated into discrete integer steps required by the OS.

Zoom Direction Fix: Fixed a bug where zooming was only working in one direction; it now correctly uses both scrollUp and scrollDown .

Upstream Alignment: Built from a fresh sync with upstream/main to ensure full compatibility with the latest processMovement architecture.

How Has This Been Tested?

**Manual Verification: ** Verified on Windows that mouse movement, scrolling, and zooming are smooth and respect both high and very low sensitivity settings.

Build Check:

Ran npm run build to verify that all TypeScript type errors (especially in InputHandler.ts ) are resolved.

Checklist

My code follows the style guidelines of this project
I have performed a self-review of my own code
I have commented my code, particularly in hard-to-understand areas
My changes generate no new warnings

Summary by CodeRabbit

  • Bug Fixes
    • Improved trackpad and mouse movement precision through coordinate rounding.
    • Enhanced scroll behavior with refined promise resolution.
    • Corrected invert-scroll setting initialization from storage.
    • Removed unused address configuration field.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

📝 Walkthrough

Walkthrough

Invert-scroll parsing on the client was simplified, a hardcoded address was removed from server config, and server input handling was adjusted to round movement/scroll/zoom deltas and only enqueue non-zero actions with safer promise handling.

Changes

Cohort / File(s) Summary
Client: trackpad UI
src/routes/trackpad.tsx
Changed invert-scroll initialization from JSON.parse(s) to direct string comparison (s === 'true'); minor formatting whitespace edits.
Server: input processing
src/server/InputHandler.ts
Round coordinates and delta amounts with Math.round, guard scroll/zoom actions to only run when rounded amount ≠ 0, batch/await promises only when non-empty, and minor switch/formatting adjustments.
Config
src/server-config.json
Removed the address field ("rein.local") from server configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰
I hopped through code with careful feet,
Rounded paths and promises neat,
A swipe, a scroll, no ghosts in state,
Config trimmed tidy at the gate —
Hop on, dance light, the fixes greet.

🚥 Pre-merge checks | ✅ 3 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

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.
Title check ❓ Inconclusive The title 'Fix/sensitivity redo' is vague and uses generic terminology that doesn't clearly convey the specific changes made to fix the sensitivity and inversion logic. Use a more descriptive title like 'Fix trackpad sensitivity by consolidating client-side logic and adding rounding' to better summarize the main changes.
Out of Scope Changes check ❓ Inconclusive Changes to server-config.json removing the address field appear unrelated to the sensitivity/inversion logic fixes described in issue #52 and may represent out-of-scope modifications. Clarify whether removing the address field from server-config.json is necessary for fixing the sensitivity issue or if it should be in a separate PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully addresses the core requirements from issue #52 by moving sensitivity/inversion to client-side localStorage and using Math.round() in InputHandler.ts for discrete movements.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/InputHandler.ts (1)

50-76: ⚠️ Potential issue | 🟡 Minor

Wrap scroll case body in a block to avoid switch-clause declaration leak.

The const promises declaration on line 51 is accessible to subsequent case clauses due to JavaScript's switch fall-through scoping rules. This is flagged by Biome's noSwitchDeclarations lint rule.

Also, prefer Promise<void>[] over any[] to retain type safety.

Proposed fix
-            case 'scroll':
-                const promises: any[] = [];
+            case 'scroll': {
+                const promises: Promise<void>[] = [];
                 // ... existing scroll logic ...
-                break;
+                break;
+            }
🤖 Prompt for AI Agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.
In `@src/server/InputHandler.ts` around lines 50 - 76, Wrap the entire `case
'scroll':` body in its own block to avoid leaking the `const promises`
declaration into other switch cases and change its type from `any[]` to
`Promise<void>[]`; specifically, enclose the current logic that declares `const
promises` and calls `mouse.scrollDown/scrollUp/scrollRight/scrollLeft` in `{ ...
}`, update `const promises: any[]` to `const promises: Promise<void>[]`, and
keep the `await Promise.all(promises)` call inside that block so the variable
scope is limited to the `'scroll'` case.
🤖 Fix all issues with AI agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.

In `@src/routes/trackpad.tsx`:
- Around line 24-28: processMovement in useTrackpadGesture.ts is still
multiplying the client-side sensitivity into all deltas (move/zoom/scroll),
causing double-application; remove any multiplication by the sensitivity
variable inside processMovement and from the move/zoom/scroll handlers so the
raw delta values are sent to the server, while leaving the sensitivity state
(the sensitivity useState in trackpad.tsx) intact for server-side
use/round-trip; ensure processMovement(), and the move/zoom/scroll branches in
useTrackpadGesture.ts no longer modify deltas by sensitivity so only the server
applies the sensitivity value.

In `@src/server/InputHandler.ts`:
- Around line 78-101: Extract the hardcoded sensitivityFactor in the 'zoom' case
into a named constant (e.g., ZOOM_SENSITIVITY) alongside MAX_ZOOM_STEP to avoid
the magic number; update the code in InputHandler's switch 'zoom' block to use
this constant instead of the inline 0.5 so it's discoverable and configurable,
and ensure any related comments or tests reference ZOOM_SENSITIVITY where
appropriate.
- Around line 50-76: Wrap the entire `case 'scroll':` body in its own block to
avoid leaking the `const promises` declaration into other switch cases and
change its type from `any[]` to `Promise<void>[]`; specifically, enclose the
current logic that declares `const promises` and calls
`mouse.scrollDown/scrollUp/scrollRight/scrollLeft` in `{ ... }`, update `const
promises: any[]` to `const promises: Promise<void>[]`, and keep the `await
Promise.all(promises)` call inside that block so the variable scope is limited
to the `'scroll'` case.
🧹 Nitpick comments (1)
🤖 Fix all nitpicks with AI agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.

In `@src/server/InputHandler.ts`:
- Around line 78-101: Extract the hardcoded sensitivityFactor in the 'zoom' case
into a named constant (e.g., ZOOM_SENSITIVITY) alongside MAX_ZOOM_STEP to avoid
the magic number; update the code in InputHandler's switch 'zoom' block to use
this constant instead of the inline 0.5 so it's discoverable and configurable,
and ensure any related comments or tests reference ZOOM_SENSITIVITY where
appropriate.
src/server/InputHandler.ts (1)

78-101: Zoom implementation looks solid — good use of try/finally for key release.

The try/finally ensures LeftControl is always released even if the scroll action throws. Rounding and clamping (MAX_ZOOM_STEP) protect against erratic input. The amount !== 0 guard avoids unnecessary key presses.

One minor note: the hardcoded sensitivityFactor = 0.5 on line 80 is a magic number. Consider extracting it as a named constant alongside MAX_ZOOM_STEP for discoverability.

🤖 Prompt for AI Agents
Before applying any fix, first verify the finding against the current code and
decide whether a code change is actually needed. If the finding is not valid or
no change is required, do not modify code for that item and briefly explain why
it was skipped.
In `@src/server/InputHandler.ts` around lines 78 - 101, Extract the hardcoded
sensitivityFactor in the 'zoom' case into a named constant (e.g.,
ZOOM_SENSITIVITY) alongside MAX_ZOOM_STEP to avoid the magic number; update the
code in InputHandler's switch 'zoom' block to use this constant instead of the
inline 0.5 so it's discoverable and configurable, and ensure any related
comments or tests reference ZOOM_SENSITIVITY where appropriate.

Copy link
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.

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@src/server/InputHandler.ts`:
- Around line 57-59: Replace the empty `.then(() => { })` handlers used when
pushing the promises in InputHandler (the calls to mouse.scrollDown and
mouse.scrollUp) with a clearer discard of the resolved value; either use
`.then(() => undefined)` or cast the returned Promise to `Promise<void>` (e.g.,
`as unknown as Promise<void>`) so the intent to coerce to Promise<void> is
explicit and the code reads clearly.
- Around line 54-61: Compute and reuse the rounded delta values instead of
calling Math.round twice: in InputHandler where you currently check typeof
msg.dy and Math.round(msg.dy) !== 0, first compute const amountY =
Math.round(msg.dy) and use that in the guard and subsequent logic to push
mouse.scrollDown(amountY) / mouse.scrollUp(-amountY); do the same for msg.dx
(compute const amountX = Math.round(msg.dx) and reuse it) so both the dx and dy
branches avoid duplicate Math.round calls and reuse the precomputed amount
variables.
- Line 81: The hardcoded "const sensitivityFactor = 0.5" in InputHandler
silently halves zoom input; replace it with a configurable value by either
deriving it from the client's existing sensitivity setting or moving it to a
named config/constant (e.g., ZOOM_SENSITIVITY_FACTOR) and exposing it in the
client settings. Update the code in the InputHandler method that computes zoom
(the place where sensitivityFactor is used) to read the value from the client's
settings or the new config constant, and add validation/fallback (e.g., default
to 0.5) so behavior stays safe if the config is missing.
🧹 Nitpick comments (3)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@src/server/InputHandler.ts`:
- Around line 57-59: Replace the empty `.then(() => { })` handlers used when
pushing the promises in InputHandler (the calls to mouse.scrollDown and
mouse.scrollUp) with a clearer discard of the resolved value; either use
`.then(() => undefined)` or cast the returned Promise to `Promise<void>` (e.g.,
`as unknown as Promise<void>`) so the intent to coerce to Promise<void> is
explicit and the code reads clearly.
- Around line 54-61: Compute and reuse the rounded delta values instead of
calling Math.round twice: in InputHandler where you currently check typeof
msg.dy and Math.round(msg.dy) !== 0, first compute const amountY =
Math.round(msg.dy) and use that in the guard and subsequent logic to push
mouse.scrollDown(amountY) / mouse.scrollUp(-amountY); do the same for msg.dx
(compute const amountX = Math.round(msg.dx) and reuse it) so both the dx and dy
branches avoid duplicate Math.round calls and reuse the precomputed amount
variables.
- Line 81: The hardcoded "const sensitivityFactor = 0.5" in InputHandler
silently halves zoom input; replace it with a configurable value by either
deriving it from the client's existing sensitivity setting or moving it to a
named config/constant (e.g., ZOOM_SENSITIVITY_FACTOR) and exposing it in the
client settings. Update the code in the InputHandler method that computes zoom
(the place where sensitivityFactor is used) to read the value from the client's
settings or the new config constant, and add validation/fallback (e.g., default
to 0.5) so behavior stays safe if the config is missing.
src/server/InputHandler.ts (3)

57-59: The .then(() => { }) calls are unnecessary if the only goal is Promise<void> coercion.

If mouse.scrollDown returns Promise<Mouse>, a cleaner way to discard the resolved value is .then(() => undefined) or casting via as unknown as Promise<void>. The empty-block .then(() => { }) also silently converts the resolve value but reads like a forgotten handler.

Not a bug — just a readability nit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/InputHandler.ts` around lines 57 - 59, Replace the empty `.then(()
=> { })` handlers used when pushing the promises in InputHandler (the calls to
mouse.scrollDown and mouse.scrollUp) with a clearer discard of the resolved
value; either use `.then(() => undefined)` or cast the returned Promise to
`Promise<void>` (e.g., `as unknown as Promise<void>`) so the intent to coerce to
Promise<void> is explicit and the code reads clearly.

54-61: Math.round(msg.dy) is computed twice — once in the guard and once for amount.

Minor: compute amount first and reuse it in the guard.

♻️ Suggested refactor
-                if (typeof msg.dy === 'number' && Math.round(msg.dy) !== 0) {
-                    const amount = Math.round(msg.dy);
+                const vAmount = typeof msg.dy === 'number' ? Math.round(msg.dy) : 0;
+                if (vAmount !== 0) {
+                    const amount = vAmount;

Same pattern applies to msg.dx on lines 64-65.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/InputHandler.ts` around lines 54 - 61, Compute and reuse the
rounded delta values instead of calling Math.round twice: in InputHandler where
you currently check typeof msg.dy and Math.round(msg.dy) !== 0, first compute
const amountY = Math.round(msg.dy) and use that in the guard and subsequent
logic to push mouse.scrollDown(amountY) / mouse.scrollUp(-amountY); do the same
for msg.dx (compute const amountX = Math.round(msg.dx) and reuse it) so both the
dx and dy branches avoid duplicate Math.round calls and reuse the precomputed
amount variables.

81-81: Hardcoded sensitivityFactor = 0.5 for zoom — consider making it configurable.

Issue #52's objective is to eliminate hidden multipliers so the user's sensitivity setting directly controls speed. While this is zoom-specific dampening (not cursor sensitivity), it's still a magic number that silently halves the user's gesture input. Consider either deriving it from the client's sensitivity setting or extracting it to a named constant/config so it's discoverable and tunable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/InputHandler.ts` at line 81, The hardcoded "const
sensitivityFactor = 0.5" in InputHandler silently halves zoom input; replace it
with a configurable value by either deriving it from the client's existing
sensitivity setting or moving it to a named config/constant (e.g.,
ZOOM_SENSITIVITY_FACTOR) and exposing it in the client settings. Update the code
in the InputHandler method that computes zoom (the place where sensitivityFactor
is used) to read the value from the client's settings or the new config
constant, and add validation/fallback (e.g., default to 0.5) so behavior stays
safe if the config is missing.

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.

[Bug]: Sensitivity slider value is not wired to the trackpad, setting is ignored and double-applied

1 participant