diff --git a/src/event_loop.rs b/src/event_loop.rs index edc5670ac..54a97207d 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -87,8 +87,9 @@ pub enum ControlFlow { WaitUntil(Instant), /// Send a `LoopDestroyed` event and stop the event loop. This variant is *sticky* - once set, /// `control_flow` cannot be changed from `Exit`, and any future attempts to do so will result - /// in the `control_flow` parameter being reset to `Exit`. - Exit, + /// in the `control_flow` parameter being reset to `Exit`. The contained number will be used as + /// exit code, if the platform supports exiting with one. + Exit(i32), } impl Default for ControlFlow { diff --git a/src/platform/run_return.rs b/src/platform/run_return.rs index 932d9e38a..1e1d0d831 100644 --- a/src/platform/run_return.rs +++ b/src/platform/run_return.rs @@ -33,7 +33,7 @@ pub trait EventLoopExtRunReturn { /// underlying OS APIs, which cannot be hidden by `winit` without severe stability repercussions. /// /// You are strongly encouraged to use `run`, unless the use of this is absolutely necessary. - fn run_return(&mut self, event_handler: F) + fn run_return(&mut self, event_handler: F) -> i32 where F: FnMut( Event<'_, Self::UserEvent>, @@ -45,7 +45,7 @@ pub trait EventLoopExtRunReturn { impl EventLoopExtRunReturn for EventLoop { type UserEvent = T; - fn run_return(&mut self, event_handler: F) + fn run_return(&mut self, event_handler: F) -> i32 where F: FnMut( Event<'_, Self::UserEvent>, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index dfcc489fc..d4e803517 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -655,7 +655,7 @@ impl EventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) } - pub fn run_return(&mut self, callback: F) + pub fn run_return(&mut self, callback: F) -> i32 where F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), { @@ -743,8 +743,9 @@ fn sticky_exit_callback( { // make ControlFlow::Exit sticky by providing a dummy // control flow reference if it is already Exit. - let mut dummy = ControlFlow::Exit; - let cf = if *control_flow == ControlFlow::Exit { + let mut dummy; + let cf = if let ControlFlow::Exit(code) = *control_flow { + dummy = ControlFlow::Exit(code); &mut dummy } else { control_flow diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 9ae639356..695cd037c 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -206,11 +206,11 @@ impl EventLoop { where F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow) + 'static, { - self.run_return(callback); - process::exit(0) + let exit_code = self.run_return(callback); + process::exit(exit_code); } - pub fn run_return(&mut self, mut callback: F) + pub fn run_return(&mut self, mut callback: F) -> i32 where F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), { @@ -235,7 +235,9 @@ impl EventLoop { // really an option. Instead we inform that the event loop got destroyed. We may // communicate an error that something was terminated, but winit doesn't provide us // with an API to do that via some event. - loop { + // Still, we set the exit code as 1 (non-zero) to inform at least about something + // "unusual". + let exit_code = loop { // Handle pending user events. We don't need back buffer, since we can't dispatch // user events indirectly via callback to the user. for user_event in pending_user_events.borrow_mut().drain(..) { @@ -434,17 +436,17 @@ impl EventLoop { if let Ok(dispatched) = queue.dispatch_pending(state, |_, _, _| unimplemented!()) { dispatched > 0 } else { - break; + break 1; } }; match control_flow { - ControlFlow::Exit => break, + ControlFlow::Exit(code) => break code, ControlFlow::Poll => { // Non-blocking dispatch. let timeout = Duration::from_millis(0); if self.loop_dispatch(Some(timeout)).is_err() { - break; + break 1; } callback( @@ -461,7 +463,7 @@ impl EventLoop { }; if self.loop_dispatch(timeout).is_err() { - break; + break 1; } callback( @@ -484,7 +486,7 @@ impl EventLoop { }; if self.loop_dispatch(Some(duration)).is_err() { - break; + break 1; } let now = Instant::now(); @@ -510,9 +512,10 @@ impl EventLoop { } } } - } + }; callback(Event::LoopDestroyed, &self.window_target, &mut control_flow); + exit_code } #[inline] diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 7adf80e90..e655e6da3 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -258,7 +258,7 @@ impl EventLoop { &self.target } - pub fn run_return(&mut self, mut callback: F) + pub fn run_return(&mut self, mut callback: F) -> i32 where F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), { @@ -266,7 +266,7 @@ impl EventLoop { let mut events = Events::with_capacity(8); let mut cause = StartCause::Init; - loop { + let exit_code = loop { sticky_exit_callback( crate::event::Event::NewEvents(cause), &self.target, @@ -329,7 +329,7 @@ impl EventLoop { let (deadline, timeout); match control_flow { - ControlFlow::Exit => break, + ControlFlow::Exit(code) => break code, ControlFlow::Poll => { cause = StartCause::Poll; deadline = None; @@ -376,21 +376,22 @@ impl EventLoop { requested_resume: deadline, }; } - } + }; callback( crate::event::Event::LoopDestroyed, &self.target, &mut control_flow, ); + exit_code } pub fn run(mut self, callback: F) -> ! where F: 'static + FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), { - self.run_return(callback); - ::std::process::exit(0); + let exit_code = self.run_return(callback); + ::std::process::exit(exit_code); } fn drain_events(&mut self, callback: &mut F, control_flow: &mut ControlFlow)