Skip to content

Repeat navigation keys chosen on the scanned keyboard - #1004

Merged
enaboapps merged 2 commits into
mainfrom
claude/scanned-key-repeat
Oct 9, 2026
Merged

enaboapps merged 2 commits into
mainfrom
claude/scanned-key-repeat

Conversation

@enaboapps

Copy link
Copy Markdown
Contributor

Closes #1003

What

  • Settings → Input → Repeat keys on the scanned keyboard (off by default). When it is on, choosing Backspace, Delete, an arrow key, Tab, Page Up or Page Down on the scanned keyboard types the key straight away. The key then repeats at the existing key repeat delay and interval until a switch press stops it.
  • The stop works like Mouse moving. It happens on press or on release, as chosen under Mouse → Stop repeating, and the stop press does nothing else. The panel reads "Repeating Backspace · Press and release a switch to stop", and the Scanning page shows a keyboardRepeating phase.
  • Text, Space, Enter, modifiers, Home, End, Escape and the F keys never repeat.
  • The repeat starts only after the first press has been typed. Each of these ends it: a failed key, pausing, another window coming to the front, turning the setting off or changing its timing, any action reaching the workflow, a mode change, a config restart, or stopping scanning. Every repeated press goes through the normal scanned-keyboard path, which releases the key right after typing it, so nothing stays held.

Sync

The setting syncs between computers, so the portable settings document moves to schema version 2:

  • Version 1 documents are upgraded on read, with the setting off. A version 1 document that already contains the field is rejected.
  • A version 2 document must contain the field, because the strict round trip still applies.
  • A merge base saved by an older build still deserializes, through #[serde(default)]. The install id and base are not lost.
  • Older desktops that read a version 2 document report "update required" and do not overwrite it. That is the existing Newer path.

Validation

  • npm run prediction-model, npm run lint, npm test (291 vitest + node tests), npm run build
  • cargo fmt --check, cargo clippy --all-targets -D warnings, cargo test (715 lib tests)
  • New tests:
    • The repeat cadence: the first press is immediate, the next comes after the delay, then one per interval, with no burst after a stalled tick.
    • Both stop edges, for local and forwarded switches, through RepeatStop.
    • Every repeatable key repeats; keys that should not repeat don't; setting off; a first press that fails.
    • Every ending listed above.
    • The v1 upgrade and rejections, and loading an old merge base.
    • The UI toggle and the phase text.

🤖 Generated with Claude Code

A new Input setting, off by default, makes Backspace, Delete, the arrow
keys, Tab, Page Up and Page Down repeat after they are chosen on the
scanned keyboard, at the existing key repeat delay and interval, until a
switch stops them. The stop works like Mouse moving: on press or release
as chosen under Mouse, and the stop press does nothing else.

The repeat starts only once the first press has been typed. A failed
key, pausing, another window in front, a settings change, a mode change
or stopping scanning ends it. Each press is released as it is typed.

The setting syncs, so the settings document moves to version 2.
Version 1 documents read with the setting off, and a merge base saved
by an older build still loads.

Closes #1003

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps enaboapps added this to the v1.0.0-rc.22 milestone Oct 9, 2026
- A merge base saved by version 1 is read as this version, so updating
  uploads nothing until a setting changes and older computers keep
  syncing.
- The scanning phase is published when settling the environment or
  dispatching ends a repeat, not only when a tick changes it.
- Alt and Windows/Command shortcuts never repeat; Shift and Ctrl repeat
  with the key and are named in the prompt.
- The Input note points at the shared timing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@enaboapps
enaboapps marked this pull request as ready for review October 9, 2026 16:02
@greptile-apps

greptile-apps Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] No blocking merge issue was established in the checked behavior; complete native application execution remains unverified because a required system library is unavailable.

T-Rex evidence

Executed fake-input repeat validation runner

  • The executed runner extracts revision-specific production bodies, generates narrow assertions, and captures commands and exit codes without editing production source.

Native repeat test attempt with missing GDK

  • The bounded Cargo test attempt failed because pkg-config could not find gdk-3.0, establishing the native execution limit.

Persistence validation command script

  • The executed script extracts source from the exact base and head commits, captures the native blocker, and runs isolated Rust checks without modifying repository source.

Native test output with missing GDK

  • The narrow existing portable-settings test command exited 101 because pkg-config could not find GDK, so native test coverage remains blocked.

Before: Keyboard Repeat 01 Poster

  • What the screen looked like at this point in the check.

Before: Keyboard Repeat 01 Press

  • What the screen looked like at this point in the check.

Before: Keyboard Repeat 01 Release

  • What the screen looked like at this point in the check.

▶ keyboard-repeat-01-before.webm

  • The flow T-Rex ran, recorded end to end.

After: Keyboard Repeat 02 Poster

  • What the screen looked like at this point in the check.

After: Keyboard Repeat 02 Press

  • What the screen looked like at this point in the check.

After: Keyboard Repeat 02 Release

  • What the screen looked like at this point in the check.

▶ keyboard-repeat-02-after.webm

  • The flow T-Rex ran, recorded end to end.

Evidence from the check

  • The executed runner extracts revision-specific production bodies, generates narrow assertions, and captures commands and exit codes without editing production source.

Command output from the check

  • The bounded Cargo test attempt failed because pkg-config could not find gdk-3.0, establishing the native execution limit.

Evidence from the check

  • The generated baseline Rust executable contains extracted production workflow and input bodies plus assertions, making the baseline run reproducible.

Command output from the check

  • The baseline executable typed and released each navigation key once and observed no repeat over 3000ms, confirming the pre-change behavior.

Evidence from the check

  • The generated head Rust executable contains actual changed workflow bodies and the runtime stop gate with narrow assertions, making the head checks reproducible.

Command output from the check

  • The head executable passed cancellation, stop-switch consumption, cadence, modifier, and failure-cleanup assertions, clearing the hypothesis within the tested scope.

Evidence from the check

  • The executed script extracts source from the exact base and head commits, captures the native blocker, and runs isolated Rust checks without modifying repository source.

Evidence from the check

  • The executed Rust assertions test old saved settings, file-backed merge bases, upgrade writes, and malformed/newer document guards, with harness limitations explicitly identified.

Command output from the check

  • The narrow existing portable-settings test command exited 101 because pkg-config could not find GDK, so native test coverage remains blocked.

Evidence from the check

  • This generated compilation unit contains base persistence source slices and the authored harness, making the passing before run inspectable.

Command output from the check

  • The base revision passed the file persistence and remote-write guard assertions, establishing the comparison baseline.

Evidence from the check

  • This generated compilation unit contains head persistence source slices and the authored harness, making the passing upgrade run inspectable.

Command output from the check

  • The head revision passed upgrade, saved-identity, file-reread, and remote-write guard assertions, with no scoped regression reproduced.

Command output from the check

  • The final script invocation exited 0 and captured both executed Rust test runs, confirming the uploaded source and assertions ran successfully.

Evidence from the check

  • Runs the Chromium comparison and narrow settings test while capturing commands and exit codes, making the execution reproducible.

Evidence from the check

  • Serves base and head source and asserts toggle, timing, and phase behavior while recording both runs, providing executable verification.

Evidence from the check

  • Renders actual InputSection and ScanningSection components with fake settings and runtime state, isolating the requested UI behavior.

Evidence from the check

  • Loads the uploaded React harness in Chromium, supplying the entry point used for both comparisons.

▶ Recording of the check

  • Records base settings with held repeat off and press/release repeating-state fixtures, showing the independent toggle and phase support were absent.

▶ Recording of the check

  • Records scanned-only repeat with edited timing and both repeating stop instructions on head, showing the scoped behavior works.

Before: Input settings with held repeat off

  • Captures base Input settings after opening More options, documenting the comparison's initial disabled timing state.

After: scanned-only repeat with editable shared timing

  • Captures head after enabling scanned repeat and changing timing while held repeat stays off, documenting successful independent enablement.

Before: injected keyboardRepeating state with press stop

  • Captures the base component with the new repeating phase and press edge, documenting the unsupported phase baseline.

Before: injected keyboardRepeating state with release stop

  • Captures the base component with the new repeating phase and release edge, documenting the unsupported phase baseline.

After: keyboardRepeating status with press stop

  • Captures head with runtime press stop and an opposing draft setting, documenting the asserted press instruction.

After: keyboardRepeating status with release stop

  • Captures head with runtime release stop and an opposing draft setting, documenting the asserted press-and-release instruction.

Command output from the check

  • Contains the actual command, exit code, settings values, and base/head status observations, confirming all browser assertions passed.

Command output from the check

  • Contains the executed Vitest command and result for the relevant repeat-settings test, confirming one test passed.

View artifacts

Summary

Adds optional repeating navigation keys to the scanned keyboard, using the existing key delay and interval.

  • Selected navigation keys repeat on the scanned keyboard until a switch stops them.
  • Portable settings carry scanned-keyboard repeat in schema version 2.

No actionable issues were found. No blocking merge issue was established in the checked behavior.

T-Rex validation blocked

Full native tests could not run because the environment lacks gdk-3.0 >= 3.22. The isolated Rust checks do not establish complete native event-loop or platform input behavior.

Reviews (1) · Last reviewed commit: "Address review: sync upgrade, stale phas..." · Reviewed by Greptile

@enaboapps
enaboapps merged commit a36680e into main Oct 9, 2026
7 checks passed
@enaboapps
enaboapps deleted the claude/scanned-key-repeat branch October 9, 2026 17:37
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.

Repeat Backspace, Delete, arrows and other navigation keys on the scanned keyboard

2 participants