From 8faae94955e610b2851604d45f400e45b9aa6c87 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Mon, 28 Aug 2023 00:06:38 +0200 Subject: [PATCH] iOS implementation --- src/platform_impl/ios/app_state.rs | 48 +++++++++------------- src/platform_impl/ios/event_loop.rs | 64 +++++++++++++++++++++-------- 2 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/platform_impl/ios/app_state.rs b/src/platform_impl/ios/app_state.rs index df371ecb627..36de6552f0a 100644 --- a/src/platform_impl/ios/app_state.rs +++ b/src/platform_impl/ios/app_state.rs @@ -24,13 +24,12 @@ use objc2::runtime::AnyObject; use objc2::{msg_send, sel}; use once_cell::sync::Lazy; -use super::event_loop::{EventHandler, Never}; +use super::event_loop::{ControlFlow, EventHandler, Never}; use super::uikit::UIView; use super::view::WinitUIWindow; use crate::{ dpi::PhysicalSize, event::{Event, InnerSizeWriter, StartCause, WindowEvent}, - event_loop::ControlFlow, window::WindowId as RootWindowId, }; @@ -121,7 +120,7 @@ enum AppStateImpl { Terminated, } -struct AppState { +pub(crate) struct AppState { // This should never be `None`, except for briefly during a state transition. app_state: Option, control_flow: ControlFlow, @@ -129,7 +128,7 @@ struct AppState { } impl AppState { - fn get_mut(_mtm: MainThreadMarker) -> RefMut<'static, AppState> { + pub(crate) fn get_mut(_mtm: MainThreadMarker) -> RefMut<'static, AppState> { // basically everything in UIKit requires the main thread, so it's pointless to use the // std::sync APIs. // must be mut because plain `static` requires `Sync` @@ -290,7 +289,7 @@ impl AppState { }; (waiting_event_handler, event) } - (ControlFlow::ExitWithCode(_), _) => bug!("unexpected `ControlFlow` `Exit`"), + (ControlFlow::Exit, _) => bug!("unexpected `ControlFlow` `Exit`"), s => bug!("`EventHandler` unexpectedly woke up {:?}", s), }; @@ -443,7 +442,7 @@ impl AppState { }); self.waker.start() } - (_, ControlFlow::ExitWithCode(_)) => { + (_, ControlFlow::Exit) => { // https://developer.apple.com/library/archive/qa/qa1561/_index.html // it is not possible to quit an iOS app gracefully and programatically warn!("`ControlFlow::Exit` ignored on iOS"); @@ -458,6 +457,10 @@ impl AppState { s => bug!("`LoopExiting` happened while not processing events {:?}", s), } } + + pub(crate) fn set_control_flow(&mut self, control_flow: ControlFlow) { + self.control_flow = control_flow; + } } pub(crate) fn set_key_window(mtm: MainThreadMarker, window: &Id) { @@ -602,7 +605,6 @@ pub(crate) fn handle_nonuser_events>( processing_redraws, } => (event_handler, active_control_flow, processing_redraws), }; - let mut control_flow = this.control_flow; drop(this); for wrapper in events { @@ -616,10 +618,10 @@ pub(crate) fn handle_nonuser_events>( event ); } - event_handler.handle_nonuser_event(event, &mut control_flow) + event_handler.handle_nonuser_event(event) } EventWrapper::ScaleFactorChanged(event) => { - handle_hidpi_proxy(&mut event_handler, control_flow, event) + handle_hidpi_proxy(&mut event_handler, event) } } } @@ -657,7 +659,6 @@ pub(crate) fn handle_nonuser_events>( active_control_flow, } }); - this.control_flow = control_flow; break; } drop(this); @@ -673,10 +674,10 @@ pub(crate) fn handle_nonuser_events>( event ); } - event_handler.handle_nonuser_event(event, &mut control_flow) + event_handler.handle_nonuser_event(event) } EventWrapper::ScaleFactorChanged(event) => { - handle_hidpi_proxy(&mut event_handler, control_flow, event) + handle_hidpi_proxy(&mut event_handler, event) } } } @@ -685,7 +686,6 @@ pub(crate) fn handle_nonuser_events>( fn handle_user_events(mtm: MainThreadMarker) { let mut this = AppState::get_mut(mtm); - let mut control_flow = this.control_flow; let (mut event_handler, active_control_flow, processing_redraws) = match this.try_user_callback_transition() { UserCallbackTransitionResult::ReentrancyPrevented { .. } => { @@ -702,7 +702,7 @@ fn handle_user_events(mtm: MainThreadMarker) { } drop(this); - event_handler.handle_user_events(&mut control_flow); + event_handler.handle_user_events(); loop { let mut this = AppState::get_mut(mtm); @@ -726,22 +726,19 @@ fn handle_user_events(mtm: MainThreadMarker) { queued_gpu_redraws, active_control_flow, }); - this.control_flow = control_flow; break; } drop(this); for wrapper in queued_events { match wrapper { - EventWrapper::StaticEvent(event) => { - event_handler.handle_nonuser_event(event, &mut control_flow) - } + EventWrapper::StaticEvent(event) => event_handler.handle_nonuser_event(event), EventWrapper::ScaleFactorChanged(event) => { - handle_hidpi_proxy(&mut event_handler, control_flow, event) + handle_hidpi_proxy(&mut event_handler, event) } } } - event_handler.handle_user_events(&mut control_flow); + event_handler.handle_user_events(); } } @@ -782,17 +779,12 @@ pub fn handle_events_cleared(mtm: MainThreadMarker) { pub fn terminated(mtm: MainThreadMarker) { let mut this = AppState::get_mut(mtm); let mut event_handler = this.terminated_transition(); - let mut control_flow = this.control_flow; drop(this); - event_handler.handle_nonuser_event(Event::LoopExiting, &mut control_flow) + event_handler.handle_nonuser_event(Event::LoopExiting) } -fn handle_hidpi_proxy( - event_handler: &mut Box, - mut control_flow: ControlFlow, - event: ScaleFactorChanged, -) { +fn handle_hidpi_proxy(event_handler: &mut Box, event: ScaleFactorChanged) { let ScaleFactorChanged { suggested_size, scale_factor, @@ -806,7 +798,7 @@ fn handle_hidpi_proxy( inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }; - event_handler.handle_nonuser_event(event, &mut control_flow); + event_handler.handle_nonuser_event(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/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index e3ad63b5f73..3246ce8aac7 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -5,6 +5,7 @@ use std::{ marker::PhantomData, ptr, sync::mpsc::{self, Receiver, Sender}, + time::Instant, }; use core_foundation::base::{CFIndex, CFRelease}; @@ -21,14 +22,15 @@ use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle}; use crate::{ error::EventLoopError, event::Event, - event_loop::{ - ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget, - }, + event_loop::{EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget}, platform::ios::Idiom, }; -use super::uikit::{UIApplication, UIApplicationMain, UIDevice, UIScreen}; use super::{app_state, monitor, view, MonitorHandle}; +use super::{ + app_state::AppState, + uikit::{UIApplication, UIApplicationMain, UIDevice, UIScreen}, +}; #[derive(Debug)] pub struct EventLoopWindowTarget { @@ -48,6 +50,22 @@ impl EventLoopWindowTarget { pub fn raw_display_handle(&self) -> RawDisplayHandle { RawDisplayHandle::UiKit(UiKitDisplayHandle::empty()) } + + pub(crate) fn set_poll(&self) { + AppState::get_mut(self.mtm).set_control_flow(ControlFlow::Poll) + } + + pub(crate) fn set_wait(&self) { + AppState::get_mut(self.mtm).set_control_flow(ControlFlow::Wait) + } + + pub(crate) fn set_wait_until(&self, instant: Instant) { + AppState::get_mut(self.mtm).set_control_flow(ControlFlow::WaitUntil(instant)) + } + + pub(crate) fn set_exit(&self) { + AppState::get_mut(self.mtm).set_control_flow(ControlFlow::Exit) + } } pub struct EventLoop { @@ -98,7 +116,7 @@ impl EventLoop { pub fn run(self, event_handler: F) -> ! where - F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget), { unsafe { let application = UIApplication::shared(self.mtm); @@ -110,7 +128,7 @@ impl EventLoop { ); let event_handler = std::mem::transmute::< - Box, &RootEventLoopWindowTarget, &mut ControlFlow)>, + Box, &RootEventLoopWindowTarget)>, Box>, >(Box::new(event_handler)); @@ -217,6 +235,21 @@ impl EventLoopProxy { } } +#[derive(Clone, Copy, Debug, PartialEq)] +pub(crate) enum ControlFlow { + Poll, + Wait, + WaitUntil(Instant), + Exit, +} + +impl Default for ControlFlow { + #[inline(always)] + fn default() -> Self { + Self::Poll + } +} + fn setup_control_flow_observers() { unsafe { // begin is queued with the highest priority to ensure it is processed before other observers @@ -310,12 +343,11 @@ fn setup_control_flow_observers() { #[derive(Debug)] pub enum Never {} -type EventHandlerCallback = - dyn FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow) + 'static; +type EventHandlerCallback = dyn FnMut(Event, &RootEventLoopWindowTarget) + 'static; pub trait EventHandler: Debug { - fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow); - fn handle_user_events(&mut self, control_flow: &mut ControlFlow); + fn handle_nonuser_event(&mut self, event: Event); + fn handle_user_events(&mut self); } struct EventLoopHandler { @@ -333,17 +365,13 @@ impl Debug for EventLoopHandler { } impl EventHandler for EventLoopHandler { - fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow) { - (self.f)( - event.map_nonuser_event().unwrap(), - &self.event_loop, - control_flow, - ); + fn handle_nonuser_event(&mut self, event: Event) { + (self.f)(event.map_nonuser_event().unwrap(), &self.event_loop); } - fn handle_user_events(&mut self, control_flow: &mut ControlFlow) { + fn handle_user_events(&mut self) { for event in self.receiver.try_iter() { - (self.f)(Event::UserEvent(event), &self.event_loop, control_flow); + (self.f)(Event::UserEvent(event), &self.event_loop); } } }