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

commit3e10670749be0a32e14db60ea45329e918b45283
parenteff3a43650
authorLucas Galante <[email protected]>
date2026-07-10 12:34
feat!: delete the global widget::popovers registry (Phase 6ae, legacy deletion part 1)

Write-only since the popup path went away in 6x: the engine's readers
(popup spawn trigger, PopupHandler::done unfocus sweep) are gone, so the
thread-local registry, render_widget's register() write, and layout.rs's
clear() are deleted; the four apps that still called clear() are updated in
their repos. UiContext::active_popovers (the per-frame registration that
drives the dl-text occlusion clamp and in-frame drawing) is unaffected.

Also corrects the RFC's legacy-deletion precondition map: six apps still
implement the view*/text_items path (test-interface, authenticator,
display-manager, email, layout-interface, status-interface) and must migrate
before those paths — and later Element + Adapted — can be carved.

Co-Authored-By: Claude Fable 5 <[email protected]>

 docs/rfc-core-rebuild.md | 28 +++++++++++++++++++++----
 src/layout.rs            |  2 --
 src/widget/core.rs       | 53 ------------------------------------------------
 src/widget/mod.rs        |  2 +-
 4 files changed, 25 insertions(+), 60 deletions(-)

diff --git a/docs/rfc-core-rebuild.md b/docs/rfc-core-rebuild.md
index f0897ae..8f74c8c 100644
--- a/docs/rfc-core-rebuild.md
+++ b/docs/rfc-core-rebuild.md
@@ -1222,10 +1222,30 @@ Constraint respected: **each crate still builds standalone** — the new core is
     footgun surfaced for the log: `Slider::set_value` takes the NORMALIZED
     0..1 value (`with_range` only scales `get_scaled_value`) — passing a
     ranged value silently clamps to 1.0.
-  - **Still to do:** the legacy deletion — the `view*`/`text_items` paths, the
-    per-widget text getters, the write-only global popovers registry, and
-    finally `Element` + `Adapted` (TreeList converting to narrow traits with
-    it).
+  - **6ae — legacy deletion, part 1: the global `widget::popovers` registry is
+    DELETED. DONE (write-only since 6x; the mod, its `render_widget` write, and
+    the four apps' `clear()` calls are gone; settings' popover renders
+    byte-identically after).** Part 1 also produced a CORRECTED precondition
+    map for the rest of the deletion — the endgame list had been assuming "the
+    last app is across," and it is not:
+    - The `view*`/`text_items` paths CANNOT be deleted yet: SIX apps still
+      implement them — cce-test-interface (2.1k), cce-authenticator (0.9k),
+      cce-display-manager (1.5k), cce-email (2.5k), cce-layout-interface
+      (3.8k), cce-status-interface (4.2k). Each needs its own Phase-6-style
+      migration (display-list flip at minimum; dissolutions as found).
+      Suggested order: smallest/least-critical first (test-interface,
+      authenticator — NOTE it may be the lock screen, verify carefully),
+      status-interface last (layer-shell, always-running).
+    - The per-widget text getters are additionally load-bearing for the walk's
+      legacy branches (`renders_own_subtree`, container `text_labels`
+      aggregation) and the migrated apps' hand-rolled window aggregates
+      (settings' `collect_window_child`, files' assembly) — they go when those
+      consumers move to `paint_self`-only trees.
+    - `Element` + `Adapted` go last, after both of the above; TreeList
+      converts to narrow traits then.
+  - **Still to do:** migrate the six legacy-path apps (above), then delete
+    `view*`/`text_items` + the backend tuple-wrapping path, then the per-widget
+    text getters, then `Element` + `Adapted`.
 
 Order rationale: each phase is independently valuable and reversible, and no phase requires the
 next to compile. Phase 0 can land immediately regardless of the rest.
diff --git a/src/layout.rs b/src/layout.rs
index 5c0b832..62044bc 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -3358,7 +3358,6 @@ pub fn render_widget<T: Element + 'static>(pc: &mut dyn RenderTarget, w: &mut T,
     }
     if w.popover_rect().is_some() {
         ctx.register_popover(w);
-        crate::widget::popovers::register(w);
     }
 }
 
@@ -3434,7 +3433,6 @@ impl UiFrame {
     pub fn start(scroll_offset: f32) -> Self {
         crate::widget::hover_animation::reset_frame_registration();
         crate::widget::hover_animation::set_scroll_offset(scroll_offset);
-        crate::widget::popovers::clear();
         Self
     }
 
diff --git a/src/widget/core.rs b/src/widget/core.rs
index ab63a0d..9444f0a 100644
--- a/src/widget/core.rs
+++ b/src/widget/core.rs
@@ -153,59 +153,6 @@ pub mod focus {
     }
 }
 
-pub mod popovers {
-    use super:: Element;
-    use std::cell::RefCell;
-
-    thread_local! {
-        static ACTIVE_POPOVERS: RefCell<Vec<*const (dyn Element + 'static)>> = RefCell::new(Vec::new());
-    }
-
-    pub fn clear() {
-        ACTIVE_POPOVERS.with(|list| {
-            list.borrow_mut().clear();
-        });
-    }
-
-    pub fn register(w: &(dyn Element + 'static)) {
-        ACTIVE_POPOVERS.with(|list| {
-            let ptr = w as *const (dyn Element + 'static);
-            let mut list = list.borrow_mut();
-            if !list.contains(&ptr) {
-                list.push(ptr);
-            }
-        });
-    }
-
-    pub fn get_active() -> Vec<*const (dyn Element + 'static)> {
-        ACTIVE_POPOVERS.with(|list| {
-            list.borrow().clone()
-        })
-    }
-
-    pub fn is_coordinate_covered(query_address: usize, px: f32, py: f32) -> bool {
-        ACTIVE_POPOVERS.with(|list| {
-            let list = list.borrow();
-            for popover_ptr in list.iter() {
-                let current_data = *popover_ptr as *const () as usize;
-                if query_address == current_data {
-                    continue;
-                }
-                unsafe {
-                    if let Some(popover) = popover_ptr.as_ref() {
-                        if let Some((x, y, width, height)) = popover.popover_rect() {
-                            if px >= x && px <= x + width && py >= y && py <= y + height {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-            false
-        })
-    }
-}
-
 pub mod hover_animation {
     use std::cell::RefCell;
 
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 7876a23..47043ff 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -829,7 +829,7 @@ pub mod model;
 pub use self::editor::TextEditorState;
 pub use self::layout_helper::{ColumnLayout, RowLayout};
 pub use self::model::{Adapted, EventCtx, Input, Layout, Paint};
-pub use self::core::{Widget, focus, hover_animation, popovers, clipboard, context_menu, clear_widget_references};
+pub use self::core::{Widget, focus, hover_animation, clipboard, context_menu, clear_widget_references};
 pub use self::core::focus::link_parent_child;
 pub use self::input::{
     Button, TextBox, Spinbox, Dropdown, Checkbox, Toggle, Slider, RangeSlider,