mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 13:20:05 -04:00
Fix closing of viewports (#3591)
This ensures the closed viewport gets a close-event, and that it and the parent viewport gets repainting, allowing the event to be registered.
This commit is contained in:
@@ -194,7 +194,7 @@ impl EpiIntegration {
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
pub fn init_accesskit<E: From<egui_winit::accesskit_winit::ActionRequestEvent> + Send>(
|
||||
&mut self,
|
||||
&self,
|
||||
egui_winit: &mut egui_winit::State,
|
||||
window: &winit::window::Window,
|
||||
event_loop_proxy: winit::event_loop::EventLoopProxy<E>,
|
||||
@@ -231,9 +231,10 @@ impl EpiIntegration {
|
||||
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
log::debug!("Received WindowEvent::CloseRequested");
|
||||
self.close = app.on_close_event() && viewport_id == ViewportId::ROOT;
|
||||
log::debug!("App::on_close_event returned {}", self.close);
|
||||
if viewport_id == ViewportId::ROOT {
|
||||
self.close = app.on_close_event();
|
||||
log::debug!("App::on_close_event returned {}", self.close);
|
||||
}
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
log::debug!("Received WindowEvent::Destroyed");
|
||||
@@ -255,7 +256,7 @@ impl EpiIntegration {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
egui_winit.on_window_event(&self.egui_ctx, event, viewport_id)
|
||||
egui_winit.on_window_event(&self.egui_ctx, event)
|
||||
}
|
||||
|
||||
pub fn pre_update(&mut self) {
|
||||
@@ -281,7 +282,7 @@ impl EpiIntegration {
|
||||
viewport_ui_cb(egui_ctx);
|
||||
} else {
|
||||
// Root viewport
|
||||
if egui_ctx.input(|i| i.viewport().close_requested) {
|
||||
if egui_ctx.input(|i| i.viewport().close_requested()) {
|
||||
self.close = app.on_close_event();
|
||||
log::debug!("App::on_close_event returned {}", self.close);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ impl GlowWinitApp {
|
||||
let system_theme =
|
||||
winit_integration::system_theme(&glutin.window(ViewportId::ROOT), &self.native_options);
|
||||
|
||||
let mut integration = EpiIntegration::new(
|
||||
let integration = EpiIntegration::new(
|
||||
&glutin.window(ViewportId::ROOT),
|
||||
system_theme,
|
||||
&self.app_name,
|
||||
@@ -656,12 +656,8 @@ impl GlowWinitRunning {
|
||||
) -> EventResult {
|
||||
crate::profile_function!(egui_winit::short_window_event_description(event));
|
||||
|
||||
let viewport_id = self
|
||||
.glutin
|
||||
.borrow()
|
||||
.viewport_from_window
|
||||
.get(&window_id)
|
||||
.copied();
|
||||
let mut glutin = self.glutin.borrow_mut();
|
||||
let viewport_id = glutin.viewport_from_window.get(&window_id).copied();
|
||||
|
||||
// On Windows, if a window is resized by the user, it should repaint synchronously, inside the
|
||||
// event handler.
|
||||
@@ -680,8 +676,7 @@ impl GlowWinitRunning {
|
||||
|
||||
match event {
|
||||
winit::event::WindowEvent::Focused(new_focused) => {
|
||||
self.glutin.borrow_mut().focused_viewport =
|
||||
new_focused.then(|| viewport_id).flatten();
|
||||
glutin.focused_viewport = new_focused.then(|| viewport_id).flatten();
|
||||
}
|
||||
|
||||
winit::event::WindowEvent::Resized(physical_size) => {
|
||||
@@ -691,7 +686,7 @@ impl GlowWinitRunning {
|
||||
if 0 < physical_size.width && 0 < physical_size.height {
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
repaint_asap = true;
|
||||
self.glutin.borrow_mut().resize(viewport_id, *physical_size);
|
||||
glutin.resize(viewport_id, *physical_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -699,45 +694,59 @@ impl GlowWinitRunning {
|
||||
winit::event::WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
repaint_asap = true;
|
||||
self.glutin
|
||||
.borrow_mut()
|
||||
.resize(viewport_id, **new_inner_size);
|
||||
glutin.resize(viewport_id, **new_inner_size);
|
||||
}
|
||||
}
|
||||
|
||||
winit::event::WindowEvent::CloseRequested => {
|
||||
let is_root = viewport_id == Some(ViewportId::ROOT);
|
||||
if is_root && self.integration.should_close() {
|
||||
log::debug!("Received WindowEvent::CloseRequested");
|
||||
if viewport_id == Some(ViewportId::ROOT) && self.integration.should_close() {
|
||||
log::debug!(
|
||||
"Received WindowEvent::CloseRequested for main viewport - shutting down."
|
||||
);
|
||||
return EventResult::Exit;
|
||||
}
|
||||
|
||||
log::debug!("Received WindowEvent::CloseRequested for viewport {viewport_id:?}");
|
||||
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
|
||||
// Tell viewport it should close:
|
||||
viewport.info.events.push(egui::ViewportEvent::Close);
|
||||
|
||||
// We may need to repaint both us and our parent to close the window,
|
||||
// and perhaps twice (once to notice the close-event, once again to enforce it).
|
||||
// `request_repaint_of` does a double-repaint though:
|
||||
self.integration.egui_ctx.request_repaint_of(viewport_id);
|
||||
self.integration
|
||||
.egui_ctx
|
||||
.request_repaint_of(viewport.ids.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let event_response = 'res: {
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
let mut glutin = self.glutin.borrow_mut();
|
||||
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
|
||||
break 'res self.integration.on_window_event(
|
||||
self.app.as_mut(),
|
||||
event,
|
||||
viewport.egui_winit.as_mut().unwrap(),
|
||||
viewport.ids.this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
EventResponse {
|
||||
consumed: false,
|
||||
repaint: false,
|
||||
}
|
||||
};
|
||||
|
||||
if self.integration.should_close() {
|
||||
EventResult::Exit
|
||||
} else if event_response.repaint {
|
||||
return EventResult::Exit;
|
||||
}
|
||||
|
||||
let mut event_response = EventResponse {
|
||||
consumed: false,
|
||||
repaint: false,
|
||||
};
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
if let Some(viewport) = glutin.viewports.get_mut(&viewport_id) {
|
||||
event_response = self.integration.on_window_event(
|
||||
self.app.as_mut(),
|
||||
event,
|
||||
viewport.egui_winit.as_mut().unwrap(),
|
||||
viewport.ids.this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if event_response.repaint {
|
||||
if repaint_asap {
|
||||
EventResult::RepaintNow(window_id)
|
||||
} else {
|
||||
|
||||
@@ -147,7 +147,6 @@ fn run_and_return(
|
||||
}
|
||||
}
|
||||
EventResult::RepaintNext(window_id) => {
|
||||
log::trace!("Repaint caused by {}", short_event_description(&event));
|
||||
windows_next_repaint_times.insert(window_id, Instant::now());
|
||||
}
|
||||
EventResult::RepaintAt(window_id, repaint_time) => {
|
||||
|
||||
@@ -162,7 +162,7 @@ impl WgpuWinitApp {
|
||||
let wgpu_render_state = painter.render_state();
|
||||
|
||||
let system_theme = winit_integration::system_theme(&window, &self.native_options);
|
||||
let mut integration = EpiIntegration::new(
|
||||
let integration = EpiIntegration::new(
|
||||
&window,
|
||||
system_theme,
|
||||
&self.app_name,
|
||||
@@ -697,40 +697,57 @@ impl WgpuWinitRunning {
|
||||
if let (Some(width), Some(height), Some(viewport_id)) = (
|
||||
NonZeroU32::new(new_inner_size.width),
|
||||
NonZeroU32::new(new_inner_size.height),
|
||||
shared.viewport_from_window.get(&window_id).copied(),
|
||||
viewport_id,
|
||||
) {
|
||||
repaint_asap = true;
|
||||
shared.painter.on_window_resized(viewport_id, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
winit::event::WindowEvent::CloseRequested if integration.should_close() => {
|
||||
log::debug!("Received WindowEvent::CloseRequested");
|
||||
return EventResult::Exit;
|
||||
winit::event::WindowEvent::CloseRequested => {
|
||||
if viewport_id == Some(ViewportId::ROOT) && integration.should_close() {
|
||||
log::debug!(
|
||||
"Received WindowEvent::CloseRequested for main viewport - shutting down."
|
||||
);
|
||||
return EventResult::Exit;
|
||||
}
|
||||
|
||||
log::debug!("Received WindowEvent::CloseRequested for viewport {viewport_id:?}");
|
||||
|
||||
if let Some(viewport_id) = viewport_id {
|
||||
if let Some(viewport) = shared.viewports.get_mut(&viewport_id) {
|
||||
// Tell viewport it should close:
|
||||
viewport.info.events.push(egui::ViewportEvent::Close);
|
||||
|
||||
// We may need to repaint both us and our parent to close the window,
|
||||
// and perhaps twice (once to notice the close-event, once again to enforce it).
|
||||
// `request_repaint_of` does a double-repaint though:
|
||||
integration.egui_ctx.request_repaint_of(viewport_id);
|
||||
integration.egui_ctx.request_repaint_of(viewport.ids.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
};
|
||||
|
||||
let event_response = viewport_id.and_then(|viewport_id| {
|
||||
shared.viewports.get_mut(&viewport_id).and_then(|viewport| {
|
||||
viewport.egui_winit.as_mut().map(|egui_winit| {
|
||||
integration.on_window_event(app.as_mut(), event, egui_winit, viewport_id)
|
||||
let event_response = viewport_id
|
||||
.and_then(|viewport_id| {
|
||||
shared.viewports.get_mut(&viewport_id).and_then(|viewport| {
|
||||
viewport.egui_winit.as_mut().map(|egui_winit| {
|
||||
integration.on_window_event(app.as_mut(), event, egui_winit, viewport_id)
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
.unwrap_or_default();
|
||||
|
||||
if integration.should_close() {
|
||||
EventResult::Exit
|
||||
} else if let Some(event_response) = event_response {
|
||||
if event_response.repaint {
|
||||
if repaint_asap {
|
||||
EventResult::RepaintNow(window_id)
|
||||
} else {
|
||||
EventResult::RepaintNext(window_id)
|
||||
}
|
||||
} else if event_response.repaint {
|
||||
if repaint_asap {
|
||||
EventResult::RepaintNow(window_id)
|
||||
} else {
|
||||
EventResult::Wait
|
||||
EventResult::RepaintNext(window_id)
|
||||
}
|
||||
} else {
|
||||
EventResult::Wait
|
||||
|
||||
Reference in New Issue
Block a user