Skip to content

feat(screen-mirror): implement cursor-follow interaction using absolute pointer mapping#344

Open
Arbaaz123676 wants to merge 2 commits into
AOSSIE-Org:mainfrom
Arbaaz123676:fix/issue-343-cursor-follow
Open

feat(screen-mirror): implement cursor-follow interaction using absolute pointer mapping#344
Arbaaz123676 wants to merge 2 commits into
AOSSIE-Org:mainfrom
Arbaaz123676:fix/issue-343-cursor-follow

Conversation

@Arbaaz123676
Copy link
Copy Markdown
Contributor

@Arbaaz123676 Arbaaz123676 commented May 1, 2026

Summary

Implements cursor-follow interaction for Screen Mirror with accurate absolute pointer mapping and improved input handling.

Changes

  • Added absolute pointer mapping for cursor-follow behavior
  • Updated pointer handlers (onPointerDown, onPointerMove, onPointerUp)
  • Prevented cursor teleport during scroll gestures (touch/pen in scrollMode)
  • Added throttling (~60fps) for pointer move events
  • Guarded releasePointerCapture to avoid DOMException
  • Improved coordinate mapping with object-contain handling

Testing

  • Verified cursor follows correctly with mouse input
  • Verified touch interaction works without unintended cursor movement in scrollMode
  • Verified scroll gestures do not move cursor
  • Verified click and drag interactions function correctly
  • Tested on both desktop and mobile clients

Checklist

  • Cursor follows pointer accurately
  • Scroll mode does not trigger cursor movement
  • Mouse interactions (click/drag) work correctly
  • Touch interactions behave as expected
  • No console errors or crashes
  • Performance is smooth (throttled pointer events)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 1, 2026

Walkthrough

ScreenMirror inlines pointer handling and sends absolute/scroll/click input messages via useRemoteConnection; server accepts an "absolute" InputMessage (x/y), routes to moveRelative (with absolute flag) and falls back to direct positioning; ydotool moveRelative gains an optional absolute mode.

Changes

ScreenMirror → Absolute input flow

Layer / File(s) Summary
Data Shape / Protocol
src/server/InputHandler.ts, src/server/websocket.ts
Adds "absolute" to InputMessage / VALID_INPUT_TYPES and includes optional x?: number, y?: number; clamps coordinates server-side.
Client Implementation
src/components/Trackpad/ScreenMirror.tsx, src/routes/trackpad.tsx
Removes external handlers prop; wires internal onPointerDown/Move/Up/Cancel, computes/clamps absolute canvas coords, throttles moves, sends {type:"absolute"}, {type:"click"}, or {type:"scroll"} depending on pointer and scrollMode; prevents context menu and updates cursor logic.
Server Wiring / Behavior
src/server/InputHandler.ts
Handles "absolute" messages: validates x/y, attempts moveRelative(..., ..., true) and falls back to directly setting mouse position if needed; adds error handling for absolute move failures.
Native Exec Integration
src/server/ydotool.ts
moveRelative(dx, dy, absolute = false) updated to conditionally include --absolute in ydotool args.
Tests / Docs (none changed)
-
No test or documentation files changed in this diff.

Sequence Diagram

sequenceDiagram
    participant Client as ScreenMirror
    participant Remote as RemoteConnection
    participant Server as InputHandler
    participant Ydotool as ydotool
    Client->>Remote: send("absolute", {x, y})
    Remote->>Server: receive InputMessage(type:"absolute", x, y)
    Server->>Server: clamp/validate x,y
    Server->>Ydotool: moveRelative(x, y, absolute=true)
    alt moveRelative succeeds
        Ydotool-->>Server: success
    else moveRelative fails
        Server->>Ydotool: set mouse position (rounded x,y)
        Ydotool-->>Server: position set
    end
    Server-->>Remote: ack / processed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Typescript Lang

Poem

🐰
I hopped from handler to wire,
Sent absolute moves with desire,
No props passed — I leap and send,
To ydotool's dance the cursor bends,
A rabbit's tap, and systems conspire.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description lacks critical sections from the template including addressed issues, screenshots/recordings, functional verification checklist, and general checklist items. Add the 'Addressed Issues' section with issue number, include screenshots/recordings demonstrating the cursor-follow feature, and complete the functional verification checklist with all gesture behaviors tested and documented.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: implementing cursor-follow interaction using absolute pointer mapping, which is the core feature added across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Trackpad/ScreenMirror.tsx`:
- Around line 97-109: handlePointerUp calls
e.currentTarget.releasePointerCapture unconditionally which can throw if capture
was never set (see handlePointerUp, lastPos). Before calling
releasePointerCapture, guard it by checking
e.currentTarget.hasPointerCapture(e.pointerId) (or wrap releasePointerCapture in
a try/catch) and only call releasePointerCapture when true; keep the rest of the
logic (pointerType branch, send calls, and lastPos.current = null) unchanged.

In `@src/server/InputHandler.ts`:
- Around line 161-182: The new "absolute" event handler issues high-frequency OS
calls but isn't passing through the existing throttling used for
"move"/"scroll"; update the input dispatch so "absolute" events go through the
same throttled path (or add "absolute" to the throttle switch) instead of
executing moveRelative/ mouse.setPosition directly. Concretely, route the
"absolute" branch to call the same throttled handler (or wrap its logic in the
existing throttle function), preserving the numeric validation and the try/catch
around moveRelative and mouse.setPosition (functions referenced: moveRelative,
mouse.setPosition, Point) so the absolute positioning respects the throttle
interval and falls back correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3c6c3116-631b-405c-8d90-653a1be15115

📥 Commits

Reviewing files that changed from the base of the PR and between 782183e and 6f6568d.

📒 Files selected for processing (5)
  • src/components/Trackpad/ScreenMirror.tsx
  • src/routes/trackpad.tsx
  • src/server/InputHandler.ts
  • src/server/websocket.ts
  • src/server/ydotool.ts

Comment thread src/components/Trackpad/ScreenMirror.tsx
Comment thread src/server/InputHandler.ts
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Trackpad/ScreenMirror.tsx`:
- Around line 61-67: The initial absolute cursor send in handlePointerDown (and
the similar send in the pointer-move handler) should be skipped for touch/pen
scroll gestures; update the code around the send({ type: "absolute", x: ..., y:
... }) calls inside handlePointerDown and the pointer-move handler to only call
send when e.pointerType === "mouse" || !scrollMode, so touch/pen events in
scrollMode do not teleport the remote cursor.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 41b1681a-b001-4f39-9eef-8df8d71186a9

📥 Commits

Reviewing files that changed from the base of the PR and between 6f6568d and 66fceea.

📒 Files selected for processing (1)
  • src/components/Trackpad/ScreenMirror.tsx

Comment thread src/components/Trackpad/ScreenMirror.tsx Outdated
…rg#343)

perf: throttle pointer move events and guard pointer capture
@Arbaaz123676 Arbaaz123676 force-pushed the fix/issue-343-cursor-follow branch from 0898958 to 38c8e6a Compare May 3, 2026 04:38
@Arbaaz123676 Arbaaz123676 force-pushed the fix/issue-343-cursor-follow branch from 38c8e6a to 4a9c122 Compare May 3, 2026 04:40
@Arbaaz123676 Arbaaz123676 deleted the fix/issue-343-cursor-follow branch May 4, 2026 11:22
@Arbaaz123676 Arbaaz123676 restored the fix/issue-343-cursor-follow branch May 4, 2026 11:23
@Arbaaz123676 Arbaaz123676 reopened this May 4, 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.

1 participant