From f4a196cddc59c31e11c7533eedad134626dafdc8 Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Mon, 24 Jul 2023 16:15:34 +0300 Subject: [PATCH] Now a WindowEvent::CloseRequested is received will be sent to egui_winit::State in RawInput Now when we press the close button from a native window if the window has a open variabile connected the window will be closed --- crates/eframe/src/native/epi_integration.rs | 3 +- crates/eframe/src/native/run.rs | 52 ++++++++++++++++++--- crates/egui-winit/src/lib.rs | 12 ++++- crates/egui/src/containers/window.rs | 38 +++++++++++++-- crates/egui/src/data/input.rs | 8 ++++ examples/hello_world_simple/src/main.rs | 9 ++-- 6 files changed, 106 insertions(+), 16 deletions(-) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index 5b56c109d..0db9b7b30 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -449,13 +449,14 @@ impl EpiIntegration { event: &winit::event::WindowEvent<'_>, window_id: &winit::window::WindowId, egui_winit: &mut egui_winit::State, + viewport_id: u64, ) -> EventResponse { use winit::event::{ElementState, MouseButton, WindowEvent}; match event { WindowEvent::CloseRequested => { log::debug!("Received WindowEvent::CloseRequested"); - self.close = app.on_close_event(); + self.close = app.on_close_event() && viewport_id == 0; log::debug!("App::on_close_event returned {}", self.close); } WindowEvent::Destroyed => { diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index bf7de470b..80e1250d8 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -75,7 +75,8 @@ trait WinitApp { fn window(&self, window_id: winit::window::WindowId) -> Option<&winit::window::Window>; - fn get_window_id(&self, id: u64) -> Option; + fn get_window_winit_id(&self, id: u64) -> Option; + fn get_window_id(&self, id: &winit::window::WindowId) -> Option; fn save_and_destroy(&mut self); @@ -167,7 +168,7 @@ fn run_and_return( }) => { if winit_app.frame_nr() == *frame_nr { log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}"); - if let Some(window_id) = winit_app.get_window_id(*window_id) { + if let Some(window_id) = winit_app.get_window_winit_id(*window_id) { vec![EventResult::RepaintAt(window_id, *when)] } else { vec![EventResult::Wait] @@ -320,7 +321,7 @@ fn run_and_exit(event_loop: EventLoop, mut winit_app: impl WinitApp + window_id, }) => { if winit_app.frame_nr() == frame_nr { - if let Some(window_id) = winit_app.get_window_id(window_id) { + if let Some(window_id) = winit_app.get_window_winit_id(window_id) { vec![EventResult::RepaintAt(window_id, when)] } else { vec![EventResult::Wait] @@ -960,7 +961,7 @@ mod glow_integration { .flatten() } - fn get_window_id(&self, id: u64) -> Option { + fn get_window_winit_id(&self, id: u64) -> Option { self.running .as_ref() .map(|r| { @@ -974,6 +975,22 @@ mod glow_integration { .flatten() } + fn get_window_id(&self, id: &winit::window::WindowId) -> Option { + self.running + .as_ref() + .map(|r| { + for window in r.gl_window.windows.iter() { + if let Some(win) = &window.window { + if win.id() == *id { + return Some(window.window_id); + } + } + } + None + }) + .flatten() + } + fn save_and_destroy(&mut self) { if let Some(mut running) = self.running.take() { running @@ -1319,7 +1336,25 @@ mod glow_integration { } } winit::event::WindowEvent::CloseRequested - if running.integration.should_close() => + if running + .gl_window + .windows + .iter() + .flat_map(|window| { + if let Some(win) = &window.window { + if win.id() == *window_id { + Some(window.window_id) + } else { + None + } + } else { + None + } + }) + .flat_map(|id| if id == 0 { Some(()) } else { None }) + .count() + == 1 + && running.integration.should_close() => { log::debug!("Received WindowEvent::CloseRequested"); return Ok(EventResult::Exit); @@ -1335,6 +1370,7 @@ mod glow_integration { event, window_id, window.egui_winit.as_mut().unwrap(), + window.window_id, ); } } @@ -1617,7 +1653,7 @@ mod wgpu_integration { self.window.as_ref() } - fn get_window_id(&self, id: u64) -> Option { + fn get_window_winit_id(&self, id: u64) -> Option { if id == 0 { return self.window.as_ref().map(|w| w.id()); } @@ -1849,6 +1885,10 @@ mod wgpu_integration { // }) // } + + fn get_window_id(&self, id: &winit::window::WindowId) -> Option { + todo!() + } } pub fn run_wgpu( diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 75c9028cf..543dc7d78 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -372,8 +372,16 @@ impl State { } // Things that may require repaint: - WindowEvent::CloseRequested - | WindowEvent::CursorEntered { .. } + WindowEvent::CloseRequested => { + self.egui_input + .events + .push(egui::Event::WindowEvent(egui::WindowEvent::CloseRequested)); + EventResponse { + consumed: true, + repaint: true, + } + } + WindowEvent::CursorEntered { .. } | WindowEvent::Destroyed | WindowEvent::Occluded(_) | WindowEvent::Resized(_) diff --git a/crates/egui/src/containers/window.rs b/crates/egui/src/containers/window.rs index 8e9920b5a..07c13bd7f 100644 --- a/crates/egui/src/containers/window.rs +++ b/crates/egui/src/containers/window.rs @@ -432,7 +432,7 @@ impl<'open> Window<'open> { ) { let Window { title, - open, + mut open, area, frame, resize, @@ -444,8 +444,21 @@ impl<'open> Window<'open> { mut window_builder, } = self; - let is_explicitly_closed = matches!(open, Some(false)); - let is_open = !is_explicitly_closed || ctx.memory(|mem| mem.everything_is_visible()); + let is_open = if let Some(open) = &mut open { + if let Some(tmp_open) = ctx.data_mut(|data| { + let tmp = data.get_persisted::(area.id.with("_open")); + data.remove::(area.id.with("_open")); + tmp + }) { + **open = tmp_open; + } + **open + } else { + true + }; + + // let is_explicitly_closed = matches!(open, Some(false)); + let is_open = is_open || ctx.memory(|mem| mem.everything_is_visible()); if !embedded { if !is_open { return; @@ -456,10 +469,29 @@ impl<'open> Window<'open> { window_builder.with_inner_size((size.x as u32 + 1, size.y as u32 + 1)); } + let area_id = area.id; + ctx.create_viewport( window_builder, move |ctx, viewport_id, parent_viewport_id| { let mut frame = frame.unwrap_or(Frame::window(&ctx.style())).rounding(0.0); + let count = ctx.input(|input| { + input + .events + .iter() + .filter(|event| { + if let Event::WindowEvent(WindowEvent::CloseRequested) = **event { + true + } else { + false + } + }) + .count() + }); + if count > 0 { + ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), false)); + ctx.request_repaint_viewport(parent_viewport_id); + } CentralPanel::default().frame(frame).show(ctx, |ui| { Some(add_contents(ui, viewport_id, parent_viewport_id)) }); diff --git a/crates/egui/src/data/input.rs b/crates/egui/src/data/input.rs index 99ea6ac03..21bb852fd 100644 --- a/crates/egui/src/data/input.rs +++ b/crates/egui/src/data/input.rs @@ -302,6 +302,14 @@ pub enum Event { /// An assistive technology (e.g. screen reader) requested an action. #[cfg(feature = "accesskit")] AccessKitActionRequest(accesskit::ActionRequest), + + WindowEvent(WindowEvent), +} + +#[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub enum WindowEvent { + CloseRequested, } /// Mouse button (or similar for touch input) diff --git a/examples/hello_world_simple/src/main.rs b/examples/hello_world_simple/src/main.rs index 31d090abc..987199e00 100644 --- a/examples/hello_world_simple/src/main.rs +++ b/examples/hello_world_simple/src/main.rs @@ -39,16 +39,17 @@ fn main() -> Result<(), eframe::Error> { let clone = window1_embedded.clone(); let embedded = *window1_embedded.read().unwrap(); egui::CollapsingHeader::new("Show Test1").show(ui, |ui| { - egui::Window::new("Test1") - .embedded(embedded) - .show(ctx, move |ui, _, _| { + egui::Window::new("Test1").embedded(embedded).show( + ctx, + move |ui, id, parent_id| { ui.checkbox(&mut *clone.write().unwrap(), "Should embedd?"); let ctx = ui.ctx().clone(); ui.label(format!( "Current rendering window: {}", ctx.current_rendering_viewport() )); - }); + }, + ); }); let clone = window2_embedded.clone(); let embedded = *window2_embedded.read().unwrap();