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

Example of migrating backends to ApplicationHandler #3387

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/event_loop.rs
Expand Up @@ -20,7 +20,7 @@ use web_time::{Duration, Instant};

use crate::error::EventLoopError;
use crate::event::Event;
use crate::event_helper::{map_event, MapEventHelper};
use crate::event_helper::MapEventHelper;
use crate::handler::ApplicationHandler;
use crate::{monitor::MonitorHandle, platform_impl};

Expand Down Expand Up @@ -317,8 +317,16 @@ impl<T> EventLoop<T> {

#[cfg(not(all(wasm_platform, target_feature = "exception-handling")))]
pub fn run_with<A: ApplicationHandler<T>>(self, mut handler: A) -> Result<(), EventLoopError> {
self.event_loop
.run(|event, inner| map_event(&mut handler, event, ActiveEventLoop { inner }))
#[cfg(any(macos_platform, orbital_platform))]
{
self.event_loop.run(handler)
}
#[cfg(not(any(macos_platform, orbital_platform)))]
{
self.event_loop.run(|event, inner| {
crate::event_helper::map_event(&mut handler, event, ActiveEventLoop { inner })
})
}
}

/// Set the initial [`ControlFlow`].
Expand Down
24 changes: 17 additions & 7 deletions src/platform_impl/macos/app_state.rs
Expand Up @@ -25,6 +25,7 @@ use crate::{
dpi::PhysicalSize,
event::{Event, InnerSizeWriter, StartCause, WindowEvent},
event_loop::ControlFlow,
handler::ApplicationHandler,
window::WindowId,
};

Expand All @@ -45,7 +46,7 @@ pub trait EventHandler: Debug {
fn handle_user_events(&mut self);
}

pub(crate) type Callback<T> = RefCell<dyn FnMut(Event<T>, &EventLoopWindowTarget)>;
pub(crate) type Callback<T> = RefCell<dyn ApplicationHandler<T>>;

struct EventLoopHandler<T: 'static> {
callback: Weak<Callback<T>>,
Expand All @@ -56,10 +57,7 @@ struct EventLoopHandler<T: 'static> {
impl<T> EventLoopHandler<T> {
fn with_callback<F>(&mut self, f: F)
where
F: FnOnce(
&mut EventLoopHandler<T>,
RefMut<'_, dyn FnMut(Event<T>, &EventLoopWindowTarget)>,
),
F: FnOnce(&mut EventLoopHandler<T>, RefMut<'_, dyn ApplicationHandler<T>>),
{
// `NSApplication` and our `HANDLER` are global state and so it's possible
// that we could get a delegate callback after the application has exit an
Expand Down Expand Up @@ -88,14 +86,26 @@ impl<T> Debug for EventLoopHandler<T> {
impl<T> EventHandler for EventLoopHandler<T> {
fn handle_nonuser_event(&mut self, event: Event<Never>) {
self.with_callback(|this, mut callback| {
(callback)(event.userify(), &this.window_target);
crate::event_helper::map_event(
&mut *callback,
event.userify(),
crate::event_loop::ActiveEventLoop {
inner: &this.window_target,
},
);
});
}

fn handle_user_events(&mut self) {
self.with_callback(|this, mut callback| {
for event in this.receiver.try_iter() {
(callback)(Event::UserEvent(event), &this.window_target);
crate::event_helper::map_event(
&mut *callback,
Event::UserEvent(event),
crate::event_loop::ActiveEventLoop {
inner: &this.window_target,
},
);
}
});
}
Expand Down
29 changes: 13 additions & 16 deletions src/platform_impl/macos/event_loop.rs
Expand Up @@ -30,8 +30,8 @@ use objc2::{
use super::event::dummy_event;
use crate::{
error::EventLoopError,
event::Event,
event_loop::{ControlFlow, DeviceEvents, EventLoopClosed},
handler::ApplicationHandler,
platform::{macos::ActivationPolicy, pump_events::PumpStatus},
platform_impl::platform::{
app::WinitApplication,
Expand Down Expand Up @@ -235,20 +235,17 @@ impl<T> EventLoop<T> {
&self.window_target
}

pub fn run<F>(mut self, callback: F) -> Result<(), EventLoopError>
where
F: FnMut(Event<T>, &EventLoopWindowTarget),
{
self.run_on_demand(callback)
pub fn run(mut self, handler: impl ApplicationHandler<T>) -> Result<(), EventLoopError> {
self.run_on_demand(handler)
}

// NB: we don't base this on `pump_events` because for `MacOs` we can't support
// `pump_events` elegantly (we just ask to run the loop for a "short" amount of
// time and so a layered implementation would end up using a lot of CPU due to
// redundant wake ups.
pub fn run_on_demand<F>(&mut self, callback: F) -> Result<(), EventLoopError>
pub fn run_on_demand<A>(&mut self, handler: A) -> Result<(), EventLoopError>
where
F: FnMut(Event<T>, &EventLoopWindowTarget),
A: ApplicationHandler<T>,
{
if AppState::is_running() {
return Err(EventLoopError::AlreadyRunning);
Expand All @@ -265,9 +262,9 @@ impl<T> EventLoop<T> {

let callback = unsafe {
mem::transmute::<
Rc<RefCell<dyn FnMut(Event<T>, &EventLoopWindowTarget)>>,
Rc<RefCell<dyn FnMut(Event<T>, &EventLoopWindowTarget)>>,
>(Rc::new(RefCell::new(callback)))
Rc<RefCell<dyn ApplicationHandler<T>>>,
Rc<RefCell<dyn ApplicationHandler<T>>>,
>(Rc::new(RefCell::new(handler)))
};

self._callback = Some(Rc::clone(&callback));
Expand Down Expand Up @@ -330,9 +327,9 @@ impl<T> EventLoop<T> {
Ok(())
}

pub fn pump_events<F>(&mut self, timeout: Option<Duration>, callback: F) -> PumpStatus
pub fn pump_events<A>(&mut self, timeout: Option<Duration>, handler: A) -> PumpStatus
where
F: FnMut(Event<T>, &EventLoopWindowTarget),
A: ApplicationHandler<T>,
{
// # Safety
// We are erasing the lifetime of the application callback here so that we
Expand All @@ -345,9 +342,9 @@ impl<T> EventLoop<T> {

let callback = unsafe {
mem::transmute::<
Rc<RefCell<dyn FnMut(Event<T>, &EventLoopWindowTarget)>>,
Rc<RefCell<dyn FnMut(Event<T>, &EventLoopWindowTarget)>>,
>(Rc::new(RefCell::new(callback)))
Rc<RefCell<dyn ApplicationHandler<T>>>,
Rc<RefCell<dyn ApplicationHandler<T>>>,
>(Rc::new(RefCell::new(handler)))
};

self._callback = Some(Rc::clone(&callback));
Expand Down