diff --git a/CHANGELOG.md b/CHANGELOG.md index 17f0f522d2..eccec931f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased +- The `EventLoopWindowTarget` passed to the `EventLoop::run` callback now has a lifetime of `'static`. +- The `EventLoopWindowTarget` passed to the `EventLoop::run_return` callback now lives for as long as the reference to the event loop. - Build docs on `docs.rs` for iOS and Android as well. - **Breaking:** Removed the `WindowAttributes` struct, since all its functionality is accessible from `WindowBuilder`. - Added `WindowBuilder::transparent` getter to check if the user set `transparent` attribute. diff --git a/src/event_loop.rs b/src/event_loop.rs index 890e4e560e..335c394ad7 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -271,7 +271,7 @@ impl EventLoop { #[inline] pub fn run(self, event_handler: F) -> ! where - F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event<'_, T>, &'static EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.run(event_handler) } diff --git a/src/platform/run_return.rs b/src/platform/run_return.rs index 5c25461540..f5bad52c5b 100644 --- a/src/platform/run_return.rs +++ b/src/platform/run_return.rs @@ -9,6 +9,11 @@ target_os = "openbsd" ))] +use std::{ + panic::{catch_unwind, AssertUnwindSafe}, + process, +}; + use crate::{ event::Event, event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, @@ -39,11 +44,11 @@ pub trait EventLoopExtRunReturn { /// /// - **Unix-alikes** (**X11** or **Wayland**): This function returns `1` upon disconnection from /// the display server. - fn run_return(&mut self, event_handler: F) -> i32 + fn run_return<'a, F>(&'a mut self, event_handler: F) -> i32 where F: FnMut( Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, + &'a EventLoopWindowTarget, &mut ControlFlow, ); } @@ -51,14 +56,37 @@ pub trait EventLoopExtRunReturn { impl EventLoopExtRunReturn for EventLoop { type UserEvent = T; - fn run_return(&mut self, event_handler: F) -> i32 + fn run_return<'a, F>(&'a mut self, event_handler: F) -> i32 where F: FnMut( Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, + &'a EventLoopWindowTarget, &mut ControlFlow, ), { self.event_loop.run_return(event_handler) } } + +impl crate::platform_impl::EventLoop { + pub fn run(mut self, callback: F) -> ! + where + F: 'static + FnMut(Event<'_, T>, &'static EventLoopWindowTarget, &mut ControlFlow), + { + // SAFETY: `process::exit` will terminate the entire program before `self` is + // dropped, and `catch_unwind` prevents control from from exiting this function + // by panicking, therefore it will live for the rest of the program ('static). + // + // I believe this pointer casting is the correct way to do it because that's how + // `Box::leak` is implemented (https://doc.rust-lang.org/1.60.0/src/alloc/boxed.rs.html#1147-1152) + let this: &'static mut Self = unsafe { &mut *(&mut self as *mut Self) }; + // Note: we don't touch `callback` again if this unwinds, so it doesn't matter + // if it's unwind safe. + let exit_code = catch_unwind(AssertUnwindSafe(|| this.run_return(callback))) + // 101 seems to be the status code Rust uses for panics. + // Note: the panic message gets printed before unwinding, so we don't have to print it + // ourselves. + .unwrap_or(101); + process::exit(exit_code); + } +} diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index d7b643b381..2e02a98b92 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -271,25 +271,16 @@ impl EventLoop { } } - pub fn run(mut self, event_handler: F) -> ! + pub fn run_return<'a, F>(&'a mut self, mut event_handler: F) -> i32 where - F: 'static - + FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), - { - let exit_code = self.run_return(event_handler); - ::std::process::exit(exit_code); - } - - pub fn run_return(&mut self, mut event_handler: F) -> i32 - where - F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + F: FnMut(event::Event<'_, T>, &'a event_loop::EventLoopWindowTarget, &mut ControlFlow), { let mut control_flow = ControlFlow::default(); 'event_loop: loop { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::NewEvents(self.start_cause) ); @@ -302,7 +293,7 @@ impl EventLoop { Event::WindowCreated => { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::Resumed ); @@ -312,7 +303,7 @@ impl EventLoop { Event::WindowDestroyed => { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::Suspended ); @@ -337,7 +328,7 @@ impl EventLoop { }; call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event ); @@ -346,7 +337,7 @@ impl EventLoop { Event::WindowHasFocus => { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::WindowEvent { window_id: window::WindowId(WindowId), @@ -357,7 +348,7 @@ impl EventLoop { Event::WindowLostFocus => { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::WindowEvent { window_id: window::WindowId(WindowId), @@ -427,7 +418,7 @@ impl EventLoop { }; call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event ); @@ -458,7 +449,7 @@ impl EventLoop { }; call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event ); @@ -474,7 +465,7 @@ impl EventLoop { while let Some(event) = user_queue.pop_front() { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::UserEvent(event) ); @@ -488,7 +479,7 @@ impl EventLoop { call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::MainEventsCleared ); @@ -499,17 +490,17 @@ impl EventLoop { window_id: window::WindowId(WindowId), event: event::WindowEvent::Resized(size), }; - call_event_handler!(event_handler, self.window_target(), control_flow, event); + call_event_handler!(event_handler, &self.window_target, control_flow, event); } if redraw && self.running { let event = event::Event::RedrawRequested(window::WindowId(WindowId)); - call_event_handler!(event_handler, self.window_target(), control_flow, event); + call_event_handler!(event_handler, &self.window_target, control_flow, event); } call_event_handler!( event_handler, - self.window_target(), + &self.window_target, control_flow, event::Event::RedrawEventsCleared ); diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index 1a32fe56b2..628a969f3c 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -104,7 +104,7 @@ impl EventLoop { pub fn run(self, event_handler: F) -> ! where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event<'_, T>, &'static RootEventLoopWindowTarget, &mut ControlFlow), { unsafe { let application: *mut c_void = msg_send![class!(UIApplication), sharedApplication]; @@ -115,9 +115,16 @@ impl EventLoop { `EventLoop` cannot be `run` after a call to `UIApplicationMain` on iOS\n\ Note: `EventLoop::run` calls `UIApplicationMain` on iOS" ); + // SAFETY: `UIApplicationMain` will never return, meaning that this function + // will never return, and so `self.window_target` will never be dropped and live + // for `'static`. + // + // I believe this pointer casting is the correct way to do it because that's how + // `Box::leak` is implemented (https://doc.rust-lang.org/1.60.0/src/alloc/boxed.rs.html#1147-1152) + let window_target: &'static _ = &*(&self.window_target as *const _); app_state::will_launch(Box::new(EventLoopHandler { f: event_handler, - event_loop: self.window_target, + event_loop: window_target, })); UIApplicationMain( @@ -308,7 +315,7 @@ pub trait EventHandler: Debug { struct EventLoopHandler { f: F, - event_loop: RootEventLoopWindowTarget, + event_loop: &'static RootEventLoopWindowTarget, } impl Debug for EventLoopHandler { @@ -321,20 +328,20 @@ impl Debug for EventLoopHandler { impl EventHandler for EventLoopHandler where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event<'_, T>, &'static RootEventLoopWindowTarget, &mut ControlFlow), T: 'static, { fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) { (self.f)( event.map_nonuser_event().unwrap(), - &self.event_loop, + self.event_loop, control_flow, ); } fn handle_user_events(&mut self, control_flow: &mut ControlFlow) { for event in self.event_loop.p.receiver.try_iter() { - (self.f)(Event::UserEvent(event), &self.event_loop, control_flow); + (self.f)(Event::UserEvent(event), self.event_loop, control_flow); } } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index b2e779479d..6fb717931d 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -710,20 +710,13 @@ impl EventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) } - pub fn run_return(&mut self, callback: F) -> i32 + pub fn run_return<'a, F>(&'a mut self, callback: F) -> i32 where - F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(crate::event::Event<'_, T>, &'a RootELW, &mut ControlFlow), { x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_return(callback)) } - pub fn run(self, callback: F) -> ! - where - F: 'static + FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), - { - x11_or_wayland!(match self; EventLoop(evlp) => evlp.run(callback)) - } - pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target()) } @@ -798,13 +791,13 @@ impl EventLoopWindowTarget { } } -fn sticky_exit_callback( +fn sticky_exit_callback<'a, T, F>( evt: Event<'_, T>, - target: &RootELW, + target: &'a RootELW, control_flow: &mut ControlFlow, callback: &mut F, ) where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootELW, &mut ControlFlow), { // make ControlFlow::ExitWithCode sticky by providing a dummy // control flow reference if it is already ExitWithCode. diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index b2948a9b15..67c948d6c1 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -1,8 +1,7 @@ use std::cell::RefCell; use std::collections::HashMap; use std::error::Error; -use std::io::Result as IOResult; -use std::process; +use std::io; use std::rc::Rc; use std::time::{Duration, Instant}; @@ -201,17 +200,9 @@ impl EventLoop { Ok(event_loop) } - pub fn run(mut self, callback: F) -> ! + pub fn run_return<'a, F>(&'a mut self, mut callback: F) -> i32 where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow) + 'static, - { - let exit_code = self.run_return(callback); - process::exit(exit_code); - } - - pub fn run_return(&mut self, mut callback: F) -> i32 - where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootEventLoopWindowTarget, &mut ControlFlow), { let mut control_flow = ControlFlow::Poll; let pending_user_events = self.pending_user_events.clone(); @@ -235,6 +226,14 @@ impl EventLoop { // Send pending events to the server. let _ = self.display.flush(); + let mut state = match &self.window_target.p { + PlatformEventLoopWindowTarget::Wayland(window_target) => { + window_target.state.borrow_mut() + } + #[cfg(feature = "x11")] + _ => unreachable!(), + }; + // During the run of the user callback, some other code monitoring and reading the // Wayland socket may have been run (mesa for example does this with vsync), if that // is the case, some events may have been enqueued in our event queue. @@ -245,15 +244,8 @@ impl EventLoop { let instant_wakeup = { let mut wayland_source = self.wayland_dispatcher.as_source_mut(); let queue = wayland_source.queue(); - let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => { - window_target.state.get_mut() - } - #[cfg(feature = "x11")] - _ => unreachable!(), - }; - match queue.dispatch_pending(state, |_, _, _| unimplemented!()) { + match queue.dispatch_pending(&mut *state, |_, _, _| unimplemented!()) { Ok(dispatched) => dispatched > 0, Err(error) => break error.raw_os_error().unwrap_or(1), } @@ -264,10 +256,12 @@ impl EventLoop { ControlFlow::Poll => { // Non-blocking dispatch. let timeout = Duration::from_millis(0); - if let Err(error) = self.loop_dispatch(Some(timeout)) { - break error.raw_os_error().unwrap_or(1); + if let Err(error) = self.event_loop.dispatch(timeout, &mut state) { + break io::Error::from(error).raw_os_error().unwrap_or(1); } + drop(state); + callback( Event::NewEvents(StartCause::Poll), &self.window_target, @@ -281,10 +275,12 @@ impl EventLoop { None }; - if let Err(error) = self.loop_dispatch(timeout) { - break error.raw_os_error().unwrap_or(1); + if let Err(error) = self.event_loop.dispatch(timeout, &mut state) { + break io::Error::from(error).raw_os_error().unwrap_or(1); } + drop(state); + callback( Event::NewEvents(StartCause::WaitCancelled { start: Instant::now(), @@ -304,12 +300,14 @@ impl EventLoop { Duration::from_millis(0) }; - if let Err(error) = self.loop_dispatch(Some(duration)) { - break error.raw_os_error().unwrap_or(1); + if let Err(error) = self.event_loop.dispatch(duration, &mut state) { + break io::Error::from(error).raw_os_error().unwrap_or(1); } let now = Instant::now(); + drop(state); + if now < deadline { callback( Event::NewEvents(StartCause::WaitCancelled { @@ -521,25 +519,13 @@ impl EventLoop { &self.window_target } - fn with_state U>(&mut self, f: F) -> U { - let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(feature = "x11")] - _ => unreachable!(), - }; - - f(state) - } - - fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { - let state = match &mut self.window_target.p { - PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), + fn with_state U>(&self, f: F) -> U { + match &self.window_target.p { + PlatformEventLoopWindowTarget::Wayland(window_target) => { + f(&mut window_target.state.borrow_mut()) + } #[cfg(feature = "x11")] _ => unreachable!(), - }; - - self.event_loop - .dispatch(timeout, state) - .map_err(|error| error.into()) + } } } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 9789f03625..77414e20f9 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -304,40 +304,44 @@ impl EventLoop { &self.target } - pub fn run_return(&mut self, mut callback: F) -> i32 + pub fn run_return<'a, F>(&'a mut self, mut callback: F) -> i32 where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootELW, &mut ControlFlow), { struct IterationResult { deadline: Option, timeout: Option, wait_start: Instant, } - fn single_iteration( - this: &mut EventLoop, + // We can't just take an `&mut EventLoop` because that results in having to have an immutable reference to `self.target` and a mutable reference to `self` at the same time, due to `target`'s extended lifetime. + fn single_iteration<'a, T, F>( + target: &'a RootELW, + event_processor: &mut EventProcessor, + user_receiver: &mut PeekableReceiver, + redraw_receiver: &mut PeekableReceiver, control_flow: &mut ControlFlow, cause: &mut StartCause, callback: &mut F, ) -> IterationResult where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootELW, &mut ControlFlow), { sticky_exit_callback( crate::event::Event::NewEvents(*cause), - &this.target, + target, control_flow, callback, ); // Process all pending events - this.drain_events(callback, control_flow); + EventLoop::::drain_events(target, event_processor, callback, control_flow); // Empty the user event buffer { - while let Ok(event) = this.user_receiver.try_recv() { + while let Ok(event) = user_receiver.try_recv() { sticky_exit_callback( crate::event::Event::UserEvent(event), - &this.target, + target, control_flow, callback, ); @@ -347,7 +351,7 @@ impl EventLoop { { sticky_exit_callback( crate::event::Event::MainEventsCleared, - &this.target, + target, control_flow, callback, ); @@ -356,7 +360,7 @@ impl EventLoop { { let mut windows = HashSet::new(); - while let Ok(window_id) = this.redraw_receiver.try_recv() { + while let Ok(window_id) = redraw_receiver.try_recv() { windows.insert(window_id); } @@ -364,7 +368,7 @@ impl EventLoop { let window_id = crate::window::WindowId(super::WindowId::X(window_id)); sticky_exit_callback( Event::RedrawRequested(window_id), - &this.target, + target, control_flow, callback, ); @@ -374,7 +378,7 @@ impl EventLoop { { sticky_exit_callback( crate::event::Event::RedrawEventsCleared, - &this.target, + target, control_flow, callback, ); @@ -430,7 +434,15 @@ impl EventLoop { let mut cause = StartCause::Init; // run the initial loop iteration - let mut iter_result = single_iteration(self, &mut control_flow, &mut cause, &mut callback); + let mut iter_result = single_iteration( + &self.target, + &mut self.event_processor, + &mut self.user_receiver, + &mut self.redraw_receiver, + &mut control_flow, + &mut cause, + &mut callback, + ); let exit_code = loop { if let ControlFlow::ExitWithCode(code) = control_flow { @@ -470,7 +482,15 @@ impl EventLoop { }; } - iter_result = single_iteration(self, &mut control_flow, &mut cause, &mut callback); + iter_result = single_iteration( + &self.target, + &mut self.event_processor, + &mut self.user_receiver, + &mut self.redraw_receiver, + &mut control_flow, + &mut cause, + &mut callback, + ); }; callback( @@ -481,25 +501,21 @@ impl EventLoop { exit_code } - pub fn run(mut self, callback: F) -> ! - where - F: 'static + FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), - { - let exit_code = self.run_return(callback); - ::std::process::exit(exit_code); - } - - fn drain_events(&mut self, callback: &mut F, control_flow: &mut ControlFlow) - where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + // We can't just take `self` because that results in having to have an immutable reference to `self.target` and a mutable reference to `self` at the same time. + fn drain_events<'a, F>( + target: &'a RootELW, + event_processor: &mut EventProcessor, + callback: &mut F, + control_flow: &mut ControlFlow, + ) where + F: FnMut(Event<'_, T>, &'a RootELW, &mut ControlFlow), { - let target = &self.target; let mut xev = MaybeUninit::uninit(); - let wt = get_xtarget(&self.target); + let wt = get_xtarget(target); - while unsafe { self.event_processor.poll_one_event(xev.as_mut_ptr()) } { + while unsafe { event_processor.poll_one_event(xev.as_mut_ptr()) } { let mut xev = unsafe { xev.assume_init() }; - self.event_processor.process_event(&mut xev, |event| { + event_processor.process_event(&mut xev, |event| { sticky_exit_callback( event, target, diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index c39036997d..1f5b3d0ba1 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -6,7 +6,7 @@ use std::{ mem, os::raw::c_void, panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe}, - process, ptr, + ptr, rc::{Rc, Weak}, sync::mpsc, }; @@ -178,17 +178,9 @@ impl EventLoop { &self.window_target } - pub fn run(mut self, callback: F) -> ! + pub fn run_return<'a, F>(&'a mut self, callback: F) -> i32 where - F: 'static + FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow), - { - let exit_code = self.run_return(callback); - process::exit(exit_code); - } - - pub fn run_return(&mut self, callback: F) -> i32 - where - F: FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootWindowTarget, &mut ControlFlow), { // This transmute is always safe, in case it was reached through `run`, since our // lifetime will be already 'static. In other cases caller should ensure that all data @@ -196,7 +188,7 @@ impl EventLoop { // everything to event loop, so this is something that they should care about. let callback = unsafe { mem::transmute::< - Rc, &RootWindowTarget, &mut ControlFlow)>>, + Rc, &'a RootWindowTarget, &mut ControlFlow)>>, Rc, &RootWindowTarget, &mut ControlFlow)>>, >(Rc::new(RefCell::new(callback))) }; diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index a8d234cf29..a90983d00c 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -31,15 +31,18 @@ impl EventLoop { pub fn run(self, mut event_handler: F) -> ! where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event<'_, T>, &'static RootEventLoopWindowTarget, &mut ControlFlow), { - let target = RootEventLoopWindowTarget { + // `Box::leak` the `EventLoopWindowTarget` to make it last for `'static`. + // This is a memory leak, but it doesn't really matter because only one + // `EventLoop` can ever be created. + let target: &'static _ = Box::leak(Box::new(RootEventLoopWindowTarget { p: self.elw.p.clone(), _marker: PhantomData, - }; + })); self.elw.p.run(Box::new(move |event, flow| { - event_handler(event, &target, flow) + event_handler(event, target, flow) })); // Throw an exception to break out of Rust exceution and use unreachable to tell the diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 7e4b7fbdb8..94ce476d91 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -223,17 +223,9 @@ impl EventLoop { &self.window_target } - pub fn run(mut self, event_handler: F) -> ! + pub fn run_return<'a, F>(&'a mut self, mut event_handler: F) -> i32 where - F: 'static + FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), - { - let exit_code = self.run_return(event_handler); - ::std::process::exit(exit_code); - } - - pub fn run_return(&mut self, mut event_handler: F) -> i32 - where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event<'_, T>, &'a RootELW, &mut ControlFlow), { let event_loop_windows_ref = &self.window_target;