summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2021-03-31 10:20:22 +0200
committerLibravatar GitHub <noreply@github.com>2021-03-31 10:20:22 +0200
commitb9ec44446ed4d99b9b17aceafdcb353dd1595877 (patch)
tree86b3e4d9a7257a6d5b0d82988111f2a3a5ca7117
parentbbb4e4678f14b4b187f9537a32063440e727e919 (diff)
parent8f952452ce3d61203856bcebae7016372556be31 (diff)
downloadiced-b9ec44446ed4d99b9b17aceafdcb353dd1595877.tar.gz
iced-b9ec44446ed4d99b9b17aceafdcb353dd1595877.tar.bz2
iced-b9ec44446ed4d99b9b17aceafdcb353dd1595877.zip
Merge pull request #804 from hecrj/feature/graceful-exit
Graceful exiting for `Application`
-rw-r--r--examples/events/src/main.rs47
-rw-r--r--glutin/src/application.rs13
-rw-r--r--native/src/window/event.rs6
-rw-r--r--src/application.rs11
-rw-r--r--src/settings.rs15
-rw-r--r--winit/src/application.rs23
-rw-r--r--winit/src/conversion.rs3
-rw-r--r--winit/src/settings.rs4
8 files changed, 103 insertions, 19 deletions
diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs
index 18e6364b..446c190b 100644
--- a/examples/events/src/main.rs
+++ b/examples/events/src/main.rs
@@ -1,22 +1,30 @@
use iced::{
- executor, Align, Application, Checkbox, Clipboard, Column, Command,
- Container, Element, Length, Settings, Subscription, Text,
+ button, executor, Align, Application, Button, Checkbox, Clipboard, Column,
+ Command, Container, Element, HorizontalAlignment, Length, Settings,
+ Subscription, Text,
};
+use iced_native::{window, Event};
pub fn main() -> iced::Result {
- Events::run(Settings::default())
+ Events::run(Settings {
+ exit_on_close_request: false,
+ ..Settings::default()
+ })
}
#[derive(Debug, Default)]
struct Events {
last: Vec<iced_native::Event>,
enabled: bool,
+ exit: button::State,
+ should_exit: bool,
}
#[derive(Debug, Clone)]
enum Message {
EventOccurred(iced_native::Event),
Toggled(bool),
+ Exit,
}
impl Application for Events {
@@ -38,27 +46,35 @@ impl Application for Events {
_clipboard: &mut Clipboard,
) -> Command<Message> {
match message {
- Message::EventOccurred(event) => {
+ Message::EventOccurred(event) if self.enabled => {
self.last.push(event);
if self.last.len() > 5 {
let _ = self.last.remove(0);
}
}
+ Message::EventOccurred(event) => {
+ if let Event::Window(window::Event::CloseRequested) = event {
+ self.should_exit = true;
+ }
+ }
Message::Toggled(enabled) => {
self.enabled = enabled;
}
+ Message::Exit => {
+ self.should_exit = true;
+ }
};
Command::none()
}
fn subscription(&self) -> Subscription<Message> {
- if self.enabled {
- iced_native::subscription::events().map(Message::EventOccurred)
- } else {
- Subscription::none()
- }
+ iced_native::subscription::events().map(Message::EventOccurred)
+ }
+
+ fn should_exit(&self) -> bool {
+ self.should_exit
}
fn view(&mut self) -> Element<Message> {
@@ -75,11 +91,22 @@ impl Application for Events {
Message::Toggled,
);
+ let exit = Button::new(
+ &mut self.exit,
+ Text::new("Exit")
+ .width(Length::Fill)
+ .horizontal_alignment(HorizontalAlignment::Center),
+ )
+ .width(Length::Units(100))
+ .padding(10)
+ .on_press(Message::Exit);
+
let content = Column::new()
.align_items(Align::Center)
.spacing(20)
.push(events)
- .push(toggle);
+ .push(toggle)
+ .push(exit);
Container::new(content)
.width(Length::Fill)
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
index 163bc9f9..79fcf745 100644
--- a/glutin/src/application.rs
+++ b/glutin/src/application.rs
@@ -92,10 +92,11 @@ where
application,
compositor,
renderer,
- context,
runtime,
debug,
receiver,
+ context,
+ settings.exit_on_close_request,
));
let mut context = task::Context::from_waker(task::noop_waker_ref());
@@ -139,10 +140,11 @@ async fn run_instance<A, E, C>(
mut application: A,
mut compositor: C,
mut renderer: A::Renderer,
- context: glutin::ContextWrapper<glutin::PossiblyCurrent, Window>,
mut runtime: Runtime<E, Proxy<A::Message>, A::Message>,
mut debug: Debug,
mut receiver: mpsc::UnboundedReceiver<glutin::event::Event<'_, A::Message>>,
+ context: glutin::ContextWrapper<glutin::PossiblyCurrent, Window>,
+ exit_on_close_request: bool,
) where
A: Application + 'static,
E: Executor + 'static,
@@ -212,6 +214,8 @@ async fn run_instance<A, E, C>(
// Update window
state.synchronize(&application, context.window());
+ let should_exit = application.should_exit();
+
user_interface =
ManuallyDrop::new(application::build_user_interface(
&mut application,
@@ -220,6 +224,10 @@ async fn run_instance<A, E, C>(
state.logical_size(),
&mut debug,
));
+
+ if should_exit {
+ break;
+ }
}
debug.draw_started();
@@ -290,6 +298,7 @@ async fn run_instance<A, E, C>(
..
} => {
if application::requests_exit(&window_event, state.modifiers())
+ && exit_on_close_request
{
break;
}
diff --git a/native/src/window/event.rs b/native/src/window/event.rs
index fc746781..3aa1ab0b 100644
--- a/native/src/window/event.rs
+++ b/native/src/window/event.rs
@@ -12,6 +12,12 @@ pub enum Event {
height: u32,
},
+ /// 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 focused.
Focused,
diff --git a/src/application.rs b/src/application.rs
index 83ce900a..7b7de6d4 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -184,6 +184,13 @@ pub trait Application: Sized {
1.0
}
+ /// Returns whether the [`Application`] should be terminated.
+ ///
+ /// By default, it returns `false`.
+ fn should_exit(&self) -> bool {
+ false
+ }
+
/// Runs the [`Application`].
///
/// On native platforms, this method will take control of the current thread
@@ -284,6 +291,10 @@ where
fn scale_factor(&self) -> f64 {
self.0.scale_factor()
}
+
+ fn should_exit(&self) -> bool {
+ self.0.should_exit()
+ }
}
#[cfg(target_arch = "wasm32")]
diff --git a/src/settings.rs b/src/settings.rs
index c82a1354..2b32258d 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -25,6 +25,10 @@ pub struct Settings<Flags> {
/// The default value is 20.
pub default_text_size: u16,
+ /// Whether the [`Application`] should exit when the user requests the
+ /// window to close (e.g. the user presses the close button).
+ pub exit_on_close_request: bool,
+
/// If set to true, the renderer will try to perform antialiasing for some
/// primitives.
///
@@ -46,10 +50,11 @@ impl<Flags> Settings<Flags> {
Self {
flags,
- antialiasing: default_settings.antialiasing,
+ window: default_settings.window,
default_font: default_settings.default_font,
default_text_size: default_settings.default_text_size,
- window: default_settings.window,
+ exit_on_close_request: default_settings.exit_on_close_request,
+ antialiasing: default_settings.antialiasing,
}
}
}
@@ -61,10 +66,11 @@ where
fn default() -> Self {
Self {
flags: Default::default(),
- antialiasing: Default::default(),
+ window: Default::default(),
default_font: Default::default(),
default_text_size: 20,
- window: Default::default(),
+ exit_on_close_request: true,
+ antialiasing: false,
}
}
}
@@ -75,6 +81,7 @@ impl<Flags> From<Settings<Flags>> for iced_winit::Settings<Flags> {
iced_winit::Settings {
window: settings.window.into(),
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 ef6c8463..106d5218 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -91,6 +91,13 @@ pub trait Application: Program<Clipboard = Clipboard> {
fn scale_factor(&self) -> f64 {
1.0
}
+
+ /// Returns whether the [`Application`] should be terminated.
+ ///
+ /// By default, it returns `false`.
+ fn should_exit(&self) -> bool {
+ false
+ }
}
/// Runs an [`Application`] with an executor, compositor, and the provided
@@ -149,10 +156,11 @@ where
application,
compositor,
renderer,
- window,
runtime,
debug,
receiver,
+ window,
+ settings.exit_on_close_request,
));
let mut context = task::Context::from_waker(task::noop_waker_ref());
@@ -196,10 +204,11 @@ async fn run_instance<A, E, C>(
mut application: A,
mut compositor: C,
mut renderer: A::Renderer,
- window: winit::window::Window,
mut runtime: Runtime<E, Proxy<A::Message>, A::Message>,
mut debug: Debug,
mut receiver: mpsc::UnboundedReceiver<winit::event::Event<'_, A::Message>>,
+ window: winit::window::Window,
+ exit_on_close_request: bool,
) where
A: Application + 'static,
E: Executor + 'static,
@@ -279,6 +288,8 @@ async fn run_instance<A, E, C>(
// Update window
state.synchronize(&application, &window);
+ let should_exit = application.should_exit();
+
user_interface = ManuallyDrop::new(build_user_interface(
&mut application,
cache,
@@ -286,6 +297,10 @@ async fn run_instance<A, E, C>(
state.logical_size(),
&mut debug,
));
+
+ if should_exit {
+ break;
+ }
}
debug.draw_started();
@@ -358,7 +373,9 @@ async fn run_instance<A, E, C>(
event: window_event,
..
} => {
- if requests_exit(&window_event, state.modifiers()) {
+ if requests_exit(&window_event, state.modifiers())
+ && exit_on_close_request
+ {
break;
}
diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs
index 0e04b35d..0fa27413 100644
--- a/winit/src/conversion.rs
+++ b/winit/src/conversion.rs
@@ -33,6 +33,9 @@ pub fn window_event(
height: logical_size.height,
}))
}
+ WindowEvent::CloseRequested => {
+ Some(Event::Window(window::Event::CloseRequested))
+ }
WindowEvent::CursorMoved { position, .. } => {
let position = position.to_logical::<f64>(scale_factor);
diff --git a/winit/src/settings.rs b/winit/src/settings.rs
index 2e8715cd..9ce5cfc5 100644
--- a/winit/src/settings.rs
+++ b/winit/src/settings.rs
@@ -23,6 +23,10 @@ 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).
+ pub exit_on_close_request: bool,
}
/// The window settings of an application.