summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/src/window/event.rs3
-rw-r--r--core/src/window/settings.rs11
-rw-r--r--examples/multi_window/src/main.rs6
-rw-r--r--src/settings.rs11
-rw-r--r--winit/src/application.rs4
-rw-r--r--winit/src/multi_window.rs148
-rw-r--r--winit/src/multi_window/windows.rs26
-rw-r--r--winit/src/settings.rs12
8 files changed, 133 insertions, 88 deletions
diff --git a/core/src/window/event.rs b/core/src/window/event.rs
index 3efce05e..f7759435 100644
--- a/core/src/window/event.rs
+++ b/core/src/window/event.rs
@@ -28,9 +28,6 @@ pub enum Event {
RedrawRequested(Instant),
/// The user has requested for the window to close.
- ///
- /// Usually, you will want to terminate the execution whenever this event
- /// occurs.
CloseRequested,
/// A window was destroyed by the runtime.
diff --git a/core/src/window/settings.rs b/core/src/window/settings.rs
index 20811e83..eba27914 100644
--- a/core/src/window/settings.rs
+++ b/core/src/window/settings.rs
@@ -57,6 +57,16 @@ pub struct Settings {
/// Platform specific settings.
pub platform_specific: PlatformSpecific,
+
+ /// Whether the window will close when the user requests it, e.g. when a user presses the
+ /// close button.
+ ///
+ /// This can be useful if you want to have some behavior that executes before the window is
+ /// actually destroyed. If you disable this, you must manually close the window with the
+ /// `window::close` command.
+ ///
+ /// By default this is enabled.
+ pub exit_on_close_request: bool,
}
impl Default for Settings {
@@ -73,6 +83,7 @@ impl Default for Settings {
level: Level::default(),
icon: None,
platform_specific: Default::default(),
+ exit_on_close_request: true,
}
}
}
diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs
index 58604702..51ec3595 100644
--- a/examples/multi_window/src/main.rs
+++ b/examples/multi_window/src/main.rs
@@ -8,10 +8,7 @@ use iced::{
use std::collections::HashMap;
fn main() -> iced::Result {
- Example::run(Settings {
- exit_on_close_request: false,
- ..Default::default()
- })
+ Example::run(Settings::default())
}
#[derive(Default)]
@@ -111,6 +108,7 @@ impl multi_window::Application for Example {
id,
window::Settings {
position: self.next_window_pos,
+ exit_on_close_request: count % 2 == 0,
..Default::default()
},
);
diff --git a/src/settings.rs b/src/settings.rs
index 4ce2d135..e2a43581 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -41,14 +41,6 @@ pub struct Settings<Flags> {
///
/// [`Canvas`]: crate::widget::Canvas
pub antialiasing: bool,
-
- /// Whether the [`Application`] should exit when the user requests the
- /// window to close (e.g. the user presses the close button).
- ///
- /// By default, it is enabled.
- ///
- /// [`Application`]: crate::Application
- pub exit_on_close_request: bool,
}
impl<Flags> Settings<Flags> {
@@ -65,7 +57,6 @@ impl<Flags> Settings<Flags> {
default_font: default_settings.default_font,
default_text_size: default_settings.default_text_size,
antialiasing: default_settings.antialiasing,
- exit_on_close_request: default_settings.exit_on_close_request,
}
}
}
@@ -82,7 +73,6 @@ where
default_font: Default::default(),
default_text_size: 16.0,
antialiasing: false,
- exit_on_close_request: true,
}
}
}
@@ -93,7 +83,6 @@ impl<Flags> From<Settings<Flags>> for iced_winit::Settings<Flags> {
id: settings.id,
window: settings.window,
flags: settings.flags,
- exit_on_close_request: settings.exit_on_close_request,
}
}
}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 5c45bbda..cffcb884 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -136,6 +136,8 @@ where
let target = settings.window.platform_specific.target.clone();
let should_be_visible = settings.window.visible;
+ let exit_on_close_request = settings.window.exit_on_close_request;
+
let builder = settings::window_builder(
settings.window,
&application.title(),
@@ -197,7 +199,7 @@ where
init_command,
window,
should_be_visible,
- settings.exit_on_close_request,
+ exit_on_close_request,
));
let mut context = task::Context::from_waker(task::noop_waker_ref());
diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs
index e6f440bc..b67c0a48 100644
--- a/winit/src/multi_window.rs
+++ b/winit/src/multi_window.rs
@@ -46,7 +46,14 @@ pub enum Event<Message> {
/// An internal event for closing a window.
CloseWindow(window::Id),
/// An internal event for when the window has finished being created.
- WindowCreated(window::Id, winit::window::Window),
+ WindowCreated {
+ /// The internal ID of the window.
+ id: window::Id,
+ /// The raw window.
+ window: winit::window::Window,
+ /// Whether or not the window should close when a user requests it does.
+ exit_on_close_request: bool,
+ },
}
#[allow(unsafe_code)]
@@ -161,6 +168,8 @@ where
};
let should_main_be_visible = settings.window.visible;
+ let exit_on_close_request = settings.window.exit_on_close_request;
+
let builder = window_builder(
settings.window,
&application.title(window::Id::MAIN),
@@ -208,8 +217,13 @@ where
let (mut compositor, renderer) =
C::new(compositor_settings, Some(&main_window))?;
- let windows =
- Windows::new(&application, &mut compositor, renderer, main_window);
+ let windows = Windows::new(
+ &application,
+ &mut compositor,
+ renderer,
+ main_window,
+ exit_on_close_request,
+ );
let (mut event_sender, event_receiver) = mpsc::unbounded();
let (control_sender, mut control_receiver) = mpsc::unbounded();
@@ -225,7 +239,6 @@ where
init_command,
windows,
should_main_be_visible,
- settings.exit_on_close_request,
));
let mut context = task::Context::from_waker(task::noop_waker_ref());
@@ -255,14 +268,18 @@ where
title,
monitor,
}) => {
+ let exit_on_close_request = settings.exit_on_close_request;
+
let window =
settings::window_builder(settings, &title, monitor, None)
.build(window_target)
.expect("Failed to build window");
- Some(winit::event::Event::UserEvent(Event::WindowCreated(
- id, window,
- )))
+ Some(winit::event::Event::UserEvent(Event::WindowCreated {
+ id,
+ window,
+ exit_on_close_request,
+ }))
}
_ => event.to_static(),
};
@@ -299,7 +316,6 @@ async fn run_instance<A, E, C>(
init_command: Command<A::Message>,
mut windows: Windows<A, C>,
should_main_window_be_visible: bool,
- exit_on_main_closed: bool,
) where
A: Application + 'static,
E: Executor + 'static,
@@ -548,11 +564,20 @@ async fn run_instance<A, E, C>(
Event::Application(message) => {
messages.push(message);
}
- Event::WindowCreated(id, window) => {
+ Event::WindowCreated {
+ id,
+ window,
+ exit_on_close_request,
+ } => {
let bounds = logical_bounds_of(&window);
- let (inner_size, i) =
- windows.add(&application, &mut compositor, id, window);
+ let (inner_size, i) = windows.add(
+ &application,
+ &mut compositor,
+ id,
+ window,
+ exit_on_close_request,
+ );
user_interfaces.push(build_user_interface(
&application,
@@ -680,50 +705,61 @@ async fn run_instance<A, E, C>(
event: window_event,
window_id,
} => {
- let window_deleted = windows
- .pending_destroy
- .iter()
- .any(|(_, w_id)| window_id == *w_id);
+ let window_index =
+ windows.raw.iter().position(|w| w.id() == window_id);
+
+ match window_index {
+ Some(i) => {
+ let id = windows.ids[i];
+ let raw = &windows.raw[i];
+ let exit_on_close_request =
+ windows.exit_on_close_requested[i];
+
+ if matches!(
+ window_event,
+ winit::event::WindowEvent::CloseRequested
+ ) && exit_on_close_request
+ {
+ let i = windows.delete(id);
+ let _ = user_interfaces.remove(i);
+ let _ = ui_caches.remove(i);
+
+ if windows.is_empty() {
+ break 'main;
+ }
+ } else {
+ let state = &mut windows.states[i];
+ state.update(raw, &window_event, &mut debug);
- if matches!(window_event, winit::event::WindowEvent::Destroyed)
- {
- // This is the only special case, since in order trigger the Destroyed event the
- // window reference from winit must be dropped, but we still want to inform the
- // user that the window was destroyed so they can clean up any specific window
- // code for this window
- let id = windows.get_pending_destroy(window_id);
-
- events.push((
- None,
- core::Event::Window(id, window::Event::Destroyed),
- ));
- } else if !window_deleted {
- let i = windows.index_from_raw(window_id);
- let id = windows.ids[i];
- let raw = &windows.raw[i];
- let state = &mut windows.states[i];
-
- // first check if we need to just break the entire application
- // e.g. a user does a force quit on MacOS, or if a user has set "exit on main closed"
- // as an option in window settings and wants to close the main window
- if requests_exit(
- i,
- exit_on_main_closed,
- &window_event,
- state.modifiers(),
- ) {
- break 'main;
+ if let Some(event) = conversion::window_event(
+ id,
+ &window_event,
+ state.scale_factor(),
+ state.modifiers(),
+ ) {
+ events.push((Some(id), event));
+ }
+ }
}
-
- state.update(raw, &window_event, &mut debug);
-
- if let Some(event) = conversion::window_event(
- id,
- &window_event,
- state.scale_factor(),
- state.modifiers(),
- ) {
- events.push((Some(id), event));
+ None => {
+ // This is the only special case, since in order to trigger the Destroyed event the
+ // window reference from winit must be dropped, but we still want to inform the
+ // user that the window was destroyed so they can clean up any specific window
+ // code for this window
+ if matches!(
+ window_event,
+ winit::event::WindowEvent::Destroyed
+ ) {
+ let id = windows.get_pending_destroy(window_id);
+
+ events.push((
+ None,
+ core::Event::Window(
+ id,
+ window::Event::Destroyed,
+ ),
+ ));
+ }
}
}
}
@@ -1068,17 +1104,13 @@ where
/// Returns true if the provided event should cause an [`Application`] to
/// exit.
-pub fn requests_exit(
- window: usize,
- exit_on_main_closed: bool,
+pub fn user_force_quit(
event: &winit::event::WindowEvent<'_>,
_modifiers: winit::event::ModifiersState,
) -> bool {
use winit::event::WindowEvent;
- //TODO alt f4..?
match event {
- WindowEvent::CloseRequested => exit_on_main_closed && window == 0,
#[cfg(target_os = "macos")]
WindowEvent::KeyboardInput {
input:
diff --git a/winit/src/multi_window/windows.rs b/winit/src/multi_window/windows.rs
index 7b63defa..1f606b31 100644
--- a/winit/src/multi_window/windows.rs
+++ b/winit/src/multi_window/windows.rs
@@ -14,6 +14,7 @@ where
pub raw: Vec<winit::window::Window>,
pub states: Vec<State<A>>,
pub viewport_versions: Vec<usize>,
+ pub exit_on_close_requested: Vec<bool>,
pub surfaces: Vec<C::Surface>,
pub renderers: Vec<A::Renderer>,
pub pending_destroy: Vec<(window::Id, winit::window::WindowId)>,
@@ -52,6 +53,7 @@ where
compositor: &mut C,
renderer: A::Renderer,
main: winit::window::Window,
+ exit_on_close_requested: bool,
) -> Self {
let state = State::new(application, window::Id::MAIN, &main);
let viewport_version = state.viewport_version();
@@ -67,6 +69,7 @@ where
raw: vec![main],
states: vec![state],
viewport_versions: vec![viewport_version],
+ exit_on_close_requested: vec![exit_on_close_requested],
surfaces: vec![surface],
renderers: vec![renderer],
pending_destroy: vec![],
@@ -81,6 +84,7 @@ where
compositor: &mut C,
id: window::Id,
window: winit::window::Window,
+ exit_on_close_requested: bool,
) -> (Size, usize) {
let state = State::new(application, id, &window);
let window_size = state.logical_size();
@@ -96,6 +100,7 @@ where
self.ids.push(id);
self.raw.push(window);
self.states.push(state);
+ self.exit_on_close_requested.push(exit_on_close_requested);
self.viewport_versions.push(viewport_version);
self.surfaces.push(surface);
self.renderers.push(renderer);
@@ -145,6 +150,7 @@ where
let id = self.ids.remove(i);
let window = self.raw.remove(i);
let _ = self.states.remove(i);
+ let _ = self.exit_on_close_requested.remove(i);
let _ = self.viewport_versions.remove(i);
let _ = self.surfaces.remove(i);
@@ -167,4 +173,24 @@ where
let (id, _) = self.pending_destroy.remove(i);
id
}
+
+ /// Returns the windows that need to be requested to closed, and also the windows that can be
+ /// closed immediately.
+ pub fn partition_close_requests(&self) -> (Vec<window::Id>, Vec<window::Id>) {
+ self.exit_on_close_requested.iter().enumerate().fold(
+ (vec![], vec![]),
+ |(mut close_immediately, mut needs_request_closed),
+ (i, close)| {
+ let id = self.ids[i];
+
+ if *close {
+ close_immediately.push(id);
+ } else {
+ needs_request_closed.push(id);
+ }
+
+ (close_immediately, needs_request_closed)
+ },
+ )
+ }
}
diff --git a/winit/src/settings.rs b/winit/src/settings.rs
index 2b846fbd..c0b3b047 100644
--- a/winit/src/settings.rs
+++ b/winit/src/settings.rs
@@ -1,6 +1,6 @@
//! Configure your application.
-use crate::conversion;
use crate::core::window;
+use crate::conversion;
use winit::monitor::MonitorHandle;
use winit::window::WindowBuilder;
@@ -21,16 +21,6 @@ pub struct Settings<Flags> {
///
/// [`Application`]: crate::Application
pub flags: Flags,
-
- /// Whether the [`Application`] should exit when the user requests the
- /// window to close (e.g. the user presses the close button).
- ///
- /// With a [`multi_window::Application`] this will instead be used to determine whether the
- /// application should exit when the "main"" window is closed, i.e. the first window created on
- /// app launch.
- ///
- /// [`Application`]: crate::Application
- pub exit_on_close_request: bool,
}
/// Converts the window settings into a `WindowBuilder` from `winit`.