Skip to content

Share modal editing through native TextArea owners - #134

Merged
trissim merged 12 commits into
mainfrom
feat/native-modal-editing
Oct 16, 2026
Merged

trissim merged 12 commits into
mainfrom
feat/native-modal-editing

Conversation

@trissim

@trissim trissim commented Oct 15, 2026 •

Copy link
Copy Markdown

Shared native modal editing and visible-target activation

Merged, installed by Codex, and verified through real Toad: Textual main 2d3aecb5106db6e0048d8b8ec21a9837f6d7f64b / Toad main e8716b963a02f0844d4696ed6d5eb6e35b3a9dbf, pinning reviewed Textual 18f4e7a67403d56846ef5abf55c93e3e0639be33.

Installed acceptance (10603)

Normal ~/.local/bin/toad, plain st/:278, installed e871/Core2209/native6468, no source overlay or model input/new participant. Menu reopening captured 2→0→2→0→2 with 250 ms Escape/f gaps. Hint a invoked the original export-dialog effect. With two dialog hints still visible, clicking the path Input retired hints and retained Input focus through a later settled capture. Hint s cancelled the dialog without export. The prior rapid-reopen and active-hint click coverage gaps are closed by this actual installed path.

Native Visual word motions/copy yielded beta in the real isolated clipboard. Native Home/Shift+End and Ctrl+C copied alpha beta gamma while preserving the draft. Edit/undo and Ctrl+U/D history navigation, G/latest and i/editor worked. Own original empty draft restored; frontend, ACP, pool and isolated display closed, native participant retained. Evidence and exact caveats: paired checkout .artifacts/vim/live-installed-e871-normal/OWNER and named screenshots/clipboard files. No automated tests, performance result, forced scheduler interleaving, full Vim or exhaustive IME/modal claim. Initial inherited-PATH launch failure and mistaken Ctrl+A/Home assumption remain recorded, not hidden.

Single-owner hint repair (10285)

Screen now composes HintHost through C3. Native direct children replace _hint_session; labels own their target mapping instead of keeping targets/choices copies. The existing Activation owns exposed-paint decoding, removed from Widget. The compositor still owns published geometry. No counter-driven relocation of that geometry work.

The old focus comment was wrong: Widget.focus() queues work. Restoring through native Screen.set_focus() now happens before pointer dispatch, without a deferred focus overwrite. HintHost supplies the three lifecycle/action methods, and the existing Workspace super hook reaches it.

Shepherd reviewed the repair at 10382. Paired source queries owner-repair-{before,after}.txt cover 283 Toad / 254 Textual modules with no parse omissions. Source imports and the actual MRO work. Both original receiving commands still exit 1 under the installed heuristic checker; their results are retained, not hidden. Slop-census owns that correction; no thresholds or file exemptions changed.

The plain-st/:278 source preview showed hints, Settings opening and returning without stale labels, reopening with one label set, and prompt focus surviving a click. No model input or installation. Physical screenshots and bounded observations are in the paired checkout's .artifacts/vim/live-owner-repair/; this does not force the click/late-callback race or establish the normal-launcher result. Initial remote read-only observations stopped when instructed; later checks used keys/pointer and screenshots only. Native ESC delay is 100 ms, so the separated-key run—not the earlier 40/80 ms Escape/f sequences—demonstrates reopening.

Earlier implementation and verification

Paired with OpenHCSDev/toad#664. Native source head 9a18a0f0fe41a2d5edde25f9e2371de1c3877559; Toad integration head 8c264fb0478354def9089ff8234eaef0f4cec79f pins it exactly and normally merges main/#668; broad editor checks used 4a374eb89dd63c1b072394945ae864dad35d2d93; latest-pair modal retirement was physically verified as described below. The #668 merge has static/import preservation checks, not archive acceptance. The size-review gate is deleted. Per 10261, Codex merges and installs this Vim pair FIRST, before Forms #135 / Toad Textualize#670. Source review of this pair is closed; installed normal-launcher behavior remains unverified.

Owners and deleted competing paths

  • One TextArea.editing_mode capability uses the existing native document/selection/EditHistory. TextAreaState transfers settled mode with those original objects; no second editor, document or undo store.
  • Mode/command declarations own counts, motions, operators and pending operands. Base VimMode owns command checkpoints; subclasses specialize commands. Native editing helpers enforce accepts-text/read-only admission, so Normal cannot mutate through ordinary bindings.
  • Mode-owned selection_range drives paint, selected text and Visual operators, including pending Visual operands. Cursor paint remains at the real cursor. Replaced selection interpretations and incomplete undo boundaries were removed.
  • DocumentNavigator owns existing Ctrl-word and nominal Vim endpoints; duplicate TextArea regex/navigation bodies were deleted. Counted traversal consumes required matches in one pass, not repeated prefix scans. This is a source-cost observation, not measured frame performance.
  • App owns typed characterwise/linewise clipboard content with a plain-text facade and publication transport hook. Equal bytes do not establish provenance. Modal p/P uses the retained typed register; fresh external paste is characterwise. No observed-text compatibility branch or transport mirror.
  • PrimaryActivation exposes original widget effects; StyleTarget borrows the existing decoded style action. HandlerArguments decodes once for pointer/hint dispatch. No synthetic clicks or activation registry.
  • Compositor discovery uses bounded exposed published geometry/paint ancestry. Activation.available owns discovery admission and later revalidation, including native inherited is_disabled, display ancestry, attachment, visibility, current screen and hit/style ownership. The competing local disabled prefilter was deleted from Widget.
  • Screen owns hint publication/retirement. Labels activate only on a complete prefix. Retirement runs on the surviving Screen rather than the removed session.
  • App's Escape path respects focused-ancestor key custody. The original legacy ANSI decoder now preserves Alt on control tuples, matching canonical alt+ctrl+x.

Source evidence

Existing refactor-audit Package census before: 282 Toad / 250 Textual modules; final: 283 / 254, zero parse omissions. .artifacts/vim/owners-final.txt in the paired Toad checkout records imports, inheritance, declarations, writes and consumers; earlier selection/activation/pending/clipboard family evidence is retained alongside it. Computed callbacks and generic action attributes remain dynamic; AST is not behavioral proof.

Actual owner search: rg -n 'editing_mode:|_word_pattern|class (ClipboardContent|LinewiseClipboard)' src/textual finds one active reactive mode declaration plus its retained transfer field, the navigator-owned regex, and typed clipboard declarations. No mode mirror in Toad.

Physical source-candidate checks

Actual Toad source candidate, plain st on isolated display :278, saved-history fork, configured native provider. Not installed-PATH acceptance.

  • Native submission returned actual VIM9142; Normal Enter retained the unsent draft. Active f/r pending cancellation confirmed and cancelled; g was queued cancellation only.
  • Inclusive Visual paint/replace/undo, command undo boundaries, retained draft/Normal mode/undo across comms tab return, native selected-text Ctrl+C, committed Unicode and typed clipboard provenance exercised.
  • Global/style/menu hints and native modal Cancel activated original effects. Resize dismissed hints. Latest shared availability admitted visible controls and excluded disabled history controls.
  • With ShellTerminal focus confirmed, f/j/k/g reached the real local stdin process and its output, not the hint/navigation dispatcher. Popup Enter/Escape and image paste were also exercised in prior candidates.
  • Ordinary-profile literal navigation keys and clearing exercised with opt-in disabled.

Evidence in paired Toad .artifacts/vim/live-{native,ranges,latest,ordinary,final-controls}/. All original/uncertain histories retained; failed exploratory inputs/captures are explicitly recorded in the Toad PR.

Earlier mount-pointer correction (9292, replaced above)

Native mount registers synchronously; Screen records the session before awaiting completion. The continuation focuses only its still-owned, non-disabled session on App.screen. Screen.is_current denotes drawn backdrops too, so App.screen supplies active identity. Existing Screen suspension and retirement remain the lifecycle; no new flag.

Latest exact source pair physically exercised with an existing running participant, no new model input: one focused session / 46 labels before Settings; Workspace custody null with zero sessions and labels during the modal and after return. Focus did not return to stale hints. Actual snapshots/screenshots: paired Toad .artifacts/vim/live-hint-custody-final/; source census hint-custody-{before,after}.txt has zero parse omissions (283/254 modules). This verifies modal return, not a forced await/suspend interleaving. No installed-PATH acceptance claim.

Delivery order (10261)

This native head and Toad Textualize#664 8c264fb0478354def9089ff8234eaef0f4cec79f go first. The earlier instruction to wait for Forms is superseded; its unfinished changes remain with their owner.

Codex owns merging current main normally, preserving the current application/Core/schema changes, and building the resulting exact pair into a new output path. The earlier uncertain attempt remains preserved and abandoned, not replayed. No provider input is authorized for replay.

The normal launcher still needs the paired editing, clipboard, modal-hint, popup/terminal, cancellation and tab-return journey. The earlier source previews above do not establish that installed result.

Delivery boundary

No automated tests, fake response, fixture, synthetic app, build or install by this worker. Codex owns integration and installed normal-launcher acceptance. No measured performance, IME preedit, full Vim, oldest-source gg, arbitrary native-control hints, or exhaustive stale-target/stream/retirement acceptance claim. Existing native-form #135 work is separate; its owner confirmed no activation/admission overlap.

@trissim
trissim marked this pull request as ready for review October 16, 2026 01:16
Copilot AI balanced review requested due to automatic review settings October 16, 2026 01:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@trissim
trissim merged commit 2d3aecb into main Oct 16, 2026
@trissim
trissim deleted the feat/native-modal-editing branch October 17, 2026 20:52
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