Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove 'static requirement on run #3006

Merged
merged 3 commits into from
Aug 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,14 @@ impl<T> EventLoop<T> {
/// 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<F>(self, event_handler: F) -> Result<(), RunLoopError>
where
F: 'static + FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
F: FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
{
self.event_loop.run(event_handler)
}
Expand Down
3 changes: 1 addition & 2 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,7 @@ impl<T: 'static> EventLoop<T> {

pub fn run<F>(mut self, event_handler: F) -> Result<(), RunLoopError>
where
F: 'static
+ FnMut(event::Event<T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
F: FnMut(event::Event<T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
self.run_ondemand(event_handler)
}
Expand Down
29 changes: 18 additions & 11 deletions src/platform_impl/ios/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl<T: 'static> EventLoop<T> {

pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
F: FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{
unsafe {
let application = UIApplication::shared(MainThreadMarker::new().unwrap());
Expand All @@ -116,10 +116,18 @@ impl<T: 'static> EventLoop<T> {
`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<dyn FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow)>,
Box<EventHandlerCallback<T>>,
>(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();
Expand Down Expand Up @@ -314,29 +322,28 @@ fn setup_control_flow_observers() {
#[derive(Debug)]
pub enum Never {}

type EventHandlerCallback<T> =
dyn FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow) + 'static;

pub trait EventHandler: Debug {
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow);
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
}

struct EventLoopHandler<F, T: 'static> {
f: F,
struct EventLoopHandler<T: 'static> {
f: Box<EventHandlerCallback<T>>,
event_loop: RootEventLoopWindowTarget<T>,
}

impl<F, T: 'static> Debug for EventLoopHandler<F, T> {
impl<T: 'static> Debug for EventLoopHandler<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventLoopHandler")
.field("event_loop", &self.event_loop)
.finish()
}
}

impl<F, T> EventHandler for EventLoopHandler<F, T>
where
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
T: 'static,
{
impl<T: 'static> EventHandler for EventLoopHandler<T> {
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow) {
(self.f)(
event.map_nonuser_event().unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/macos/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl<T> EventLoop<T> {

pub fn run<F>(mut self, callback: F) -> Result<(), RunLoopError>
where
F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
{
self.run_ondemand(callback)
}
Expand Down
3 changes: 1 addition & 2 deletions src/platform_impl/orbital/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,7 @@ impl<T: 'static> EventLoop<T> {

pub fn run<F>(mut self, mut event_handler_inner: F) -> Result<(), RunLoopError>
where
F: 'static
+ FnMut(event::Event<T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
F: FnMut(event::Event<T>, &event_loop::EventLoopWindowTarget<T>, &mut ControlFlow),
{
// Wrapper for event handler function that prevents ExitWithCode from being unset.
let mut event_handler =
Expand Down
29 changes: 17 additions & 12 deletions src/platform_impl/web/event_loop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,23 @@ impl<T> EventLoop<T> {
}
}

pub fn run<F>(self, event_handler: F) -> !
pub fn run<F>(self, mut event_handler: F) -> !
where
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
F: FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &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<dyn FnMut(_, _)> =
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 '!'
Expand All @@ -44,14 +56,7 @@ impl<T> EventLoop<T> {
unreachable!();
}

pub fn spawn<F>(self, event_handler: F)
where
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{
self.spawn_inner(event_handler, true);
}

fn spawn_inner<F>(self, mut event_handler: F, event_loop_recreation: bool)
pub fn spawn<F>(self, mut event_handler: F)
where
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{
Expand All @@ -62,7 +67,7 @@ impl<T> EventLoop<T> {

self.elw.p.run(
Box::new(move |event, flow| event_handler(event, &target, flow)),
event_loop_recreation,
true,
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ impl<T: 'static> EventLoop<T> {

pub fn run<F>(mut self, event_handler: F) -> Result<(), RunLoopError>
where
F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
{
self.run_ondemand(event_handler)
}
Expand Down