Skip to content

Move the cursor with the radar - #1050

Merged
enaboapps merged 4 commits into
mainfrom
claude/1047-radar-cursor
Oct 13, 2026
Merged

enaboapps merged 4 commits into
mainfrom
claude/1047-radar-cursor

Conversation

@enaboapps

@enaboapps enaboapps commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1047

What changed

  • scan_radar.rs: new Radar::follow() gives the pointer position only when it differs from the position last sent. During the Angle phase that is the chosen area's centre. During Distance it is the marker's target(), the same rounded and clamped display-unit point the final move already uses. While an area is being picked it returns nothing. choose_area (back or exhaustion) clears the last sent position, so choosing an area again re-centres the pointer and nothing snaps back.
  • point_workflow.rs: Stage::MouseRadar returns MouseMoveAbsolute from handle when an action moves the target. That covers picking an area and manual distance steps. The tick path (advance) sets it as pending, the same route the mouse move repeat uses, so there is at most one move per tick. An exhausted pass goes back without moving.
  • The beam drops its own tip marker. The real pointer is now the tip. The origin square, the beam dots (which still stop short of the pointer) and the chosen quarter's outline stay.
  • docs/point-scan.md: describes the pointer following the radar, the tick-rate limit and unit conversion, and that back, cancel and the session ending leave the pointer where it is. The Settings status copy ("Choose an area, then a direction, then a distance, to move the pointer") is still accurate, so I left it unchanged.

Judgement calls

  • Final Select still sends the move. It goes to the point the pointer is already on, so the fake sequence ends with the same position twice. This keeps the selection performing exactly the action it does today, ending the radar and restoring the panel via repeat_stopped. It also corrects any drift if the physical mouse was nudged.
  • Drag: move_pointer_pixels_absolute has no drag guard (unlike move_pointer_absolute), so a held button stays down and drags with each follow move. Release still happens only through the existing cleanup paths. If a follow move fails, the runtime's existing execution_failed + cleanup path drops the radar and releases input, the same as a failed final move.
  • Pausing: no moves happen while paused or while a switch is held, because advance does not run then. Manual steps while paused still move the pointer, since they are explicit actions.
  • The pointer stays inside the radar's display (targets are clamped to the area), so set_mouse_area does not see a display change and end the radar mid-sweep.

Validation (Windows, Node 24, Rust 1.97.1)

  • npm run lint: pass
  • npm test: 13 files / 295 tests passed; node tests 12 passed, 0 failed
  • npm run build: pass
  • cargo fmt --check: pass
  • cargo clippy --all-targets -D warnings: pass
  • cargo test: 773 passed, 0 failed, 5 ignored (+7 passed in the second binary). That includes 20 radar tests, 2 of them new: scan_radar::...the_pointer_follows_the_centre_then_the_marker_only_when_it_moves and scan_executor::...radar_takes_the_fake_pointer_along_and_never_snaps_it_back.
  • The tests use only the Fake injector. They assert the exact sequence of fake moves:
    • the centre on area pick;
    • nothing while picking an area or during Angle ticks and steps;
    • nothing on Open Mouse step-back or cancel;
    • 12 px per tick and 20 px per step during Distance;
    • nothing while paused;
    • the final position on Select;
    • a held fake drag still active after the moves and released by cleanup.
  • npm run prediction-model was not run: it fails locally with an EPERM rename lock that is unrelated to this change. The gitignored src-tauri/resources/prediction-model, prediction-neural and src-tauri/binaries were copied from the main checkout to build.

Needs a real-device check

The pointer following the radar, a held drag, and scaled or negative-coordinate displays need checking on real Windows and macOS hardware (npm run macos:run for Accessibility).

Review- Independent review of 4dcbc3e found the code sound: no feedback loops from synthetic moves, drag released by every cleanup path, and tests use fake input only. Its one finding, a stale docs sentence, is fixed in 4376f3f. A second independent review of 4376f3f reported no actionable findings.- Extra real-device checks: the pointer briefly touches the display edge on each automatic distance pass, which may trigger hot corners or an auto-hidden taskbar or Dock. A held drag passing over folders may trigger spring-loaded folders.

🤖 Generated with Claude Code

OwenMcGirr and others added 2 commits October 13, 2026 17:48
Choosing an area takes the pointer to its centre, where it stays while
the beam turns. During the distance it follows the marker, at most once
a tick and only when the target pixel changes, using the same display
units as the final move. Back, cancel and the session ending leave it
where it is. The beam no longer draws its own tip marker under the pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps enaboapps added this to the v1.0.0-rc.26 milestone Oct 13, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps
enaboapps marked this pull request as ready for review October 13, 2026 17:02
@enaboapps
enaboapps merged commit 7afb8e8 into main Oct 13, 2026
6 checks passed
@enaboapps
enaboapps deleted the claude/1047-radar-cursor branch October 13, 2026 17:57
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.

Move the cursor with the radar

2 participants