diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index ee3b68a..766677b 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -209,9 +209,7 @@ impl View { center_x: LayoutAnchorX::center(view), center_y: LayoutAnchorY::center(view), - layer: Layer::wrap(unsafe { - msg_send![view, layer] - }), + layer: Layer::from_id(unsafe { msg_send_id![view, layer] }), objc: ObjcProperty::retain(view), } @@ -293,7 +291,8 @@ impl View { #[cfg(target_os = "macos")] self.objc.with_mut(|obj| unsafe { - (&mut *obj).set_ivar(BACKGROUND_COLOR, color); + // TODO: Fix this unnecessary retain! + (&mut *obj).set_ivar::(BACKGROUND_COLOR, msg_send![color, retain]); }); #[cfg(target_os = "ios")] @@ -352,22 +351,22 @@ We'll step through an example (abridged) `View` bridge below, for macOS. You sho For our basic `View` type, we want to just map to the corresponding class on the Objective-C side (in this case, `NSView`), and maybe do a bit of tweaking for sanity reasons. ``` rust -pub(crate) fn register_view_class() -> *const Class { - static mut VIEW_CLASS: *const Class = 0 as *const Class; +pub(crate) fn register_view_class() -> &'static Class { + static mut VIEW_CLASS: Option<'static Class> = None; 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(_, _) -> _); decl.add_ivar::(BACKGROUND_COLOR); - VIEW_CLASS = decl.register(); + VIEW_CLASS = Some(decl.register()); }); - unsafe { VIEW_CLASS } + unsafe { VIEW_CLASS.unwrap() } } ``` @@ -377,19 +376,19 @@ Objective-C method signatures, as well as provision space for variable storage ( For our _delegate_ types, we need a different class creation method - one that creates a subclass per-unique-type: ``` rust -pub(crate) fn register_view_class_with_delegate(instance: &T) -> *const Class { +pub(crate) fn register_view_class_with_delegate(instance: &T) -> &'static Class { load_or_register_class("NSView", instance.subclass_name(), |decl| unsafe { decl.add_ivar::(VIEW_DELEGATE_PTR); decl.add_ivar::(BACKGROUND_COLOR); decl.add_method( sel!(isFlipped), - enforce_normalcy as extern "C" fn(&Object, _) -> BOOL + enforce_normalcy as extern "C" fn(_, _) -> _, ); decl.add_method( sel!(draggingEntered:), - dragging_entered:: as extern "C" fn (&mut Object, _, _) -> NSUInteger + dragging_entered:: as extern "C" fn (_, _, _) -> _, ); }) } @@ -401,18 +400,18 @@ to the Rust `ViewDelegate` implementation. The methods we're setting up can range from simple to complex - take `isFlipped`: ``` rust -extern "C" fn is_flipped(_: &Object, _: Sel) -> BOOL { - return YES; +extern "C" fn is_flipped(_: &Object, _: Sel) -> Bool { + return Bool::YES; } ``` -Here, we just want to tell `NSView` to use top,left as the origin point, so we need to respond `YES` in this subclass method. +Here, we just want to tell `NSView` to use top,left as the origin point, so we need to respond `Bool::YES` in this subclass method. ``` rust extern "C" fn dragging_entered(this: &mut Object, _: Sel, info: id) -> NSUInteger { let view = utils::load::(this, VIEW_DELEGATE_PTR); view.dragging_entered(DragInfo { - info: unsafe { Id::from_ptr(info) } + info: unsafe { Id::retain(info).unwrap() } }).into() } ``` diff --git a/Cargo.toml b/Cargo.toml index 6d0e8ac..639e96c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,15 +20,16 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] bitmask-enum = "2.2.1" -block = "0.1.6" -core-foundation = "0.9" -core-graphics = "0.23" +objc = { version = "=0.3.0-beta.2", package = "objc2" } +block = { version = "=0.2.0-alpha.6", package = "block2" } +# Temporary: Patched versions that implement `Encode` for common types +# Branch: `objc2` +core-foundation = { git = "https://github.com/madsmtm/core-foundation-rs.git", rev = "7d593d016175755e492a92ef89edca68ac3bd5cd" } +core-graphics = { git = "https://github.com/madsmtm/core-foundation-rs.git", rev = "7d593d016175755e492a92ef89edca68ac3bd5cd" } dispatch = "0.2.0" infer = { version = "0.15", optional = true } lazy_static = "1.4.0" libc = "0.2" -objc = "0.2.7" -objc_id = "0.1.1" os_info = "3.0.1" url = "2.1.1" uuid = { version = "1.1", features = ["v4"], optional = true } diff --git a/examples/browser/toolbar.rs b/examples/browser/toolbar.rs index b4416dd..ce49e3d 100644 --- a/examples/browser/toolbar.rs +++ b/examples/browser/toolbar.rs @@ -1,4 +1,4 @@ -use cacao::objc::{msg_send, sel, sel_impl}; +use cacao::objc::{msg_send, sel}; use cacao::button::Button; use cacao::input::{TextField, TextFieldDelegate}; @@ -35,12 +35,12 @@ impl BrowserToolbar { let back_button = Button::new("Back"); let mut back_item = ToolbarItem::new(BACK_BUTTON); back_item.set_button(back_button); - back_item.set_action(|| Action::Back.dispatch()); + back_item.set_action(|_| Action::Back.dispatch()); let forwards_button = Button::new("Forwards"); let mut forwards_item = ToolbarItem::new(FWDS_BUTTON); forwards_item.set_button(forwards_button); - forwards_item.set_action(|| Action::Forwards.dispatch()); + forwards_item.set_action(|_| Action::Forwards.dispatch()); let url_bar = TextField::with(URLBar); let url_bar_item = ToolbarItem::new(URL_BAR); diff --git a/src/appkit/alert.rs b/src/appkit/alert.rs index 3483f30..12ef78d 100644 --- a/src/appkit/alert.rs +++ b/src/appkit/alert.rs @@ -24,16 +24,16 @@ //! } //! ``` +use objc::rc::{Id, Owned}; use objc::runtime::Object; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::Id; +use objc::{class, msg_send, msg_send_id, sel}; use crate::foundation::{id, NSString}; /// Represents an `NSAlert`. Has no information other than the retained pointer to the Objective C /// side, so... don't bother inspecting this. #[derive(Debug)] -pub struct Alert(Id); +pub struct Alert(Id); impl Alert { /// Creates a basic `NSAlert`, storing a pointer to it in the Objective C runtime. @@ -44,11 +44,11 @@ impl Alert { let ok = NSString::new("OK"); Alert(unsafe { - let alert: id = msg_send![class!(NSAlert), new]; - let _: () = msg_send![alert, setMessageText: title]; - let _: () = msg_send![alert, setInformativeText: message]; - let _: () = msg_send![alert, addButtonWithTitle: ok]; - Id::from_ptr(alert) + let mut alert = msg_send_id![class!(NSAlert), new]; + let _: () = msg_send![&mut alert, setMessageText: &*title]; + let _: () = msg_send![&mut alert, setInformativeText: &*message]; + let _: () = msg_send![&mut alert, addButtonWithTitle: &*ok]; + alert }) } diff --git a/src/appkit/animation.rs b/src/appkit/animation.rs index 73a2f8b..48deb21 100644 --- a/src/appkit/animation.rs +++ b/src/appkit/animation.rs @@ -1,5 +1,5 @@ use block::ConcreteBlock; -use objc::{class, msg_send, sel, sel_impl}; +use objc::{class, msg_send, sel}; use crate::foundation::id; @@ -39,7 +39,7 @@ impl AnimationContext { unsafe { //let context: id = msg_send![class!(NSAnimationContext), currentContext]; - let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup: block]; + let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup: &*block]; } } @@ -66,8 +66,11 @@ impl AnimationContext { unsafe { //let context: id = msg_send![class!(NSAnimationContext), currentContext]; - let _: () = msg_send![class!(NSAnimationContext), runAnimationGroup:block - completionHandler:completion_block]; + let _: () = msg_send![ + class!(NSAnimationContext), + runAnimationGroup: &*block, + completionHandler: &*completion_block, + ]; } } } diff --git a/src/appkit/app/class.rs b/src/appkit/app/class.rs index 59690d9..223be7f 100644 --- a/src/appkit/app/class.rs +++ b/src/appkit/app/class.rs @@ -7,6 +7,6 @@ use objc::runtime::Class; use crate::foundation::load_or_register_class; /// Used for injecting a custom NSApplication. Currently does nothing. -pub(crate) fn register_app_class() -> *const Class { +pub(crate) fn register_app_class() -> &'static Class { load_or_register_class("NSApplication", "RSTApplication", |decl| unsafe {}) } diff --git a/src/appkit/app/delegate.rs b/src/appkit/app/delegate.rs index 0e90c2f..4f4fce3 100644 --- a/src/appkit/app/delegate.rs +++ b/src/appkit/app/delegate.rs @@ -5,8 +5,8 @@ use std::ffi::c_void; use block::Block; -use objc::runtime::{Class, Object, Sel}; -use objc::{msg_send, sel, sel_impl}; +use objc::runtime::{Bool, Class, Object, Sel}; +use objc::{msg_send, sel}; use url::Url; use crate::appkit::app::{AppDelegate, APP_PTR}; @@ -14,7 +14,7 @@ use crate::appkit::printing::PrintSettings; #[cfg(feature = "cloudkit")] 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::foundation::{id, load_or_register_class, nil, NSArray, NSString, NSUInteger}; use crate::user_activity::UserActivity; /// A handy method for grabbing our `AppDelegate` from the pointer. This is different from our @@ -99,11 +99,8 @@ extern "C" fn did_update(this: &Object, _: Sel, _: id) { /// Fires when the Application Delegate receives a /// `applicationShouldHandleReopen:hasVisibleWindows:` notification. -extern "C" fn should_handle_reopen(this: &Object, _: Sel, _: id, has_visible_windows: BOOL) -> BOOL { - match app::(this).should_handle_reopen(to_bool(has_visible_windows)) { - true => YES, - false => NO - } +extern "C" fn should_handle_reopen(this: &Object, _: Sel, _: id, has_visible_windows: Bool) -> Bool { + Bool::new(app::(this).should_handle_reopen(has_visible_windows.as_bool())) } /// Fires when the application delegate receives a `applicationDockMenu:` request. @@ -128,29 +125,23 @@ extern "C" fn did_change_screen_parameters(this: &Object, _: Sel /// Fires when the application receives a `application:willContinueUserActivityWithType:` /// notification. -extern "C" fn will_continue_user_activity_with_type(this: &Object, _: Sel, _: id, activity_type: id) -> BOOL { +extern "C" fn will_continue_user_activity_with_type(this: &Object, _: Sel, _: id, activity_type: id) -> Bool { let activity = NSString::retain(activity_type); - match app::(this).will_continue_user_activity(activity.to_str()) { - true => YES, - false => NO - } + Bool::new(app::(this).will_continue_user_activity(activity.to_str())) } /// Fires when the application receives a `application:continueUserActivity:restorationHandler:` notification. -extern "C" fn continue_user_activity(this: &Object, _: Sel, _: id, activity: id, handler: id) -> BOOL { +extern "C" fn continue_user_activity(this: &Object, _: Sel, _: id, activity: id, handler: id) -> Bool { // @TODO: This needs to support restorable objects, but it involves a larger question about how // much `NSObject` retainping we want to do here. For now, pass the handler for whenever it's // useful. let activity = UserActivity::with_inner(activity); - match app::(this).continue_user_activity(activity, || unsafe { - let handler = handler as *const Block<(id,), c_void>; + Bool::new(app::(this).continue_user_activity(activity, || unsafe { + let handler = handler as *const Block<(id,), ()>; (*handler).call((nil,)); - }) { - true => YES, - false => NO - } + })) } /// Fires when the application receives a @@ -199,57 +190,39 @@ extern "C" fn open_urls(this: &Object, _: Sel, _: id, file_urls: } /// Fires when the application receives an `application:openFileWithoutUI:` message. -extern "C" fn open_file_without_ui(this: &Object, _: Sel, _: id, file: id) -> BOOL { +extern "C" fn open_file_without_ui(this: &Object, _: Sel, _: id, file: id) -> Bool { let filename = NSString::retain(file); - match app::(this).open_file_without_ui(filename.to_str()) { - true => YES, - false => NO - } + Bool::new(app::(this).open_file_without_ui(filename.to_str())) } /// Fired when the application receives an `applicationShouldOpenUntitledFile:` message. -extern "C" fn should_open_untitled_file(this: &Object, _: Sel, _: id) -> BOOL { - match app::(this).should_open_untitled_file() { - true => YES, - false => NO - } +extern "C" fn should_open_untitled_file(this: &Object, _: Sel, _: id) -> Bool { + Bool::new(app::(this).should_open_untitled_file()) } /// Fired when the application receives an `applicationShouldTerminateAfterLastWindowClosed:` message. -extern "C" fn should_terminate_after_last_window_closed(this: &Object, _: Sel, _: id) -> BOOL { - match app::(this).should_terminate_after_last_window_closed() { - true => YES, - false => NO - } +extern "C" fn should_terminate_after_last_window_closed(this: &Object, _: Sel, _: id) -> Bool { + Bool::new(app::(this).should_terminate_after_last_window_closed()) } /// Fired when the application receives an `applicationOpenUntitledFile:` message. -extern "C" fn open_untitled_file(this: &Object, _: Sel, _: id) -> BOOL { - match app::(this).open_untitled_file() { - true => YES, - false => NO - } +extern "C" fn open_untitled_file(this: &Object, _: Sel, _: id) -> Bool { + Bool::new(app::(this).open_untitled_file()) } /// Fired when the application receives an `application:openTempFile:` message. -extern "C" fn open_temp_file(this: &Object, _: Sel, _: id, filename: id) -> BOOL { +extern "C" fn open_temp_file(this: &Object, _: Sel, _: id, filename: id) -> Bool { let filename = NSString::retain(filename); - match app::(this).open_temp_file(filename.to_str()) { - true => YES, - false => NO - } + Bool::new(app::(this).open_temp_file(filename.to_str())) } /// Fired when the application receives an `application:printFile:` message. -extern "C" fn print_file(this: &Object, _: Sel, _: id, file: id) -> BOOL { +extern "C" fn print_file(this: &Object, _: Sel, _: id, file: id) -> Bool { let filename = NSString::retain(file); - match app::(this).print_file(filename.to_str()) { - true => YES, - false => NO - } + Bool::new(app::(this).print_file(filename.to_str())) } /// Fired when the application receives an `application:printFiles:withSettings:showPrintPanels:` @@ -260,7 +233,7 @@ extern "C" fn print_files( _: id, files: id, settings: id, - show_print_panels: BOOL + show_print_panels: Bool ) -> NSUInteger { let files = NSArray::retain(files) .iter() @@ -269,7 +242,9 @@ extern "C" fn print_files( let settings = PrintSettings::with_inner(settings); - app::(this).print_files(files, settings, to_bool(show_print_panels)).into() + app::(this) + .print_files(files, settings, show_print_panels.as_bool()) + .into() } /// Called when the application's occlusion state has changed. @@ -280,168 +255,156 @@ extern "C" fn did_change_occlusion_state(this: &Object, _: Sel, /// Called when the application receives an `application:delegateHandlesKey:` message. /// Note: this may not fire in sandboxed applications. Apple's documentation is unclear on the /// matter. -extern "C" fn delegate_handles_key(this: &Object, _: Sel, _: id, key: id) -> BOOL { +extern "C" fn delegate_handles_key(this: &Object, _: Sel, _: id, key: id) -> Bool { let key = NSString::retain(key); - match app::(this).delegate_handles_key(key.to_str()) { - true => YES, - false => NO - } + Bool::new(app::(this).delegate_handles_key(key.to_str())) } /// Registers an `NSObject` application delegate, and configures it for the various callbacks and /// pointers we need to have. -pub(crate) fn register_app_delegate_class() -> *const Class { +pub(crate) fn register_app_delegate_class() -> &'static Class { load_or_register_class("NSObject", "RSTAppDelegate", |decl| unsafe { decl.add_ivar::(APP_PTR); // Launching Applications decl.add_method( sel!(applicationWillFinishLaunching:), - will_finish_launching:: as extern "C" fn(&Object, _, _) + will_finish_launching:: as extern "C" fn(_, _, _) ); decl.add_method( sel!(applicationDidFinishLaunching:), - did_finish_launching:: as extern "C" fn(&Object, _, _) + did_finish_launching:: as extern "C" fn(_, _, _) ); // Managing Active Status decl.add_method( sel!(applicationWillBecomeActive:), - will_become_active:: as extern "C" fn(&Object, _, _) + will_become_active:: as extern "C" fn(_, _, _) ); decl.add_method( sel!(applicationDidBecomeActive:), - did_become_active:: as extern "C" fn(&Object, _, _) + did_become_active:: as extern "C" fn(_, _, _) ); decl.add_method( sel!(applicationWillResignActive:), - will_resign_active:: as extern "C" fn(&Object, _, _) + will_resign_active:: as extern "C" fn(_, _, _) ); decl.add_method( sel!(applicationDidResignActive:), - did_resign_active:: as extern "C" fn(&Object, _, _) + did_resign_active:: as extern "C" fn(_, _, _) ); // Terminating Applications decl.add_method( sel!(applicationShouldTerminate:), - should_terminate:: as extern "C" fn(&Object, _, _) -> NSUInteger - ); - decl.add_method( - sel!(applicationWillTerminate:), - will_terminate:: as extern "C" fn(&Object, _, _) + should_terminate:: as extern "C" fn(_, _, _) -> _ ); + decl.add_method(sel!(applicationWillTerminate:), will_terminate:: as extern "C" fn(_, _, _)); decl.add_method( sel!(applicationShouldTerminateAfterLastWindowClosed:), - should_terminate_after_last_window_closed:: as extern "C" fn(&Object, _, _) -> BOOL + should_terminate_after_last_window_closed:: as extern "C" fn(_, _, _) -> _ ); // Hiding Applications - decl.add_method(sel!(applicationWillHide:), will_hide:: as extern "C" fn(&Object, _, _)); - decl.add_method(sel!(applicationDidHide:), did_hide:: as extern "C" fn(&Object, _, _)); - decl.add_method(sel!(applicationWillUnhide:), will_unhide:: as extern "C" fn(&Object, _, _)); - decl.add_method(sel!(applicationDidUnhide:), did_unhide:: as extern "C" fn(&Object, _, _)); + decl.add_method(sel!(applicationWillHide:), will_hide:: as extern "C" fn(_, _, _)); + decl.add_method(sel!(applicationDidHide:), did_hide:: as extern "C" fn(_, _, _)); + decl.add_method(sel!(applicationWillUnhide:), will_unhide:: as extern "C" fn(_, _, _)); + decl.add_method(sel!(applicationDidUnhide:), did_unhide:: as extern "C" fn(_, _, _)); // Managing Windows - decl.add_method(sel!(applicationWillUpdate:), will_update:: as extern "C" fn(&Object, _, _)); - decl.add_method(sel!(applicationDidUpdate:), did_update:: as extern "C" fn(&Object, _, _)); + decl.add_method(sel!(applicationWillUpdate:), will_update:: as extern "C" fn(_, _, _)); + decl.add_method(sel!(applicationDidUpdate:), did_update:: as extern "C" fn(_, _, _)); decl.add_method( sel!(applicationShouldHandleReopen:hasVisibleWindows:), - should_handle_reopen:: as extern "C" fn(&Object, _, _, BOOL) -> BOOL + should_handle_reopen:: as extern "C" fn(_, _, _, _) -> _ ); // Dock Menu - decl.add_method( - sel!(applicationDockMenu:), - dock_menu:: as extern "C" fn(&Object, _, _) -> id - ); + decl.add_method(sel!(applicationDockMenu:), dock_menu:: as extern "C" fn(_, _, _) -> _); // Displaying Errors decl.add_method( sel!(application:willPresentError:), - will_present_error:: as extern "C" fn(&Object, _, _, id) -> id + will_present_error:: as extern "C" fn(_, _, _, _) -> _ ); // Managing the Screen decl.add_method( sel!(applicationDidChangeScreenParameters:), - did_change_screen_parameters:: as extern "C" fn(&Object, _, _) + did_change_screen_parameters:: as extern "C" fn(_, _, _) ); decl.add_method( sel!(applicationDidChangeOcclusionState:), - did_change_occlusion_state:: as extern "C" fn(&Object, _, _) + did_change_occlusion_state:: as extern "C" fn(_, _, _) ); // User Activities decl.add_method( sel!(application:willContinueUserActivityWithType:), - will_continue_user_activity_with_type:: as extern "C" fn(&Object, _, _, id) -> BOOL + will_continue_user_activity_with_type:: as extern "C" fn(_, _, _, _) -> _ ); decl.add_method( sel!(application:continueUserActivity:restorationHandler:), - continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) -> BOOL + continue_user_activity:: as extern "C" fn(_, _, _, _, _) -> _ ); decl.add_method( sel!(application:didFailToContinueUserActivityWithType:error:), - failed_to_continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) + failed_to_continue_user_activity:: as extern "C" fn(_, _, _, _, _) ); decl.add_method( sel!(application:didUpdateUserActivity:), - did_update_user_activity:: as extern "C" fn(&Object, _, _, id) + did_update_user_activity:: as extern "C" fn(_, _, _, _) ); // Handling push notifications decl.add_method( sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:), - registered_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) + registered_for_remote_notifications:: as extern "C" fn(_, _, _, _) ); decl.add_method( sel!(application:didFailToRegisterForRemoteNotificationsWithError:), - failed_to_register_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) + failed_to_register_for_remote_notifications:: as extern "C" fn(_, _, _, _) ); decl.add_method( sel!(application:didReceiveRemoteNotification:), - did_receive_remote_notification:: as extern "C" fn(&Object, _, _, id) + did_receive_remote_notification:: as extern "C" fn(_, _, _, _) ); // CloudKit #[cfg(feature = "cloudkit")] decl.add_method( sel!(application:userDidAcceptCloudKitShareWithMetadata:), - accepted_cloudkit_share:: as extern "C" fn(&Object, _, _, id) + accepted_cloudkit_share:: as extern "C" fn(_, _, _, _) ); // Opening Files - decl.add_method( - sel!(application:openURLs:), - open_urls:: as extern "C" fn(&Object, _, _, id) - ); + decl.add_method(sel!(application:openURLs:), open_urls:: as extern "C" fn(_, _, _, _)); decl.add_method( sel!(application:openFileWithoutUI:), - open_file_without_ui:: as extern "C" fn(&Object, _, _, id) -> BOOL + open_file_without_ui:: as extern "C" fn(_, _, _, _) -> _ ); decl.add_method( sel!(applicationShouldOpenUntitledFile:), - should_open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL + should_open_untitled_file:: as extern "C" fn(_, _, _) -> _ ); decl.add_method( sel!(applicationOpenUntitledFile:), - open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL + open_untitled_file:: as extern "C" fn(_, _, _) -> _ ); decl.add_method( sel!(application:openTempFile:), - open_temp_file:: as extern "C" fn(&Object, _, _, id) -> BOOL + open_temp_file:: as extern "C" fn(_, _, _, _) -> _ ); // Printing decl.add_method( sel!(application:printFile:), - print_file:: as extern "C" fn(&Object, _, _, id) -> BOOL + print_file:: as extern "C" fn(_, _, _, _) -> _ ); decl.add_method( sel!(application:printFiles:withSettings:showPrintPanels:), - print_files:: as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger + print_files:: as extern "C" fn(_, _, _, _, _, _) -> _ ); // @TODO: Restoring Application State @@ -450,7 +413,7 @@ pub(crate) fn register_app_delegate_class() -> *co // Scripting decl.add_method( sel!(application:delegateHandlesKey:), - delegate_handles_key:: as extern "C" fn(&Object, _, _, id) -> BOOL + delegate_handles_key:: as extern "C" fn(_, _, _, _) -> _ ); }) } diff --git a/src/appkit/app/mod.rs b/src/appkit/app/mod.rs index 9828855..a266d92 100644 --- a/src/appkit/app/mod.rs +++ b/src/appkit/app/mod.rs @@ -39,9 +39,9 @@ use std::sync::{Arc, Mutex}; use lazy_static::lazy_static; +use objc::rc::{Id, Owned}; use objc::runtime::Object; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::Id; +use objc::{class, msg_send, msg_send_id, sel}; use crate::appkit::menu::Menu; use crate::foundation::{id, nil, AutoReleasePool, NSUInteger, NO, YES}; @@ -88,11 +88,11 @@ pub(crate) fn shared_application T>(handler: F) -> T { /// application. pub struct App { /// The underlying Objective-C Object. - pub objc: Id, + pub objc: Id, /// The underlying Objective-C Object, which in this case is a delegate that forwards to the /// app delegate. - pub objc_delegate: Id, + pub objc_delegate: Id, /// The stored `AppDelegate`. pub delegate: Box, @@ -144,20 +144,17 @@ where let pool = AutoReleasePool::new(); - let objc = unsafe { - let app: id = msg_send![register_app_class(), sharedApplication]; - Id::from_ptr(app) - }; + let objc: Id<_, _> = unsafe { msg_send_id![register_app_class(), sharedApplication] }; let app_delegate = Box::new(delegate); let objc_delegate = unsafe { let delegate_class = register_app_delegate_class::(); - let delegate: id = msg_send![delegate_class, new]; + let mut delegate: Id = msg_send_id![delegate_class, new]; let delegate_ptr: *const T = &*app_delegate; - (&mut *delegate).set_ivar(APP_PTR, delegate_ptr as usize); - let _: () = msg_send![&*objc, setDelegate: delegate]; - Id::from_ptr(delegate) + delegate.set_ivar(APP_PTR, delegate_ptr as usize); + let _: () = msg_send![&*objc, setDelegate: &*delegate]; + delegate }; App { diff --git a/src/appkit/cursor.rs b/src/appkit/cursor.rs index 838f0d9..2a161f3 100644 --- a/src/appkit/cursor.rs +++ b/src/appkit/cursor.rs @@ -1,4 +1,4 @@ -use objc::{class, msg_send, sel, sel_impl}; +use objc::{class, msg_send, sel}; use crate::foundation::{id, NO, YES}; diff --git a/src/appkit/event/mod.rs b/src/appkit/event/mod.rs index 851639f..9d6568c 100644 --- a/src/appkit/event/mod.rs +++ b/src/appkit/event/mod.rs @@ -1,9 +1,9 @@ use bitmask_enum::bitmask; use block::ConcreteBlock; +use objc::rc::{Id, Owned}; use objc::runtime::Object; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::Id; +use objc::{class, msg_send, msg_send_id, sel}; use crate::events::EventType; use crate::foundation::{id, nil, NSInteger, NSPoint, NSString}; @@ -53,15 +53,15 @@ pub enum EventMask { /// A wrapper over an `NSEvent`. #[derive(Debug)] -pub struct EventMonitor(pub Id); +pub struct EventMonitor(pub Id); /// A wrapper over an `NSEvent`. #[derive(Debug)] -pub struct Event(pub Id); +pub struct Event(pub Id); impl Event { pub(crate) fn new(objc: id) -> Self { - Event(unsafe { Id::from_ptr(objc) }) + Event(unsafe { Id::retain(objc).unwrap() }) } /// The event's type. @@ -137,8 +137,11 @@ impl Event { let block = block.copy(); EventMonitor(unsafe { - msg_send![class!(NSEvent), addLocalMonitorForEventsMatchingMask:mask.bits - handler:block] + msg_send_id![ + class!(NSEvent), + addLocalMonitorForEventsMatchingMask: mask.bits, + handler: &*block, + ] }) } @@ -163,8 +166,11 @@ impl Event { let block = block.copy(); EventMonitor(unsafe { - msg_send![class!(NSEvent), addGlobalMonitorForEventsMatchingMask:mask.bits - handler:block] + msg_send_id![ + class!(NSEvent), + addGlobalMonitorForEventsMatchingMask: mask.bits, + handler: &*block, + ] }) } } diff --git a/src/appkit/haptics.rs b/src/appkit/haptics.rs index adf1356..e786b28 100644 --- a/src/appkit/haptics.rs +++ b/src/appkit/haptics.rs @@ -1,17 +1,17 @@ use std::convert::TryFrom; -use objc::{class, msg_send, runtime::Object, sel, sel_impl}; -use objc_id::ShareId; +use objc::rc::{Id, Shared}; +use objc::{class, msg_send, msg_send_id, runtime::Object, sel}; use crate::foundation::NSUInteger; #[derive(Clone, Debug)] -pub struct HapticFeedbackPerformer(pub ShareId); +pub struct HapticFeedbackPerformer(pub Id); impl HapticFeedbackPerformer { pub fn perform(&self, pattern: FeedbackPattern, performance_time: PerformanceTime) { unsafe { - let _: () = msg_send![&*self.0, performFeedbackPattern: pattern performanceTime: performance_time]; + let _: () = msg_send![&*self.0, performFeedbackPattern: pattern as isize performanceTime: performance_time as usize]; } } } @@ -19,10 +19,7 @@ impl HapticFeedbackPerformer { impl Default for HapticFeedbackPerformer { /// Returns the default haptic feedback performer. fn default() -> Self { - HapticFeedbackPerformer(unsafe { - let manager = msg_send![class!(NSHapticFeedbackManager), defaultPerformer]; - ShareId::from_ptr(manager) - }) + HapticFeedbackPerformer(unsafe { msg_send_id![class!(NSHapticFeedbackManager), defaultPerformer] }) } } diff --git a/src/appkit/menu/item.rs b/src/appkit/menu/item.rs index 6218e19..7ea6c09 100644 --- a/src/appkit/menu/item.rs +++ b/src/appkit/menu/item.rs @@ -4,9 +4,9 @@ use std::fmt; +use objc::rc::{Id, Owned}; use objc::runtime::{Class, Object, Sel}; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::Id; +use objc::{class, msg_send, msg_send_id, sel}; use crate::events::EventModifierFlag; use crate::foundation::{id, load_or_register_class, NSString, NSUInteger}; @@ -37,7 +37,7 @@ fn make_menu_item>( key: Option<&str>, action: Option, modifiers: Option<&[EventModifierFlag]> -) -> Id { +) -> Id { unsafe { let title = NSString::new(title.as_ref()); @@ -50,14 +50,21 @@ fn make_menu_item>( // Stock menu items that use selectors targeted at system pieces are just standard // `NSMenuItem`s. If there's no custom ones, we use our subclass that has a slot to store a // handler pointer. - let alloc: id = msg_send![register_menu_item_class(), alloc]; - let item = Id::from_retained_ptr(match action { - Some(a) => msg_send![alloc, initWithTitle:&*title action:a keyEquivalent:&*key], - - None => msg_send![alloc, initWithTitle:&*title - action:sel!(fireBlockAction:) - keyEquivalent:&*key] - }); + let alloc = msg_send_id![register_menu_item_class(), alloc]; + let item: Id<_, _> = match action { + Some(a) => msg_send_id![ + alloc, + initWithTitle: &*title, + action: a, + keyEquivalent: &*key, + ], + None => msg_send_id![ + alloc, + initWithTitle: &*title, + action: sel!(fireBlockAction:), + keyEquivalent: &*key, + ] + }; if let Some(modifiers) = modifiers { let mut key_mask: NSUInteger = 0; @@ -83,7 +90,7 @@ pub enum MenuItem { /// You can (and should) create this variant via the `new(title)` method, but if you need to do /// something crazier, then wrap it in this and you can hook into the Cacao menu system /// accordingly. - Custom(Id), + Custom(Id), /// Shows a standard "About" item, which will bring up the necessary window when clicked /// (include a `credits.html` in your App to make use of here). The argument baked in here @@ -150,7 +157,7 @@ pub enum MenuItem { impl MenuItem { /// Consumes and returns a handle for the underlying MenuItem. This is internal as we make a few assumptions /// for how it interacts with our `Menu` setup, but this could be made public in the future. - pub(crate) unsafe fn to_objc(self) -> Id { + pub(crate) unsafe fn to_objc(self) -> Id { match self { Self::Custom(objc) => objc, @@ -211,8 +218,7 @@ impl MenuItem { Self::Separator => { let cls = class!(NSMenuItem); - let separator: id = msg_send![cls, separatorItem]; - Id::from_ptr(separator) + msg_send_id![cls, separatorItem] } } } @@ -229,7 +235,7 @@ impl MenuItem { if let MenuItem::Custom(objc) = self { unsafe { let key = NSString::new(key); - let _: () = msg_send![&*objc, setKeyEquivalent: key]; + let _: () = msg_send![&*objc, setKeyEquivalent: &*key]; } return MenuItem::Custom(objc); @@ -314,11 +320,11 @@ 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 /// 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() -> &'static Class { load_or_register_class("NSMenuItem", "CacaoMenuItem", |decl| unsafe { decl.add_ivar::(BLOCK_PTR); - 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!(dealloc), dealloc_cacao_menuitem as extern "C" fn(_, _)); + decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(_, _, _)); }) } diff --git a/src/appkit/menu/menu.rs b/src/appkit/menu/menu.rs index 8e22ff6..d53bbdb 100644 --- a/src/appkit/menu/menu.rs +++ b/src/appkit/menu/menu.rs @@ -2,9 +2,9 @@ use std::sync::{Arc, Mutex}; +use objc::rc::{Id, Owned, Shared}; use objc::runtime::Object; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::{Id, ShareId}; +use objc::{class, msg_send, msg_send_id, sel}; use crate::appkit::menu::item::MenuItem; use crate::foundation::{id, NSInteger, NSString}; @@ -12,7 +12,7 @@ use crate::foundation::{id, NSInteger, NSString}; /// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting /// them throughout the application lifecycle. #[derive(Debug)] -pub struct Menu(pub Id); +pub struct Menu(pub Id); impl Menu { /// Creates a new `Menu` with the given title, and uses the passed items as submenu items. @@ -27,16 +27,16 @@ impl Menu { pub fn new(title: &str, items: Vec) -> Self { Menu(unsafe { let cls = class!(NSMenu); - let alloc: id = msg_send![cls, alloc]; + let alloc = msg_send_id![cls, alloc]; let title = NSString::new(title); - let menu: id = msg_send![alloc, initWithTitle:&*title]; + let mut menu = msg_send_id![alloc, initWithTitle: &*title]; for item in items.into_iter() { let objc = item.to_objc(); - let _: () = msg_send![menu, addItem:&*objc]; + let _: () = msg_send![&mut menu, addItem:&*objc]; } - Id::from_retained_ptr(menu) + menu }) } diff --git a/src/appkit/printing/settings.rs b/src/appkit/printing/settings.rs index df40dba..b13281b 100644 --- a/src/appkit/printing/settings.rs +++ b/src/appkit/printing/settings.rs @@ -1,8 +1,8 @@ //! Represents settings for printing items. Backed by an `NSDictionary` in Objective-C, this struct //! aims to make it easier to query/process printing operations. +use objc::rc::{Id, Shared}; use objc::runtime::Object; -use objc_id::ShareId; use crate::foundation::id; @@ -10,14 +10,14 @@ use crate::foundation::id; /// application/user. #[derive(Clone, Debug)] pub struct PrintSettings { - pub inner: ShareId + pub inner: Id } impl PrintSettings { /// Internal method, constructs a wrapper around the backing `NSDictionary` print settings. pub(crate) fn with_inner(inner: id) -> Self { PrintSettings { - inner: unsafe { ShareId::from_ptr(inner) } + inner: unsafe { Id::retain(inner).unwrap() } } } } diff --git a/src/appkit/segmentedcontrol.rs b/src/appkit/segmentedcontrol.rs index ba9fbb7..a6a8468 100644 --- a/src/appkit/segmentedcontrol.rs +++ b/src/appkit/segmentedcontrol.rs @@ -7,9 +7,9 @@ use std::cell::RefCell; use std::rc::Rc; use objc::declare::ClassDecl; +use objc::rc::{Id, Shared}; use objc::runtime::{Class, Object, Sel}; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::ShareId; +use objc::{class, msg_send, msg_send_id, sel}; use crate::color::Color; use crate::control::Control; @@ -171,7 +171,7 @@ impl SegmentedControl { pub fn set_tooltip_segment(&mut self, index: NSUInteger, tooltip: &str) { self.objc.with_mut(|obj| unsafe { let converted = NSString::new(tooltip); - let _: () = msg_send![obj, setToolTip: converted forSegment: index]; + let _: () = msg_send![obj, setToolTip: &*converted.objc, forSegment: index]; }) } @@ -193,7 +193,7 @@ impl SegmentedControl { /// best just to message pass or something. pub fn set_action(&mut self, action: F) { // @TODO: This probably isn't ideal but gets the job done for now; needs revisiting. - let this = self.objc.get(|obj| unsafe { ShareId::from_ptr(msg_send![obj, self]) }); + let this: Id<_, Shared> = self.objc.get(|obj| unsafe { msg_send_id![obj, self] }); let handler = TargetActionHandler::new(&*this, move |obj: *const Object| unsafe { let selected: i32 = msg_send![obj, selectedSegment]; action(selected) diff --git a/src/appkit/toolbar/class.rs b/src/appkit/toolbar/class.rs index 719f799..60ff60d 100644 --- a/src/appkit/toolbar/class.rs +++ b/src/appkit/toolbar/class.rs @@ -3,11 +3,12 @@ use std::sync::Once; use objc::declare::ClassDecl; -use objc::runtime::{Class, Object, Sel}; -use objc::{class, msg_send, sel, sel_impl}; +use objc::rc::Id; +use objc::runtime::{Bool, Class, Object, Sel}; +use objc::{class, msg_send, sel}; use crate::appkit::toolbar::{ToolbarDelegate, TOOLBAR_PTR}; -use crate::foundation::{id, load_or_register_class, NSArray, NSString, BOOL}; +use crate::foundation::{id, load_or_register_class, NSArray, NSString}; use crate::utils::load; /// Retrieves and passes the allowed item identifiers for this toolbar. @@ -21,7 +22,7 @@ extern "C" fn allowed_item_identifiers(this: &Object, _: Sel .collect::>() .into(); - identifiers.into() + Id::autorelease_return(identifiers.0) } /// Retrieves and passes the default item identifiers for this toolbar. @@ -35,7 +36,7 @@ extern "C" fn default_item_identifiers(this: &Object, _: Sel .collect::>() .into(); - identifiers.into() + Id::autorelease_return(identifiers.0) } /// Retrieves and passes the default item identifiers for this toolbar. @@ -49,14 +50,14 @@ extern "C" fn selectable_item_identifiers(this: &Object, _: .collect::>() .into(); - identifiers.into() + Id::autorelease_return(identifiers.0) } /// Loads the controller, grabs whatever item is for this identifier, and returns what the /// Objective-C runtime needs. -extern "C" fn item_for_identifier(this: &Object, _: Sel, _: id, identifier: id, _: BOOL) -> id { +extern "C" fn item_for_identifier(this: &Object, _: Sel, _: id, identifier: id, _: Bool) -> id { let toolbar = load::(this, TOOLBAR_PTR); - let identifier = NSString::from_retained(identifier); + let identifier = NSString::retain(identifier); let item = toolbar.item_for(identifier.to_str()); unsafe { msg_send![&*item.objc, self] } @@ -65,7 +66,7 @@ extern "C" fn item_for_identifier(this: &Object, _: Sel, _: /// Registers a `NSToolbar` subclass, and configures it to hold some ivars for various things we need /// to store. We use it as our delegate as well, just to cut down on moving pieces. -pub(crate) fn register_toolbar_class(instance: &T) -> *const Class { +pub(crate) fn register_toolbar_class(instance: &T) -> &'static Class { load_or_register_class("NSObject", instance.subclass_name(), |decl| unsafe { // For callbacks decl.add_ivar::(TOOLBAR_PTR); @@ -73,19 +74,19 @@ pub(crate) fn register_toolbar_class(instance: &T) -> *const // Add callback methods decl.add_method( sel!(toolbarAllowedItemIdentifiers:), - allowed_item_identifiers:: as extern "C" fn(&Object, _, _) -> id + allowed_item_identifiers:: as extern "C" fn(_, _, _) -> _ ); decl.add_method( sel!(toolbarDefaultItemIdentifiers:), - default_item_identifiers:: as extern "C" fn(&Object, _, _) -> id + default_item_identifiers:: as extern "C" fn(_, _, _) -> _ ); decl.add_method( sel!(toolbarSelectableItemIdentifiers:), - selectable_item_identifiers:: as extern "C" fn(&Object, _, _) -> id + selectable_item_identifiers:: as extern "C" fn(_, _, _) -> _ ); decl.add_method( sel!(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:), - item_for_identifier:: as extern "C" fn(&Object, _, _, _, _) -> id + item_for_identifier:: as extern "C" fn(_, _, _, _, _) -> _ ); }) } diff --git a/src/appkit/toolbar/enums.rs b/src/appkit/toolbar/enums.rs index da94764..d54e230 100644 --- a/src/appkit/toolbar/enums.rs +++ b/src/appkit/toolbar/enums.rs @@ -1,5 +1,7 @@ //! Various types used for Toolbar configuration. +use objc::rc::Id; + use crate::foundation::{id, NSString, NSUInteger}; /// Represents the display mode(s) a Toolbar can render in. @@ -95,7 +97,8 @@ impl ItemIdentifier { pub(crate) fn to_nsstring(&self) -> id { unsafe { match self { - Self::Custom(s) => NSString::new(s).into(), + // FIXME: We shouldn't use autorelease here + Self::Custom(s) => Id::autorelease_return(NSString::new(s).objc), Self::CloudSharing => NSToolbarCloudSharingItemIdentifier, Self::FlexibleSpace => NSToolbarFlexibleSpaceItemIdentifier, Self::Print => NSToolbarPrintItemIdentifier, @@ -106,7 +109,10 @@ impl ItemIdentifier { // This ensures that the framework compiles and runs on 10.15.7 and lower; it will // not actually work on anything except 11.0+. Use a runtime check to be safe. - Self::SidebarTracker => NSString::no_copy("NSToolbarSidebarTrackingSeparatorItemIdentifier").into() + // FIXME: We shouldn't use autorelease here + Self::SidebarTracker => { + Id::autorelease_return(NSString::no_copy("NSToolbarSidebarTrackingSeparatorItemIdentifier").objc) + }, } } } diff --git a/src/appkit/toolbar/item.rs b/src/appkit/toolbar/item.rs index 201fc37..22428d4 100644 --- a/src/appkit/toolbar/item.rs +++ b/src/appkit/toolbar/item.rs @@ -6,9 +6,9 @@ use core_graphics::geometry::CGSize; use std::fmt; +use objc::rc::{Id, Owned, Shared}; use objc::runtime::Object; -use objc::{class, msg_send, sel, sel_impl}; -use objc_id::{Id, ShareId}; +use objc::{class, msg_send, msg_send_id, sel}; use crate::appkit::segmentedcontrol::SegmentedControl; use crate::button::{BezelStyle, Button}; @@ -20,7 +20,7 @@ use crate::invoker::TargetActionHandler; #[derive(Debug)] pub struct ToolbarItem { pub identifier: String, - pub objc: Id, + pub objc: Id, pub button: Option