diff --git a/cidre/src/core_motion/accelerometer.rs b/cidre/src/core_motion/accelerometer.rs index 56a6eb5f..60027f2a 100644 --- a/cidre/src/core_motion/accelerometer.rs +++ b/cidre/src/core_motion/accelerometer.rs @@ -1,5 +1,6 @@ use crate::{core_motion as cm, define_obj_type, objc}; +#[doc(alias = "CMAcceleration")] #[derive(Debug, Copy, Clone, PartialEq)] #[repr(C)] pub struct Acceleration { diff --git a/cidre/src/ns/date.rs b/cidre/src/ns/date.rs index 62b53d2d..2b951c36 100644 --- a/cidre/src/ns/date.rs +++ b/cidre/src/ns/date.rs @@ -1,5 +1,6 @@ use crate::{arc, define_obj_type, ns, objc}; +#[doc(alias = "NSTimeInterval")] pub type TimeInterval = f64; pub const TIME_INTERVAL_SINCE_1970: TimeInterval = 978307200.0f64; diff --git a/cidre/src/objc.rs b/cidre/src/objc.rs index 4d7105f8..1bd8cdca 100644 --- a/cidre/src/objc.rs +++ b/cidre/src/objc.rs @@ -31,7 +31,67 @@ impl Class { #[derive(Debug)] #[repr(transparent)] pub struct ClassInstExtra(Class, PhantomData); -pub const NS_OBJECT_SIZE: usize = 8; + +impl std::ops::Deref for ClassInstExtra { + type Target = Class; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +// class_getInstanceSize([NSObject class]); +pub const NS_OBJECT_SIZE: usize = std::mem::size_of::(); + +#[macro_export] +macro_rules! init_with_default { + ($NewType:ty, $InnerType:ty) => {{ + trait A { + fn init_fn(&self) -> Option; + } + + struct B(core::marker::PhantomData); + + impl core::ops::Deref for B { + type Target = (); + fn deref(&self) -> &Self::Target { + &() + } + } + + impl A for B + where + T: Default, + { + fn init_fn(&self) -> Option { + extern "C" fn impl_init( + s: &mut $NewType, + _sel: Option<$crate::objc::Sel>, + ) -> $crate::arc::R<$NewType> { + unsafe { + let ptr: *mut u8 = std::mem::transmute(s); + let d_ptr: *mut std::mem::ManuallyDrop = + ptr.add($crate::objc::NS_OBJECT_SIZE) as _; + *d_ptr = std::mem::ManuallyDrop::new(T::default()); + + std::mem::transmute(ptr) + } + } + + let ptr = unsafe { std::mem::transmute(impl_init:: as *const u8) }; + Some(ptr) + } + } + + impl A for () { + fn init_fn(&self) -> Option { + None + } + } + + B::<$InnerType>(core::marker::PhantomData).init_fn() + }}; +} impl ClassInstExtra { #[inline] @@ -54,6 +114,12 @@ impl ClassInstExtra { } } +impl ClassInstExtra { + pub fn new(&self) -> arc::R { + unsafe { self.alloc_init(Default::default()).unwrap_unchecked() } + } +} + impl Class { #[inline] pub fn as_type_ref(&self) -> &Type { @@ -264,6 +330,13 @@ extern "C-unwind" { types: *const u8, ) -> bool; + pub fn class_replaceMethod( + cls: &Class, + name: &Sel, + imp: extern "C" fn(), + types: *const u8, + ) -> Option; + pub fn objc_allocateClassPair( super_cls: &Class, name: *const u8, @@ -403,6 +476,14 @@ macro_rules! define_obj_type { $(::cls_add_methods(cls);)* $(::cls_add_protocol(cls);)* + if let Some(init_fn_ptr) = $crate::init_with_default!($NewType, $InnerType) { + unsafe { + let sel = $crate::objc::sel_reg_name(c"init".as_ptr() as _); + let imp: extern "C" fn() = init_fn_ptr; + $crate::objc::class_addMethod(cls, sel, imp, std::ptr::null()); + } + } + if std::mem::needs_drop::<$InnerType>() { extern "C" fn impl_dealloc(s: &mut $NewType, _sel: Option<$crate::objc::Sel>) { let ptr = s.inner_mut() as *mut _; @@ -476,7 +557,7 @@ macro_rules! define_obj_type { #[allow(dead_code)] pub fn new() -> $crate::arc::R { - unsafe { Self::cls().alloc_init(()).unwrap_unchecked() } + unsafe { Self::cls().new() } } } }; diff --git a/cidre/src/ui/application.rs b/cidre/src/ui/application.rs index dea91371..f93bbdae 100644 --- a/cidre/src/ui/application.rs +++ b/cidre/src/ui/application.rs @@ -1,4 +1,4 @@ -use crate::{arc, define_obj_type, objc, ui}; +use crate::{arc, define_obj_type, ns, objc, ui}; #[objc::protocol(UIApplication)] pub trait AppDelegate { @@ -22,6 +22,10 @@ pub trait AppDelegate { #[objc::optional] #[objc::msg_send(setWindow:)] fn set_window(&mut self, val: Option<&ui::Window>); + + #[objc::optional] + #[objc::msg_send(applicationDidBecomeActive:)] + fn app_did_become_active(&mut self, app: &App); } define_obj_type!( @@ -29,7 +33,28 @@ define_obj_type!( UI_APPLICATION ); -impl App {} +define_obj_type!( + pub AnyAppDelegate(ns::Id) +); + +impl AppDelegate for AnyAppDelegate {} + +impl App { + #[objc::msg_send(delegate)] + pub fn delegate(&self) -> Option<&AnyAppDelegate>; + + #[objc::msg_send(delegate)] + pub fn delegate_mut(&self) -> Option<&mut AnyAppDelegate>; + + #[objc::msg_send(setDelegate:)] + pub fn set_delegate(&mut self, val: Option<&AnyAppDelegate>); + + #[objc::msg_send(sharedApplication)] + pub fn shared() -> &'static Self; + + #[objc::msg_send(sharedApplication)] + pub fn shared_mut() -> &'static mut Self; +} extern "C" { static UI_APPLICATION: &'static objc::Class;