git.lucas.co / cce-gallery
widget gallery and compositor test bench

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

A right-click on an exhibit 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 rows did nothing. While it is open a press now goes to the menu
first, ahead of the exhibit scrollbar -- a row runs, anywhere else
dismisses -- a release it does not use still reaches the exhibits so a
drag can end, and the pointer drives its rows.

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

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

diff --git a/src/main.rs b/src/main.rs
index f91169c..3b81f2d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1646,6 +1646,15 @@ impl cce_ui::engine::Application for State {
     fn handle_pointer_move(&mut self, pos: LogicalPosition, needs_rebuild: &mut bool) {
         let (lx, ly) = (pos.x as f32, pos.y as f32);
 
+        // The shared context menu (any exhibit's) gets the pointer to itself
+        // while open: its row highlight and slider rows.
+        if cce_ui::widget::context_menu::is_visible() {
+            if cce_ui::widget::context_menu::cursor_moved(lx, ly) {
+                *needs_rebuild = true;
+            }
+            return;
+        }
+
         let mut changed = false;
         if !self.is_child && self.exhibit_scroll.cursor_moved(lx, ly, &mut self.ui_context)
         {
@@ -1679,6 +1688,22 @@ impl cce_ui::engine::Application for State {
     fn handle_mouse_input(&mut self, button: MouseButton, state: ElementState, pos: LogicalPosition, needs_rebuild: &mut bool) -> Option<Self::Message> {
         let (lx, ly) = (pos.x as f32, pos.y as f32);
 
+        // The shared context menu a right-click on an exhibit opens takes every
+        // press while open, ahead of the exhibit scrollbar: a row runs, a press
+        // anywhere else dismisses it. A release it does not use (its slider
+        // rows take theirs) still reaches the exhibits, whose drags end on 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() {
+            let used = cce_ui::widget::context_menu::mouse_input(button, state, lx, ly, Some(&mut self.ui_context));
+            if used {
+                *needs_rebuild = true;
+            }
+            if used || state == ElementState::Pressed {
+                return None;
+            }
+        }
+
         let mut changed = false;
         let vis = self.visibility();
         let is_visible = move |index: usize| vis.is_visible(index);