mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-23 10:26:34 +11:00
Add exit code to ControlFlow::Exit
(#2100)
* Add exit code to control flow and impl on linux * Fix examples to have an exit code * Fix doc examples to use an exit code * Improve documentation wording on the exit code * Add exit code example * Add exit code on windows * Change i32 as exit code to u8 This avoids nasty surprises with negative numbers on some unix-alikes due to two's complement. * Fix android usages of ControlFlow::Exit * Fix ios usages of ControlFlow::Exit * Fix web usages of ControlFlow::Exit * Add macos exit code * Add changelog note * Document exit code on display server disconnection * Revert "Change i32 as exit code to u8" This reverts commit f88fba0253b45de6a2ac0c3cbcf01f50503c9396. * Change Exit to ExitWithCode and make an Exit const * Revert "Add exit code example" This reverts commit fbd3d03de9c2d7516c7a63da489c99f498b710df. * Revert "Fix doc examples to use an exit code" This reverts commit daabcdf9ef9e16acad715c094ae442529e39fcbc. * Revert "Fix examples to have an exit code" This reverts commit 0df486896b8d106acf65ba83c45cc88d60d228e1. * Fix unix-alike to use ExitWithCode instead of Exit * Fix windows to use ExitWithCode rather than Exit * Silence warning about non-uppercase Exit const * Refactor exit code handling * Fix macos Exit usage and recover original semantic * Fix ios to use ExitWithCode instead of Exit * Update documentation to reflect ExitWithCode * Fix web to use ExitWithCode when needed, not Exit * Fix android to use ExitWithCode, not Exit * Apply documenation nits * Apply even more documentation nits * Move change in CHANGELOG.md under "Unreleased" * Try to use OS error code as exit code on wayland
This commit is contained in:
parent
2a2abc4843
commit
a52f755ce8
14 changed files with 140 additions and 92 deletions
|
@ -1,3 +1,7 @@
|
|||
# Unreleased
|
||||
|
||||
- **Breaking:** Rename the `Exit` variant of `ControlFlow` to `ExitWithCode`, which holds a value to control the exit code after running. Add an `Exit` constant which aliases to `ExitWithCode(0)` instead to avoid major breakage. This shouldn't affect most existing programs.
|
||||
|
||||
# 0.26.1 (2022-01-05)
|
||||
|
||||
- Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions.
|
||||
|
|
|
@ -64,9 +64,9 @@ impl<T> fmt::Debug for EventLoopWindowTarget<T> {
|
|||
///
|
||||
/// ## Persistency
|
||||
/// Almost every change is persistent between multiple calls to the event loop closure within a
|
||||
/// given run loop. The only exception to this is `Exit` which, once set, cannot be unset. Changes
|
||||
/// are **not** persistent between multiple calls to `run_return` - issuing a new call will reset
|
||||
/// the control flow to `Poll`.
|
||||
/// given run loop. The only exception to this is `ExitWithCode` which, once set, cannot be unset.
|
||||
/// Changes are **not** persistent between multiple calls to `run_return` - issuing a new call will
|
||||
/// reset the control flow to `Poll`.
|
||||
///
|
||||
/// [events_cleared]: crate::event::Event::RedrawEventsCleared
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -86,9 +86,29 @@ pub enum ControlFlow {
|
|||
/// arrives or the given time is reached.
|
||||
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,
|
||||
/// `control_flow` cannot be changed from `ExitWithCode`, and any future attempts to do so will
|
||||
/// result in the `control_flow` parameter being reset to `ExitWithCode`.
|
||||
///
|
||||
/// The contained number will be used as exit code. The [`Exit`] constant is a shortcut for this
|
||||
/// with exit code 0.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Android / iOS / WASM**: The supplied exit code is unused.
|
||||
/// - **Unix**: On most Unix-like platforms, only the 8 least significant bits will be used,
|
||||
/// which can cause surprises with negative exit values (`-42` would end up as `214`). See
|
||||
/// [`std::process::exit`].
|
||||
///
|
||||
/// [`Exit`]: ControlFlow::Exit
|
||||
ExitWithCode(i32),
|
||||
}
|
||||
|
||||
impl ControlFlow {
|
||||
/// Alias for [`ExitWithCode`]`(0)`.
|
||||
///
|
||||
/// [`ExitWithCode`]: ControlFlow::ExitWithCode
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Exit: Self = Self::ExitWithCode(0);
|
||||
}
|
||||
|
||||
impl Default for ControlFlow {
|
||||
|
@ -145,6 +165,11 @@ impl<T> EventLoop<T> {
|
|||
///
|
||||
/// Any values not passed to this function will *not* be dropped.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **X11 / Wayland**: The program terminates with exit code 1 if the display server
|
||||
/// disconnects.
|
||||
///
|
||||
/// [`ControlFlow`]: crate::event_loop::ControlFlow
|
||||
#[inline]
|
||||
pub fn run<F>(self, event_handler: F) -> !
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
//! You can retrieve events by calling [`EventLoop::run`][event_loop_run]. This function will
|
||||
//! dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and
|
||||
//! will run until the `control_flow` argument given to the closure is set to
|
||||
//! [`ControlFlow`]`::`[`Exit`], at which point [`Event`]`::`[`LoopDestroyed`] is emitted and the
|
||||
//! entire program terminates.
|
||||
//! [`ControlFlow`]`::`[`ExitWithCode`] (which [`ControlFlow`]`::`[`Exit`] aliases to), at which
|
||||
//! point [`Event`]`::`[`LoopDestroyed`] is emitted and the entire program terminates.
|
||||
//!
|
||||
//! Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop
|
||||
//! model, since that can't be implemented properly on some platforms (e.g web, iOS) and works poorly on
|
||||
|
@ -114,6 +114,7 @@
|
|||
//! [event_loop_run]: event_loop::EventLoop::run
|
||||
//! [`ControlFlow`]: event_loop::ControlFlow
|
||||
//! [`Exit`]: event_loop::ControlFlow::Exit
|
||||
//! [`ExitWithCode`]: event_loop::ControlFlow::ExitWithCode
|
||||
//! [`Window`]: window::Window
|
||||
//! [`WindowId`]: window::WindowId
|
||||
//! [`WindowBuilder`]: window::WindowBuilder
|
||||
|
|
|
@ -33,7 +33,12 @@ 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<F>(&mut self, event_handler: F)
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Unix-alikes** (**X11** or **Wayland**): This function returns `1` upon disconnection from
|
||||
/// the display server.
|
||||
fn run_return<F>(&mut self, event_handler: F) -> i32
|
||||
where
|
||||
F: FnMut(
|
||||
Event<'_, Self::UserEvent>,
|
||||
|
@ -45,7 +50,7 @@ pub trait EventLoopExtRunReturn {
|
|||
impl<T> EventLoopExtRunReturn for EventLoop<T> {
|
||||
type UserEvent = T;
|
||||
|
||||
fn run_return<F>(&mut self, event_handler: F)
|
||||
fn run_return<F>(&mut self, event_handler: F) -> i32
|
||||
where
|
||||
F: FnMut(
|
||||
Event<'_, Self::UserEvent>,
|
||||
|
|
|
@ -73,10 +73,10 @@ pub struct EventLoop<T: 'static> {
|
|||
|
||||
macro_rules! call_event_handler {
|
||||
( $event_handler:expr, $window_target:expr, $cf:expr, $event:expr ) => {{
|
||||
if $cf != ControlFlow::Exit {
|
||||
$event_handler($event, $window_target, &mut $cf);
|
||||
if let ControlFlow::ExitWithCode(code) = $cf {
|
||||
$event_handler($event, $window_target, &mut ControlFlow::ExitWithCode(code));
|
||||
} else {
|
||||
$event_handler($event, $window_target, &mut ControlFlow::Exit);
|
||||
$event_handler($event, $window_target, &mut $cf);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -103,11 +103,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
F: 'static
|
||||
+ FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
self.run_return(event_handler);
|
||||
::std::process::exit(0);
|
||||
let exit_code = self.run_return(event_handler);
|
||||
::std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, mut event_handler: F)
|
||||
pub fn run_return<F>(&mut self, mut event_handler: F) -> i32
|
||||
where
|
||||
F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -339,7 +339,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
);
|
||||
|
||||
match control_flow {
|
||||
ControlFlow::Exit => {
|
||||
ControlFlow::ExitWithCode(code) => {
|
||||
self.first_event = poll(
|
||||
self.looper
|
||||
.poll_once_timeout(Duration::from_millis(0))
|
||||
|
@ -349,7 +349,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
start: Instant::now(),
|
||||
requested_resume: None,
|
||||
};
|
||||
break 'event_loop;
|
||||
break 'event_loop code;
|
||||
}
|
||||
ControlFlow::Poll => {
|
||||
self.first_event = poll(
|
||||
|
|
|
@ -296,7 +296,7 @@ impl AppState {
|
|||
};
|
||||
(waiting_event_handler, event)
|
||||
}
|
||||
(ControlFlow::Exit, _) => bug!("unexpected `ControlFlow` `Exit`"),
|
||||
(ControlFlow::ExitWithCode(_), _) => bug!("unexpected `ControlFlow` `Exit`"),
|
||||
s => bug!("`EventHandler` unexpectedly woke up {:?}", s),
|
||||
};
|
||||
|
||||
|
@ -451,7 +451,7 @@ impl AppState {
|
|||
});
|
||||
self.waker.start()
|
||||
}
|
||||
(_, ControlFlow::Exit) => {
|
||||
(_, ControlFlow::ExitWithCode(_)) => {
|
||||
// https://developer.apple.com/library/archive/qa/qa1561/_index.html
|
||||
// it is not possible to quit an iOS app gracefully and programatically
|
||||
warn!("`ControlFlow::Exit` ignored on iOS");
|
||||
|
|
|
@ -655,7 +655,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy)
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, callback: F)
|
||||
pub fn run_return<F>(&mut self, callback: F) -> i32
|
||||
where
|
||||
F: FnMut(crate::event::Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -741,16 +741,13 @@ fn sticky_exit_callback<T, F>(
|
|||
) where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
// 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 {
|
||||
&mut dummy
|
||||
// make ControlFlow::ExitWithCode sticky by providing a dummy
|
||||
// control flow reference if it is already ExitWithCode.
|
||||
if let ControlFlow::ExitWithCode(code) = *control_flow {
|
||||
callback(evt, target, &mut ControlFlow::ExitWithCode(code))
|
||||
} else {
|
||||
control_flow
|
||||
};
|
||||
// user callback
|
||||
callback(evt, target, cf)
|
||||
callback(evt, target, control_flow)
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_is_main_thread(suggested_method: &str) {
|
||||
|
|
|
@ -206,11 +206,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
where
|
||||
F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &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<F>(&mut self, mut callback: F)
|
||||
pub fn run_return<F>(&mut self, mut callback: F) -> i32
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -235,7 +235,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
// 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 to the error's OS error code, or to 1 if not possible.
|
||||
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(..) {
|
||||
|
@ -431,20 +432,19 @@ impl<T: 'static> EventLoop<T> {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let Ok(dispatched) = queue.dispatch_pending(state, |_, _, _| unimplemented!()) {
|
||||
dispatched > 0
|
||||
} else {
|
||||
break;
|
||||
match queue.dispatch_pending(state, |_, _, _| unimplemented!()) {
|
||||
Ok(dispatched) => dispatched > 0,
|
||||
Err(error) => break error.raw_os_error().unwrap_or(1),
|
||||
}
|
||||
};
|
||||
|
||||
match control_flow {
|
||||
ControlFlow::Exit => break,
|
||||
ControlFlow::ExitWithCode(code) => break code,
|
||||
ControlFlow::Poll => {
|
||||
// Non-blocking dispatch.
|
||||
let timeout = Duration::from_millis(0);
|
||||
if self.loop_dispatch(Some(timeout)).is_err() {
|
||||
break;
|
||||
if let Err(error) = self.loop_dispatch(Some(timeout)) {
|
||||
break error.raw_os_error().unwrap_or(1);
|
||||
}
|
||||
|
||||
callback(
|
||||
|
@ -460,8 +460,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
None
|
||||
};
|
||||
|
||||
if self.loop_dispatch(timeout).is_err() {
|
||||
break;
|
||||
if let Err(error) = self.loop_dispatch(timeout) {
|
||||
break error.raw_os_error().unwrap_or(1);
|
||||
}
|
||||
|
||||
callback(
|
||||
|
@ -483,8 +483,8 @@ impl<T: 'static> EventLoop<T> {
|
|||
Duration::from_millis(0)
|
||||
};
|
||||
|
||||
if self.loop_dispatch(Some(duration)).is_err() {
|
||||
break;
|
||||
if let Err(error) = self.loop_dispatch(Some(duration)) {
|
||||
break error.raw_os_error().unwrap_or(1);
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
|
@ -510,9 +510,10 @@ impl<T: 'static> EventLoop<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
callback(Event::LoopDestroyed, &self.window_target, &mut control_flow);
|
||||
exit_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -258,7 +258,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
&self.target
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, mut callback: F)
|
||||
pub fn run_return<F>(&mut self, mut callback: F) -> i32
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -266,7 +266,7 @@ impl<T: 'static> EventLoop<T> {
|
|||
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<T: 'static> EventLoop<T> {
|
|||
let (deadline, timeout);
|
||||
|
||||
match control_flow {
|
||||
ControlFlow::Exit => break,
|
||||
ControlFlow::ExitWithCode(code) => break code,
|
||||
ControlFlow::Poll => {
|
||||
cause = StartCause::Poll;
|
||||
deadline = None;
|
||||
|
@ -376,21 +376,22 @@ impl<T: 'static> EventLoop<T> {
|
|||
requested_resume: deadline,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
callback(
|
||||
crate::event::Event::LoopDestroyed,
|
||||
&self.target,
|
||||
&mut control_flow,
|
||||
);
|
||||
exit_code
|
||||
}
|
||||
|
||||
pub fn run<F>(mut self, callback: F) -> !
|
||||
where
|
||||
F: 'static + FnMut(Event<'_, T>, &RootELW<T>, &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<F>(&mut self, callback: &mut F, control_flow: &mut ControlFlow)
|
||||
|
|
|
@ -62,7 +62,6 @@ pub trait EventHandler: Debug {
|
|||
|
||||
struct EventLoopHandler<T: 'static> {
|
||||
callback: Weak<RefCell<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>>,
|
||||
will_exit: bool,
|
||||
window_target: Rc<RootWindowTarget<T>>,
|
||||
}
|
||||
|
||||
|
@ -98,25 +97,25 @@ impl<T> Debug for EventLoopHandler<T> {
|
|||
impl<T> EventHandler for EventLoopHandler<T> {
|
||||
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) {
|
||||
self.with_callback(|this, mut callback| {
|
||||
(callback)(event.userify(), &this.window_target, control_flow);
|
||||
this.will_exit |= *control_flow == ControlFlow::Exit;
|
||||
if this.will_exit {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
if let ControlFlow::ExitWithCode(code) = *control_flow {
|
||||
let dummy = &mut ControlFlow::ExitWithCode(code);
|
||||
(callback)(event.userify(), &this.window_target, dummy);
|
||||
} else {
|
||||
(callback)(event.userify(), &this.window_target, control_flow);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_user_events(&mut self, control_flow: &mut ControlFlow) {
|
||||
self.with_callback(|this, mut callback| {
|
||||
let mut will_exit = this.will_exit;
|
||||
for event in this.window_target.p.receiver.try_iter() {
|
||||
(callback)(Event::UserEvent(event), &this.window_target, control_flow);
|
||||
will_exit |= *control_flow == ControlFlow::Exit;
|
||||
if will_exit {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
if let ControlFlow::ExitWithCode(code) = *control_flow {
|
||||
let dummy = &mut ControlFlow::ExitWithCode(code);
|
||||
(callback)(Event::UserEvent(event), &this.window_target, dummy);
|
||||
} else {
|
||||
(callback)(Event::UserEvent(event), &this.window_target, control_flow);
|
||||
}
|
||||
}
|
||||
this.will_exit = will_exit;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +159,10 @@ impl Handler {
|
|||
}
|
||||
|
||||
fn should_exit(&self) -> bool {
|
||||
*self.control_flow.lock().unwrap() == ControlFlow::Exit
|
||||
matches!(
|
||||
*self.control_flow.lock().unwrap(),
|
||||
ControlFlow::ExitWithCode(_)
|
||||
)
|
||||
}
|
||||
|
||||
fn get_control_flow_and_update_prev(&self) -> ControlFlow {
|
||||
|
@ -268,16 +270,20 @@ impl AppState {
|
|||
) {
|
||||
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
|
||||
callback,
|
||||
will_exit: false,
|
||||
window_target,
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn exit() {
|
||||
pub fn exit() -> i32 {
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::LoopDestroyed));
|
||||
HANDLER.set_in_callback(false);
|
||||
HANDLER.callback.lock().unwrap().take();
|
||||
if let ControlFlow::ExitWithCode(code) = HANDLER.get_old_and_new_control_flow().1 {
|
||||
code
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn launched(app_delegate: &Object) {
|
||||
|
@ -332,7 +338,7 @@ impl AppState {
|
|||
}
|
||||
}
|
||||
}
|
||||
ControlFlow::Exit => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
|
||||
ControlFlow::ExitWithCode(_) => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
|
||||
};
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(cause)));
|
||||
|
@ -435,7 +441,7 @@ impl AppState {
|
|||
}
|
||||
HANDLER.update_start_time();
|
||||
match HANDLER.get_old_and_new_control_flow() {
|
||||
(ControlFlow::Exit, _) | (_, ControlFlow::Exit) => (),
|
||||
(ControlFlow::ExitWithCode(_), _) | (_, ControlFlow::ExitWithCode(_)) => (),
|
||||
(old, new) if old == new => (),
|
||||
(_, ControlFlow::Wait) => HANDLER.waker().stop(),
|
||||
(_, ControlFlow::WaitUntil(instant)) => HANDLER.waker().start_at(instant),
|
||||
|
|
|
@ -155,11 +155,11 @@ impl<T> EventLoop<T> {
|
|||
where
|
||||
F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
self.run_return(callback);
|
||||
process::exit(0);
|
||||
let exit_code = self.run_return(callback);
|
||||
process::exit(exit_code);
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, callback: F)
|
||||
pub fn run_return<F>(&mut self, callback: F) -> i32
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ impl<T> EventLoop<T> {
|
|||
|
||||
self._callback = Some(Rc::clone(&callback));
|
||||
|
||||
autoreleasepool(|| unsafe {
|
||||
let exit_code = autoreleasepool(|| unsafe {
|
||||
let app = NSApp();
|
||||
assert_ne!(app, nil);
|
||||
|
||||
|
@ -192,9 +192,11 @@ impl<T> EventLoop<T> {
|
|||
drop(self._callback.take());
|
||||
resume_unwind(panic);
|
||||
}
|
||||
AppState::exit();
|
||||
AppState::exit()
|
||||
});
|
||||
drop(self._callback.take());
|
||||
|
||||
exit_code
|
||||
}
|
||||
|
||||
pub fn create_proxy(&self) -> Proxy<T> {
|
||||
|
|
|
@ -84,7 +84,7 @@ impl<T: 'static> Runner<T> {
|
|||
}
|
||||
|
||||
fn handle_single_event(&mut self, event: Event<'_, T>, control: &mut root::ControlFlow) {
|
||||
let is_closed = *control == root::ControlFlow::Exit;
|
||||
let is_closed = matches!(*control, root::ControlFlow::ExitWithCode(_));
|
||||
|
||||
(self.event_handler)(event, control);
|
||||
|
||||
|
@ -409,7 +409,7 @@ impl<T: 'static> Shared<T> {
|
|||
RunnerEnum::Destroyed => return,
|
||||
}
|
||||
|
||||
let is_closed = *control == root::ControlFlow::Exit;
|
||||
let is_closed = matches!(*control, root::ControlFlow::ExitWithCode(_));
|
||||
|
||||
// Don't take events out of the queue if the loop is closed or the runner doesn't exist
|
||||
// If the runner doesn't exist and this method recurses, it will recurse infinitely
|
||||
|
@ -456,7 +456,7 @@ impl<T: 'static> Shared<T> {
|
|||
),
|
||||
}
|
||||
}
|
||||
root::ControlFlow::Exit => State::Exit,
|
||||
root::ControlFlow::ExitWithCode(_) => State::Exit,
|
||||
};
|
||||
|
||||
match *self.0.runner.borrow_mut() {
|
||||
|
|
|
@ -188,11 +188,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
where
|
||||
F: 'static + FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
self.run_return(event_handler);
|
||||
::std::process::exit(0);
|
||||
let exit_code = self.run_return(event_handler);
|
||||
::std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
pub fn run_return<F>(&mut self, mut event_handler: F)
|
||||
pub fn run_return<F>(&mut self, mut event_handler: F) -> i32
|
||||
where
|
||||
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||
{
|
||||
|
@ -209,13 +209,13 @@ impl<T: 'static> EventLoop<T> {
|
|||
|
||||
let runner = &self.window_target.p.runner_shared;
|
||||
|
||||
unsafe {
|
||||
let exit_code = unsafe {
|
||||
let mut msg = mem::zeroed();
|
||||
|
||||
runner.poll();
|
||||
'main: loop {
|
||||
if 0 == winuser::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) {
|
||||
break 'main;
|
||||
break 'main 0;
|
||||
}
|
||||
winuser::TranslateMessage(&msg);
|
||||
winuser::DispatchMessageW(&msg);
|
||||
|
@ -225,16 +225,20 @@ impl<T: 'static> EventLoop<T> {
|
|||
panic::resume_unwind(payload);
|
||||
}
|
||||
|
||||
if runner.control_flow() == ControlFlow::Exit && !runner.handling_events() {
|
||||
break 'main;
|
||||
if let ControlFlow::ExitWithCode(code) = runner.control_flow() {
|
||||
if !runner.handling_events() {
|
||||
break 'main code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unsafe {
|
||||
runner.loop_destroyed();
|
||||
}
|
||||
|
||||
runner.reset_runner();
|
||||
exit_code
|
||||
}
|
||||
|
||||
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
||||
|
@ -763,7 +767,7 @@ unsafe fn process_control_flow<T: 'static>(runner: &EventLoopRunner<T>) {
|
|||
Box::into_raw(WaitUntilInstantBox::new(until)) as LPARAM,
|
||||
);
|
||||
}
|
||||
ControlFlow::Exit => (),
|
||||
ControlFlow::ExitWithCode(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -241,10 +241,10 @@ impl<T> EventLoopRunner<T> {
|
|||
let mut event_handler = self.event_handler.take()
|
||||
.expect("either event handler is re-entrant (likely), or no event handler is registered (very unlikely)");
|
||||
|
||||
if control_flow != ControlFlow::Exit {
|
||||
event_handler(event, &mut control_flow);
|
||||
if let ControlFlow::ExitWithCode(code) = control_flow {
|
||||
event_handler(event, &mut ControlFlow::ExitWithCode(code));
|
||||
} else {
|
||||
event_handler(event, &mut ControlFlow::Exit);
|
||||
event_handler(event, &mut control_flow);
|
||||
}
|
||||
|
||||
assert!(self.event_handler.replace(Some(event_handler)).is_none());
|
||||
|
@ -372,10 +372,12 @@ impl<T> EventLoopRunner<T> {
|
|||
let start_cause = match (init, self.control_flow()) {
|
||||
(true, _) => StartCause::Init,
|
||||
(false, ControlFlow::Poll) => StartCause::Poll,
|
||||
(false, ControlFlow::Exit) | (false, ControlFlow::Wait) => StartCause::WaitCancelled {
|
||||
requested_resume: None,
|
||||
start: self.last_events_cleared.get(),
|
||||
},
|
||||
(false, ControlFlow::ExitWithCode(_)) | (false, ControlFlow::Wait) => {
|
||||
StartCause::WaitCancelled {
|
||||
requested_resume: None,
|
||||
start: self.last_events_cleared.get(),
|
||||
}
|
||||
}
|
||||
(false, ControlFlow::WaitUntil(requested_resume)) => {
|
||||
if Instant::now() < requested_resume {
|
||||
StartCause::WaitCancelled {
|
||||
|
|
Loading…
Add table
Reference in a new issue