Skip to content

fix(windows): harden cursor context and target capture - #1163

Closed
HKLHaoBin wants to merge 7 commits into
Open-Less:betafrom
HKLHaoBin:HKLHaoBin/fix-pr-1137-review
Closed

HKLHaoBin wants to merge 7 commits into
Open-Less:betafrom
HKLHaoBin:HKLHaoBin/fix-pr-1137-review

Conversation

@HKLHaoBin

Copy link
Copy Markdown
Collaborator

Summary

  • Pair the frozen insertion target with its host-context adapter across asynchronous dictation.
  • Harden Windows UI Automation range reads with bounded over-fetching, strict movement validation, UTF-16 decoding, focus fences, and fail-closed security gates.
  • Fix cursor-window budget edge cases, SendInput inter-write pacing, mobile compilation stubs, logging privacy, and macOS frontmost-app snapshot consistency.

Validation

  • cargo test --manifest-path openless-all/app/crates/openless-core/Cargo.toml --test dictation_target_capture
  • cargo test --manifest-path openless-all/app/crates/openless-core/Cargo.toml host_document::window
  • cargo check --manifest-path openless-all/app/src-tauri/Cargo.toml
  • cargo fmt --manifest-path openless-all/app/src-tauri/Cargo.toml -- --check
  • git diff --check
  • review-bugbot: no bugs found

This branch contains the reviewed implementation of the Windows cursor-context feature and its follow-up fixes for #1137.

🤖 Generated with Claude Code

DepengWang and others added 7 commits October 2, 2026 18:55
Adds a Windows UI Automation implementation of read_around_cursor, reusing
the existing HostContextAdapter -> cursor_context_input() pipeline instead
of a parallel path. Prefers TextPattern2::GetCaretRange (active caret only),
falls back to TextPattern::GetSelection for collapsed selections only, and
never guesses a caret from ValuePattern. The text window is built by
expanding a Range from the caret (never reading the whole document), then
sliced to budget by Core's existing window_around_cursor/plan_window.

Gated by the same password-field (CurrentIsPassword) and process-blocklist
checks as the existing edit watcher, plus a focus-consistency recheck
before returning a result so an Alt+Tab mid-read can't mix two apps' text.
Runs on spawn_blocking with a 1s outer timeout; any failure degrades to
no context, never affects dictation.

Adds budget-split/redistribution/emoji-boundary tests to openless-core's
window.rs (previously untested) and a pure is_blocked_process_name helper
with tests in windows.rs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
Shows the Cursor context toggle on Windows as well as macOS (Linux still
has no implementation, so it stays hidden there). Updates the
cursorContextEnabled doc comment in types.ts and all 8 locale descriptions
to drop the "macOS only" wording and mention password fields/terminals are
excluded on both platforms.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
Updates the Cursor Context sections in README.md and README.zh.md to
cover Windows: TextPattern2 caret-range priority, TextPattern selection
fallback, and the "skip rather than guess" rule when the caret can't be
reliably located. Password-field exclusion wording now also mentions the
Windows UIA password-control flag alongside macOS Secure Input.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
TauriHostContextAdapter::capture previously logged nothing on success —
only debug_read_cursor_context exercised the status/chars_before/
chars_after/elapsed_ms/app log line. Extends the same metadata-only log
(no document body, per design doc §18/§19) to every real dictation that
has cursor context enabled, so whether a capture actually happened is
visible from the normal log file without a devtools round-trip.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
Windows SendInput text injection sent characters within a chunk back to
back with zero delay, only pausing every 16 characters. Found while
testing cursor context (windowsInsertionMode=sendInput): dictating mixed
Chinese/English text dropped the leading character(s) of a Latin-script
word right after the CJK-to-ASCII transition, e.g. "open" arrived as
"pen" and "OpenLess" vanished entirely — well before the 16-char chunk
boundary, so the existing chunk-level pause never applied.

macOS already works around the same class of problem (its
INTER_KEYSTROKE_DELAY comment: "Chromium / Electron / Tauri themselves
drop characters when keyDown/keyUp have no delay"); Windows had no
equivalent. Adds a 1ms gap after every character, not just at chunk
boundaries — confirmed on hardware to stop the drops, with no
perceptible typing latency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
Confirmed on hardware: Chromium-based editors (VS Code) only keep their
accessibility tree's caret position in sync once they detect an active
accessibility client, so with default settings the position UI Automation
reads back can be stale even though the read itself succeeds. Setting
editor.accessibilitySupport to "on" (plus a window reload) fixed it.
Documents this in both READMEs so users don't mistake it for a bug.

Also adds a metadata-only diagnostic log (source pattern + requested vs.
actual Move distances, no document content) to host_document/windows.rs,
added while narrowing this down between VS Code/Chrome — kept because it
is cheap, useful for future reports of "wrong context" on a given app,
and fully compliant with the no-document-body logging rule.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011h9QUkoFtCoDLsJjRDB6dX
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@HKLHaoBin

Copy link
Copy Markdown
Collaborator Author

Superseded by the direct update to #1137; the reviewed fixes now live on the original PR head branch.

@HKLHaoBin HKLHaoBin closed this Oct 8, 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.

2 participants