From 33a6c3dfbcfbe88ad035279d9bd0c950eeef9df0 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Tue, 13 Oct 2026 04:38:59 -0400 Subject: [PATCH] Test Mix in a separate window: the toggle and closing it window.mix_separate toggles (and takes a value), Toggle Mix/Edit keeps Edit in the main window while Mix is separate, a few frames draw both, and closing the Mix window brings Mix back into the main one. The close handling moves into mix_window::separate_closed so the test can reach it. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/mix_window.rs | 9 +++++-- crates/ui-egui/tests/mix_separate.rs | 37 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 crates/ui-egui/tests/mix_separate.rs diff --git a/crates/ui-egui/src/mix_window.rs b/crates/ui-egui/src/mix_window.rs index d335b4be..80aab685 100644 --- a/crates/ui-egui/src/mix_window.rs +++ b/crates/ui-egui/src/mix_window.rs @@ -32,12 +32,17 @@ pub fn show_separate(app: &mut SoundApp, ctx: &egui::Context) { } show(app, ui); if ui.ctx().input(|i| i.viewport().close_requested()) { - app.ui.mix_separate = false; - app.ui.window = crate::MainWindow::Mix; + separate_closed(app); } }); } +/// The separate Mix window was closed: Mix goes back into the main window. +pub fn separate_closed(app: &mut SoundApp) { + app.ui.mix_separate = false; + app.ui.window = crate::MainWindow::Mix; +} + pub(crate) fn content(app: &mut SoundApp, ui: &mut Ui) { let ids: Vec = app.engine.session().tracks.iter().filter(|x| !x.hidden && x.kind != TrackKind::Video).map(|x| x.id).collect(); // Per-channel peaks for multichannel meters (read once per frame). diff --git a/crates/ui-egui/tests/mix_separate.rs b/crates/ui-egui/tests/mix_separate.rs new file mode 100644 index 00000000..ad883b96 --- /dev/null +++ b/crates/ui-egui/tests/mix_separate.rs @@ -0,0 +1,37 @@ +//! Window › Mix in Separate Window: Edit stays in the main window, and closing the Mix window +//! brings Mix back into it. +use egui::vec2; +use egui_kittest::Harness; +use serde_json::json; +use soundcraft_ui_egui::{MainWindow, Services, SoundApp, mix_window}; + +#[test] +fn mix_in_a_separate_window_toggles_and_closing_it_returns_to_the_main_window() { + let mut app = SoundApp::new(soundcraft_engine::demo::demo_engine(), None, Services::default()); + assert!(!app.ui.mix_separate); + app.run("window.mix_separate", json!({})).unwrap(); + assert!(app.ui.mix_separate); + app.run("window.toggle_mix_edit", json!({})).unwrap(); + assert_eq!(app.ui.window, MainWindow::Edit, "Mix is already on screen: the main window keeps Edit"); + + let mut h = Harness::builder().with_size(vec2(1600.0, 1000.0)).build_ui_state( + |ui, app: &mut SoundApp| { + app.logic(&ui.ctx().clone()); + app.ui(ui); + }, + app, + ); + h.run_steps(3); + let app = h.state_mut(); + assert!(app.ui.mix_separate, "drawing both windows keeps them both"); + + mix_window::separate_closed(app); + assert!(!app.ui.mix_separate); + assert_eq!(app.ui.window, MainWindow::Mix, "closing the Mix window shows Mix in the main one"); + h.run_steps(3); + + let app = h.state_mut(); + app.run("window.mix_separate", json!({"value": true})).unwrap(); + app.run("window.mix_separate", json!({"value": false})).unwrap(); + assert!(!app.ui.mix_separate); +}