git.lucas.co / cce-authenticator
login authentication (PAM + fingerprint)
git clone https://git.lucas.co/cce-authenticator.git

commitb1387a37135fc4c7537e0c40e59f9adf7abf3034
parent629397c8a9
authorLucas Galante <[email protected]>
date2026-07-12 21:33
refactor: cce-authenticator on routed events (6bd shrink — the tail is done)

The flat dialog dispatch — background, password box, verify/cancel/
fingerprint buttons, and the single-target keyboard delivery — routes one
Event per root through ui_context.propagate_event. The unfocus-on-missed-
press rule and the take_click drains stay. No chains, no composites, no
drags: the simplest conversion of the set, and the last one.

Verified live A/B under CCE_AUTH_SIMULATE --standalone (the dialog stays up
in simulate, no 3s auto-exit as previously recorded): password-box focus
click byte-identical (AE=0); Cancel click closes the window in both builds
(0 windows after — the process lingers briefly in teardown, don't read
pgrep at +1s as a hang); static differs by one cursor sprite. Password
typing / Enter-verify / fingerprint flow: user spot-check.

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

 src/main.rs | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 453c12c..7a6cf20 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -523,32 +523,35 @@ impl Application for AuthenticatorApp {
     }
 
     fn handle_pointer_move(&mut self, pos: LogicalPosition, needs_rebuild: &mut bool) {
+        // Routed dispatch (6bd shrink): one Event per widget root through the router.
+        let mv = cce_ui::widget::Event::PointerMove { x: pos.x, y: pos.y, local_x: pos.x, local_y: pos.y };
         let ctx = &mut self.ui_context;
-        if self.bg.cursor_moved(pos.x, pos.y, ctx) { *needs_rebuild = true; }
-        if self.password_box.cursor_moved(pos.x, pos.y, ctx) { *needs_rebuild = true; }
-        if self.verify_btn.cursor_moved(pos.x, pos.y, ctx) { *needs_rebuild = true; }
-        if self.cancel_btn.cursor_moved(pos.x, pos.y, ctx) { *needs_rebuild = true; }
-        if self.fingerprint_btn.cursor_moved(pos.x, pos.y, ctx) { *needs_rebuild = true; }
+        if ctx.propagate_event(&mv, self.bg.as_ptr_mut()) { *needs_rebuild = true; }
+        if ctx.propagate_event(&mv, self.password_box.as_ptr_mut()) { *needs_rebuild = true; }
+        if ctx.propagate_event(&mv, self.verify_btn.as_ptr_mut()) { *needs_rebuild = true; }
+        if ctx.propagate_event(&mv, self.cancel_btn.as_ptr_mut()) { *needs_rebuild = true; }
+        if ctx.propagate_event(&mv, self.fingerprint_btn.as_ptr_mut()) { *needs_rebuild = true; }
     }
 
     fn handle_mouse_input(&mut self, button: MouseButton, state: ElementState, pos: LogicalPosition, needs_rebuild: &mut bool) -> Option<Self::Message> {
         let (lx, ly) = (pos.x, pos.y);
-        
-        if self.verify_btn.mouse_input(button, state, lx, ly, &mut self.ui_context) {
+        let ev = cce_ui::widget::Event::MouseButton { button, state, x: lx, y: ly, local_x: lx, local_y: ly };
+
+        if { let ptr = self.verify_btn.as_ptr_mut(); self.ui_context.propagate_event(&ev, ptr) } {
             *needs_rebuild = true;
         }
         if self.verify_btn.take_click() {
             return Some(AppMessage::PasswordVerify);
         }
         
-        if self.cancel_btn.mouse_input(button, state, lx, ly, &mut self.ui_context) {
+        if { let ptr = self.cancel_btn.as_ptr_mut(); self.ui_context.propagate_event(&ev, ptr) } {
             *needs_rebuild = true;
         }
         if self.cancel_btn.take_click() {
             return Some(AppMessage::Cancel);
         }
         
-        if self.fingerprint_btn.mouse_input(button, state, lx, ly, &mut self.ui_context) {
+        if { let ptr = self.fingerprint_btn.as_ptr_mut(); self.ui_context.propagate_event(&ev, ptr) } {
             *needs_rebuild = true;
         }
         if self.fingerprint_btn.take_click() {
@@ -559,7 +562,7 @@ impl Application for AuthenticatorApp {
         if state == ElementState::Pressed && !tb.hit_test(lx, ly, &self.ui_context) {
             tb.unfocus();
         }
-        if tb.mouse_input(button, state, lx, ly, &mut self.ui_context) {
+        if { let ptr = tb.as_ptr_mut(); self.ui_context.propagate_event(&ev, ptr) } {
             *needs_rebuild = true;
         }
         
@@ -596,7 +599,9 @@ impl Application for AuthenticatorApp {
             }
         }
         
-        if self.password_box.keyboard_input(event, &mut self.ui_context) {
+        let kev = cce_ui::widget::Event::KeyInput(event.clone());
+        let ptr = self.password_box.as_ptr_mut();
+        if self.ui_context.propagate_event(&kev, ptr) {
             *needs_rebuild = true;
         }