Skip to content

Commit

Permalink
web: Add EventLoop::spawn (rust-windowing#2208)
Browse files Browse the repository at this point in the history
* 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 rust-windowing#1714

* Update src/platform/web.rs

Co-authored-by: Markus Røyset <[email protected]>

* Fix outdated names

Co-authored-by: Markus Røyset <[email protected]>
  • Loading branch information
Liamolucko and maroider authored Jul 13, 2022
1 parent cdd9b1e commit aa8f8db
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
39 changes: 39 additions & 0 deletions src/platform/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<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)
}
}
25 changes: 16 additions & 9 deletions src/platform_impl/web/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{
Expand All @@ -41,14 +56,6 @@ impl<T> EventLoop<T> {
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<T> {
Expand Down

0 comments on commit aa8f8db

Please sign in to comment.