Reduce amount of unsafe on iOS (#2579)

* Use objc2::foundation CG types

* Add safe abstraction over UIApplication

* Add safe abstraction over UIDevice

* Add safe abstraction over UIScreen

* Add safe abstraction over UIWindow

* Add safe abstraction over UIViewController

* Add safe abstraction over UIView

* Appease clippy
This commit is contained in:
Mads Marquart 2022-12-28 18:36:32 +01:00 committed by GitHub
parent 5e77d70245
commit ee88e38f13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1048 additions and 962 deletions

View file

@ -14,10 +14,13 @@ use core_foundation::runloop::{
CFRunLoopObserverCreate, CFRunLoopObserverRef, CFRunLoopSourceContext, CFRunLoopSourceCreate,
CFRunLoopSourceInvalidate, CFRunLoopSourceRef, CFRunLoopSourceSignal, CFRunLoopWakeUp,
};
use objc2::runtime::Object;
use objc2::{class, msg_send, ClassType};
use objc2::foundation::MainThreadMarker;
use objc2::rc::{Id, Shared};
use objc2::ClassType;
use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle};
use super::uikit::{UIApplication, UIDevice, UIScreen};
use super::view::WinitUIWindow;
use crate::{
dpi::LogicalSize,
event::Event,
@ -29,20 +32,20 @@ use crate::{
use crate::platform_impl::platform::{
app_state,
ffi::{id, nil, NSStringRust, UIApplicationMain, UIUserInterfaceIdiom},
ffi::{nil, NSStringRust, UIApplicationMain},
monitor, view, MonitorHandle,
};
#[derive(Debug)]
pub enum EventWrapper {
pub(crate) enum EventWrapper {
StaticEvent(Event<'static, Never>),
EventProxy(EventProxy),
}
#[derive(Debug, PartialEq)]
pub enum EventProxy {
pub(crate) enum EventProxy {
DpiChangedProxy {
window_id: id,
window: Id<WinitUIWindow, Shared>,
suggested_size: LogicalSize<f64>,
scale_factor: f64,
},
@ -55,15 +58,13 @@ pub struct EventLoopWindowTarget<T: 'static> {
impl<T: 'static> EventLoopWindowTarget<T> {
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
// guaranteed to be on main thread
unsafe { monitor::uiscreens() }
monitor::uiscreens(MainThreadMarker::new().unwrap())
}
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
// guaranteed to be on main thread
let monitor = unsafe { monitor::main_uiscreen() };
Some(monitor)
Some(MonitorHandle::new(UIScreen::main(
MainThreadMarker::new().unwrap(),
)))
}
pub fn raw_display_handle(&self) -> RawDisplayHandle {
@ -113,13 +114,10 @@ impl<T: 'static> EventLoop<T> {
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
{
unsafe {
let application: *mut Object = msg_send![class!(UIApplication), sharedApplication];
assert_eq!(
application,
ptr::null_mut(),
let _application = UIApplication::shared(MainThreadMarker::new().unwrap()).expect(
"\
`EventLoop` cannot be `run` after a call to `UIApplicationMain` on iOS\n\
Note: `EventLoop::run` calls `UIApplicationMain` on iOS"
`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 {
f: event_handler,
@ -151,8 +149,9 @@ impl<T: 'static> EventLoop<T> {
// EventLoopExtIOS
impl<T: 'static> EventLoop<T> {
pub fn idiom(&self) -> Idiom {
// guaranteed to be on main thread
unsafe { self::get_idiom() }
UIDevice::current(MainThreadMarker::new().unwrap())
.userInterfaceIdiom()
.into()
}
}
@ -355,10 +354,3 @@ where
}
}
}
// must be called on main thread
pub unsafe fn get_idiom() -> Idiom {
let device: id = msg_send![class!(UIDevice), currentDevice];
let raw_idiom: UIUserInterfaceIdiom = msg_send![device, userInterfaceIdiom];
raw_idiom.into()
}