From fb248eaadc07466031aac1cbdbfb0e6a325ee973 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 8 Sep 2022 20:30:34 +0200 Subject: [PATCH] Clean up iOS class declaration (#2462) * Begin abstraction over UIKit * Clean up UIWindow override declaration * Clean up UIApplication delegate declaration * Clean up UIViewController override declaration * Finalize objc -> objc2 rename --- Cargo.toml | 2 +- src/lib.rs | 5 - src/platform_impl/ios/app_state.rs | 5 +- src/platform_impl/ios/event_loop.rs | 9 +- src/platform_impl/ios/ffi.rs | 6 +- src/platform_impl/ios/mod.rs | 3 +- src/platform_impl/ios/monitor.rs | 3 +- src/platform_impl/ios/uikit/mod.rs | 12 + src/platform_impl/ios/uikit/responder.rs | 11 + src/platform_impl/ios/uikit/view.rs | 14 + .../ios/uikit/view_controller.rs | 14 + src/platform_impl/ios/uikit/window.rs | 14 + src/platform_impl/ios/view.rs | 398 ++++++++---------- src/platform_impl/ios/window.rs | 3 +- 14 files changed, 250 insertions(+), 249 deletions(-) create mode 100644 src/platform_impl/ios/uikit/mod.rs create mode 100644 src/platform_impl/ios/uikit/responder.rs create mode 100644 src/platform_impl/ios/uikit/view.rs create mode 100644 src/platform_impl/ios/uikit/view_controller.rs create mode 100644 src/platform_impl/ios/uikit/window.rs diff --git a/Cargo.toml b/Cargo.toml index c3da432e..d38039e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ ndk = "0.7.0" ndk-glue = "0.7.0" [target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies] -objc = { version = "=0.3.0-beta.3", package = "objc2" } +objc2 = "=0.3.0-beta.3" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9.3" diff --git a/src/lib.rs b/src/lib.rs index 26a7fdc7..d6d99ebb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,11 +145,6 @@ extern crate log; extern crate serde; #[macro_use] extern crate bitflags; -#[cfg(target_os = "ios")] -#[macro_use] -extern crate objc; -#[cfg(target_os = "macos")] -extern crate objc as objc2; pub mod dpi; #[macro_use] diff --git a/src/platform_impl/ios/app_state.rs b/src/platform_impl/ios/app_state.rs index ed8fc36e..ae527b0b 100644 --- a/src/platform_impl/ios/app_state.rs +++ b/src/platform_impl/ios/app_state.rs @@ -9,8 +9,9 @@ use std::{ time::Instant, }; -use objc::foundation::{NSInteger, NSUInteger}; -use objc::runtime::Object; +use objc2::foundation::{NSInteger, NSUInteger}; +use objc2::runtime::Object; +use objc2::{class, msg_send, sel}; use once_cell::sync::Lazy; use crate::{ diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index af9e15db..3afcc8fc 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -7,7 +7,8 @@ use std::{ sync::mpsc::{self, Receiver, Sender}, }; -use objc::runtime::Object; +use objc2::runtime::Object; +use objc2::{class, msg_send, ClassType}; use raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle}; use crate::{ @@ -91,7 +92,6 @@ impl EventLoop { `EventLoopProxy` might be helpful" ); SINGLETON_INIT = true; - view::create_delegate_class(); } let (sender_to_clone, receiver) = mpsc::channel(); @@ -128,11 +128,14 @@ impl EventLoop { event_loop: self.window_target, })); + // Ensure application delegate is initialized + view::WinitApplicationDelegate::class(); + UIApplicationMain( 0, ptr::null(), nil, - NSStringRust::alloc(nil).init_str("AppDelegate"), + NSStringRust::alloc(nil).init_str("WinitApplicationDelegate"), ); unreachable!() } diff --git a/src/platform_impl/ios/ffi.rs b/src/platform_impl/ios/ffi.rs index 7de3dce0..3bfbbcfc 100644 --- a/src/platform_impl/ios/ffi.rs +++ b/src/platform_impl/ios/ffi.rs @@ -2,8 +2,10 @@ use std::{convert::TryInto, ffi::CString, ops::BitOr, os::raw::*}; -use objc::foundation::{NSInteger, NSUInteger}; -use objc::{runtime::Object, Encode, Encoding}; +use objc2::encode::{Encode, Encoding}; +use objc2::foundation::{NSInteger, NSUInteger}; +use objc2::runtime::Object; +use objc2::{class, msg_send}; use crate::{ dpi::LogicalSize, diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index cdac67cf..71a23f43 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -63,7 +63,7 @@ // window size/position. macro_rules! assert_main_thread { ($($t:tt)*) => { - if !::objc::foundation::is_main_thread() { + if !::objc2::foundation::is_main_thread() { panic!($($t)*); } }; @@ -73,6 +73,7 @@ mod app_state; mod event_loop; mod ffi; mod monitor; +mod uikit; mod view; mod window; diff --git a/src/platform_impl/ios/monitor.rs b/src/platform_impl/ios/monitor.rs index b309fe62..e736610d 100644 --- a/src/platform_impl/ios/monitor.rs +++ b/src/platform_impl/ios/monitor.rs @@ -4,7 +4,8 @@ use std::{ ops::{Deref, DerefMut}, }; -use objc::foundation::{NSInteger, NSUInteger}; +use objc2::foundation::{NSInteger, NSUInteger}; +use objc2::{class, msg_send}; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, diff --git a/src/platform_impl/ios/uikit/mod.rs b/src/platform_impl/ios/uikit/mod.rs new file mode 100644 index 00000000..34f5baa1 --- /dev/null +++ b/src/platform_impl/ios/uikit/mod.rs @@ -0,0 +1,12 @@ +#![deny(unsafe_op_in_unsafe_fn)] + +mod responder; +mod view; +mod view_controller; +mod window; + +pub(crate) use self::responder::UIResponder; +#[allow(unused)] +pub(crate) use self::view::UIView; +pub(crate) use self::view_controller::UIViewController; +pub(crate) use self::window::UIWindow; diff --git a/src/platform_impl/ios/uikit/responder.rs b/src/platform_impl/ios/uikit/responder.rs new file mode 100644 index 00000000..2a3cdb0a --- /dev/null +++ b/src/platform_impl/ios/uikit/responder.rs @@ -0,0 +1,11 @@ +use objc2::foundation::NSObject; +use objc2::{extern_class, ClassType}; + +extern_class!( + #[derive(Debug, PartialEq, Eq, Hash)] + pub(crate) struct UIResponder; + + unsafe impl ClassType for UIResponder { + type Super = NSObject; + } +); diff --git a/src/platform_impl/ios/uikit/view.rs b/src/platform_impl/ios/uikit/view.rs new file mode 100644 index 00000000..4646845e --- /dev/null +++ b/src/platform_impl/ios/uikit/view.rs @@ -0,0 +1,14 @@ +use objc2::foundation::NSObject; +use objc2::{extern_class, ClassType}; + +use super::UIResponder; + +extern_class!( + #[derive(Debug, PartialEq, Eq, Hash)] + pub(crate) struct UIView; + + unsafe impl ClassType for UIView { + #[inherits(NSObject)] + type Super = UIResponder; + } +); diff --git a/src/platform_impl/ios/uikit/view_controller.rs b/src/platform_impl/ios/uikit/view_controller.rs new file mode 100644 index 00000000..bacd1d97 --- /dev/null +++ b/src/platform_impl/ios/uikit/view_controller.rs @@ -0,0 +1,14 @@ +use objc2::foundation::NSObject; +use objc2::{extern_class, ClassType}; + +use super::UIResponder; + +extern_class!( + #[derive(Debug, PartialEq, Eq, Hash)] + pub(crate) struct UIViewController; + + unsafe impl ClassType for UIViewController { + #[inherits(NSObject)] + type Super = UIResponder; + } +); diff --git a/src/platform_impl/ios/uikit/window.rs b/src/platform_impl/ios/uikit/window.rs new file mode 100644 index 00000000..dfd45494 --- /dev/null +++ b/src/platform_impl/ios/uikit/window.rs @@ -0,0 +1,14 @@ +use objc2::foundation::NSObject; +use objc2::{extern_class, ClassType}; + +use super::UIResponder; + +extern_class!( + #[derive(Debug, PartialEq, Eq, Hash)] + pub(crate) struct UIWindow; + + unsafe impl ClassType for UIWindow { + #[inherits(NSObject)] + type Super = UIResponder; + } +); diff --git a/src/platform_impl/ios/view.rs b/src/platform_impl/ios/view.rs index 6afe9757..874864dc 100644 --- a/src/platform_impl/ios/view.rs +++ b/src/platform_impl/ios/view.rs @@ -1,16 +1,17 @@ use std::collections::HashMap; -use objc::{ - declare::ClassBuilder, - runtime::{Bool, Class, Object, Sel}, -}; +use objc2::declare::ClassBuilder; +use objc2::foundation::NSObject; +use objc2::runtime::{Bool, Class, Object, Sel}; +use objc2::{class, declare_class, msg_send, sel, ClassType}; +use super::uikit::{UIResponder, UIViewController, UIWindow}; use crate::{ dpi::PhysicalPosition, event::{DeviceId as RootDeviceId, Event, Force, Touch, TouchPhase, WindowEvent}, platform::ios::MonitorHandleExtIOS, platform_impl::platform::{ - app_state::{self, OSCapabilities}, + app_state, event_loop::{self, EventProxy, EventWrapper}, ffi::{ id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask, @@ -22,64 +23,6 @@ use crate::{ window::{Fullscreen, WindowAttributes, WindowId as RootWindowId}, }; -macro_rules! add_property { - ( - $decl:ident, - $name:ident: $t:ty, - $setter_name:ident: |$object:ident| $after_set:expr, - $getter_name:ident, - ) => { - add_property!( - $decl, - $name: $t, - $setter_name: true, |_, _|{}; |$object| $after_set, - $getter_name, - ) - }; - ( - $decl:ident, - $name:ident: $t:ty, - $setter_name:ident: $capability:expr, $err:expr; |$object:ident| $after_set:expr, - $getter_name:ident, - ) => { - { - const VAR_NAME: &'static str = concat!("_", stringify!($name)); - $decl.add_ivar::<$t>(VAR_NAME); - let setter = if $capability { - #[allow(non_snake_case)] - extern "C" fn $setter_name($object: &mut Object, _: Sel, value: $t) { - unsafe { - $object.set_ivar::<$t>(VAR_NAME, value); - } - $after_set - } - $setter_name - } else { - #[allow(non_snake_case)] - extern "C" fn $setter_name($object: &mut Object, _: Sel, value: $t) { - unsafe { - $object.set_ivar::<$t>(VAR_NAME, value); - } - $err(&app_state::os_capabilities(), "ignoring") - } - $setter_name - }; - #[allow(non_snake_case)] - extern "C" fn $getter_name($object: &Object, _: Sel) -> $t { - unsafe { *$object.ivar::<$t>(VAR_NAME) } - } - $decl.add_method( - sel!($setter_name:), - setter as extern "C" fn(_, _, _), - ); - $decl.add_method( - sel!($getter_name), - $getter_name as extern "C" fn(_, _) -> _, - ); - } - }; -} - // requires main thread unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class { static mut CLASSES: Option> = None; @@ -312,116 +255,127 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class { }) } -// requires main thread -unsafe fn get_view_controller_class() -> &'static Class { - static mut CLASS: Option<&'static Class> = None; - if CLASS.is_none() { - let os_capabilities = app_state::os_capabilities(); - - let uiviewcontroller_class = class!(UIViewController); - - extern "C" fn should_autorotate(_: &Object, _: Sel) -> Bool { - Bool::YES - } - - let mut decl = ClassBuilder::new("WinitUIViewController", uiviewcontroller_class) - .expect("Failed to declare class `WinitUIViewController`"); - decl.add_method( - sel!(shouldAutorotate), - should_autorotate as extern "C" fn(_, _) -> _, - ); - add_property! { - decl, - prefers_status_bar_hidden: Bool, - setPrefersStatusBarHidden: |object| { - unsafe { - let _: () = msg_send![object, setNeedsStatusBarAppearanceUpdate]; - } - }, - prefersStatusBarHidden, - } - add_property! { - decl, - prefers_home_indicator_auto_hidden: Bool, - setPrefersHomeIndicatorAutoHidden: - os_capabilities.home_indicator_hidden, - OSCapabilities::home_indicator_hidden_err_msg; - |object| { - unsafe { - let _: () = msg_send![object, setNeedsUpdateOfHomeIndicatorAutoHidden]; - } - }, - prefersHomeIndicatorAutoHidden, - } - add_property! { - decl, - supported_orientations: UIInterfaceOrientationMask, - setSupportedInterfaceOrientations: |object| { - unsafe { - let _: () = msg_send![class!(UIViewController), attemptRotationToDeviceOrientation]; - } - }, - supportedInterfaceOrientations, - } - add_property! { - decl, - preferred_screen_edges_deferring_system_gestures: UIRectEdge, - setPreferredScreenEdgesDeferringSystemGestures: - os_capabilities.defer_system_gestures, - OSCapabilities::defer_system_gestures_err_msg; - |object| { - unsafe { - let _: () = msg_send![object, setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; - } - }, - preferredScreenEdgesDeferringSystemGestures, - } - CLASS = Some(decl.register()); +declare_class!( + struct WinitViewController { + _prefers_status_bar_hidden: bool, + _prefers_home_indicator_auto_hidden: bool, + _supported_orientations: UIInterfaceOrientationMask, + _preferred_screen_edges_deferring_system_gestures: UIRectEdge, } - CLASS.unwrap() -} -// requires main thread -unsafe fn get_window_class() -> &'static Class { - static mut CLASS: Option<&'static Class> = None; - if CLASS.is_none() { - let uiwindow_class = class!(UIWindow); + unsafe impl ClassType for WinitViewController { + #[inherits(UIResponder, NSObject)] + type Super = UIViewController; + const NAME: &'static str = "WinitUIViewController"; + } - extern "C" fn become_key_window(object: &Object, _: Sel) { + unsafe impl WinitViewController { + #[sel(shouldAutorotate)] + fn should_autorotate(&self) -> bool { + true + } + } + + unsafe impl WinitViewController { + #[sel(prefersStatusBarHidden)] + fn prefers_status_bar_hidden(&self) -> bool { + *self._prefers_status_bar_hidden + } + + #[sel(setPrefersStatusBarHidden:)] + fn set_prefers_status_bar_hidden(&mut self, val: bool) { + *self._prefers_status_bar_hidden = val; + unsafe { + let _: () = msg_send![self, setNeedsStatusBarAppearanceUpdate]; + } + } + + #[sel(prefersHomeIndicatorAutoHidden)] + fn prefers_home_indicator_auto_hidden(&self) -> bool { + *self._prefers_home_indicator_auto_hidden + } + + #[sel(setPrefersHomeIndicatorAutoHidden:)] + fn set_prefers_home_indicator_auto_hidden(&mut self, val: bool) { + *self._prefers_home_indicator_auto_hidden = val; + let os_capabilities = app_state::os_capabilities(); + if os_capabilities.home_indicator_hidden { + unsafe { + let _: () = msg_send![self, setNeedsUpdateOfHomeIndicatorAutoHidden]; + } + } else { + os_capabilities.home_indicator_hidden_err_msg("ignoring") + } + } + + #[sel(supportedInterfaceOrientations)] + fn supported_orientations(&self) -> UIInterfaceOrientationMask { + *self._supported_orientations + } + + #[sel(setSupportedInterfaceOrientations:)] + fn set_supported_orientations(&mut self, val: UIInterfaceOrientationMask) { + *self._supported_orientations = val; + unsafe { + let _: () = msg_send![ + UIViewController::class(), + attemptRotationToDeviceOrientation + ]; + } + } + + #[sel(preferredScreenEdgesDeferringSystemGestures)] + fn preferred_screen_edges_deferring_system_gestures(&self) -> UIRectEdge { + *self._preferred_screen_edges_deferring_system_gestures + } + + #[sel(setPreferredScreenEdgesDeferringSystemGestures:)] + fn set_preferred_screen_edges_deferring_system_gestures(&mut self, val: UIRectEdge) { + *self._preferred_screen_edges_deferring_system_gestures = val; + let os_capabilities = app_state::os_capabilities(); + if os_capabilities.defer_system_gestures { + unsafe { + let _: () = msg_send![self, setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; + } + } else { + os_capabilities.defer_system_gestures_err_msg("ignoring") + } + } + } +); + +declare_class!( + struct WinitUIWindow {} + + unsafe impl ClassType for WinitUIWindow { + #[inherits(UIResponder, NSObject)] + type Super = UIWindow; + } + + unsafe impl WinitUIWindow { + #[sel(becomeKeyWindow)] + fn become_key_window(&self) { unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent { - window_id: RootWindowId(object.into()), + window_id: RootWindowId((&*****self).into()), event: WindowEvent::Focused(true), })); - let _: () = msg_send![super(object, class!(UIWindow)), becomeKeyWindow]; + let _: () = msg_send![super(self), becomeKeyWindow]; } } - extern "C" fn resign_key_window(object: &Object, _: Sel) { + #[sel(resignKeyWindow)] + fn resign_key_window(&self) { unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent { - window_id: RootWindowId(object.into()), + window_id: RootWindowId((&*****self).into()), event: WindowEvent::Focused(false), })); - let _: () = msg_send![super(object, class!(UIWindow)), resignKeyWindow]; + let _: () = msg_send![super(self), resignKeyWindow]; } } - - let mut decl = ClassBuilder::new("WinitUIWindow", uiwindow_class) - .expect("Failed to declare class `WinitUIWindow`"); - decl.add_method( - sel!(becomeKeyWindow), - become_key_window as extern "C" fn(_, _), - ); - decl.add_method( - sel!(resignKeyWindow), - resign_key_window as extern "C" fn(_, _), - ); - - CLASS = Some(decl.register()); } - CLASS.unwrap() -} +); // requires main thread pub(crate) unsafe fn create_view( @@ -449,7 +403,7 @@ pub(crate) unsafe fn create_view_controller( platform_attributes: &PlatformSpecificWindowBuilderAttributes, view: id, ) -> id { - let class = get_view_controller_class(); + let class = WinitViewController::class(); let view_controller: id = msg_send![class, alloc]; assert!( @@ -499,9 +453,7 @@ pub(crate) unsafe fn create_window( frame: CGRect, view_controller: id, ) -> id { - let class = get_window_class(); - - let window: id = msg_send![class, alloc]; + let window: id = msg_send![WinitUIWindow::class(), alloc]; assert!(!window.is_null(), "Failed to create `UIWindow` instance"); let window: id = msg_send![window, initWithFrame: frame]; assert!( @@ -532,81 +484,61 @@ pub(crate) unsafe fn create_window( window } -pub fn create_delegate_class() { - extern "C" fn did_finish_launching(_: &mut Object, _: Sel, _: id, _: id) -> Bool { - unsafe { - app_state::did_finish_launching(); - } - Bool::YES +declare_class!( + pub struct WinitApplicationDelegate {} + + unsafe impl ClassType for WinitApplicationDelegate { + type Super = NSObject; } - extern "C" fn did_become_active(_: &Object, _: Sel, _: id) { - unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) } - } - - extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) { - unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) } - } - - extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {} - extern "C" fn did_enter_background(_: &Object, _: Sel, _: id) {} - - extern "C" fn will_terminate(_: &Object, _: Sel, _: id) { - unsafe { - let app: id = msg_send![class!(UIApplication), sharedApplication]; - let windows: id = msg_send![app, windows]; - let windows_enum: id = msg_send![windows, objectEnumerator]; - let mut events = Vec::new(); - loop { - let window: id = msg_send![windows_enum, nextObject]; - if window == nil { - break; - } - let is_winit_window = msg_send![window, isKindOfClass: class!(WinitUIWindow)]; - if is_winit_window { - events.push(EventWrapper::StaticEvent(Event::WindowEvent { - window_id: RootWindowId(window.into()), - event: WindowEvent::Destroyed, - })); - } + // UIApplicationDelegate protocol + unsafe impl WinitApplicationDelegate { + #[sel(application:didFinishLaunchingWithOptions:)] + fn did_finish_launching(&self, _: id, _: id) -> bool { + unsafe { + app_state::did_finish_launching(); + } + true + } + + #[sel(applicationDidBecomeActive:)] + fn did_become_active(&self, _: id) { + unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) } + } + + #[sel(applicationWillResignActive:)] + fn will_resign_active(&self, _: id) { + unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) } + } + + #[sel(applicationWillEnterForeground:)] + fn will_enter_foreground(&self, _: id) {} + #[sel(applicationDidEnterBackground:)] + fn did_enter_background(&self, _: id) {} + + #[sel(applicationWillTerminate:)] + fn will_terminate(&self, _: id) { + unsafe { + let app: id = msg_send![class!(UIApplication), sharedApplication]; + let windows: id = msg_send![app, windows]; + let windows_enum: id = msg_send![windows, objectEnumerator]; + let mut events = Vec::new(); + loop { + let window: id = msg_send![windows_enum, nextObject]; + if window == nil { + break; + } + let is_winit_window = msg_send![window, isKindOfClass: WinitUIWindow::class()]; + if is_winit_window { + events.push(EventWrapper::StaticEvent(Event::WindowEvent { + window_id: RootWindowId(window.into()), + event: WindowEvent::Destroyed, + })); + } + } + app_state::handle_nonuser_events(events); + app_state::terminated(); } - app_state::handle_nonuser_events(events); - app_state::terminated(); } } - - let ui_responder = class!(UIResponder); - let mut decl = ClassBuilder::new("AppDelegate", ui_responder) - .expect("Failed to declare class `AppDelegate`"); - - unsafe { - decl.add_method( - sel!(application:didFinishLaunchingWithOptions:), - did_finish_launching as extern "C" fn(_, _, _, _) -> _, - ); - - decl.add_method( - sel!(applicationDidBecomeActive:), - did_become_active as extern "C" fn(_, _, _), - ); - decl.add_method( - sel!(applicationWillResignActive:), - will_resign_active as extern "C" fn(_, _, _), - ); - decl.add_method( - sel!(applicationWillEnterForeground:), - will_enter_foreground as extern "C" fn(_, _, _), - ); - decl.add_method( - sel!(applicationDidEnterBackground:), - did_enter_background as extern "C" fn(_, _, _), - ); - - decl.add_method( - sel!(applicationWillTerminate:), - will_terminate as extern "C" fn(_, _, _), - ); - - decl.register(); - } -} +); diff --git a/src/platform_impl/ios/window.rs b/src/platform_impl/ios/window.rs index dd62211d..6c8552ef 100644 --- a/src/platform_impl/ios/window.rs +++ b/src/platform_impl/ios/window.rs @@ -3,7 +3,8 @@ use std::{ ops::{Deref, DerefMut}, }; -use objc::runtime::{Class, Object}; +use objc2::runtime::{Class, Object}; +use objc2::{class, msg_send}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle}; use crate::{