mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
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
This commit is contained in:
parent
da7bf8e29b
commit
fb248eaadc
|
@ -62,7 +62,7 @@ ndk = "0.7.0"
|
||||||
ndk-glue = "0.7.0"
|
ndk-glue = "0.7.0"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
|
[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]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
core-foundation = "0.9.3"
|
core-foundation = "0.9.3"
|
||||||
|
|
|
@ -145,11 +145,6 @@ extern crate log;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[cfg(target_os = "ios")]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate objc;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
extern crate objc as objc2;
|
|
||||||
|
|
||||||
pub mod dpi;
|
pub mod dpi;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -9,8 +9,9 @@ use std::{
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use objc::foundation::{NSInteger, NSUInteger};
|
use objc2::foundation::{NSInteger, NSUInteger};
|
||||||
use objc::runtime::Object;
|
use objc2::runtime::Object;
|
||||||
|
use objc2::{class, msg_send, sel};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -7,7 +7,8 @@ use std::{
|
||||||
sync::mpsc::{self, Receiver, Sender},
|
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 raw_window_handle::{RawDisplayHandle, UiKitDisplayHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -91,7 +92,6 @@ impl<T: 'static> EventLoop<T> {
|
||||||
`EventLoopProxy` might be helpful"
|
`EventLoopProxy` might be helpful"
|
||||||
);
|
);
|
||||||
SINGLETON_INIT = true;
|
SINGLETON_INIT = true;
|
||||||
view::create_delegate_class();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (sender_to_clone, receiver) = mpsc::channel();
|
let (sender_to_clone, receiver) = mpsc::channel();
|
||||||
|
@ -128,11 +128,14 @@ impl<T: 'static> EventLoop<T> {
|
||||||
event_loop: self.window_target,
|
event_loop: self.window_target,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Ensure application delegate is initialized
|
||||||
|
view::WinitApplicationDelegate::class();
|
||||||
|
|
||||||
UIApplicationMain(
|
UIApplicationMain(
|
||||||
0,
|
0,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
nil,
|
nil,
|
||||||
NSStringRust::alloc(nil).init_str("AppDelegate"),
|
NSStringRust::alloc(nil).init_str("WinitApplicationDelegate"),
|
||||||
);
|
);
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
use std::{convert::TryInto, ffi::CString, ops::BitOr, os::raw::*};
|
use std::{convert::TryInto, ffi::CString, ops::BitOr, os::raw::*};
|
||||||
|
|
||||||
use objc::foundation::{NSInteger, NSUInteger};
|
use objc2::encode::{Encode, Encoding};
|
||||||
use objc::{runtime::Object, Encode, Encoding};
|
use objc2::foundation::{NSInteger, NSUInteger};
|
||||||
|
use objc2::runtime::Object;
|
||||||
|
use objc2::{class, msg_send};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
dpi::LogicalSize,
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
// window size/position.
|
// window size/position.
|
||||||
macro_rules! assert_main_thread {
|
macro_rules! assert_main_thread {
|
||||||
($($t:tt)*) => {
|
($($t:tt)*) => {
|
||||||
if !::objc::foundation::is_main_thread() {
|
if !::objc2::foundation::is_main_thread() {
|
||||||
panic!($($t)*);
|
panic!($($t)*);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -73,6 +73,7 @@ mod app_state;
|
||||||
mod event_loop;
|
mod event_loop;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
mod monitor;
|
mod monitor;
|
||||||
|
mod uikit;
|
||||||
mod view;
|
mod view;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ use std::{
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use objc::foundation::{NSInteger, NSUInteger};
|
use objc2::foundation::{NSInteger, NSUInteger};
|
||||||
|
use objc2::{class, msg_send};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{PhysicalPosition, PhysicalSize},
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
|
|
12
src/platform_impl/ios/uikit/mod.rs
Normal file
12
src/platform_impl/ios/uikit/mod.rs
Normal file
|
@ -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;
|
11
src/platform_impl/ios/uikit/responder.rs
Normal file
11
src/platform_impl/ios/uikit/responder.rs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
);
|
14
src/platform_impl/ios/uikit/view.rs
Normal file
14
src/platform_impl/ios/uikit/view.rs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
);
|
14
src/platform_impl/ios/uikit/view_controller.rs
Normal file
14
src/platform_impl/ios/uikit/view_controller.rs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
);
|
14
src/platform_impl/ios/uikit/window.rs
Normal file
14
src/platform_impl/ios/uikit/window.rs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
);
|
|
@ -1,16 +1,17 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use objc::{
|
use objc2::declare::ClassBuilder;
|
||||||
declare::ClassBuilder,
|
use objc2::foundation::NSObject;
|
||||||
runtime::{Bool, Class, Object, Sel},
|
use objc2::runtime::{Bool, Class, Object, Sel};
|
||||||
};
|
use objc2::{class, declare_class, msg_send, sel, ClassType};
|
||||||
|
|
||||||
|
use super::uikit::{UIResponder, UIViewController, UIWindow};
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::PhysicalPosition,
|
dpi::PhysicalPosition,
|
||||||
event::{DeviceId as RootDeviceId, Event, Force, Touch, TouchPhase, WindowEvent},
|
event::{DeviceId as RootDeviceId, Event, Force, Touch, TouchPhase, WindowEvent},
|
||||||
platform::ios::MonitorHandleExtIOS,
|
platform::ios::MonitorHandleExtIOS,
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::{self, OSCapabilities},
|
app_state,
|
||||||
event_loop::{self, EventProxy, EventWrapper},
|
event_loop::{self, EventProxy, EventWrapper},
|
||||||
ffi::{
|
ffi::{
|
||||||
id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask,
|
id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask,
|
||||||
|
@ -22,64 +23,6 @@ use crate::{
|
||||||
window::{Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
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
|
// requires main thread
|
||||||
unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
static mut CLASSES: Option<HashMap<*const Class, &'static Class>> = None;
|
static mut CLASSES: Option<HashMap<*const Class, &'static Class>> = None;
|
||||||
|
@ -312,116 +255,127 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires main thread
|
declare_class!(
|
||||||
unsafe fn get_view_controller_class() -> &'static Class {
|
struct WinitViewController {
|
||||||
static mut CLASS: Option<&'static Class> = None;
|
_prefers_status_bar_hidden: bool,
|
||||||
if CLASS.is_none() {
|
_prefers_home_indicator_auto_hidden: bool,
|
||||||
|
_supported_orientations: UIInterfaceOrientationMask,
|
||||||
|
_preferred_screen_edges_deferring_system_gestures: UIRectEdge,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ClassType for WinitViewController {
|
||||||
|
#[inherits(UIResponder, NSObject)]
|
||||||
|
type Super = UIViewController;
|
||||||
|
const NAME: &'static str = "WinitUIViewController";
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
let os_capabilities = app_state::os_capabilities();
|
||||||
|
if os_capabilities.home_indicator_hidden {
|
||||||
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 {
|
unsafe {
|
||||||
let _: () = msg_send![object, setNeedsStatusBarAppearanceUpdate];
|
let _: () = msg_send![self, setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
prefersStatusBarHidden,
|
os_capabilities.home_indicator_hidden_err_msg("ignoring")
|
||||||
}
|
}
|
||||||
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());
|
|
||||||
}
|
|
||||||
CLASS.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// requires main thread
|
#[sel(supportedInterfaceOrientations)]
|
||||||
unsafe fn get_window_class() -> &'static Class {
|
fn supported_orientations(&self) -> UIInterfaceOrientationMask {
|
||||||
static mut CLASS: Option<&'static Class> = None;
|
*self._supported_orientations
|
||||||
if CLASS.is_none() {
|
}
|
||||||
let uiwindow_class = class!(UIWindow);
|
|
||||||
|
|
||||||
extern "C" fn become_key_window(object: &Object, _: Sel) {
|
#[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 {
|
unsafe {
|
||||||
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(object.into()),
|
window_id: RootWindowId((&*****self).into()),
|
||||||
event: WindowEvent::Focused(true),
|
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 {
|
unsafe {
|
||||||
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(object.into()),
|
window_id: RootWindowId((&*****self).into()),
|
||||||
event: WindowEvent::Focused(false),
|
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
|
// requires main thread
|
||||||
pub(crate) unsafe fn create_view(
|
pub(crate) unsafe fn create_view(
|
||||||
|
@ -449,7 +403,7 @@ pub(crate) unsafe fn create_view_controller(
|
||||||
platform_attributes: &PlatformSpecificWindowBuilderAttributes,
|
platform_attributes: &PlatformSpecificWindowBuilderAttributes,
|
||||||
view: id,
|
view: id,
|
||||||
) -> id {
|
) -> id {
|
||||||
let class = get_view_controller_class();
|
let class = WinitViewController::class();
|
||||||
|
|
||||||
let view_controller: id = msg_send![class, alloc];
|
let view_controller: id = msg_send![class, alloc];
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -499,9 +453,7 @@ pub(crate) unsafe fn create_window(
|
||||||
frame: CGRect,
|
frame: CGRect,
|
||||||
view_controller: id,
|
view_controller: id,
|
||||||
) -> id {
|
) -> id {
|
||||||
let class = get_window_class();
|
let window: id = msg_send![WinitUIWindow::class(), alloc];
|
||||||
|
|
||||||
let window: id = msg_send![class, alloc];
|
|
||||||
assert!(!window.is_null(), "Failed to create `UIWindow` instance");
|
assert!(!window.is_null(), "Failed to create `UIWindow` instance");
|
||||||
let window: id = msg_send![window, initWithFrame: frame];
|
let window: id = msg_send![window, initWithFrame: frame];
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -532,26 +484,40 @@ pub(crate) unsafe fn create_window(
|
||||||
window
|
window
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_delegate_class() {
|
declare_class!(
|
||||||
extern "C" fn did_finish_launching(_: &mut Object, _: Sel, _: id, _: id) -> Bool {
|
pub struct WinitApplicationDelegate {}
|
||||||
|
|
||||||
|
unsafe impl ClassType for WinitApplicationDelegate {
|
||||||
|
type Super = NSObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UIApplicationDelegate protocol
|
||||||
|
unsafe impl WinitApplicationDelegate {
|
||||||
|
#[sel(application:didFinishLaunchingWithOptions:)]
|
||||||
|
fn did_finish_launching(&self, _: id, _: id) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
app_state::did_finish_launching();
|
app_state::did_finish_launching();
|
||||||
}
|
}
|
||||||
Bool::YES
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn did_become_active(_: &Object, _: Sel, _: id) {
|
#[sel(applicationDidBecomeActive:)]
|
||||||
|
fn did_become_active(&self, _: id) {
|
||||||
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) }
|
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) {
|
#[sel(applicationWillResignActive:)]
|
||||||
|
fn will_resign_active(&self, _: id) {
|
||||||
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) }
|
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {}
|
#[sel(applicationWillEnterForeground:)]
|
||||||
extern "C" fn did_enter_background(_: &Object, _: Sel, _: id) {}
|
fn will_enter_foreground(&self, _: id) {}
|
||||||
|
#[sel(applicationDidEnterBackground:)]
|
||||||
|
fn did_enter_background(&self, _: id) {}
|
||||||
|
|
||||||
extern "C" fn will_terminate(_: &Object, _: Sel, _: id) {
|
#[sel(applicationWillTerminate:)]
|
||||||
|
fn will_terminate(&self, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let app: id = msg_send![class!(UIApplication), sharedApplication];
|
let app: id = msg_send![class!(UIApplication), sharedApplication];
|
||||||
let windows: id = msg_send![app, windows];
|
let windows: id = msg_send![app, windows];
|
||||||
|
@ -562,7 +528,7 @@ pub fn create_delegate_class() {
|
||||||
if window == nil {
|
if window == nil {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let is_winit_window = msg_send![window, isKindOfClass: class!(WinitUIWindow)];
|
let is_winit_window = msg_send![window, isKindOfClass: WinitUIWindow::class()];
|
||||||
if is_winit_window {
|
if is_winit_window {
|
||||||
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(window.into()),
|
window_id: RootWindowId(window.into()),
|
||||||
|
@ -574,39 +540,5 @@ pub fn create_delegate_class() {
|
||||||
app_state::terminated();
|
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();
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
|
@ -3,7 +3,8 @@ use std::{
|
||||||
ops::{Deref, DerefMut},
|
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 raw_window_handle::{RawDisplayHandle, RawWindowHandle, UiKitDisplayHandle, UiKitWindowHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
Loading…
Reference in a new issue