Skip to content

feat(text-editing): E6 — lifecycle + placeholder + auto-scroll + TextInput + closure (campaign complete)#67

Merged
intendednull merged 1 commit into
mainfrom
text-editing-e6
Jun 16, 2026
Merged

feat(text-editing): E6 — lifecycle + placeholder + auto-scroll + TextInput + closure (campaign complete)#67
intendednull merged 1 commit into
mainfrom
text-editing-e6

Conversation

@intendednull

Copy link
Copy Markdown
Owner

Final phase of the text-editing campaign (E1–E6). Completes the F-tier editor surface and closes the campaign. Headless + one additive GPU golden.

What lands

  • Focus lifecycle (text/edit/lifecycle.rs): a Local transition detector. On blur: seals the undo group + removes the active preedit (the E5-deferred removal, with the dirty-mark) + retains selection (web parity). Caret visibility is reworked — write_caret_blink becomes the single focus-aware owner (a non-FocusedEntity editor caret is steady-hidden; also fixes a latent blurred-caret-blink bug); bare-CaretVisual paths keep the global phase so the E3/E5 goldens are unaffected.
  • Placeholder (text/edit/placeholder.rs): a separate display-only PlaceholderBuffer, shaped under the lock by sync_placeholder, shown when value().is_empty() && !has_preedit(). Paints as a SEPARATE additive branch — the §3.2 extract tripwire stays on the editor buffer only.
  • Auto-scroll (text/edit/scroll.rs): pans ScrollOffset to keep the caret in the clip viewport (x single-line / y multi-line), clamping against ResolvedLayout.size.
  • EditSubmitted (single-line Enter) — finalizes the § 11 taxonomy; an audit test pins all nine Messages.
  • buiy_widgets::TextInput::{single_line,multi_line} — an impl Bundle (the Button::new precedent) over TextEditState (via the new cosmic-free for_font_size) + markers + focus; focus_on_click is widget-side.

Two majors caught in review + fixed before coding (caret-visibility ownership; the placeholder being shaped by nobody / §3.2 tripwire), two more in-driver.

Campaign closure (docs)

The editing spec is flipped from design-only to implemented (editing, E1–E6); six "As landed (E_n)" errata folded (E1 intrinsics-cache, E4 empty-Change, E5 ime_position Vec2, E6 Edges Length / A11yRole::Text / lock-free set_text); spec README, docs/README.md, and follow-ups.md updated.

Gate

Headless 1010 / 0 / 57; GPU lane (RX 6700 XT) 8 / 0 incl. the new placeholder_paints_when_empty_and_ink_when_typed golden. fmt/clippy/doc clean.

This PR completes the text-editing campaign — the F-tier editor surface of foundation text.md § 3.5 is delivered (E1–E6).

Plan: docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md · Campaign: docs/plans/2026-06-13-buiy-text-editing-campaign.md

🤖 Generated with Claude Code

…Input + closure

Final phase of the text-editing campaign (E1–E6). Completes the F-tier editor
surface: focus lifecycle, placeholder rendering, auto-scroll, the host-facing
`EditSubmitted` Message, the `buiy_widgets::TextInput` widget bundle — and the
campaign closure (errata fold + spec status flip). Headless + one additive GPU
golden.

What lands:
- **Focus lifecycle** (`text/edit/lifecycle.rs`): a `Local`-based transition
  detector. On blur, `focus_lifecycle` seals the open undo group and removes
  the active preedit (the E5-deferred focus-loss removal, with the
  `invalidate_intrinsics` + Taffy dirty-mark so the orphaned preedit glyphs
  don't persist a frame), while RETAINING the selection (web parity). Caret
  visibility is NOT written here — `write_caret_blink` is reworked into the
  single focus-aware owner: an editor caret that is not the `FocusedEntity` is
  forced steady-hidden (this also fixes the latent pre-E6 bug that a blurred
  caret kept blinking); the bare-`CaretVisual`/no-focus-resource paths keep the
  global phase, so the E3/E5 goldens are unaffected.
- **Placeholder** (`text/edit/placeholder.rs`): a separate display-only
  `PlaceholderBuffer`, shaped under the `SharedFontSystem` lock by
  `sync_placeholder` (it has no downstream shaper, unlike the editor buffer),
  shown when `value().is_empty() && !has_preedit()` in the
  `color.text.placeholder` token. It paints as a SEPARATE additive branch in
  the glyph producer — the §3.2 extract tripwire stays on the editor buffer
  only (the placeholder is not part of the editor's `ComputedTextLayout`).
- **Auto-scroll** (`text/edit/scroll.rs`): a pure `clamp_into_view` + a system
  that pans the layout `ScrollOffset` (x single-line / y multi-line) to keep
  the caret in the clip viewport after each move/edit; clamps against
  `ResolvedLayout.size`.
- **`EditSubmitted`** Message (single-line Enter) — finalizing the § 11
  taxonomy; an audit test pins all nine Messages registered.
- **`buiy_widgets::TextInput::{single_line,multi_line}`** — an `impl Bundle`
  (the `Button::new` precedent) composing the core `TextEditState` (built via
  the new `TextEditState::for_font_size`, which keeps `cosmic_text::Metrics`
  out of `buiy_widgets`) + markers + focus; `focus_on_click` is widget-side
  policy (core never auto-focuses).

Two majors caught in review + fixed before coding (the caret-visibility
ownership collision; the placeholder buffer being shaped by nobody / the §3.2
tripwire) and two more in-driver (the placeholder damage-gate; the GPU golden's
ink assertion).

Campaign closure (docs): the editing spec is flipped from design-only to
**implemented (editing, E1–E6)**; six "As landed (E_n)" errata folded
(E1 intrinsics-cache relocation, E4 empty-`Change` drop, E5 `ime_position`
is `Vec2`, E6 `Edges` are `Length` / `A11yRole::Text` / lock-free `set_text`);
the spec README, `docs/README.md`, and `follow-ups.md` (the named deferrals)
updated.

Gate: headless 1010 / 0 / 57; GPU lane (RX 6700 XT) 8 / 0 incl. the new
`placeholder_paints_when_empty_and_ink_when_typed` golden.

**This completes the text-editing campaign — the F-tier editor surface of
foundation text.md § 3.5 is delivered (E1–E6).**

Plan: docs/plans/2026-06-13-buiy-text-editing-e6-lifecycle-widget-closure.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@intendednull intendednull merged commit a9ccd04 into main Jun 16, 2026
6 checks passed
@intendednull intendednull deleted the text-editing-e6 branch June 16, 2026 05:11
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