git.lucas.co / cce-text-editor
text editor
git clone https://git.lucas.co/cce-text-editor.git

commit7f04f8c10f197af5da392e81e0c25b8b525632b4
parent881eac317f
authorLucas Galante <lsgalante12@gmail.com>
date2026-10-07 10:09
Route clicks and hover to the shared context menu while it is open

A right-click on the editor or the File menu opens cce-ui's shared
context menu, and cce-ui leaves routing to it to the app: no click
outside it closed it, and its Cut / Copy / Paste / Select All rows did
nothing. While it is open a press now goes to the menu first, ahead of
the File menu's own list -- a row runs, anywhere else dismisses -- and
the pointer drives its row highlight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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

diff --git a/src/main.rs b/src/main.rs
index f9014de..e3815e1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -498,6 +498,16 @@ impl Application for TextEditorApp {
         let px = pos.x as f32;
         let py = pos.y as f32;
 
+        // The shared context menu (the editor's, the File menu's) gets the
+        // pointer to itself while open: its row highlight.
+        if cce_ui::widget::context_menu::is_visible() {
+            if cce_ui::widget::context_menu::cursor_moved(px, py) {
+                *needs_rebuild = true;
+                self.needs_rebuild = true;
+            }
+            return;
+        }
+
         // Routed dispatch (Phase 6ab): one Event through the UiContext router per root;
         // PointerMove visits both (hover bookkeeping + the router's drag forwarding).
         let ev = cce_ui::widget::Event::PointerMove { x: px, y: py, local_x: px, local_y: py };
@@ -518,6 +528,20 @@ impl Application for TextEditorApp {
         let px = pos.x as f32;
         let py = pos.y as f32;
 
+        // The shared context menu a right-click on the editor or the File menu
+        // opens takes every click while open, ahead of the File menu's own list:
+        // a row (Cut / Copy / Paste / Select All) runs, a press anywhere else
+        // dismisses it. The toolkit leaves this routing to the app; without it
+        // the menu could not be closed by clicking outside it, and its rows did
+        // nothing.
+        if cce_ui::widget::context_menu::is_visible() {
+            if cce_ui::widget::context_menu::mouse_input(button, state, px, py, Some(&mut self.ui_context)) {
+                *needs_rebuild = true;
+                self.needs_rebuild = true;
+            }
+            return None;
+        }
+
         // Routed dispatch (Phase 6ab): the router hit-gates presses, synthesizes
         // Enter/Leave, and records drag targets; the app keeps only take_change plumbing.
         let ev = cce_ui::widget::Event::MouseButton { button, state, x: px, y: py, local_x: px, local_y: py };