Skip to content

Give the search field a real caret and selection - #68

Open
ak127a wants to merge 1 commit into
typecraft-dev:mainfrom
ak127a:fix/search-field-selection
Open

ak127a wants to merge 1 commit into
typecraft-dev:mainfrom
ak127a:fix/search-field-selection

Conversation

@ak127a

@ak127a ak127a commented Nov 3, 2026

Copy link
Copy Markdown

Problem

The search field was a plain Text element with a hand-drawn fake caret. handleKey() appended characters or sliced them off the end of the string, so the field had no caret model and no selection at all:

  • Shift+←/→, Ctrl+Shift+←/→ (select word) and mouse selection did nothing
  • Ctrl+←/→ word motions, Home/End, Ctrl+A, Ctrl+C/X and IME did nothing
  • Paste always appended to the end instead of inserting at the caret

Fix

ui/LauncherWindow.qml

  • The query is now a real TextInput, focused whenever the launcher opens. Qt owns the caret, selection, mouse editing and IME:
    • ←/→, Ctrl+←/→, Home/End
    • Shift and Ctrl+Shift selection, Ctrl+A / Ctrl+C / Ctrl+X / Ctrl+V
    • drag and double-click selection (selectByMouse)
  • omacast's own keys are still handled first via Keys.onPressed on the input (list navigation, action panel, Enter, popups, Ctrl+U); everything else falls through to Qt.
  • Existing look preserved: accent-coloured blinking caret bound to cursorRectangle, same placeholder/font/colors, and the field is clipped while scrolling so a long query no longer paints over the back arrow.
  • Paste inserts at the caret and replaces the selection. Programmatic query changes (history, push/pop, Esc) put the caret at the end and clear the selection.
  • Ctrl+Backspace / Ctrl+Delete word deletion kept (Qt Quick's TextInput doesn't implement it consistently).
  • Backspace on an empty submenu query still pops back, and the alias view still blocks spaces.

core/TextCursor.js (new) — word bounds and deletion ranges for Ctrl+Backspace / Ctrl+Delete, with unit tests in tests/textcursor.test.js.

tests/launcher-paste.test.js — harness extended with a TextInput stand-in; new coverage for paste-at-caret/replace-selection and word deletion.

CLAUDE.md — status note for the field behaviour.

No backend, IPC or contract changes.

Testing

  • node --test tests/*.test.js: 146 pass, 0 fail, 3 skipped in a fresh clone. The skips are the native-search helper (built by CI via bin/build-search) and the two environment-dependent tests.
  • omarchy plugin validate . passes.
  • Verified live on Omarchy/Quickshell with synthesized keys: Ctrl+Shift+← selects a word and typing replaces it; Shift+← and Ctrl+← move/select correctly; Ctrl+A/C/X/V work; Ctrl+Backspace deletes a word; long queries scroll and clip correctly; placeholder, ↑/↓ list navigation, Ctrl+K action panel, Enter/menu push and Backspace-on-empty-submenu pop all still work.

The query was a Text with a hand-drawn fake caret: every key was appended
or removed at the end of the string, so Shift/Ctrl+arrows, selection, word
motions, IME input and paste-at-caret had nothing to act on.

Use a TextInput for the field and let Qt own the caret, selection and
keyboard editing. omacast's own keys (list navigation, popups, Enter,
Ctrl+U) are still handled first. Add core/TextCursor.js for the
Ctrl+Backspace / Ctrl+Delete word bounds, make paste insert at the caret
and replace the selection, and extend the launcher tests.
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