git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commitf5fdb0897307eb57caa48521eb3b511cb931e4dd
parent22bb8c6eec
authorLucas Galante <[email protected]>
date2026-07-09 00:28
docs(rfc): record Phase 5q — TextBox migrated

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011vTEhEwTGYYhHRbh658SAc

 docs/rfc-core-rebuild.md | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/docs/rfc-core-rebuild.md b/docs/rfc-core-rebuild.md
index ad798b5..abd9069 100644
--- a/docs/rfc-core-rebuild.md
+++ b/docs/rfc-core-rebuild.md
@@ -607,10 +607,38 @@ Constraint respected: **each crate still builds standalone** — the new core is
     text-editor, fonts, layout-interface, system-settings, data-editor, files,
     test-interface) — field types to `Adapted<Dropdown>`, raw casts to `.as_ptr_mut()`,
     two `&mut Dropdown` fn params in cce-files pages.
+  - **5q — `TextBox` (widest-surface leaf; the clipboard/selection tier). DONE (render-dump
+    + live-A/B verified, data-editor byte-identical).** New adapter surface: the `Input`
+    clipboard quintet (`cut_selection`/`copy_selection`/`paste_from_clipboard`/`select_all`/
+    `clear_text` — defaults replicate the whole-value `Element` defaults so earlier
+    migrations keep their shipped behavior), `Paint::prepare_text` (TextBox's glyph shaping
+    is load-bearing: `map_x_to_idx` reads the measured advances), `Layout::hit_row_rect`
+    (restores the legacy row-substituted, side-label-inset hit geometry — cce-files'
+    save-name box relies on row hits; earlier migrations' drop of it stands, opt-in),
+    `Layout::adjust_row_rect` + `Layout::rect_assigned` (the width/max-width clamp on both
+    rect paths; ungated scroll re-clamp on every `set_rect`), `Input::tracks_base_focus`
+    (legacy TextBox's `focus()` never set the base flag — its detached label must not color
+    as focused), and **`Paint::legacy_focus_highlight`**: the shared focus-highlight overlay
+    the adapter suppresses for every migrated widget is re-enabled per-widget — legacy
+    TextBox kept the `Element` default, and the focused editor's primary-tint wash
+    (data-editor's teal editing surface) is real legacy behavior. Found the honest way: the
+    first A/B came back 1.4M pixels apart; after restoring the overlay (replicated
+    byte-for-byte in `Adapted::highlight_quad` + the `all_quads`/`paint_self` inclusion
+    points), data-editor startup AND focused-editor states are **byte-identical (AE=0)**.
+    The asymmetric legacy render split is preserved (non-rounded `extra_quads`: full-width
+    background + disabled special-case; rounded `all_rounded_quads`: side-label inset, no
+    disabled branch). Flagged approximations: releases re-check plain-rect containment
+    (legacy hit-gated them through the row-substituted test); wheel is now hit-gated by the
+    adapter (legacy hosts dispatched it to the hovered widget themselves). Verified: 169
+    tests, workspace builds, settings fonts/processes dumps content-identical (processes
+    modulo live PID/CPU data), cce-data-editor live A/B byte-identical. Sweep: 9 app repos
+    (authenticator, data-editor, display-manager, email, files, fonts, layout-interface,
+    system-settings, text-editor) + 5 in-crate embedders (treelist, scrolling_list,
+    keybinds_control, multi_control's `InstancedWidget` variant, parameters_bg).
   - **Still to do:** migrate remaining widgets
     off `impl Element` onto the narrow traits (per-widget, Phase 6 flavour). Remaining:
     Paginator (embeds ButtonStrip + Vec<Page>), ParametersBg (real container, 1.8k lines),
-    and the deferred leaves (TextBox, StatusBar, Float3, LayoutPreview,
+    and the deferred leaves (StatusBar, Float3, LayoutPreview,
     PreviewState); the embedded-base containers
     (Layer/Container/Page/Plate/Backplate/ScrollBox/List/…) dissolve via Phase 6 scene
     adoption instead. Then delete `Element` + `Adapted` once the last widget is across, at