web: Add EventLoop::spawn (#2208)

* web: Add `EventLoop::spawn`

This is the same as `EventLoop::run`, but doesn't throw an exception in order to return `!`.

I decided to name it `spawn` rather than `run_web` because I think that's more descriptive, but I'm happy to change it to `run_web`.

Resolves #1714

* Update src/platform/web.rs

Co-authored-by: Markus Røyset <maroider@protonmail.com>

* Fix outdated names

Co-authored-by: Markus Røyset <maroider@protonmail.com>
This commit is contained in:
Liam Murphy 2022-07-14 01:17:18 +10:00 committed by GitHub
parent cdd9b1e1eb
commit aa8f8db305
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 9 deletions

View file

@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
# Unreleased # 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. - Added `WindowEvent::Occluded(bool)`, currently implemented on macOS and X11.
- On X11, fix events for caps lock key not being sent - On X11, fix events for caps lock key not being sent
- Build docs on `docs.rs` for iOS and Android as well. - Build docs on `docs.rs` for iOS and Android as well.

View file

@ -5,6 +5,10 @@
//! to retrieve the canvas from the Window. Alternatively, use the [`WindowBuilderExtWebSys`] trait //! to retrieve the canvas from the Window. Alternatively, use the [`WindowBuilderExtWebSys`] trait
//! to provide your own canvas. //! 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 crate::window::WindowBuilder;
use web_sys::HtmlCanvasElement; use web_sys::HtmlCanvasElement;
@ -27,3 +31,38 @@ impl WindowBuilderExtWebSys for WindowBuilder {
self 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<F>(self, event_handler: F)
where
F: 'static
+ FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
);
}
impl<T> EventLoopExtWebSys for EventLoop<T> {
type UserEvent = T;
fn spawn<F>(self, event_handler: F)
where
F: 'static
+ FnMut(
Event<'_, Self::UserEvent>,
&EventLoopWindowTarget<Self::UserEvent>,
&mut ControlFlow,
),
{
self.event_loop.spawn(event_handler)
}
}

View file

@ -29,7 +29,22 @@ impl<T> EventLoop<T> {
} }
} }
pub fn run<F>(self, mut event_handler: F) -> ! pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &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<F>(self, mut event_handler: F)
where where
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow), F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{ {
@ -41,14 +56,6 @@ impl<T> EventLoop<T> {
self.elw.p.run(Box::new(move |event, flow| { 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
// 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<T> { pub fn create_proxy(&self) -> EventLoopProxy<T> {