Merge pull request #79 from MerlinDE/fix_register_class

Fixes possible duplicate objc class registration.
This commit is contained in:
Ryan McGrath 2023-04-25 16:53:44 -07:00 committed by GitHub
commit f24261747c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 161 additions and 546 deletions

View file

@ -15,35 +15,29 @@ use cacao::text::{Font, Label};
use cacao::view::{Popover, PopoverConfig, View, ViewController, ViewDelegate}; use cacao::view::{Popover, PopoverConfig, View, ViewController, ViewDelegate};
struct BasicApp { struct BasicApp {
window: WindowController<MyWindow>, window: WindowController<MyWindow>
} }
impl AppDelegate for BasicApp { impl AppDelegate for BasicApp {
fn did_finish_launching(&self) { fn did_finish_launching(&self) {
App::set_menu(vec![ App::set_menu(vec![
Menu::new( Menu::new("", vec![
"", MenuItem::Services,
vec![ MenuItem::Separator,
MenuItem::Services, MenuItem::Hide,
MenuItem::Separator, MenuItem::HideOthers,
MenuItem::Hide, MenuItem::ShowAll,
MenuItem::HideOthers, MenuItem::Separator,
MenuItem::ShowAll, MenuItem::Quit,
MenuItem::Separator, ]),
MenuItem::Quit,
],
),
Menu::new("File", vec![MenuItem::CloseWindow]), Menu::new("File", vec![MenuItem::CloseWindow]),
Menu::new("View", vec![MenuItem::EnterFullScreen]), Menu::new("View", vec![MenuItem::EnterFullScreen]),
Menu::new( Menu::new("Window", vec![
"Window", MenuItem::Minimize,
vec![ MenuItem::Zoom,
MenuItem::Minimize, MenuItem::Separator,
MenuItem::Zoom, MenuItem::new("Bring All to Front"),
MenuItem::Separator, ]),
MenuItem::new("Bring All to Front"),
],
),
]); ]);
App::activate(); App::activate();
@ -58,7 +52,7 @@ impl AppDelegate for BasicApp {
#[derive(Default)] #[derive(Default)]
struct MyWindow { struct MyWindow {
controller: Option<ViewController<PopoverExampleContentView>>, controller: Option<ViewController<PopoverExampleContentView>>
} }
impl WindowDelegate for MyWindow { impl WindowDelegate for MyWindow {
@ -87,25 +81,22 @@ impl MyWindow {
} }
fn main() { fn main() {
App::new( App::new("com.test.window-delegate", BasicApp {
"com.test.window-delegate", window: WindowController::with(WindowConfig::default(), MyWindow::default())
BasicApp { })
window: WindowController::with(WindowConfig::default(), MyWindow::default()),
},
)
.run(); .run();
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Msg { pub enum Msg {
Click, Click
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct PopoverExampleContentView { struct PopoverExampleContentView {
view: Option<View>, view: Option<View>,
button: Option<Button>, button: Option<Button>,
popover: Option<Popover<PopoverExampleContentViewController>>, popover: Option<Popover<PopoverExampleContentViewController>>
} }
impl PopoverExampleContentView { impl PopoverExampleContentView {
@ -113,7 +104,7 @@ impl PopoverExampleContentView {
Self { Self {
view: None, view: None,
button: None, button: None,
popover: None, popover: None
} }
} }
@ -123,7 +114,7 @@ impl PopoverExampleContentView {
let Some(ref popover) = self.popover else { return }; let Some(ref popover) = self.popover else { return };
let Some(ref button) = self.button else { return }; let Some(ref button) = self.button else { return };
popover.show_popover(Rect::zero(), button, Edge::MaxY); popover.show_popover(Rect::zero(), button, Edge::MaxY);
}, }
} }
} }
} }
@ -147,7 +138,7 @@ impl ViewDelegate for PopoverExampleContentView {
LayoutConstraint::activate(&[ LayoutConstraint::activate(&[
button.center_x.constraint_equal_to(&view.center_x), button.center_x.constraint_equal_to(&view.center_x),
button.center_y.constraint_equal_to(&view.center_y), button.center_y.constraint_equal_to(&view.center_y)
]); ]);
self.view = Some(view); self.view = Some(view);
@ -173,7 +164,7 @@ impl Dispatcher for BasicApp {
#[derive(Debug)] #[derive(Debug)]
struct PopoverExampleContentViewController { struct PopoverExampleContentViewController {
pub label: Label, pub label: Label
} }
impl PopoverExampleContentViewController { impl PopoverExampleContentViewController {

View file

@ -2,22 +2,11 @@
//! creates a custom `NSApplication` subclass that currently does nothing; this is meant as a hook //! creates a custom `NSApplication` subclass that currently does nothing; this is meant as a hook
//! for potential future use. //! for potential future use.
use std::sync::Once;
use objc::class;
use objc::declare::ClassDecl;
use objc::runtime::Class; use objc::runtime::Class;
use crate::foundation::load_or_register_class;
/// Used for injecting a custom NSApplication. Currently does nothing. /// Used for injecting a custom NSApplication. Currently does nothing.
pub(crate) fn register_app_class() -> *const Class { pub(crate) fn register_app_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSApplication", "RSTApplication", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSApplication);
let decl = ClassDecl::new("RSTApplication", superclass).unwrap();
APP_CLASS = decl.register();
});
unsafe { APP_CLASS }
} }

View file

@ -3,24 +3,19 @@
//! for potential future use. //! for potential future use.
use std::ffi::c_void; use std::ffi::c_void;
use std::sync::Once;
use block::Block; use block::Block;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use url::Url; use url::Url;
use crate::appkit::app::{AppDelegate, APP_PTR}; use crate::appkit::app::{AppDelegate, APP_PTR};
use crate::appkit::printing::PrintSettings; use crate::appkit::printing::PrintSettings;
use crate::error::Error;
use crate::foundation::{id, nil, to_bool, NSArray, NSString, NSUInteger, BOOL, NO, YES};
use crate::user_activity::UserActivity;
#[cfg(feature = "cloudkit")] #[cfg(feature = "cloudkit")]
use crate::cloudkit::share::CKShareMetaData; use crate::cloudkit::share::CKShareMetaData;
use crate::error::Error;
use crate::foundation::{id, load_or_register_class, nil, to_bool, NSArray, NSString, NSUInteger, BOOL, NO, YES};
use crate::user_activity::UserActivity;
/// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our /// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our
/// standard `utils` version as this doesn't require `RefCell` backing. /// standard `utils` version as this doesn't require `RefCell` backing.
@ -295,13 +290,7 @@ extern "C" fn delegate_handles_key<T: AppDelegate>(this: &Object, _: Sel, _: id,
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and /// Registers an `NSObject` application delegate, and configures it for the various callbacks and
/// pointers we need to have. /// pointers we need to have.
pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class { pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSObject", "RSTAppDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap();
decl.add_ivar::<usize>(APP_PTR); decl.add_ivar::<usize>(APP_PTR);
// Launching Applications // Launching Applications
@ -461,9 +450,5 @@ pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *co
sel!(application:delegateHandlesKey:), sel!(application:delegateHandlesKey:),
delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
})
DELEGATE_CLASS = decl.register();
});
unsafe { DELEGATE_CLASS }
} }

View file

@ -3,16 +3,13 @@
//! now. //! now.
use std::fmt; use std::fmt;
use std::sync::Once;
use block::ConcreteBlock;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::events::EventModifierFlag; use crate::events::EventModifierFlag;
use crate::foundation::{id, nil, NSString, NSUInteger}; use crate::foundation::{id, load_or_register_class, NSString, NSUInteger};
static BLOCK_PTR: &'static str = "cacaoMenuItemBlockPtr"; static BLOCK_PTR: &'static str = "cacaoMenuItemBlockPtr";
@ -314,19 +311,10 @@ extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) {
/// In general, we do not want to do more than we need to here - menus are one of the last areas /// In general, we do not want to do more than we need to here - menus are one of the last areas
/// where Carbon still lurks, and subclassing things can get weird. /// where Carbon still lurks, and subclassing things can get weird.
pub(crate) fn register_menu_item_class() -> *const Class { pub(crate) fn register_menu_item_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSMenuItem", "CacaoMenuItem", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSMenuItem);
let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap();
decl.add_ivar::<usize>(BLOCK_PTR); decl.add_ivar::<usize>(BLOCK_PTR);
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _)); decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id)); decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
})
APP_CLASS = decl.register();
});
unsafe { APP_CLASS }
} }

View file

@ -1,26 +1,15 @@
//! Everything useful for the `WindowController`. Handles injecting an `NSWindowController` subclass //! Everything useful for the `WindowController`. Handles injecting an `NSWindowController` subclass
//! into the Objective C runtime, which loops back to give us lifecycle methods. //! into the Objective C runtime, which loops back to give us lifecycle methods.
use std::sync::Once;
use objc::class;
use objc::declare::ClassDecl;
use objc::runtime::Class; use objc::runtime::Class;
use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
use crate::foundation::load_or_register_class;
/// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we /// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class { pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSWindowController", "RSTWindowController", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSWindowController);
let mut decl = ClassDecl::new("RSTWindowController", superclass).unwrap();
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR); decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
DELEGATE_CLASS = decl.register(); })
});
unsafe { DELEGATE_CLASS }
} }

View file

@ -110,14 +110,14 @@ impl Window {
Window { Window {
objc: objc, objc: objc,
delegate: None, delegate: None
} }
} }
pub(crate) unsafe fn existing(window: *mut Object) -> Window { pub(crate) unsafe fn existing(window: *mut Object) -> Window {
Window { Window {
objc: ShareId::from_ptr(window), objc: ShareId::from_ptr(window),
delegate: None, delegate: None
} }
} }
} }

View file

@ -21,36 +21,28 @@
//! my_view.add_subview(&button); //! my_view.add_subview(&button);
//! ``` //! ```
use std::fmt; use objc::runtime::{Class, Object};
use std::sync::Once; use objc::{msg_send, sel, sel_impl};
use std::cell::RefCell;
use std::rc::Rc;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
pub use enums::*;
#[cfg(feature = "appkit")]
use crate::appkit::FocusRingType;
use crate::color::Color; use crate::color::Color;
use crate::control::Control; use crate::control::Control;
use crate::foundation::{id, nil, NSString, NSUInteger, BOOL, NO, YES}; use crate::foundation::{id, load_or_register_class, nil, NSString, NSUInteger, NO, YES};
use crate::image::Image; use crate::image::Image;
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::keys::Key; use crate::keys::Key;
use crate::layout::Layout; use crate::layout::Layout;
use crate::objc_access::ObjcAccess;
use crate::text::{AttributedString, Font};
use crate::utils::{load, properties::ObjcProperty};
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
use crate::objc_access::ObjcAccess;
#[cfg(feature = "appkit")] use crate::text::{AttributedString, Font};
use crate::appkit::FocusRingType; use crate::utils::properties::ObjcProperty;
mod enums; mod enums;
pub use enums::*;
/// Wraps `NSButton` on appkit, and `UIButton` on iOS and tvOS. /// Wraps `NSButton` on appkit, and `UIButton` on iOS and tvOS.
/// ///
@ -313,6 +305,7 @@ impl ObjcAccess for Button {
} }
impl Layout for Button {} impl Layout for Button {}
impl Control for Button {} impl Control for Button {}
impl ObjcAccess for &Button { impl ObjcAccess for &Button {
@ -326,6 +319,7 @@ impl ObjcAccess for &Button {
} }
impl Layout for &Button {} impl Layout for &Button {}
impl Control for &Button {} impl Control for &Button {}
impl Drop for Button { impl Drop for Button {
@ -343,14 +337,5 @@ impl Drop for Button {
/// Registers an `NSButton` subclass, and configures it to hold some ivars /// Registers an `NSButton` subclass, and configures it to hold some ivars
/// for various things we need to store. /// for various things we need to store.
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSButton", "RSTButton", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSButton);
let decl = ClassDecl::new("RSTButton", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -10,16 +10,11 @@
//! that enables this functionality, we want to be able to provide this with some level of //! that enables this functionality, we want to be able to provide this with some level of
//! backwards compatibility for Mojave, as that's still a supported OS. //! backwards compatibility for Mojave, as that's still a supported OS.
use std::os::raw::c_void;
use std::sync::Once;
use core_graphics::base::CGFloat; use core_graphics::base::CGFloat;
use objc::runtime::{Class, Object, Sel};
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, NSArray, NSInteger, NSString, NSUInteger, NO, YES}; use crate::foundation::{id, load_or_register_class, nil, NSArray, NSInteger};
use crate::utils::os; use crate::utils::os;
pub(crate) const AQUA_LIGHT_COLOR_NORMAL_CONTRAST: &'static str = "AQUA_LIGHT_COLOR_NORMAL_CONTRAST"; pub(crate) const AQUA_LIGHT_COLOR_NORMAL_CONTRAST: &'static str = "AQUA_LIGHT_COLOR_NORMAL_CONTRAST";
@ -259,13 +254,7 @@ extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger)
} }
pub(crate) fn register_class() -> *const Class { pub(crate) fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSColor", "CacaoDynamicColor", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSColor);
let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap();
// These methods all need to be forwarded, so let's hook them up. // These methods all need to be forwarded, so let's hook them up.
decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id); decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id);
decl.add_method( decl.add_method(
@ -359,9 +348,5 @@ pub(crate) fn register_class() -> *const Class {
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST); decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST);
decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST); decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST);
decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST); decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST);
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -47,7 +47,7 @@ pub enum Edge {
MinX = 0, MinX = 0,
MinY = 1, MinY = 1,
MaxX = 2, MaxX = 2,
MaxY = 3, MaxY = 3
} }
impl From<Rect> for CGRect { impl From<Rect> for CGRect {
fn from(rect: Rect) -> CGRect { fn from(rect: Rect) -> CGRect {

View file

@ -7,33 +7,15 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once; use objc::runtime::Class;
use objc::declare::ClassDecl; use crate::foundation::load_or_register_class;
use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl};
use objc_id::Id;
use crate::dragdrop::DragInfo;
use crate::foundation::{id, NSUInteger, NO, YES};
use crate::utils::load;
use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we /// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_image_view_class() -> *const Class { pub(crate) fn register_image_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSImageView", "RSTImageView", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSImageView);
let decl = ClassDecl::new("RSTImageView", superclass).unwrap();
//decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); //decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -1,26 +1,10 @@
use std::sync::Once; use objc::runtime::Class;
use objc::declare::ClassDecl; use crate::foundation::load_or_register_class;
use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl};
use objc_id::Id;
use crate::foundation::{id, NSUInteger, NO, YES};
use crate::utils::load;
use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we /// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_image_view_class() -> *const Class { pub(crate) fn register_image_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIImageView", "RSTImageView", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIImageView);
let mut decl = ClassDecl::new("RSTImageView", superclass).expect("Failed to get RSTVIEW");
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -1,12 +1,7 @@
use std::sync::Once;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::Id;
use crate::dragdrop::DragInfo; use crate::foundation::{id, load_or_register_class, NSString, NO, YES};
use crate::foundation::{id, load_or_register_class, NSString, NSUInteger, NO, YES};
use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR}; use crate::input::{TextFieldDelegate, TEXTFIELD_DELEGATE_PTR};
use crate::utils::load; use crate::utils::load;
@ -52,16 +47,7 @@ extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSTextField", "RSTTextInputField", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSTextField);
let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we /// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we

View file

@ -9,15 +9,12 @@
//! is going away. //! is going away.
use std::fmt; use std::fmt;
use std::sync::{Arc, Mutex, Once};
use block::{Block, ConcreteBlock, RcBlock};
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, NSString}; use crate::foundation::{id, load_or_register_class};
use crate::utils::load; use crate::utils::load;
pub static ACTION_CALLBACK_PTR: &str = "rstTargetActionPtr"; pub static ACTION_CALLBACK_PTR: &str = "rstTargetActionPtr";
@ -95,18 +92,8 @@ extern "C" fn perform<F: Fn() + 'static>(this: &mut Object, _: Sel, _sender: id)
/// on drop. We handle the heap copy on the Rust side, so setting the block /// on drop. We handle the heap copy on the Rust side, so setting the block
/// is just an ivar. /// is just an ivar.
pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class { pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSObject", "RSTTargetActionHandler", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap();
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR); decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id)); decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -7,16 +7,13 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::appkit::menu::{Menu, MenuItem}; use crate::appkit::menu::Menu;
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::foundation::{id, load_or_register_class, nil, NSArray, NSInteger, NSUInteger, NO, YES}; use crate::foundation::{id, load_or_register_class, NSArray, NSInteger, NSUInteger, NO, YES};
use crate::listview::{ListViewDelegate, RowEdge, LISTVIEW_DELEGATE_PTR}; use crate::listview::{ListViewDelegate, RowEdge, LISTVIEW_DELEGATE_PTR};
use crate::utils::load; use crate::utils::load;
@ -185,16 +182,7 @@ extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, in
/// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can /// `UITableView` semantics; if `NSTableView`'s multi column behavior is needed, then it can
/// be added in. /// be added in.
pub(crate) fn register_listview_class() -> *const Class { pub(crate) fn register_listview_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSTableView", "RSTListView", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSTableView);
let decl = ClassDecl::new("RSTListView", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSTableView` subclass, with some callback and pointer ivars for what we /// Injects an `NSTableView` subclass, with some callback and pointer ivars for what we

View file

@ -7,15 +7,12 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::foundation::{id, nil, NSUInteger, NO, YES}; use crate::foundation::{id, load_or_register_class, nil, NSUInteger, NO, YES};
use crate::listview::row::{ViewDelegate, BACKGROUND_COLOR, LISTVIEW_ROW_DELEGATE_PTR}; use crate::listview::row::{ViewDelegate, BACKGROUND_COLOR, LISTVIEW_ROW_DELEGATE_PTR};
use crate::utils::load; use crate::utils::load;
@ -107,31 +104,15 @@ extern "C" fn dealloc<T: ViewDelegate>(this: &Object, _: Sel) {
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_listview_row_class() -> *const Class { pub(crate) fn register_listview_row_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSView", "RSTTableViewRow", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTTableViewRow", superclass).unwrap();
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we /// Injects an `NSView` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *const Class { pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSView", "RSTableViewRowWithDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTableViewRowWithDelegate", superclass).unwrap();
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR); decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR);
@ -164,9 +145,5 @@ pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *c
// Cleanup // Cleanup
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _)); decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _));
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -1,45 +1,24 @@
use std::sync::Once;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::foundation::{id, YES, NO, NSUInteger};
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; use crate::foundation::{id, NSUInteger, NO, YES};
use crate::utils::load; use crate::utils::load;
use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
/// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we /// Injects an `NSView` subclass. This is used for the default views that don't use delegates - we
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIView", "RSTView", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIView);
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we /// Injects an `NSView` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class { pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIView", "RSTViewWithDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIView);
let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap();
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR); decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
VIEW_CLASS = decl.register(); })
});
unsafe {
VIEW_CLASS
}
} }

View file

@ -7,15 +7,12 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl}; use objc::{sel, sel_impl};
use objc_id::Id; use objc_id::Id;
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::foundation::{id, NSUInteger, NO, YES}; use crate::foundation::{id, load_or_register_class, NSUInteger, NO, YES};
use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR}; use crate::scrollview::{ScrollViewDelegate, SCROLLVIEW_DELEGATE_PTR};
use crate::utils::load; use crate::utils::load;
@ -77,28 +74,13 @@ extern "C" fn dragging_exited<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
/// Injects an `NSScrollView` subclass. /// Injects an `NSScrollView` subclass.
pub(crate) fn register_scrollview_class() -> *const Class { pub(crate) fn register_scrollview_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSScrollView", "RSTScrollView", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSScrollView);
let decl = ClassDecl::new("RSTScrollView", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we /// Injects an `NSView` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class { pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSScrollView", "RSTScrollViewWithDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSScrollView);
let mut decl = ClassDecl::new("RSTScrollViewWithDelegate", superclass).unwrap();
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR); decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
@ -126,9 +108,5 @@ pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -
sel!(draggingExited:), sel!(draggingExited:),
dragging_exited::<T> as extern "C" fn(&mut Object, _, _) dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
); );
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -1,24 +1,19 @@
//! Implements a Select-style dropdown. By default this uses NSPopupSelect on macOS. //! Implements a Select-style dropdown. By default this uses NSPopupSelect on macOS.
use std::sync::Once;
use core_graphics::geometry::CGRect; use core_graphics::geometry::CGRect;
use objc::runtime::{Class, Object};
use objc::declare::ClassDecl; use objc::{msg_send, sel, sel_impl};
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::control::Control; use crate::control::Control;
use crate::foundation::{id, nil, NSInteger, NSString, NO, YES}; use crate::foundation::{id, load_or_register_class, nil, NSInteger, NSString, NO, YES};
use crate::geometry::Rect; use crate::geometry::Rect;
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::layout::Layout; use crate::layout::Layout;
use crate::objc_access::ObjcAccess;
use crate::utils::properties::ObjcProperty;
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
use crate::objc_access::ObjcAccess;
use crate::utils::properties::ObjcProperty;
/// Wraps `NSPopUpSelect` on AppKit. Not currently implemented for iOS. /// Wraps `NSPopUpSelect` on AppKit. Not currently implemented for iOS.
/// ///
@ -268,14 +263,5 @@ impl Drop for Select {
/// Registers an `NSSelect` subclass, and configures it to hold some ivars /// Registers an `NSSelect` subclass, and configures it to hold some ivars
/// for various things we need to store. /// for various things we need to store.
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSPopUpButton", "CacaoSelect", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSPopUpButton);
let decl = ClassDecl::new("CacaoSelect", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -1,22 +1,17 @@
//! A wrapper for NSSwitch. Currently the epitome of jank - if you're poking around here, expect //! A wrapper for NSSwitch. Currently the epitome of jank - if you're poking around here, expect
//! that this will change at some point. //! that this will change at some point.
use std::fmt; use objc::runtime::{Class, Object};
use std::sync::Once; use objc::{msg_send, sel, sel_impl};
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;
use crate::foundation::{id, nil, NSString, BOOL, NO, YES}; use crate::foundation::{id, load_or_register_class, nil, NSString, NO};
use crate::invoker::TargetActionHandler; use crate::invoker::TargetActionHandler;
use crate::layout::Layout; use crate::layout::Layout;
use crate::objc_access::ObjcAccess;
use crate::utils::{load, properties::ObjcProperty};
#[cfg(feature = "autolayout")] #[cfg(feature = "autolayout")]
use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY}; use crate::layout::{LayoutAnchorDimension, LayoutAnchorX, LayoutAnchorY};
use crate::objc_access::ObjcAccess;
use crate::utils::properties::ObjcProperty;
/// A wrapper for `NSSwitch`. Holds (retains) pointers for the Objective-C runtime /// A wrapper for `NSSwitch`. Holds (retains) pointers for the Objective-C runtime
/// where our `NSSwitch` lives. /// where our `NSSwitch` lives.
@ -178,14 +173,5 @@ impl Drop for Switch {
/// Registers an `NSButton` subclass, and configures it to hold some ivars /// Registers an `NSButton` subclass, and configures it to hold some ivars
/// for various things we need to store. /// for various things we need to store.
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSButton", "RSTSwitch", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSButton);
let decl = ClassDecl::new("RSTSwitch", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -7,50 +7,24 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once; use objc::runtime::Class;
use objc::declare::ClassDecl; use crate::foundation::load_or_register_class;
use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl};
use objc_id::Id;
use crate::dragdrop::DragInfo;
use crate::foundation::{id, NSUInteger, NO, YES};
use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR}; use crate::text::label::{LabelDelegate, LABEL_DELEGATE_PTR};
use crate::utils::load;
/// Injects an `NSTextField` subclass. This is used for the default views that don't use delegates - we /// Injects an `NSTextField` subclass. This is used for the default views that don't use delegates - we
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSTextField", "RSTTextField", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSTextField);
let decl = ClassDecl::new("RSTTextField", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we /// Injects an `NSTextField` subclass, with some callback and pointer ivars for what we
/// need to do. /// need to do.
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class { pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSView", "RSTTextFieldWithDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTTextFieldWithDelegate", superclass).unwrap();
// A pointer to the "view controller" on the Rust side. It's expected that this doesn't // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR); decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }

View file

@ -2,22 +2,11 @@
//! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook //! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook
//! for potential future use. //! for potential future use.
use std::sync::Once;
use objc::class;
use objc::declare::ClassDecl;
use objc::runtime::Class; use objc::runtime::Class;
use crate::foundation::load_or_register_class;
/// Used for injecting a custom UIApplication. Currently does nothing. /// Used for injecting a custom UIApplication. Currently does nothing.
pub(crate) fn register_app_class() -> *const Class { pub(crate) fn register_app_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIApplication", "RSTApplication", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIApplication);
let decl = ClassDecl::new("RSTApplication", superclass).unwrap();
APP_CLASS = decl.register();
});
unsafe { APP_CLASS }
} }

View file

@ -2,28 +2,20 @@
//! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook //! creates a custom `UIApplication` subclass that currently does nothing; this is meant as a hook
//! for potential future use. //! for potential future use.
//use std::ffi::c_void; use objc::runtime::{Class, Object, Sel};
use std::sync::Once; use objc::{sel, sel_impl};
//use crate::error::Error;
use crate::foundation::{id, load_or_register_class, BOOL, YES};
use crate::uikit::app::{AppDelegate, APP_DELEGATE};
use crate::uikit::scene::{SceneConnectionOptions, SceneSession};
//use std::unreachable; //use std::unreachable;
//use block::Block; //use block::Block;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use url::Url;
//use crate::error::Error;
use crate::foundation::{id, nil, NSArray, NSString, NSUInteger, BOOL, NO, YES};
//use crate::user_activity::UserActivity; //use crate::user_activity::UserActivity;
use crate::uikit::app::{AppDelegate, APP_DELEGATE};
use crate::uikit::scene::{SceneConfig, SceneConnectionOptions, SceneSession};
#[cfg(feature = "cloudkit")]
use crate::cloudkit::share::CKShareMetaData;
/// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our /// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our
/// standard `utils` version as this doesn't require `RefCell` backing. /// standard `utils` version as this doesn't require `RefCell` backing.
fn app<T>(this: &Object) -> &T { fn app<T>(this: &Object) -> &T {
@ -49,13 +41,7 @@ extern "C" fn configuration_for_scene_session<T: AppDelegate>(this: &Object, _:
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and /// Registers an `NSObject` application delegate, and configures it for the various callbacks and
/// pointers we need to have. /// pointers we need to have.
pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class { pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSObject", "RSTAppDelegate", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap();
// Launching Applications // Launching Applications
decl.add_method( decl.add_method(
sel!(application:didFinishLaunchingWithOptions:), sel!(application:didFinishLaunchingWithOptions:),
@ -71,9 +57,5 @@ pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class {
sel!(application:didDiscardSceneSessions:), sel!(application:didDiscardSceneSessions:),
did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id) did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id)
);*/ );*/
})
DELEGATE_CLASS = decl.register();
});
unsafe { DELEGATE_CLASS }
} }

View file

@ -1,25 +1,10 @@
use std::ffi::c_void; use objc::runtime::{Class, Object, Protocol, Sel};
use std::sync::Once;
use std::unreachable;
use block::Block;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use url::Url; use crate::foundation::{id, load_or_register_class};
use crate::error::Error;
use crate::foundation::{id, nil, NSArray, NSString, NSUInteger, BOOL, NO, YES};
use crate::user_activity::UserActivity;
use crate::utils::load;
use crate::uikit::app::SCENE_DELEGATE_VENDOR; use crate::uikit::app::SCENE_DELEGATE_VENDOR;
use crate::uikit::scene::{Scene, SceneConfig, SceneConnectionOptions, SceneSession, WindowSceneDelegate}; use crate::uikit::scene::{Scene, SceneConnectionOptions, SceneSession, WindowSceneDelegate};
use crate::utils::load;
#[cfg(feature = "cloudkit")]
use crate::cloudkit::share::CKShareMetaData;
pub(crate) static WINDOW_SCENE_PTR: &str = "rstWindowSceneDelegatePtr"; pub(crate) static WINDOW_SCENE_PTR: &str = "rstWindowSceneDelegatePtr";
@ -60,14 +45,7 @@ extern "C" fn scene_will_connect_to_session_with_options<T: WindowSceneDelegate>
/// Registers an `NSObject` application delegate, and configures it for the various callbacks and /// Registers an `NSObject` application delegate, and configures it for the various callbacks and
/// pointers we need to have. /// pointers we need to have.
pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class { pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIResponder", "RSTWindowSceneDelegate", |decl| unsafe {
static INIT: Once = Once::new();
use objc::runtime::{class_addProtocol, Protocol};
INIT.call_once(|| unsafe {
let superclass = class!(UIResponder);
let mut decl = ClassDecl::new("RSTWindowSceneDelegate", superclass).unwrap();
let p = Protocol::get("UIWindowSceneDelegate").unwrap(); let p = Protocol::get("UIWindowSceneDelegate").unwrap();
// A spot to hold a pointer to // A spot to hold a pointer to
@ -82,10 +60,5 @@ pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn
sel!(scene:willConnectToSession:options:), sel!(scene:willConnectToSession:options:),
scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _) scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _)
); );
})
// Launching Applications
DELEGATE_CLASS = decl.register();
});
unsafe { DELEGATE_CLASS }
} }

View file

@ -7,8 +7,6 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::sync::Once;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
@ -92,23 +90,13 @@ extern "C" fn update_layer(this: &Object, _: Sel) {
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("NSView", "RSTView", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSView);
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _)); decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
decl.add_ivar::<id>(BACKGROUND_COLOR); decl.add_ivar::<id>(BACKGROUND_COLOR);
})
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we /// Injects an `NSView` subclass, with some callback and pointer ivars for what we

View file

@ -20,14 +20,14 @@ pub enum PopoverBehaviour {
/// The system will close the popover when the user interacts with a user interface element outside the popover. /// The system will close the popover when the user interacts with a user interface element outside the popover.
Transient = 1, Transient = 1,
/// The system will close the popover when the user interacts with user interface elements in the window containing the popover's positioning view. /// The system will close the popover when the user interacts with user interface elements in the window containing the popover's positioning view.
Semitransient = 2, Semitransient = 2
} }
#[derive(Debug)] #[derive(Debug)]
pub struct PopoverConfig { pub struct PopoverConfig {
pub content_size: CGSize, pub content_size: CGSize,
pub animates: bool, pub animates: bool,
pub behaviour: PopoverBehaviour, pub behaviour: PopoverBehaviour
} }
impl Default for PopoverConfig { impl Default for PopoverConfig {
@ -35,10 +35,10 @@ impl Default for PopoverConfig {
Self { Self {
content_size: CGSize { content_size: CGSize {
width: 320.0, width: 320.0,
height: 320.0, height: 320.0
}, },
animates: true, animates: true,
behaviour: PopoverBehaviour::Transient, behaviour: PopoverBehaviour::Transient
} }
} }
} }
@ -49,12 +49,12 @@ pub struct Popover<Content> {
pub objc: ShareId<Object>, pub objc: ShareId<Object>,
/// The wrapped ViewController. /// The wrapped ViewController.
pub view_controller: ViewController<Content>, pub view_controller: ViewController<Content>
} }
impl<Content> Popover<Content> impl<Content> Popover<Content>
where where
Content: ViewDelegate + 'static, Content: ViewDelegate + 'static
{ {
pub fn new(content: Content, config: PopoverConfig) -> Self { pub fn new(content: Content, config: PopoverConfig) -> Self {
let view_controller = ViewController::new(content); let view_controller = ViewController::new(content);

View file

@ -1,18 +1,15 @@
use std::sync::Once;
use std::unreachable;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{BOOL}; use crate::foundation::BOOL;
use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate}; use crate::utils::{as_bool, load};
use crate::utils::{load, as_bool}; use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
/// Called when the view controller receives a `viewWillAppear:` message. /// Called when the view controller receives a `viewWillAppear:` message.
extern "C" fn will_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) { extern "C" fn will_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) {
unsafe { unsafe {
let _: () = msg_send![super(this, class!(UIViewController)), viewWillAppear:animated]; let _: () = msg_send![super(this, class!(UIViewController)), viewWillAppear: animated];
} }
let controller = load::<T>(this, VIEW_DELEGATE_PTR); let controller = load::<T>(this, VIEW_DELEGATE_PTR);
@ -22,7 +19,7 @@ extern "C" fn will_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated:
/// Called when the view controller receives a `viewDidAppear:` message. /// Called when the view controller receives a `viewDidAppear:` message.
extern "C" fn did_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) { extern "C" fn did_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) {
unsafe { unsafe {
let _: () = msg_send![super(this, class!(UIViewController)), viewDidAppear:animated]; let _: () = msg_send![super(this, class!(UIViewController)), viewDidAppear: animated];
} }
let controller = load::<T>(this, VIEW_DELEGATE_PTR); let controller = load::<T>(this, VIEW_DELEGATE_PTR);
@ -32,7 +29,7 @@ extern "C" fn did_appear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: B
/// Called when the view controller receives a `viewWillDisappear:` message. /// Called when the view controller receives a `viewWillDisappear:` message.
extern "C" fn will_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) { extern "C" fn will_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) {
unsafe { unsafe {
let _: () = msg_send![super(this, class!(UIViewController)), viewWillDisappear:animated]; let _: () = msg_send![super(this, class!(UIViewController)), viewWillDisappear: animated];
} }
let controller = load::<T>(this, VIEW_DELEGATE_PTR); let controller = load::<T>(this, VIEW_DELEGATE_PTR);
@ -42,7 +39,7 @@ extern "C" fn will_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animate
/// Called when the view controller receives a `viewDidDisappear:` message. /// Called when the view controller receives a `viewDidDisappear:` message.
extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) { extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated: BOOL) {
unsafe { unsafe {
let _: () = msg_send![super(this, class!(UIViewController)), viewDidDisappear:animated]; let _: () = msg_send![super(this, class!(UIViewController)), viewDidDisappear: animated];
} }
let controller = load::<T>(this, VIEW_DELEGATE_PTR); let controller = load::<T>(this, VIEW_DELEGATE_PTR);
@ -51,22 +48,18 @@ extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated
/// Registers an `NSViewDelegate`. /// Registers an `NSViewDelegate`.
pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>() -> *const Class { pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIViewController", "RSTViewController", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIViewController);
let mut decl = ClassDecl::new("RSTViewController", superclass).unwrap();
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR); decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
decl.add_method(sel!(viewWillDisappear:), will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(
decl.add_method(sel!(viewDidDisappear:), did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)); sel!(viewWillDisappear:),
will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
VIEW_CLASS = decl.register(); );
}); decl.add_method(
sel!(viewDidDisappear:),
unsafe { VIEW_CLASS } did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
);
})
} }

View file

@ -1,5 +1,3 @@
use std::sync::Once;
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
@ -14,16 +12,7 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
/// have separate classes here since we don't want to waste cycles on methods that will never be /// have separate classes here since we don't want to waste cycles on methods that will never be
/// used if there's no delegates. /// used if there's no delegates.
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; load_or_register_class("UIView", "RSTView", |decl| unsafe {})
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(UIView);
let mut decl = ClassDecl::new("RSTView", superclass).unwrap();
VIEW_CLASS = decl.register();
});
unsafe { VIEW_CLASS }
} }
/// Injects a `UIView` subclass, with some callback and pointer ivars for what we /// Injects a `UIView` subclass, with some callback and pointer ivars for what we

View file

@ -4,41 +4,23 @@
//! //!
//! If you use that feature, there are no guarantees you'll be accepted into the App Store. //! If you use that feature, there are no guarantees you'll be accepted into the App Store.
use std::sync::Once;
use std::ffi::c_void;
use block::Block; use block::Block;
use cocoa::foundation::{NSArray, NSInteger, NSPoint, NSRect, NSSize, NSString};
use cocoa::foundation::{NSRect, NSPoint, NSSize, NSString, NSArray, NSInteger};
use objc::declare::ClassDecl; use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel, BOOL}; use objc::runtime::{Class, Object, Sel, BOOL};
use objc::{class, msg_send, sel, sel_impl}; use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::{id, nil, YES, NO}; use crate::foundation::{id, nil, NO, YES};
use crate::webview::traits::WebViewController; use crate::webview::traits::WebViewController;
extern "C" fn download_delegate(this: &Object, _: Sel) -> id { extern "C" fn download_delegate(this: &Object, _: Sel) -> id {
println!("YO!"); println!("YO!");
unsafe { unsafe { NSString::alloc(nil).init_str("") }
NSString::alloc(nil).init_str("")
}
} }
pub fn register_process_pool() -> *const Object { pub fn register_process_pool() -> *const Object {
static mut PROCESS_POOL: *const Object = 0 as *const Object; load_or_register_class("WKProcessPool", "RSTWebViewProcessPool", |decl| unsafe {
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = Class::get("WKProcessPool").unwrap();
let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap();
//decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR); //decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR);
decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id); decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id);
})
//PROCESS_POOL = decl.register();
PROCESS_POOL = msg_send![decl.register(), new];
});
unsafe { PROCESS_POOL }
} }