node-based graph editor
git clone https://git.lucas.co/cce-graph.git
fix: dismiss menus through the engine sweep, not a direct open = false
The three dropdowns were force-closed by writing `open = false` on any
outside press. That is the one field write the toolkit asks callers not
to make: both `Paint::popover` and `draw_popover` gate on `open`, so the
menu disappeared in a single frame while the `closing` animation ran on
invisibly behind it — the contract animation every other app shows was
simply never seen here. It also fought the engine, which had already
started a proper animated close a few lines earlier.
cce-ui sweeps open popovers before app dispatch
(`close_popovers_missed_by_press`) and delivers the missed press to their
owners, which is exactly this behaviour done properly. But it runs for
Left only, and Dropdown's own MouseButton arm matches Left only as well,
so a right or middle press would strand an open menu. Calling the same
sweep for those buttons keeps the dismissal and drops the field write.
Verified live: File menu open (plate to y=456 px), Left press on the
canvas closes it (y=83); re-opened, right press on the canvas also closes
it. The restored animation is a code consequence — a 140ms transition is
finer than the screenshot cadence, so it was not photographed.
Co-Authored-By: Claude <[email protected]>
src/main.rs | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 9440a50..e9aeabb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1528,16 +1528,16 @@ impl Application for GraphApp {
}
}
- if state == ElementState::Pressed {
- if !self.dropdown_file.hit_test(pos.x, pos.y, &self.ui_context) {
- self.dropdown_file.open = false;
- }
- if !self.dropdown_edit.hit_test(pos.x, pos.y, &self.ui_context) {
- self.dropdown_edit.open = false;
- }
- if !self.dropdown_view.hit_test(pos.x, pos.y, &self.ui_context) {
- self.dropdown_view.open = false;
- }
+ // Outside-press dismissal. The engine already sweeps open popovers
+ // before app dispatch (close_popovers_missed_by_press), but only for
+ // Left — and Dropdown's own handler matches Left only too, so other
+ // buttons would leave an open menu stranded. Run the same sweep for
+ // those. Forcing `open = false` here instead (as this used to) skips
+ // the contract animation entirely: both `Paint::popover` and
+ // `draw_popover` gate on `open`, so the menu vanished in one frame
+ // while `closing` ran on invisibly.
+ if state == ElementState::Pressed && button != MouseButton::Left {
+ self.ui_context.close_popovers_missed_by_press(pos.x, pos.y);
}
} else {
let mut handled_by_panel = false;