Merge PR #1914@2f88d847f into round3a-integration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
francoisgn
2026-10-24 02:44:32 +03:00
co-authored by Claude Opus 5.5
2 changed files with 29 additions and 4 deletions
+7 -4
View File
@@ -308,6 +308,8 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context) {
let widest = if settings { ctx.data(|d| d.get_temp::<f32>(widest_id)).unwrap_or(0.0).min(screen.width() * 0.9) } else { 0.0 };
let mut content_w = 0.0f32;
let mut body_h = None;
// before the window: drawing it closes a dropdown the click lands outside of
let popup_was_open = egui::Popup::is_any_open(ctx);
let shown = egui::Window::new(crate::i18n::tr(&title)).id(window_id)
.collapsible(false)
.resizable(import)
@@ -1491,7 +1493,7 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context) {
}
if let Some(w) = &shown {
// (the import review keeps its hand-picked photos however the click lands)
if app.ui.settings.close_dialogs_outside && !import && clicked_backdrop(ctx, w.response.rect) {
if app.ui.settings.close_dialogs_outside && !import && clicked_backdrop(ctx, w.response.rect, popup_was_open) {
close = true;
}
}
@@ -1595,11 +1597,12 @@ const BACKDROP_SHOWN: &str = "dialog-backdrop-shown";
/// A click on the dimmed backdrop around the dialog: it closes the dialog like Esc. Pressed and
/// released outside the window, so a slider dragged past its edge doesn't close it; a press while a
/// popup is open (a dropdown, a date picker's calendar) only closes the popup. Only a press made
/// popup is open (a dropdown, a date picker's calendar) only closes the popup: `popup_was_open` is
/// read before the window is drawn, since drawing it already closes the popup. Only a press made
/// while the dialog is shown counts: in the frame a dialog appears, its input is the click that
/// opened it (a quick click on a slow frame presses and releases in that one frame), so it never
/// closes it. (Read from the raw events: egui forgets the press origin on release.)
fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect) -> bool {
fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect, popup_was_open: bool) -> bool {
let press_id = egui::Id::new("dialog-backdrop-press");
let frame = ctx.cumulative_frame_nr();
// the same frame too: a second pass of it gets no input
@@ -1618,7 +1621,7 @@ fn clicked_backdrop(ctx: &egui::Context, window: egui::Rect) -> bool {
(at(true), at(false), i.pointer.primary_clicked())
});
if let Some(p) = press {
let outside = !window.contains(p) && !egui::Popup::is_any_open(ctx);
let outside = !window.contains(p) && !popup_was_open;
ctx.data_mut(|d| d.insert_temp(press_id, outside));
}
let Some(release) = release else { return false };
+22
View File
@@ -128,6 +128,28 @@ fn a_click_outside_closes_the_dialog_when_settings_allow_it() {
assert!(h.app.ui.dialog.is_none(), "the next click on the backdrop does");
}
/// With a dropdown open in the dialog, a click on the backdrop only closes the dropdown, even when
/// it arrives pressed and released in one frame (the dropdown closes while the dialog is drawn).
#[test]
fn a_click_outside_an_open_dropdown_keeps_the_dialog() {
let mut h = demo([1400.0, 1000.0], json!({"view": "detail", "right": "edit"}));
h.app.ui.settings.close_dialogs_outside = true;
h.app.run("dialog.export", json!({})).unwrap();
h.step();
h.step();
let r = h.request("ui.clickWidget", json!({"id": "combo:exportPreset"}), T);
assert_eq!(r["ok"], true, "{r}");
h.step();
assert!(egui::Popup::is_any_open(&h.view.ctx), "the preset dropdown is open");
let at = egui::pos2(10.0, 990.0);
let press = |pressed| egui::Event::PointerButton { pos: at, button: egui::PointerButton::Primary, pressed, modifiers: egui::Modifiers::NONE };
h.events.extend([egui::Event::PointerMoved(at), press(true), press(false)]);
h.step();
h.step();
assert!(!egui::Popup::is_any_open(&h.view.ctx), "the click closes the dropdown");
assert!(h.app.ui.dialog.is_some(), "but not the dialog");
}
#[test]
fn modal_dialogs_close_background_menus() {
let mut h = demo([1400.0, 1000.0], json!({"view": "detail", "right": "edit"}));