Toolbar: a second click on a drop-down's button closes it (#1522) (#1576)

The workspace switcher's menu closed on the press (a press outside the
menu) and the click reopened it; the menu now keeps the button that
opened it, a press there is not outside, and its click toggles. A
panel's label toggles its command list instead of always opening it.

Fixes #1522

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DuBearteandClaude Opus 5.5 authored and GitHub committed 2026-10-15 22:04:42 -04:00
1 parent f08ed74617
commit 105a3146c0
2 files changed
+56 -3

No files matched your search

+16 -1
View File
@@ -179,6 +179,9 @@ pub struct MenuState {
pub over_geometry: bool,
/// The plane under the cursor when the viewport menu opened: it offers a sketch on it.
pub plane: Option<String>,
/// The button that opened the menu, when it toggles it: a press there is not a press outside,
/// so its click closes the menu instead of closing and reopening it (#1522).
opener: Option<Rect>,
}
#[derive(Clone, Debug, PartialEq)]
@@ -1349,12 +1352,24 @@ pub fn open_for(app: &mut SolveApp, at: Pos2, target: Target) {
app.menu.radial = target == Target::Viewport && app.preferences.radial_context_menu;
app.menu.target = target;
app.menu.flick = false;
app.menu.opener = None;
app.viewport.context_menu = Some(at);
}
/// A button's menu: a click opens it, and a click on the same button while it is open closes it.
pub fn toggle_for(app: &mut SolveApp, opener: Rect, at: Pos2, target: Target) {
if app.viewport.context_menu.is_some() && app.menu.target == target && app.menu.opener == Some(opener) {
close(app);
} else {
open_for(app, at, target);
app.menu.opener = Some(opener);
}
}
pub fn close(app: &mut SolveApp) {
app.viewport.context_menu = None;
app.menu.flick = false;
app.menu.opener = None;
}
/// Open the menu at a point for automation: the pointer moves there first so what is under it
@@ -1557,8 +1572,8 @@ pub fn show(app: &mut SolveApp, ctx: &egui::Context) {
let target = app.menu.target.clone();
let list = items(app, &target);
let mut picked: Option<Item> = None;
let mut inside = false;
let pointer = ctx.input(|i| i.pointer.latest_pos());
let mut inside = app.menu.opener.is_some_and(|r| pointer.is_some_and(|p| r.contains(p)));
let list_at = if app.menu.radial {
let c = radial_center(at, screen);