login greeter
git clone https://git.lucas.co/cce-display-manager.git
refactor: hold widgets in Owned boxes (cce-ui Owned<W>)
The UiContext registry keeps raw pointers to registered widgets, and a
widget that moved while registered (its Vec reallocating, its struct
returned by value) left one pointing at the old address. Each widget
field is now an Owned<Adapted<..>> — a heap box whose allocation, not the
widget, carries the liveness token the registry watches — so the
registered address never moves and is dropped from the registry when the
box is freed. Field access is unchanged through Deref; construction
sites wrap in Owned::new.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/main.rs | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 8df41eb..9049c67 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+use cce_ui::widget::Owned;
use cce_ui::widget::{
Button, ContentBg, WidgetHost, ElementState, MouseButton, Key, NamedKey, KeyEvent, TextBox,
focus, MouseScrollDelta
@@ -310,13 +311,13 @@ impl cce_ui::widget::Input for SessionList {
// ── App State and Renderer ──
struct State {
- bg: cce_ui::widget::Adapted<ContentBg>,
- card: cce_ui::widget::Adapted<LoginCard>,
- username_box: cce_ui::widget::Adapted<TextBox>,
- password_box: cce_ui::widget::Adapted<TextBox>,
- login_btn: cce_ui::widget::Adapted<cce_ui::widget::Button>,
- status_lbl: cce_ui::widget::Adapted<StatusLabel>,
- session_list: cce_ui::widget::Adapted<SessionList>,
+ bg: Owned<cce_ui::widget::Adapted<ContentBg>>,
+ card: Owned<cce_ui::widget::Adapted<LoginCard>>,
+ username_box: Owned<cce_ui::widget::Adapted<TextBox>>,
+ password_box: Owned<cce_ui::widget::Adapted<TextBox>>,
+ login_btn: Owned<cce_ui::widget::Adapted<cce_ui::widget::Button>>,
+ status_lbl: Owned<cce_ui::widget::Adapted<StatusLabel>>,
+ session_list: Owned<cce_ui::widget::Adapted<SessionList>>,
ui_context: cce_ui::context::UiContext,
@@ -689,13 +690,13 @@ impl cce_ui::engine::Application for State {
session_list.selected_idx = selected_idx;
let mut app = Self {
- bg,
- card,
- username_box,
- password_box,
- login_btn,
- status_lbl,
- session_list,
+ bg: Owned::new(bg),
+ card: Owned::new(card),
+ username_box: Owned::new(username_box),
+ password_box: Owned::new(password_box),
+ login_btn: Owned::new(login_btn),
+ status_lbl: Owned::new(status_lbl),
+ session_list: Owned::new(session_list),
ui_context: cce_ui::context::UiContext::new(),
cursor_x: 0.0,
cursor_y: 0.0,