diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 932644f..6e6dcd6 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -942,6 +942,28 @@ impl PixelPassApp { /// Render the current screen. Called from inside the egui frame. fn draw(&mut self, ui: &mut egui::Ui) { + // Esc backs out one level, mirroring each screen's "← Menu" button: stop + // any session and return to the menu, or (in the theme editor) close the + // editor back to the picker first so a live preview isn't left applied. + // Suppressed while a popup (colour picker, dropdown) is open, so there + // Esc just dismisses the popup rather than also navigating. + let esc = ui.input(|i| i.key_pressed(egui::Key::Escape)); + if esc && !ui.ctx().any_popup_open() { + match self.screen { + Screen::Host => { + self.stop_host(); + self.screen = Screen::Menu; + } + Screen::Viewer => { + self.stop_viewer(); + self.screen = Screen::Menu; + } + Screen::Settings if self.theme.editing => self.cancel_theme_edit(), + Screen::Settings => self.screen = Screen::Menu, + Screen::Menu => {} + } + } + // Apply whichever theme should be visible this frame. While the editor // is open its draft is previewed live; otherwise the active theme is // applied once (when dirty) and then sticks — the egui context persists