diff --git a/src/platform_impl/apple/appkit/app_state.rs b/src/platform_impl/apple/appkit/app_state.rs index 0bf7e0d57b..f65fb8b4ef 100644 --- a/src/platform_impl/apple/appkit/app_state.rs +++ b/src/platform_impl/apple/appkit/app_state.rs @@ -8,7 +8,7 @@ use std::time::Instant; use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy}; use objc2_foundation::{MainThreadMarker, NSNotification}; -use super::event_handler::EventHandler; +use super::super::event_handler::EventHandler; use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo}; use super::observer::{EventLoopWaker, RunLoop}; use super::{menu, WindowId}; @@ -291,7 +291,7 @@ impl AppState { callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop), ) { let event_loop = ActiveEventLoop { app_state: Rc::clone(self), mtm: self.mtm }; - self.event_handler.handle(callback, &event_loop); + self.event_handler.handle(|app| callback(app, &event_loop)); } /// dispatch `NewEvents(Init)` + `Resumed` diff --git a/src/platform_impl/apple/appkit/mod.rs b/src/platform_impl/apple/appkit/mod.rs index 607f17e271..f02c26d16a 100644 --- a/src/platform_impl/apple/appkit/mod.rs +++ b/src/platform_impl/apple/appkit/mod.rs @@ -5,7 +5,6 @@ mod app; mod app_state; mod cursor; mod event; -mod event_handler; mod event_loop; mod ffi; mod menu; diff --git a/src/platform_impl/apple/appkit/event_handler.rs b/src/platform_impl/apple/event_handler.rs similarity index 93% rename from src/platform_impl/apple/appkit/event_handler.rs rename to src/platform_impl/apple/event_handler.rs index 9eebdba702..37765d760c 100644 --- a/src/platform_impl/apple/appkit/event_handler.rs +++ b/src/platform_impl/apple/event_handler.rs @@ -2,8 +2,9 @@ use std::cell::RefCell; use std::{fmt, mem}; use crate::application::ApplicationHandler; -use crate::platform_impl::ActiveEventLoop; +/// A helper type for storing a reference to `ApplicationHandler`, allowing interior mutable access +/// to it within the execution of a closure. #[derive(Default)] pub(crate) struct EventHandler { /// This can be in the following states: @@ -100,19 +101,17 @@ impl EventHandler { // soundness. } + #[cfg(target_os = "macos")] pub(crate) fn in_use(&self) -> bool { self.inner.try_borrow().is_err() } + #[cfg(target_os = "macos")] pub(crate) fn ready(&self) -> bool { matches!(self.inner.try_borrow().as_deref(), Ok(Some(_))) } - pub(crate) fn handle( - &self, - callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop), - event_loop: &ActiveEventLoop, - ) { + pub(crate) fn handle(&self, callback: impl FnOnce(&mut dyn ApplicationHandler)) { match self.inner.try_borrow_mut().as_deref_mut() { Ok(Some(user_app)) => { // It is important that we keep the reference borrowed here, @@ -121,7 +120,7 @@ impl EventHandler { // // If the handler unwinds, the `RefMut` will ensure that the // handler is no longer borrowed. - callback(*user_app, event_loop); + callback(*user_app); }, Ok(None) => { // `NSApplication`, our app state and this handler are all diff --git a/src/platform_impl/apple/mod.rs b/src/platform_impl/apple/mod.rs index 705ad1fc22..559492c8b5 100644 --- a/src/platform_impl/apple/mod.rs +++ b/src/platform_impl/apple/mod.rs @@ -2,6 +2,7 @@ #[cfg(target_os = "macos")] mod appkit; +mod event_handler; mod notification_center; #[cfg(not(target_os = "macos"))] mod uikit; diff --git a/src/platform_impl/apple/uikit/app_state.rs b/src/platform_impl/apple/uikit/app_state.rs index 83db6efbb0..3b9201e886 100644 --- a/src/platform_impl/apple/uikit/app_state.rs +++ b/src/platform_impl/apple/uikit/app_state.rs @@ -1,12 +1,12 @@ #![deny(unused_results)] -use std::cell::{RefCell, RefMut}; +use std::cell::{OnceCell, RefCell, RefMut}; use std::collections::HashSet; use std::os::raw::c_void; -use std::sync::atomic::AtomicBool; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, OnceLock}; use std::time::Instant; -use std::{fmt, mem, ptr}; +use std::{mem, ptr}; use core_foundation::base::CFRelease; use core_foundation::date::CFAbsoluteTimeGetCurrent; @@ -23,11 +23,13 @@ use objc2_foundation::{ }; use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow}; +use super::super::event_handler::EventHandler; use super::window::WinitUIWindow; use super::ActiveEventLoop; +use crate::application::ApplicationHandler; use crate::dpi::PhysicalSize; use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; -use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow}; +use crate::event_loop::ControlFlow; use crate::window::WindowId as RootWindowId; macro_rules! bug { @@ -42,25 +44,45 @@ macro_rules! bug_assert { }; } -pub(crate) struct EventLoopHandler { - #[allow(clippy::type_complexity)] - pub(crate) handler: Box, - pub(crate) event_loop: ActiveEventLoop, -} +/// Get the global event handler for the application. +/// +/// This is stored separately from AppState, since AppState needs to be accessible while the handler +/// is executing. +fn get_handler(mtm: MainThreadMarker) -> &'static EventHandler { + // TODO(madsmtm): Use `MainThreadBound` once that is possible in `static`s. + struct StaticMainThreadBound(T); -impl fmt::Debug for EventLoopHandler { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("EventLoopHandler") - .field("handler", &"...") - .field("event_loop", &self.event_loop) - .finish() + impl StaticMainThreadBound { + const fn get(&self, _mtm: MainThreadMarker) -> &T { + &self.0 + } } + + unsafe impl Send for StaticMainThreadBound {} + unsafe impl Sync for StaticMainThreadBound {} + + // SAFETY: Creating `StaticMainThreadBound` in a `const` context, where there is no concept + // of the main thread. + static GLOBAL: StaticMainThreadBound> = + StaticMainThreadBound(OnceCell::new()); + + GLOBAL.get(mtm).get_or_init(EventHandler::new) } -impl EventLoopHandler { - fn handle_event(&mut self, event: Event) { - (self.handler)(event, &self.event_loop) - } +fn handle_event(mtm: MainThreadMarker, event: Event) { + let event_loop = &ActiveEventLoop { mtm }; + get_handler(mtm).handle(|app| match event { + Event::NewEvents(cause) => app.new_events(event_loop, cause), + Event::WindowEvent { window_id, event } => app.window_event(event_loop, window_id, event), + Event::DeviceEvent { device_id, event } => app.device_event(event_loop, device_id, event), + Event::UserWakeUp => app.proxy_wake_up(event_loop), + Event::Suspended => app.suspended(event_loop), + Event::Resumed => app.resumed(event_loop), + Event::CreateSurfaces => app.can_create_surfaces(event_loop), + Event::AboutToWait => app.about_to_wait(event_loop), + Event::LoopExiting => app.exiting(event_loop), + Event::MemoryWarning => app.memory_warning(event_loop), + }) } #[derive(Debug)] @@ -77,14 +99,8 @@ pub struct ScaleFactorChanged { } enum UserCallbackTransitionResult<'a> { - Success { - handler: EventLoopHandler, - active_control_flow: ControlFlow, - processing_redraws: bool, - }, - ReentrancyPrevented { - queued_events: &'a mut Vec, - }, + Success { active_control_flow: ControlFlow, processing_redraws: bool }, + ReentrancyPrevented { queued_events: &'a mut Vec }, } impl Event { @@ -97,19 +113,12 @@ impl Event { #[derive(Debug)] #[must_use = "dropping `AppStateImpl` without inspecting it is probably a bug"] enum AppStateImpl { - NotLaunched { + Initial { queued_windows: Vec>, queued_events: Vec, queued_gpu_redraws: HashSet>, }, - Launching { - queued_windows: Vec>, - queued_events: Vec, - queued_handler: EventLoopHandler, - queued_gpu_redraws: HashSet>, - }, ProcessingEvents { - handler: EventLoopHandler, queued_gpu_redraws: HashSet>, active_control_flow: ControlFlow, }, @@ -119,16 +128,12 @@ enum AppStateImpl { queued_gpu_redraws: HashSet>, }, ProcessingRedraws { - handler: EventLoopHandler, active_control_flow: ControlFlow, }, Waiting { - waiting_handler: EventLoopHandler, start: Instant, }, - PollFinished { - waiting_handler: EventLoopHandler, - }, + PollFinished, Terminated, } @@ -154,7 +159,7 @@ impl AppState { fn init_guard(guard: &mut RefMut<'static, Option>) { let waker = EventLoopWaker::new(unsafe { CFRunLoopGetMain() }); **guard = Some(AppState { - app_state: Some(AppStateImpl::NotLaunched { + app_state: Some(AppStateImpl::Initial { queued_windows: Vec::new(), queued_events: Vec::new(), queued_gpu_redraws: HashSet::new(), @@ -207,42 +212,23 @@ impl AppState { } fn has_launched(&self) -> bool { - !matches!(self.state(), AppStateImpl::NotLaunched { .. } | AppStateImpl::Launching { .. }) + !matches!(self.state(), AppStateImpl::Initial { .. }) } fn has_terminated(&self) -> bool { matches!(self.state(), AppStateImpl::Terminated) } - fn will_launch_transition(&mut self, queued_handler: EventLoopHandler) { - let (queued_windows, queued_events, queued_gpu_redraws) = match self.take_state() { - AppStateImpl::NotLaunched { queued_windows, queued_events, queued_gpu_redraws } => { - (queued_windows, queued_events, queued_gpu_redraws) - }, - s => bug!("unexpected state {:?}", s), - }; - self.set_state(AppStateImpl::Launching { - queued_windows, - queued_events, - queued_handler, - queued_gpu_redraws, - }); - } - fn did_finish_launching_transition( &mut self, ) -> (Vec>, Vec) { - let (windows, events, handler, queued_gpu_redraws) = match self.take_state() { - AppStateImpl::Launching { - queued_windows, - queued_events, - queued_handler, - queued_gpu_redraws, - } => (queued_windows, queued_events, queued_handler, queued_gpu_redraws), + let (windows, events, queued_gpu_redraws) = match self.take_state() { + AppStateImpl::Initial { queued_windows, queued_events, queued_gpu_redraws } => { + (queued_windows, queued_events, queued_gpu_redraws) + }, s => bug!("unexpected state {:?}", s), }; self.set_state(AppStateImpl::ProcessingEvents { - handler, active_control_flow: self.control_flow, queued_gpu_redraws, }); @@ -256,22 +242,18 @@ impl AppState { return None; } - let (handler, event) = match (self.control_flow, self.take_state()) { - (ControlFlow::Poll, AppStateImpl::PollFinished { waiting_handler }) => { - (waiting_handler, EventWrapper::StaticEvent(Event::NewEvents(StartCause::Poll))) + let event = match (self.control_flow, self.take_state()) { + (ControlFlow::Poll, AppStateImpl::PollFinished) => { + EventWrapper::StaticEvent(Event::NewEvents(StartCause::Poll)) }, - (ControlFlow::Wait, AppStateImpl::Waiting { waiting_handler, start }) => ( - waiting_handler, + (ControlFlow::Wait, AppStateImpl::Waiting { start }) => { EventWrapper::StaticEvent(Event::NewEvents(StartCause::WaitCancelled { start, requested_resume: None, - })), - ), - ( - ControlFlow::WaitUntil(requested_resume), - AppStateImpl::Waiting { waiting_handler, start }, - ) => { - let event = if Instant::now() >= requested_resume { + })) + }, + (ControlFlow::WaitUntil(requested_resume), AppStateImpl::Waiting { start }) => { + if Instant::now() >= requested_resume { EventWrapper::StaticEvent(Event::NewEvents(StartCause::ResumeTimeReached { start, requested_resume, @@ -281,14 +263,12 @@ impl AppState { start, requested_resume: Some(requested_resume), })) - }; - (waiting_handler, event) + } }, s => bug!("`EventHandler` unexpectedly woke up {:?}", s), }; self.set_state(AppStateImpl::ProcessingEvents { - handler, queued_gpu_redraws: Default::default(), active_control_flow: self.control_flow, }); @@ -299,8 +279,7 @@ impl AppState { // If we're not able to process an event due to recursion or `Init` not having been sent out // yet, then queue the events up. match self.state_mut() { - &mut AppStateImpl::Launching { ref mut queued_events, .. } - | &mut AppStateImpl::NotLaunched { ref mut queued_events, .. } + &mut AppStateImpl::Initial { ref mut queued_events, .. } | &mut AppStateImpl::InUserCallback { ref mut queued_events, .. } => { // A lifetime cast: early returns are not currently handled well with NLL, but // polonius handles them well. This transmute is a safe workaround. @@ -324,17 +303,14 @@ impl AppState { }, } - let (handler, queued_gpu_redraws, active_control_flow, processing_redraws) = match self - .take_state() + let (queued_gpu_redraws, active_control_flow, processing_redraws) = match self.take_state() { - AppStateImpl::Launching { .. } - | AppStateImpl::NotLaunched { .. } - | AppStateImpl::InUserCallback { .. } => unreachable!(), - AppStateImpl::ProcessingEvents { handler, queued_gpu_redraws, active_control_flow } => { - (handler, queued_gpu_redraws, active_control_flow, false) + AppStateImpl::Initial { .. } | AppStateImpl::InUserCallback { .. } => unreachable!(), + AppStateImpl::ProcessingEvents { queued_gpu_redraws, active_control_flow } => { + (queued_gpu_redraws, active_control_flow, false) }, - AppStateImpl::ProcessingRedraws { handler, active_control_flow } => { - (handler, Default::default(), active_control_flow, true) + AppStateImpl::ProcessingRedraws { active_control_flow } => { + (Default::default(), active_control_flow, true) }, AppStateImpl::PollFinished { .. } | AppStateImpl::Waiting { .. } @@ -344,17 +320,17 @@ impl AppState { queued_events: Vec::new(), queued_gpu_redraws, }); - UserCallbackTransitionResult::Success { handler, active_control_flow, processing_redraws } + UserCallbackTransitionResult::Success { active_control_flow, processing_redraws } } fn main_events_cleared_transition(&mut self) -> HashSet> { - let (handler, queued_gpu_redraws, active_control_flow) = match self.take_state() { - AppStateImpl::ProcessingEvents { handler, queued_gpu_redraws, active_control_flow } => { - (handler, queued_gpu_redraws, active_control_flow) + let (queued_gpu_redraws, active_control_flow) = match self.take_state() { + AppStateImpl::ProcessingEvents { queued_gpu_redraws, active_control_flow } => { + (queued_gpu_redraws, active_control_flow) }, s => bug!("unexpected state {:?}", s), }; - self.set_state(AppStateImpl::ProcessingRedraws { handler, active_control_flow }); + self.set_state(AppStateImpl::ProcessingRedraws { active_control_flow }); queued_gpu_redraws } @@ -362,10 +338,8 @@ impl AppState { if !self.has_launched() || self.has_terminated() { return; } - let (waiting_handler, old) = match self.take_state() { - AppStateImpl::ProcessingRedraws { handler, active_control_flow } => { - (handler, active_control_flow) - }, + let old = match self.take_state() { + AppStateImpl::ProcessingRedraws { active_control_flow } => active_control_flow, s => bug!("unexpected state {:?}", s), }; @@ -373,35 +347,35 @@ impl AppState { match (old, new) { (ControlFlow::Wait, ControlFlow::Wait) => { let start = Instant::now(); - self.set_state(AppStateImpl::Waiting { waiting_handler, start }); + self.set_state(AppStateImpl::Waiting { start }); }, (ControlFlow::WaitUntil(old_instant), ControlFlow::WaitUntil(new_instant)) if old_instant == new_instant => { let start = Instant::now(); - self.set_state(AppStateImpl::Waiting { waiting_handler, start }); + self.set_state(AppStateImpl::Waiting { start }); }, (_, ControlFlow::Wait) => { let start = Instant::now(); - self.set_state(AppStateImpl::Waiting { waiting_handler, start }); + self.set_state(AppStateImpl::Waiting { start }); self.waker.stop() }, (_, ControlFlow::WaitUntil(new_instant)) => { let start = Instant::now(); - self.set_state(AppStateImpl::Waiting { waiting_handler, start }); + self.set_state(AppStateImpl::Waiting { start }); self.waker.start_at(new_instant) }, // Unlike on macOS, handle Poll to Poll transition here to call the waker (_, ControlFlow::Poll) => { - self.set_state(AppStateImpl::PollFinished { waiting_handler }); + self.set_state(AppStateImpl::PollFinished); self.waker.start() }, } } - fn terminated_transition(&mut self) -> EventLoopHandler { + fn terminated_transition(&mut self) { match self.replace_state(AppStateImpl::Terminated) { - AppStateImpl::ProcessingEvents { handler, .. } => handler, + AppStateImpl::ProcessingEvents { .. } => {}, s => bug!("`LoopExiting` happened while not processing events {:?}", s), } } @@ -422,15 +396,15 @@ impl AppState { pub(crate) fn set_key_window(mtm: MainThreadMarker, window: &Retained) { let mut this = AppState::get_mut(mtm); match this.state_mut() { - &mut AppStateImpl::NotLaunched { ref mut queued_windows, .. } => { + &mut AppStateImpl::Initial { ref mut queued_windows, .. } => { return queued_windows.push(window.clone()) }, &mut AppStateImpl::ProcessingEvents { .. } | &mut AppStateImpl::InUserCallback { .. } | &mut AppStateImpl::ProcessingRedraws { .. } => {}, - s @ &mut AppStateImpl::Launching { .. } - | s @ &mut AppStateImpl::Waiting { .. } - | s @ &mut AppStateImpl::PollFinished { .. } => bug!("unexpected state {:?}", s), + s @ &mut AppStateImpl::Waiting { .. } | s @ &mut AppStateImpl::PollFinished { .. } => { + bug!("unexpected state {:?}", s) + }, &mut AppStateImpl::Terminated => { panic!("Attempt to create a `Window` after the app has terminated") }, @@ -442,8 +416,7 @@ pub(crate) fn set_key_window(mtm: MainThreadMarker, window: &Retained) { let mut this = AppState::get_mut(mtm); match this.state_mut() { - &mut AppStateImpl::NotLaunched { ref mut queued_gpu_redraws, .. } - | &mut AppStateImpl::Launching { ref mut queued_gpu_redraws, .. } + &mut AppStateImpl::Initial { ref mut queued_gpu_redraws, .. } | &mut AppStateImpl::ProcessingEvents { ref mut queued_gpu_redraws, .. } | &mut AppStateImpl::InUserCallback { ref mut queued_gpu_redraws, .. } => { let _ = queued_gpu_redraws.insert(window); @@ -457,14 +430,14 @@ pub(crate) fn queue_gl_or_metal_redraw(mtm: MainThreadMarker, window: Retained mem::take(queued_windows), + AppStateImpl::Initial { queued_windows, .. } => mem::take(queued_windows), s => bug!("unexpected state {:?}", s), }; @@ -537,18 +510,15 @@ pub(crate) fn handle_nonuser_events>( return; } - let (mut handler, active_control_flow, processing_redraws) = - match this.try_user_callback_transition() { - UserCallbackTransitionResult::ReentrancyPrevented { queued_events } => { - queued_events.extend(events); - return; - }, - UserCallbackTransitionResult::Success { - handler, - active_control_flow, - processing_redraws, - } => (handler, active_control_flow, processing_redraws), - }; + let (active_control_flow, processing_redraws) = match this.try_user_callback_transition() { + UserCallbackTransitionResult::ReentrancyPrevented { queued_events } => { + queued_events.extend(events); + return; + }, + UserCallbackTransitionResult::Success { active_control_flow, processing_redraws } => { + (active_control_flow, processing_redraws) + }, + }; drop(this); for wrapper in events { @@ -562,9 +532,9 @@ pub(crate) fn handle_nonuser_events>( event ); } - handler.handle_event(event) + handle_event(mtm, event) }, - EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(&mut handler, event), + EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(mtm, event), } } @@ -588,9 +558,9 @@ pub(crate) fn handle_nonuser_events>( queued_gpu_redraws.is_empty(), "redraw queued while processing redraws" ); - AppStateImpl::ProcessingRedraws { handler, active_control_flow } + AppStateImpl::ProcessingRedraws { active_control_flow } } else { - AppStateImpl::ProcessingEvents { handler, queued_gpu_redraws, active_control_flow } + AppStateImpl::ProcessingEvents { queued_gpu_redraws, active_control_flow } }); break; } @@ -608,9 +578,9 @@ pub(crate) fn handle_nonuser_events>( event ); } - handler.handle_event(event) + handle_event(mtm, event) }, - EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(&mut handler, event), + EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(mtm, event), } } } @@ -618,23 +588,23 @@ pub(crate) fn handle_nonuser_events>( fn handle_user_events(mtm: MainThreadMarker) { let mut this = AppState::get_mut(mtm); - let (mut handler, active_control_flow, processing_redraws) = - match this.try_user_callback_transition() { - UserCallbackTransitionResult::ReentrancyPrevented { .. } => { - bug!("unexpected attempted to process an event") - }, - UserCallbackTransitionResult::Success { - handler, - active_control_flow, - processing_redraws, - } => (handler, active_control_flow, processing_redraws), - }; + let (active_control_flow, processing_redraws) = match this.try_user_callback_transition() { + UserCallbackTransitionResult::ReentrancyPrevented { .. } => { + bug!("unexpected attempted to process an event") + }, + UserCallbackTransitionResult::Success { active_control_flow, processing_redraws } => { + (active_control_flow, processing_redraws) + }, + }; if processing_redraws { bug!("user events attempted to be sent out while `ProcessingRedraws`"); } + let proxy_wake_up = this.proxy_wake_up.clone(); drop(this); - handler.handle_event(Event::UserWakeUp); + if proxy_wake_up.swap(false, Ordering::Relaxed) { + handle_event(mtm, Event::UserWakeUp); + } loop { let mut this = AppState::get_mut(mtm); @@ -651,23 +621,22 @@ fn handle_user_events(mtm: MainThreadMarker) { }, _ => unreachable!(), }; - this.app_state = Some(AppStateImpl::ProcessingEvents { - handler, - queued_gpu_redraws, - active_control_flow, - }); + this.app_state = + Some(AppStateImpl::ProcessingEvents { queued_gpu_redraws, active_control_flow }); break; } drop(this); for wrapper in queued_events { match wrapper { - EventWrapper::StaticEvent(event) => handler.handle_event(event), - EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(&mut handler, event), + EventWrapper::StaticEvent(event) => handle_event(mtm, event), + EventWrapper::ScaleFactorChanged(event) => handle_hidpi_proxy(mtm, event), } } - handler.handle_event(Event::UserWakeUp); + if proxy_wake_up.swap(false, Ordering::Relaxed) { + handle_event(mtm, Event::UserWakeUp); + } } } @@ -749,13 +718,13 @@ pub(crate) fn terminated(application: &UIApplication) { handle_nonuser_events(mtm, events); let mut this = AppState::get_mut(mtm); - let mut handler = this.terminated_transition(); + this.terminated_transition(); drop(this); - handler.handle_event(Event::LoopExiting) + handle_event(mtm, Event::LoopExiting) } -fn handle_hidpi_proxy(handler: &mut EventLoopHandler, event: ScaleFactorChanged) { +fn handle_hidpi_proxy(mtm: MainThreadMarker, event: ScaleFactorChanged) { let ScaleFactorChanged { suggested_size, scale_factor, window } = event; let new_inner_size = Arc::new(Mutex::new(suggested_size)); let event = Event::WindowEvent { @@ -765,7 +734,7 @@ fn handle_hidpi_proxy(handler: &mut EventLoopHandler, event: ScaleFactorChanged) inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }; - handler.handle_event(event); + handle_event(mtm, event); let (view, screen_frame) = get_view_and_screen_frame(&window); let physical_size = *new_inner_size.lock().unwrap(); drop(new_inner_size); diff --git a/src/platform_impl/apple/uikit/event_loop.rs b/src/platform_impl/apple/uikit/event_loop.rs index bd52fc4029..82599c6189 100644 --- a/src/platform_impl/apple/uikit/event_loop.rs +++ b/src/platform_impl/apple/uikit/event_loop.rs @@ -22,9 +22,7 @@ use objc2_ui_kit::{ }; use super::super::notification_center::create_observer; -use super::app_state::{ - send_occluded_event_for_all_windows, AppState, EventLoopHandler, EventWrapper, -}; +use super::app_state::{send_occluded_event_for_all_windows, AppState, EventWrapper}; use super::{app_state, monitor, MonitorHandle}; use crate::application::ApplicationHandler; use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError}; @@ -128,32 +126,6 @@ impl OwnedDisplayHandle { } } -fn map_user_event<'a, A: ApplicationHandler + 'a>( - mut app: A, - proxy_wake_up: Arc, -) -> impl FnMut(Event, &dyn RootActiveEventLoop) + 'a { - move |event, window_target| match event { - Event::NewEvents(cause) => app.new_events(window_target, cause), - Event::WindowEvent { window_id, event } => { - app.window_event(window_target, window_id, event) - }, - Event::DeviceEvent { device_id, event } => { - app.device_event(window_target, device_id, event) - }, - Event::UserWakeUp => { - if proxy_wake_up.swap(false, AtomicOrdering::Relaxed) { - app.proxy_wake_up(window_target); - } - }, - Event::Suspended => app.suspended(window_target), - Event::Resumed => app.resumed(window_target), - Event::CreateSurfaces => app.can_create_surfaces(window_target), - Event::AboutToWait => app.about_to_wait(window_target), - Event::LoopExiting => app.exiting(window_target), - Event::MemoryWarning => app.memory_warning(window_target), - } -} - pub struct EventLoop { mtm: MainThreadMarker, window_target: ActiveEventLoop, @@ -285,7 +257,7 @@ impl EventLoop { }) } - pub fn run_app(self, app: A) -> ! { + pub fn run_app(self, mut app: A) -> ! { let application: Option> = unsafe { msg_send_id![UIApplication::class(), sharedApplication] }; assert!( @@ -295,35 +267,23 @@ impl EventLoop { `EventLoop::run_app` calls `UIApplicationMain` on iOS", ); - let handler = map_user_event(app, AppState::get_mut(self.mtm).proxy_wake_up()); - - let handler = unsafe { - std::mem::transmute::< - Box, - Box, - >(Box::new(handler)) - }; - - let handler = EventLoopHandler { handler, event_loop: self.window_target }; - - app_state::will_launch(self.mtm, handler); - extern "C" { // These functions are in crt_externs.h. fn _NSGetArgc() -> *mut c_int; fn _NSGetArgv() -> *mut *mut *mut c_char; } - unsafe { + app_state::launch(self.mtm, &mut app, || unsafe { UIApplicationMain( *_NSGetArgc(), NonNull::new(*_NSGetArgv()).unwrap(), - // We intentionally override neither the application nor the delegate, to allow the - // user to do so themselves! + // We intentionally override neither the application nor the delegate, to allow + // the user to do so themselves! None, None, - ) - }; + ); + }); + unreachable!() }