diff --git a/src/event_loop.rs b/src/event_loop.rs index 881a0845..0986b3aa 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -310,11 +310,14 @@ impl EventLoop { /// asynchronously (via the browser's own, internal, event loop) and doesn't block the /// current thread of execution like it does on other platforms. /// + /// This function won't be available with `target_feature = "exception-handling"`. + /// /// [`ControlFlow`]: crate::event_loop::ControlFlow #[inline] + #[cfg(not(all(wasm_platform, target_feature = "exception-handling")))] pub fn run(self, event_handler: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.run(event_handler) } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 86cf7f92..c40377be 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -526,8 +526,7 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> where - F: 'static - + FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { self.run_ondemand(event_handler) } diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index cde6430e..070f0cb3 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -106,7 +106,7 @@ impl EventLoop { pub fn run(self, event_handler: F) -> ! where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { unsafe { let application = UIApplication::shared(MainThreadMarker::new().unwrap()); @@ -116,10 +116,18 @@ impl EventLoop { `EventLoop` cannot be `run` after a call to `UIApplicationMain` on iOS\n\ Note: `EventLoop::run` calls `UIApplicationMain` on iOS", ); - app_state::will_launch(Box::new(EventLoopHandler { + + let event_handler = std::mem::transmute::< + Box, &RootEventLoopWindowTarget, &mut ControlFlow)>, + Box>, + >(Box::new(event_handler)); + + let handler = EventLoopHandler { f: event_handler, event_loop: self.window_target, - })); + }; + + app_state::will_launch(Box::new(handler)); // Ensure application delegate is initialized view::WinitApplicationDelegate::class(); @@ -314,17 +322,20 @@ fn setup_control_flow_observers() { #[derive(Debug)] pub enum Never {} +type EventHandlerCallback = + dyn FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow) + 'static; + pub trait EventHandler: Debug { fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow); fn handle_user_events(&mut self, control_flow: &mut ControlFlow); } -struct EventLoopHandler { - f: F, +struct EventLoopHandler { + f: Box>, event_loop: RootEventLoopWindowTarget, } -impl Debug for EventLoopHandler { +impl Debug for EventLoopHandler { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("EventLoopHandler") .field("event_loop", &self.event_loop) @@ -332,11 +343,7 @@ impl Debug for EventLoopHandler { } } -impl EventHandler for EventLoopHandler -where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), - T: 'static, -{ +impl EventHandler for EventLoopHandler { fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow) { (self.f)( event.map_nonuser_event().unwrap(), diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 0adaa448..9d8b4782 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -195,7 +195,7 @@ impl EventLoop { pub fn run(mut self, callback: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event, &RootWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootWindowTarget, &mut ControlFlow), { self.run_ondemand(callback) } diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 3cfc2b86..71d733d9 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -445,8 +445,7 @@ impl EventLoop { pub fn run(mut self, mut event_handler_inner: F) -> Result<(), RunLoopError> where - F: 'static - + FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { // Wrapper for event handler function that prevents ExitWithCode from being unset. let mut event_handler = diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 4ed00367..60c9a086 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -29,11 +29,23 @@ impl EventLoop { } } - pub fn run(self, event_handler: F) -> ! + pub fn run(self, mut event_handler: F) -> ! where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { - self.spawn_inner(event_handler, false); + let target = RootEventLoopWindowTarget { + p: self.elw.p.clone(), + _marker: PhantomData, + }; + + // SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`. + let handler: Box = + Box::new(|event, flow| event_handler(event, &target, flow)); + // SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe + // because this function will never return and all resources not cleaned up by the point we + // `throw` will leak, making this actually `'static`. + let handler = unsafe { std::mem::transmute(handler) }; + self.elw.p.run(handler, false); // Throw an exception to break out of Rust execution and use unreachable to tell the // compiler this function won't return, giving it a return type of '!' @@ -44,14 +56,7 @@ impl EventLoop { unreachable!(); } - pub fn spawn(self, event_handler: F) - where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), - { - self.spawn_inner(event_handler, true); - } - - fn spawn_inner(self, mut event_handler: F, event_loop_recreation: bool) + pub fn spawn(self, mut event_handler: F) where F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { @@ -62,7 +67,7 @@ impl EventLoop { self.elw.p.run( Box::new(move |event, flow| event_handler(event, &target, flow)), - event_loop_recreation, + true, ); } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 9856fca3..7f6c1888 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -248,7 +248,7 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { self.run_ondemand(event_handler) }