diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 4e0b8b10c..5a34927b2 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -1623,7 +1623,6 @@ impl EffectcraftApp { fn frame(&mut self, ui: &mut egui::Ui) { let ctx = ui.ctx().clone(); self.apply_gpu_failure(&ctx); - self.run_dialog_answers(); self.auto.begin_frame(); self.frames.set_context(&ctx); if self.session.render_job.is_some() { @@ -1920,6 +1919,8 @@ impl eframe::App for EffectcraftApp { // window while AppKit's run loop is running (#341). craft_quit::on_close_request(ctx); } else { + // An answered file dialog can change the project, so it runs before the close decision. + self.run_dialog_answers(); panels::unsaved::close_or_quit(self, ctx); } } diff --git a/crates/ui-egui/src/panels/unsaved.rs b/crates/ui-egui/src/panels/unsaved.rs index 9c8c08870..4a94265b4 100644 --- a/crates/ui-egui/src/panels/unsaved.rs +++ b/crates/ui-egui/src/panels/unsaved.rs @@ -406,4 +406,22 @@ mod tests { assert!(canceled, "the close is canceled"); assert_eq!(app.dialog, Some(Dialog::UnsavedChanges)); } + + /// A file dialog answered in the frame that closes the window runs its command before the + /// close decision, so a change it makes is asked about. + #[test] + fn a_dialog_answer_runs_before_the_close_decision() { + let (mut app, ctx) = app(); + assert!(!app.session.is_dirty()); + let answer = crate::DialogAnswer { command: "comp.new".into(), key: "name", params: json!({"width": 64, "height": 64}), paths: vec!["Main".into()] }; + app.dialog_answers.0.send(answer).unwrap(); + let mut raw = egui::RawInput::default(); + raw.viewports.entry(egui::ViewportId::ROOT).or_default().events.push(egui::ViewportEvent::Close); + let mut frame = eframe::Frame::_new_kittest(); + let out = ctx.run_logic(&raw, |ctx| eframe::App::logic(&mut app, ctx, &mut frame)); + let canceled = out.viewport_commands.get(&egui::ViewportId::ROOT).is_some_and(|c| c.contains(&egui::ViewportCommand::CancelClose)); + assert!(app.session.is_dirty(), "the answer ran"); + assert!(canceled, "the close is canceled"); + assert_eq!(app.dialog, Some(Dialog::UnsavedChanges)); + } }