winit-web: return immediately from run_app on web
This avoids using JavaScript exceptions to support `EventLoop::run_app` on the web, which is a huge hack, and doesn't work with the Exception Handling Proposal for WebAssembly: https://github.com/WebAssembly/exception-handling This needs the application handler passed to `run_app` to be `'static`, but that works better on iOS too anyhow (since you can't accidentally forget to pass in state that then wouldn't be dropped when terminating).
This commit is contained in:
parent
e8bccfff4f
commit
f69b601abb
9 changed files with 81 additions and 102 deletions
|
|
@ -39,32 +39,9 @@ impl EventLoop {
|
|||
EVENT_LOOP_CREATED.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn run_app<A: ApplicationHandler>(self, app: A) -> ! {
|
||||
let app = Box::new(app);
|
||||
|
||||
// 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 app = unsafe {
|
||||
std::mem::transmute::<
|
||||
Box<dyn ApplicationHandler + '_>,
|
||||
Box<dyn ApplicationHandler + 'static>,
|
||||
>(app)
|
||||
};
|
||||
|
||||
self.elw.run(app, 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 '!'
|
||||
backend::throw(
|
||||
"Using exceptions for control flow, don't mind me. This isn't actually an error!",
|
||||
);
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
pub fn spawn_app<A: ApplicationHandler + 'static>(self, app: A) {
|
||||
self.elw.run(Box::new(app), true);
|
||||
pub fn run_app<A: ApplicationHandler + 'static>(self, app: A) -> Result<(), EventLoopError> {
|
||||
self.elw.run(Box::new(app));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn window_target(&self) -> &dyn RootActiveEventLoop {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ struct Execution {
|
|||
exit: Cell<bool>,
|
||||
runner: RefCell<RunnerEnum>,
|
||||
suspended: Cell<bool>,
|
||||
event_loop_recreation: Cell<bool>,
|
||||
events: RefCell<VecDeque<Event>>,
|
||||
id: Cell<usize>,
|
||||
window: web_sys::Window,
|
||||
|
|
@ -195,7 +194,6 @@ impl Shared {
|
|||
exit: Cell::new(false),
|
||||
runner: RefCell::new(RunnerEnum::Pending),
|
||||
suspended: Cell::new(false),
|
||||
event_loop_recreation: Cell::new(false),
|
||||
events: RefCell::new(VecDeque::new()),
|
||||
window,
|
||||
navigator,
|
||||
|
|
@ -772,9 +770,7 @@ impl Shared {
|
|||
// * For each undropped `Window`:
|
||||
// * The `register_redraw_request` closure.
|
||||
// * The `destroy_fn` closure.
|
||||
if self.0.event_loop_recreation.get() {
|
||||
EventLoop::allow_event_loop_recreation();
|
||||
}
|
||||
EventLoop::allow_event_loop_recreation();
|
||||
}
|
||||
|
||||
// Check if the event loop is currently closed
|
||||
|
|
@ -809,10 +805,6 @@ impl Shared {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn event_loop_recreation(&self, allow: bool) {
|
||||
self.0.event_loop_recreation.set(allow)
|
||||
}
|
||||
|
||||
pub(crate) fn control_flow(&self) -> ControlFlow {
|
||||
self.0.control_flow.get()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@ impl ActiveEventLoop {
|
|||
Self { runner: runner::Shared::new(), modifiers: ModifiersShared::default() }
|
||||
}
|
||||
|
||||
pub(crate) fn run(&self, app: Box<dyn ApplicationHandler>, event_loop_recreation: bool) {
|
||||
self.runner.event_loop_recreation(event_loop_recreation);
|
||||
pub(crate) fn run(&self, app: Box<dyn ApplicationHandler>) {
|
||||
self.runner.start(app, self.clone());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ use std::task::{Context, Poll};
|
|||
use ::web_sys::HtmlCanvasElement;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use winit_core::application::ApplicationHandler;
|
||||
use winit_core::cursor::{CustomCursor, CustomCursorSource};
|
||||
use winit_core::error::NotSupportedError;
|
||||
use winit_core::event_loop::ActiveEventLoop;
|
||||
|
|
@ -237,30 +236,6 @@ impl Default for WindowAttributesWeb {
|
|||
|
||||
/// Additional methods on `EventLoop` that are specific to the Web.
|
||||
pub trait EventLoopExtWeb {
|
||||
/// Initializes the winit event loop.
|
||||
///
|
||||
/// Unlike
|
||||
#[cfg_attr(target_feature = "exception-handling", doc = "`run_app()`")]
|
||||
#[cfg_attr(
|
||||
not(target_feature = "exception-handling"),
|
||||
doc = "[`run_app()`]"
|
||||
)]
|
||||
/// [^1], this returns immediately, and doesn't throw an exception in order to
|
||||
/// satisfy its [`!`] return type.
|
||||
///
|
||||
/// Once the event loop has been destroyed, it's possible to reinitialize another event loop
|
||||
/// by calling this function again. This can be useful if you want to recreate the event loop
|
||||
/// while the WebAssembly module is still loaded. For example, this can be used to recreate the
|
||||
/// event loop when switching between tabs on a single page application.
|
||||
#[rustfmt::skip]
|
||||
///
|
||||
#[cfg_attr(
|
||||
not(target_feature = "exception-handling"),
|
||||
doc = "[`run_app()`]: EventLoop::run_app()"
|
||||
)]
|
||||
/// [^1]: `run_app()` is _not_ available on Wasm when the target supports `exception-handling`.
|
||||
fn spawn_app<A: ApplicationHandler + 'static>(self, app: A);
|
||||
|
||||
/// Sets the strategy for [`ControlFlow::Poll`].
|
||||
///
|
||||
/// See [`PollStrategy`].
|
||||
|
|
|
|||
|
|
@ -25,10 +25,6 @@ pub use self::resize_scaling::ResizeScaleHandle;
|
|||
pub use self::safe_area::SafeAreaHandle;
|
||||
pub use self::schedule::Schedule;
|
||||
|
||||
pub fn throw(msg: &str) {
|
||||
wasm_bindgen::throw_str(msg);
|
||||
}
|
||||
|
||||
pub struct PageTransitionEventHandle {
|
||||
_show_listener: event_handle::EventListenerHandle<dyn FnMut(PageTransitionEvent)>,
|
||||
_hide_listener: event_handle::EventListenerHandle<dyn FnMut(PageTransitionEvent)>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue