diff --git a/CHANGELOG.md b/CHANGELOG.md index fbd1c237ef..9ba9563278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased +- Added `EventLoopExtWebSys` with a `spawn` method to start the event loop without throwing an exception. - Added `WindowEvent::Occluded(bool)`, currently implemented on macOS and X11. - On X11, fix events for caps lock key not being sent - Build docs on `docs.rs` for iOS and Android as well. diff --git a/src/platform/web.rs b/src/platform/web.rs index 36c2a53985..56017c8ae1 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -5,6 +5,10 @@ //! to retrieve the canvas from the Window. Alternatively, use the [`WindowBuilderExtWebSys`] trait //! to provide your own canvas. +use crate::event::Event; +use crate::event_loop::ControlFlow; +use crate::event_loop::EventLoop; +use crate::event_loop::EventLoopWindowTarget; use crate::window::WindowBuilder; use web_sys::HtmlCanvasElement; @@ -27,3 +31,38 @@ impl WindowBuilderExtWebSys for WindowBuilder { self } } + +/// Additional methods on `EventLoop` that are specific to the web. +pub trait EventLoopExtWebSys { + /// A type provided by the user that can be passed through `Event::UserEvent`. + type UserEvent; + + /// Initializes the winit event loop. + /// + /// Unlike `run`, this returns immediately, and doesn't throw an exception in order to + /// satisfy its `!` return type. + fn spawn(self, event_handler: F) + where + F: 'static + + FnMut( + Event<'_, Self::UserEvent>, + &EventLoopWindowTarget, + &mut ControlFlow, + ); +} + +impl EventLoopExtWebSys for EventLoop { + type UserEvent = T; + + fn spawn(self, event_handler: F) + where + F: 'static + + FnMut( + Event<'_, Self::UserEvent>, + &EventLoopWindowTarget, + &mut ControlFlow, + ), + { + self.event_loop.spawn(event_handler) + } +} diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index a8d234cf29..6bec70c972 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -29,7 +29,22 @@ impl EventLoop { } } - pub fn run(self, mut event_handler: F) -> ! + pub fn run(self, event_handler: F) -> ! + where + F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + { + self.spawn(event_handler); + + // 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 '!' + backend::throw( + "Using exceptions for control flow, don't mind me. This isn't actually an error!", + ); + + unreachable!(); + } + + pub fn spawn(self, mut event_handler: F) where F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), { @@ -41,14 +56,6 @@ impl EventLoop { self.elw.p.run(Box::new(move |event, flow| { event_handler(event, &target, flow) })); - - // Throw an exception to break out of Rust exceution and use unreachable to tell the - // compiler this function won't return, giving it a return type of '!' - backend::throw( - "Using exceptions for control flow, don't mind me. This isn't actually an error!", - ); - - unreachable!(); } pub fn create_proxy(&self) -> EventLoopProxy {