1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -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:
Emil Ernerfeldt
2023-11-20 17:43:40 +01:00
committed by GitHub
parent 7bfaf49636
commit 44ff29b012
11 changed files with 139 additions and 96 deletions

View File

@@ -2563,8 +2563,13 @@ impl Context {
///
/// This lets you affect another viewport, e.g. resizing its window.
pub fn send_viewport_cmd_to(&self, id: ViewportId, command: ViewportCommand) {
self.write(|ctx| ctx.viewport_for(id).commands.push(command));
self.request_repaint_of(id);
if command.requires_parent_repaint() {
self.request_repaint_of(self.parent_viewport_id());
}
self.write(|ctx| ctx.viewport_for(id).commands.push(command));
}
/// Show a deferred viewport, creating a new native window, if possible.

View File

@@ -163,6 +163,18 @@ impl RawInput {
}
}
/// An input event from the backend into egui, about a specific [viewport](crate::viewport).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum ViewportEvent {
/// The user clicked the close-button on the window, or similar.
///
/// It is up to the user to react to this by _not_ showing the viewport in the next frame in the parent viewport.
///
/// This even will wake up both the child and parent viewport.
Close,
}
/// Information about the current viewport,
/// given as input each frame.
///
@@ -176,9 +188,7 @@ pub struct ViewportInfo {
/// Name of the viewport, if known.
pub title: Option<String>,
/// The user requested the viewport should close,
/// e.g. by pressing the close button in the window decoration.
pub close_requested: bool,
pub events: Vec<ViewportEvent>,
/// Number of physical pixels per ui point.
pub pixels_per_point: f32,
@@ -212,15 +222,17 @@ pub struct ViewportInfo {
}
impl ViewportInfo {
pub fn take(&mut self) -> Self {
core::mem::take(self)
pub fn close_requested(&self) -> bool {
self.events
.iter()
.any(|&event| event == ViewportEvent::Close)
}
pub fn ui(&self, ui: &mut crate::Ui) {
let Self {
parent,
title,
close_requested,
events,
pixels_per_point,
monitor_size,
inner_rect,
@@ -240,8 +252,8 @@ impl ViewportInfo {
ui.label(opt_as_str(title));
ui.end_row();
ui.label("Close requested:");
ui.label(close_requested.to_string());
ui.label("Events:");
ui.label(format!("{events:?}"));
ui.end_row();
ui.label("Pixels per point:");

View File

@@ -369,7 +369,7 @@ impl ViewportBuilder {
/// The default icon is a white `e` on a black background (for "egui" or "eframe").
/// If you prefer the OS default, set this to `None`.
#[inline]
pub fn with_window_icon(mut self, icon: impl Into<Arc<IconData>>) -> Self {
pub fn with_icon(mut self, icon: impl Into<Arc<IconData>>) -> Self {
self.icon = Some(icon.into());
self
}
@@ -641,7 +641,7 @@ impl ViewportBuilder {
};
if is_new {
commands.push(ViewportCommand::WindowIcon(Some(new_icon.clone())));
commands.push(ViewportCommand::Icon(Some(new_icon.clone())));
self.icon = Some(new_icon.clone());
}
}
@@ -765,7 +765,9 @@ pub enum ResizeDirection {
SouthWest,
}
/// You can send a [`ViewportCommand`] to the viewport with [`Context::send_viewport_cmd`].
/// An output [viewport](crate::viewport)-command from egui to the backend, e.g. to change the window title or size.
///
/// You can send a [`ViewportCommand`] to the viewport with [`Context::send_viewport_cmd`].
///
/// See [`crate::viewport`] for how to build new viewports (native windows).
///
@@ -842,7 +844,7 @@ pub enum ViewportCommand {
WindowLevel(WindowLevel),
/// The the window icon.
WindowIcon(Option<Arc<IconData>>),
Icon(Option<Arc<IconData>>),
IMEPosition(Pos2),
IMEAllowed(bool),
@@ -903,6 +905,11 @@ impl ViewportCommand {
}
})
}
/// This command requires the parent viewport to repaint.
pub fn requires_parent_repaint(&self) -> bool {
self == &Self::Close
}
}
/// Describes a viewport, i.e. a native window.