git.lucas.co / cce-data-editor
structured data editor
git clone https://git.lucas.co/cce-data-editor.git

commit773739cf91eb63ea4413b42c86b665766433791b
parent556f8b11f5
authorLucas Galante <[email protected]>
date2026-08-10 00:17
feat: open dropdown menus dismiss on window focus loss

Clicks outside our own surface never arrive as pointer events, so an open
File/choice menu used to hang open while the user worked elsewhere. The
compositor's keyboard-leave (handle_focus_change) is the outside-click
signal; route FocusOut to whichever dropdown has its popover up and let
the widget's own animated close run.

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

 src/main.rs | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/main.rs b/src/main.rs
index 428e0e0..1cf8f53 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2433,6 +2433,26 @@ impl Application for DataEditorApp {
 
         msg_out
     }
+
+    /// Clicks outside our own surface never arrive as pointer events — the
+    /// compositor's keyboard-leave is the only "user went elsewhere" signal.
+    /// Dismiss any open dropdown menu on it (FocusOut is the widget's own
+    /// close-me event, so this rides the normal animated-close path).
+    fn handle_focus_change(&mut self, focused: bool, needs_rebuild: &mut bool) {
+        if focused {
+            return;
+        }
+        for (open, id) in [
+            (self.btn_open.popover_rect().is_some(), self.btn_open.id()),
+            (self.selected_choice_editor.popover_rect().is_some(), self.selected_choice_editor.id()),
+        ] {
+            if open {
+                self.ui_context.propagate_event(&cce_ui::widget::Event::FocusOut, id);
+                *needs_rebuild = true;
+                self.needs_rebuild = true;
+            }
+        }
+    }
 }
 
 fn parse_hex_color_rgba(s: &str) -> Option<[u8; 4]> {