From 2803922f3a019bf9a94479d708d88890244c16b6 Mon Sep 17 00:00:00 2001 From: Alexander Czernay Date: Sun, 16 Apr 2023 10:47:32 +0200 Subject: [PATCH] Fixes possible duplicate objc class registration. This can happen in environments like plugins, where cacao can exist multiple times and thus tries to create and register its objc classes more than once. --- src/appkit/app/class.rs | 15 +- src/appkit/app/delegate.rs | 303 +++++++++++++------------- src/appkit/menu/item.rs | 21 +- src/appkit/window/controller/class.rs | 17 +- src/button/mod.rs | 18 +- src/color/appkit_dynamic_color.rs | 183 ++++++++-------- src/image/appkit.rs | 17 +- src/image/uikit.rs | 15 +- src/input/appkit.rs | 15 +- src/invoker.rs | 21 +- src/listview/appkit.rs | 15 +- src/listview/row/appkit.rs | 90 ++++---- src/listview/row/uikit.rs | 36 +-- src/scrollview/appkit.rs | 80 ++++--- src/select/mod.rs | 15 +- src/switch.rs | 17 +- src/text/label/appkit.rs | 36 +-- src/uikit/app/class.rs | 15 +- src/uikit/app/delegate.rs | 43 ++-- src/uikit/scene/delegate.rs | 41 ++-- src/view/appkit.rs | 23 +- src/view/splitviewcontroller/ios.rs | 32 ++- src/view/uikit.rs | 15 +- src/webview/process_pool.rs | 21 +- 24 files changed, 626 insertions(+), 478 deletions(-) diff --git a/src/appkit/app/class.rs b/src/appkit/app/class.rs index e53885f..2b46ae7 100644 --- a/src/appkit/app/class.rs +++ b/src/appkit/app/class.rs @@ -12,12 +12,17 @@ use objc::runtime::Class; pub(crate) fn register_app_class() -> *const Class { static mut APP_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTApplication"; - INIT.call_once(|| unsafe { - let superclass = class!(NSApplication); - let decl = ClassDecl::new("RSTApplication", superclass).unwrap(); - APP_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { APP_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSApplication); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + APP_CLASS = decl.register(); + }); + } unsafe { APP_CLASS } } diff --git a/src/appkit/app/delegate.rs b/src/appkit/app/delegate.rs index 45cf6d9..d5e2069 100644 --- a/src/appkit/app/delegate.rs +++ b/src/appkit/app/delegate.rs @@ -297,173 +297,178 @@ extern "C" fn delegate_handles_key(this: &Object, _: Sel, _: id, pub(crate) fn register_app_delegate_class() -> *const Class { static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTAppDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(NSObject); - let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { DELEGATE_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSObject); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - decl.add_ivar::(APP_PTR); + decl.add_ivar::(APP_PTR); - // Launching Applications - decl.add_method( - sel!(applicationWillFinishLaunching:), - will_finish_launching:: as extern "C" fn(&Object, _, _) - ); - decl.add_method( - sel!(applicationDidFinishLaunching:), - did_finish_launching:: as extern "C" fn(&Object, _, _) - ); + // Launching Applications + decl.add_method( + sel!(applicationWillFinishLaunching:), + will_finish_launching:: as extern "C" fn(&Object, _, _) + ); + decl.add_method( + sel!(applicationDidFinishLaunching:), + did_finish_launching:: as extern "C" fn(&Object, _, _) + ); - // Managing Active Status - decl.add_method( - sel!(applicationWillBecomeActive:), - will_become_active:: as extern "C" fn(&Object, _, _) - ); - decl.add_method( - sel!(applicationDidBecomeActive:), - did_become_active:: as extern "C" fn(&Object, _, _) - ); - decl.add_method( - sel!(applicationWillResignActive:), - will_resign_active:: as extern "C" fn(&Object, _, _) - ); - decl.add_method( - sel!(applicationDidResignActive:), - did_resign_active:: as extern "C" fn(&Object, _, _) - ); + // Managing Active Status + decl.add_method( + sel!(applicationWillBecomeActive:), + will_become_active:: as extern "C" fn(&Object, _, _) + ); + decl.add_method( + sel!(applicationDidBecomeActive:), + did_become_active:: as extern "C" fn(&Object, _, _) + ); + decl.add_method( + sel!(applicationWillResignActive:), + will_resign_active:: as extern "C" fn(&Object, _, _) + ); + decl.add_method( + sel!(applicationDidResignActive:), + did_resign_active:: as extern "C" fn(&Object, _, _) + ); - // 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, _, _) - ); - decl.add_method( - sel!(applicationShouldTerminateAfterLastWindowClosed:), - should_terminate_after_last_window_closed:: as extern "C" fn(&Object, _, _) -> BOOL - ); + // 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, _, _) + ); + decl.add_method( + sel!(applicationShouldTerminateAfterLastWindowClosed:), + should_terminate_after_last_window_closed:: as extern "C" fn(&Object, _, _) -> BOOL + ); - // 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, _, _)); + // 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, _, _)); - // 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!(applicationShouldHandleReopen:hasVisibleWindows:), - should_handle_reopen:: as extern "C" fn(&Object, _, _, BOOL) -> BOOL - ); + // 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!(applicationShouldHandleReopen:hasVisibleWindows:), + should_handle_reopen:: as extern "C" fn(&Object, _, _, BOOL) -> BOOL + ); - // Dock Menu - decl.add_method( - sel!(applicationDockMenu:), - dock_menu:: as extern "C" fn(&Object, _, _) -> id - ); + // Dock Menu + decl.add_method( + sel!(applicationDockMenu:), + dock_menu:: as extern "C" fn(&Object, _, _) -> id + ); - // Displaying Errors - decl.add_method( - sel!(application:willPresentError:), - will_present_error:: as extern "C" fn(&Object, _, _, id) -> id - ); + // Displaying Errors + decl.add_method( + sel!(application:willPresentError:), + will_present_error:: as extern "C" fn(&Object, _, _, id) -> id + ); - // Managing the Screen - decl.add_method( - sel!(applicationDidChangeScreenParameters:), - did_change_screen_parameters:: as extern "C" fn(&Object, _, _) - ); - decl.add_method( - sel!(applicationDidChangeOcclusionState:), - did_change_occlusion_state:: as extern "C" fn(&Object, _, _) - ); + // Managing the Screen + decl.add_method( + sel!(applicationDidChangeScreenParameters:), + did_change_screen_parameters:: as extern "C" fn(&Object, _, _) + ); + decl.add_method( + sel!(applicationDidChangeOcclusionState:), + did_change_occlusion_state:: as extern "C" fn(&Object, _, _) + ); - // User Activities - decl.add_method( - sel!(application:willContinueUserActivityWithType:), - will_continue_user_activity_with_type:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); - decl.add_method( - sel!(application:continueUserActivity:restorationHandler:), - continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) -> BOOL - ); - decl.add_method( - sel!(application:didFailToContinueUserActivityWithType:error:), - failed_to_continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) - ); - decl.add_method( - sel!(application:didUpdateUserActivity:), - did_update_user_activity:: as extern "C" fn(&Object, _, _, id) - ); + // User Activities + decl.add_method( + sel!(application:willContinueUserActivityWithType:), + will_continue_user_activity_with_type:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); + decl.add_method( + sel!(application:continueUserActivity:restorationHandler:), + continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) -> BOOL + ); + decl.add_method( + sel!(application:didFailToContinueUserActivityWithType:error:), + failed_to_continue_user_activity:: as extern "C" fn(&Object, _, _, id, id) + ); + decl.add_method( + sel!(application:didUpdateUserActivity:), + did_update_user_activity:: as extern "C" fn(&Object, _, _, id) + ); - // Handling push notifications - decl.add_method( - sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:), - registered_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) - ); - decl.add_method( - sel!(application:didFailToRegisterForRemoteNotificationsWithError:), - failed_to_register_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) - ); - decl.add_method( - sel!(application:didReceiveRemoteNotification:), - did_receive_remote_notification:: as extern "C" fn(&Object, _, _, id) - ); + // Handling push notifications + decl.add_method( + sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:), + registered_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) + ); + decl.add_method( + sel!(application:didFailToRegisterForRemoteNotificationsWithError:), + failed_to_register_for_remote_notifications:: as extern "C" fn(&Object, _, _, id) + ); + decl.add_method( + sel!(application:didReceiveRemoteNotification:), + did_receive_remote_notification:: as extern "C" fn(&Object, _, _, id) + ); - // CloudKit - #[cfg(feature = "cloudkit")] - decl.add_method( - sel!(application:userDidAcceptCloudKitShareWithMetadata:), - accepted_cloudkit_share:: as extern "C" fn(&Object, _, _, id) - ); + // CloudKit + #[cfg(feature = "cloudkit")] + decl.add_method( + sel!(application:userDidAcceptCloudKitShareWithMetadata:), + accepted_cloudkit_share:: as extern "C" fn(&Object, _, _, id) + ); - // Opening Files - decl.add_method( - sel!(application:openURLs:), - open_urls:: as extern "C" fn(&Object, _, _, id) - ); - decl.add_method( - sel!(application:openFileWithoutUI:), - open_file_without_ui:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); - decl.add_method( - sel!(applicationShouldOpenUntitledFile:), - should_open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL - ); - decl.add_method( - sel!(applicationOpenUntitledFile:), - open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL - ); - decl.add_method( - sel!(application:openTempFile:), - open_temp_file:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); + // Opening Files + decl.add_method( + sel!(application:openURLs:), + open_urls:: as extern "C" fn(&Object, _, _, id) + ); + decl.add_method( + sel!(application:openFileWithoutUI:), + open_file_without_ui:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); + decl.add_method( + sel!(applicationShouldOpenUntitledFile:), + should_open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL + ); + decl.add_method( + sel!(applicationOpenUntitledFile:), + open_untitled_file:: as extern "C" fn(&Object, _, _) -> BOOL + ); + decl.add_method( + sel!(application:openTempFile:), + open_temp_file:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); - // Printing - decl.add_method( - sel!(application:printFile:), - print_file:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); - decl.add_method( - sel!(application:printFiles:withSettings:showPrintPanels:), - print_files:: as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger - ); + // Printing + decl.add_method( + sel!(application:printFile:), + print_file:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); + decl.add_method( + sel!(application:printFiles:withSettings:showPrintPanels:), + print_files:: as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger + ); - // @TODO: Restoring Application State - // Depends on NSCoder support, which is... welp. + // @TODO: Restoring Application State + // Depends on NSCoder support, which is... welp. - // Scripting - decl.add_method( - sel!(application:delegateHandlesKey:), - delegate_handles_key:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); + // Scripting + decl.add_method( + sel!(application:delegateHandlesKey:), + delegate_handles_key:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); - DELEGATE_CLASS = decl.register(); - }); + DELEGATE_CLASS = decl.register(); + }); + } unsafe { DELEGATE_CLASS } } diff --git a/src/appkit/menu/item.rs b/src/appkit/menu/item.rs index 3f65ed5..334ffa4 100644 --- a/src/appkit/menu/item.rs +++ b/src/appkit/menu/item.rs @@ -316,17 +316,22 @@ extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) { pub(crate) fn register_menu_item_class() -> *const Class { static mut APP_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "CacaoMenuItem"; - INIT.call_once(|| unsafe { - let superclass = class!(NSMenuItem); - let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap(); - decl.add_ivar::(BLOCK_PTR); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { APP_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSMenuItem); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + 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(&Object, _)); + decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id)); - APP_CLASS = decl.register(); - }); + APP_CLASS = decl.register(); + }); + } unsafe { APP_CLASS } } diff --git a/src/appkit/window/controller/class.rs b/src/appkit/window/controller/class.rs index 2f9c914..f82c5d0 100644 --- a/src/appkit/window/controller/class.rs +++ b/src/appkit/window/controller/class.rs @@ -14,13 +14,18 @@ use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; pub(crate) fn register_window_controller_class() -> *const Class { static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTWindowController"; - INIT.call_once(|| unsafe { - let superclass = class!(NSWindowController); - let mut decl = ClassDecl::new("RSTWindowController", superclass).unwrap(); - decl.add_ivar::(WINDOW_DELEGATE_PTR); - DELEGATE_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { DELEGATE_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSWindowController); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + decl.add_ivar::(WINDOW_DELEGATE_PTR); + DELEGATE_CLASS = decl.register(); + }); + } unsafe { DELEGATE_CLASS } } diff --git a/src/button/mod.rs b/src/button/mod.rs index 822fb5c..979385d 100644 --- a/src/button/mod.rs +++ b/src/button/mod.rs @@ -345,12 +345,18 @@ impl Drop for Button { fn register_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTButton"; - INIT.call_once(|| unsafe { - let superclass = class!(NSButton); - let decl = ClassDecl::new("RSTButton", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); - + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { + VIEW_CLASS = c; + } + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSButton); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/color/appkit_dynamic_color.rs b/src/color/appkit_dynamic_color.rs index 6283350..6502614 100644 --- a/src/color/appkit_dynamic_color.rs +++ b/src/color/appkit_dynamic_color.rs @@ -261,107 +261,112 @@ extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger) pub(crate) fn register_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "CacaoDynamicColor"; - INIT.call_once(|| unsafe { - let superclass = class!(NSColor); - let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSColor); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - // 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!(colorUsingColorSpace:), - color_using_color_space as extern "C" fn(&Object, _, id) -> id - ); - decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id); - decl.add_method( - sel!(colorUsingColorSpaceName:), - color_using_color_space_name as extern "C" fn(&Object, _, id) -> id - ); - decl.add_method( - sel!(numberOfComponents), - number_of_components as extern "C" fn(&Object, _) -> NSInteger - ); + // 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!(colorUsingColorSpace:), + color_using_color_space as extern "C" fn(&Object, _, id) -> id + ); + decl.add_method(sel!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id); + decl.add_method( + sel!(colorUsingColorSpaceName:), + color_using_color_space_name as extern "C" fn(&Object, _, id) -> id + ); + decl.add_method( + sel!(numberOfComponents), + number_of_components as extern "C" fn(&Object, _) -> NSInteger + ); - decl.add_method(sel!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat)); - decl.add_method( - sel!(getRed:green:blue:alpha:), - get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) - ); - decl.add_method(sel!(redComponent), red_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method(sel!(greenComponent), green_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method(sel!(blueComponent), blue_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method(sel!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat)); + decl.add_method( + sel!(getRed:green:blue:alpha:), + get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) + ); + decl.add_method(sel!(redComponent), red_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method(sel!(greenComponent), green_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method(sel!(blueComponent), blue_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method(sel!(hueComponent), hue_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method( - sel!(saturationComponent), - saturation_component as extern "C" fn(&Object, _) -> CGFloat - ); - decl.add_method( - sel!(brightnessComponent), - brightness_component as extern "C" fn(&Object, _) -> CGFloat - ); - decl.add_method( - sel!(getHue:saturation:brightness:alpha:), - get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) - ); + decl.add_method(sel!(hueComponent), hue_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method( + sel!(saturationComponent), + saturation_component as extern "C" fn(&Object, _) -> CGFloat + ); + decl.add_method( + sel!(brightnessComponent), + brightness_component as extern "C" fn(&Object, _) -> CGFloat + ); + decl.add_method( + sel!(getHue:saturation:brightness:alpha:), + get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) + ); - decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method( - sel!(getWhite:alpha:), - get_white as extern "C" fn(&Object, _, CGFloat, CGFloat) - ); + decl.add_method(sel!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method( + sel!(getWhite:alpha:), + get_white as extern "C" fn(&Object, _, CGFloat, CGFloat) + ); - decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method( - sel!(magentaComponent), - magenta_component as extern "C" fn(&Object, _) -> CGFloat - ); - decl.add_method( - sel!(yellowComponent), - yellow_component as extern "C" fn(&Object, _) -> CGFloat - ); - decl.add_method(sel!(blackComponent), black_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method( - sel!(getCyan:magenta:yellow:black:alpha:), - get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat) - ); + decl.add_method(sel!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method( + sel!(magentaComponent), + magenta_component as extern "C" fn(&Object, _) -> CGFloat + ); + decl.add_method( + sel!(yellowComponent), + yellow_component as extern "C" fn(&Object, _) -> CGFloat + ); + decl.add_method(sel!(blackComponent), black_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method( + sel!(getCyan:magenta:yellow:black:alpha:), + get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat) + ); - decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(&Object, _) -> CGFloat); + decl.add_method(sel!(alphaComponent), alpha_component as extern "C" fn(&Object, _) -> CGFloat); - decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id); - decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _)); - decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _)); - decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _)); + decl.add_method(sel!(CGColor), cg_color as extern "C" fn(&Object, _) -> id); + decl.add_method(sel!(setStroke), set_stroke as extern "C" fn(&Object, _)); + decl.add_method(sel!(setFill), set_fill as extern "C" fn(&Object, _)); + decl.add_method(sel!(set), call_set as extern "C" fn(&Object, _)); - decl.add_method( - sel!(highlightWithLevel:), - highlight_with_level as extern "C" fn(&Object, _, CGFloat) -> id - ); - decl.add_method( - sel!(shadowWithLevel:), - shadow_with_level as extern "C" fn(&Object, _, CGFloat) -> id - ); + decl.add_method( + sel!(highlightWithLevel:), + highlight_with_level as extern "C" fn(&Object, _, CGFloat) -> id + ); + decl.add_method( + sel!(shadowWithLevel:), + shadow_with_level as extern "C" fn(&Object, _, CGFloat) -> id + ); - decl.add_method( - sel!(colorWithAlphaComponent:), - color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id - ); - decl.add_method( - sel!(blendedColorWithFraction:ofColor:), - blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id - ); - decl.add_method( - sel!(colorWithSystemEffect:), - color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id - ); + decl.add_method( + sel!(colorWithAlphaComponent:), + color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id + ); + decl.add_method( + sel!(blendedColorWithFraction:ofColor:), + blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id + ); + decl.add_method( + sel!(colorWithSystemEffect:), + color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id + ); - decl.add_ivar::(AQUA_LIGHT_COLOR_NORMAL_CONTRAST); - decl.add_ivar::(AQUA_LIGHT_COLOR_HIGH_CONTRAST); - decl.add_ivar::(AQUA_DARK_COLOR_NORMAL_CONTRAST); - decl.add_ivar::(AQUA_DARK_COLOR_HIGH_CONTRAST); + decl.add_ivar::(AQUA_LIGHT_COLOR_NORMAL_CONTRAST); + decl.add_ivar::(AQUA_LIGHT_COLOR_HIGH_CONTRAST); + decl.add_ivar::(AQUA_DARK_COLOR_NORMAL_CONTRAST); + decl.add_ivar::(AQUA_DARK_COLOR_HIGH_CONTRAST); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/image/appkit.rs b/src/image/appkit.rs index 0dceb69..b388dd2 100644 --- a/src/image/appkit.rs +++ b/src/image/appkit.rs @@ -25,15 +25,20 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR}; pub(crate) fn register_image_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTImageView"; - INIT.call_once(|| unsafe { - let superclass = class!(NSImageView); - let decl = ClassDecl::new("RSTImageView", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSImageView); + let decl = ClassDecl::new(CLASS_NAME, 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(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/image/uikit.rs b/src/image/uikit.rs index ef989fe..43acf5d 100644 --- a/src/image/uikit.rs +++ b/src/image/uikit.rs @@ -15,12 +15,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR}; pub(crate) fn register_image_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTImageView"; - INIT.call_once(|| unsafe { - let superclass = class!(UIImageView); - let mut decl = ClassDecl::new("RSTImageView", superclass).expect("Failed to get RSTVIEW"); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIImageView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).expect("Failed to get RSTVIEW"); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/input/appkit.rs b/src/input/appkit.rs index 2138117..560c14e 100644 --- a/src/input/appkit.rs +++ b/src/input/appkit.rs @@ -54,12 +54,17 @@ extern "C" fn text_should_end_editing(this: &mut Object, _ pub(crate) fn register_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTTextInputField"; - INIT.call_once(|| unsafe { - let superclass = class!(NSTextField); - let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSTextField); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/invoker.rs b/src/invoker.rs index 26560f2..51ab45f 100644 --- a/src/invoker.rs +++ b/src/invoker.rs @@ -97,16 +97,23 @@ extern "C" fn perform(this: &mut Object, _: Sel, _sender: id) pub(crate) fn register_invoker_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTTargetActionHandler"; - INIT.call_once(|| unsafe { - let superclass = class!(NSObject); - let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { + VIEW_CLASS = c; + } + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSObject); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - decl.add_ivar::(ACTION_CALLBACK_PTR); - decl.add_method(sel!(perform:), perform:: as extern "C" fn(&mut Object, _, id)); + decl.add_ivar::(ACTION_CALLBACK_PTR); + decl.add_method(sel!(perform:), perform:: as extern "C" fn(&mut Object, _, id)); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/listview/appkit.rs b/src/listview/appkit.rs index f2c0391..95c5fd3 100644 --- a/src/listview/appkit.rs +++ b/src/listview/appkit.rs @@ -187,12 +187,17 @@ extern "C" fn dragging_exited(this: &mut Object, _: Sel, in pub(crate) fn register_listview_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &'static str = "RSTListView"; - INIT.call_once(|| unsafe { - let superclass = class!(NSTableView); - let decl = ClassDecl::new("RSTListView", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSTableView); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/listview/row/appkit.rs b/src/listview/row/appkit.rs index d6f4749..25a96e1 100644 --- a/src/listview/row/appkit.rs +++ b/src/listview/row/appkit.rs @@ -109,15 +109,20 @@ extern "C" fn dealloc(this: &Object, _: Sel) { pub(crate) fn register_listview_row_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTTableViewRow"; - INIT.call_once(|| unsafe { - let superclass = class!(NSView); - let mut decl = ClassDecl::new("RSTTableViewRow", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSView); + let mut decl = ClassDecl::new(CLASS_NAME, 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(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } @@ -127,46 +132,51 @@ pub(crate) fn register_listview_row_class() -> *const Class { pub(crate) fn register_listview_row_class_with_delegate() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTableViewRowWithDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(NSView); - let mut decl = ClassDecl::new("RSTableViewRowWithDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - // A pointer to the "view controller" on the Rust side. It's expected that this doesn't - // move. - decl.add_ivar::(LISTVIEW_ROW_DELEGATE_PTR); - decl.add_ivar::(BACKGROUND_COLOR); + // A pointer to the "view controller" on the Rust side. It's expected that this doesn't + // move. + decl.add_ivar::(LISTVIEW_ROW_DELEGATE_PTR); + decl.add_ivar::(BACKGROUND_COLOR); - 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!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); + decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _)); - // Drag and drop operations (e.g, accepting files) - decl.add_method( - sel!(draggingEntered:), - dragging_entered:: as extern "C" fn(&mut Object, _, _) -> NSUInteger - ); - decl.add_method( - sel!(prepareForDragOperation:), - prepare_for_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL - ); - decl.add_method( - sel!(performDragOperation:), - perform_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL - ); - decl.add_method( - sel!(concludeDragOperation:), - conclude_drag_operation:: as extern "C" fn(&mut Object, _, _) - ); - decl.add_method( - sel!(draggingExited:), - dragging_exited:: as extern "C" fn(&mut Object, _, _) - ); + // Drag and drop operations (e.g, accepting files) + decl.add_method( + sel!(draggingEntered:), + dragging_entered:: as extern "C" fn(&mut Object, _, _) -> NSUInteger + ); + decl.add_method( + sel!(prepareForDragOperation:), + prepare_for_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL + ); + decl.add_method( + sel!(performDragOperation:), + perform_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL + ); + decl.add_method( + sel!(concludeDragOperation:), + conclude_drag_operation:: as extern "C" fn(&mut Object, _, _) + ); + decl.add_method( + sel!(draggingExited:), + dragging_exited:: as extern "C" fn(&mut Object, _, _) + ); - // Cleanup - decl.add_method(sel!(dealloc), dealloc:: as extern "C" fn(&Object, _)); + // Cleanup + decl.add_method(sel!(dealloc), dealloc:: as extern "C" fn(&Object, _)); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/listview/row/uikit.rs b/src/listview/row/uikit.rs index 1e835ed..1ea8ce4 100644 --- a/src/listview/row/uikit.rs +++ b/src/listview/row/uikit.rs @@ -16,12 +16,17 @@ use crate::utils::load; pub(crate) fn register_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTView"; - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } @@ -31,15 +36,18 @@ pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class_with_delegate() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTViewWithDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap(); - decl.add_ivar::(VIEW_DELEGATE_PTR); - VIEW_CLASS = decl.register(); - }); - - unsafe { - VIEW_CLASS + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + decl.add_ivar::(VIEW_DELEGATE_PTR); + VIEW_CLASS = decl.register(); + }); } + + unsafe { VIEW_CLASS } } diff --git a/src/scrollview/appkit.rs b/src/scrollview/appkit.rs index f686f20..d325465 100644 --- a/src/scrollview/appkit.rs +++ b/src/scrollview/appkit.rs @@ -79,12 +79,17 @@ extern "C" fn dragging_exited(this: &mut Object, _: Sel, pub(crate) fn register_scrollview_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &'static str = "RSTScrollView"; - INIT.call_once(|| unsafe { - let superclass = class!(NSScrollView); - let decl = ClassDecl::new("RSTScrollView", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSScrollView); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } @@ -94,41 +99,46 @@ pub(crate) fn register_scrollview_class() -> *const Class { pub(crate) fn register_scrollview_class_with_delegate() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &'static str = "RSTScrollViewWithDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(NSScrollView); - let mut decl = ClassDecl::new("RSTScrollViewWithDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSScrollView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - // A pointer to the "view controller" on the Rust side. It's expected that this doesn't - // move. - decl.add_ivar::(SCROLLVIEW_DELEGATE_PTR); + // A pointer to the "view controller" on the Rust side. It's expected that this doesn't + // move. + decl.add_ivar::(SCROLLVIEW_DELEGATE_PTR); - 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); - // Drag and drop operations (e.g, accepting files) - decl.add_method( - sel!(draggingEntered:), - dragging_entered:: as extern "C" fn(&mut Object, _, _) -> NSUInteger - ); - decl.add_method( - sel!(prepareForDragOperation:), - prepare_for_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL - ); - decl.add_method( - sel!(performDragOperation:), - perform_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL - ); - decl.add_method( - sel!(concludeDragOperation:), - conclude_drag_operation:: as extern "C" fn(&mut Object, _, _) - ); - decl.add_method( - sel!(draggingExited:), - dragging_exited:: as extern "C" fn(&mut Object, _, _) - ); + // Drag and drop operations (e.g, accepting files) + decl.add_method( + sel!(draggingEntered:), + dragging_entered:: as extern "C" fn(&mut Object, _, _) -> NSUInteger + ); + decl.add_method( + sel!(prepareForDragOperation:), + prepare_for_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL + ); + decl.add_method( + sel!(performDragOperation:), + perform_drag_operation:: as extern "C" fn(&mut Object, _, _) -> BOOL + ); + decl.add_method( + sel!(concludeDragOperation:), + conclude_drag_operation:: as extern "C" fn(&mut Object, _, _) + ); + decl.add_method( + sel!(draggingExited:), + dragging_exited:: as extern "C" fn(&mut Object, _, _) + ); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/select/mod.rs b/src/select/mod.rs index 7eab27d..2cbdd2e 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -270,12 +270,17 @@ impl Drop for Select { fn register_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "CacaoSelect"; - INIT.call_once(|| unsafe { - let superclass = class!(NSPopUpButton); - let decl = ClassDecl::new("CacaoSelect", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSPopUpButton); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/switch.rs b/src/switch.rs index eab6b38..5d04c87 100644 --- a/src/switch.rs +++ b/src/switch.rs @@ -180,12 +180,19 @@ impl Drop for Switch { fn register_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTSwitch"; - INIT.call_once(|| unsafe { - let superclass = class!(NSButton); - let decl = ClassDecl::new("RSTSwitch", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { + VIEW_CLASS = c; + } + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSButton); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/text/label/appkit.rs b/src/text/label/appkit.rs index 1b3b681..e27fe1b 100644 --- a/src/text/label/appkit.rs +++ b/src/text/label/appkit.rs @@ -25,12 +25,17 @@ use crate::utils::load; pub(crate) fn register_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTTextField"; - INIT.call_once(|| unsafe { - let superclass = class!(NSTextField); - let decl = ClassDecl::new("RSTTextField", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSTextField); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } @@ -40,17 +45,22 @@ pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class_with_delegate() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTTextFieldWithDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(NSView); - let mut decl = ClassDecl::new("RSTTextFieldWithDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - // A pointer to the "view controller" on the Rust side. It's expected that this doesn't - // move. - decl.add_ivar::(LABEL_DELEGATE_PTR); + // A pointer to the "view controller" on the Rust side. It's expected that this doesn't + // move. + decl.add_ivar::(LABEL_DELEGATE_PTR); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/uikit/app/class.rs b/src/uikit/app/class.rs index 3baf350..37909f0 100644 --- a/src/uikit/app/class.rs +++ b/src/uikit/app/class.rs @@ -12,12 +12,17 @@ use objc::runtime::Class; pub(crate) fn register_app_class() -> *const Class { static mut APP_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTApplication"; - INIT.call_once(|| unsafe { - let superclass = class!(UIApplication); - let decl = ClassDecl::new("RSTApplication", superclass).unwrap(); - APP_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { APP_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIApplication); + let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + APP_CLASS = decl.register(); + }); + } unsafe { APP_CLASS } } diff --git a/src/uikit/app/delegate.rs b/src/uikit/app/delegate.rs index aba45ed..5462b69 100644 --- a/src/uikit/app/delegate.rs +++ b/src/uikit/app/delegate.rs @@ -51,29 +51,34 @@ extern "C" fn configuration_for_scene_session(this: &Object, _: pub(crate) fn register_app_delegate_class() -> *const Class { static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTAppDelegate"; - INIT.call_once(|| unsafe { - let superclass = class!(NSObject); - let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { DELEGATE_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSObject); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - // Launching Applications - decl.add_method( - sel!(application:didFinishLaunchingWithOptions:), - did_finish_launching:: as extern "C" fn(&Object, _, _, id) -> BOOL - ); + // Launching Applications + decl.add_method( + sel!(application:didFinishLaunchingWithOptions:), + did_finish_launching:: as extern "C" fn(&Object, _, _, id) -> BOOL + ); - // Scenes - decl.add_method( - sel!(application:configurationForConnectingSceneSession:options:), - configuration_for_scene_session:: as extern "C" fn(&Object, _, _, id, id) -> id - ); - /*decl.add_method( - sel!(application:didDiscardSceneSessions:), - did_discard_scene_sessions:: as extern "C" fn(&Object, _, _, id) - );*/ + // Scenes + decl.add_method( + sel!(application:configurationForConnectingSceneSession:options:), + configuration_for_scene_session:: as extern "C" fn(&Object, _, _, id, id) -> id + ); + /*decl.add_method( + sel!(application:didDiscardSceneSessions:), + did_discard_scene_sessions:: as extern "C" fn(&Object, _, _, id) + );*/ - DELEGATE_CLASS = decl.register(); - }); + DELEGATE_CLASS = decl.register(); + }); + } unsafe { DELEGATE_CLASS } } diff --git a/src/uikit/scene/delegate.rs b/src/uikit/scene/delegate.rs index 75aa69a..2406f84 100644 --- a/src/uikit/scene/delegate.rs +++ b/src/uikit/scene/delegate.rs @@ -62,30 +62,35 @@ extern "C" fn scene_will_connect_to_session_with_options pub(crate) fn register_window_scene_delegate_class Box>() -> *const Class { static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTWindowSceneDelegate"; - use objc::runtime::{class_addProtocol, Protocol}; - INIT.call_once(|| unsafe { - let superclass = class!(UIResponder); - let mut decl = ClassDecl::new("RSTWindowSceneDelegate", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { DELEGATE_CLASS = c }; + } else { + use objc::runtime::Protocol; + INIT.call_once(|| unsafe { + let superclass = class!(UIResponder); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - let p = Protocol::get("UIWindowSceneDelegate").unwrap(); + let p = Protocol::get("UIWindowSceneDelegate").unwrap(); - // A spot to hold a pointer to - decl.add_ivar::(WINDOW_SCENE_PTR); - decl.add_protocol(p); + // A spot to hold a pointer to + decl.add_ivar::(WINDOW_SCENE_PTR); + decl.add_protocol(p); - // Override the `init` call to handle creating and attaching a WindowSceneDelegate. - decl.add_method(sel!(init), init:: as extern "C" fn(&mut Object, _) -> id); + // Override the `init` call to handle creating and attaching a WindowSceneDelegate. + decl.add_method(sel!(init), init:: as extern "C" fn(&mut Object, _) -> id); - // UIWindowSceneDelegate API - decl.add_method( - sel!(scene:willConnectToSession:options:), - scene_will_connect_to_session_with_options:: as extern "C" fn(&Object, _, _, _, _) - ); + // UIWindowSceneDelegate API + decl.add_method( + sel!(scene:willConnectToSession:options:), + scene_will_connect_to_session_with_options:: as extern "C" fn(&Object, _, _, _, _) + ); - // Launching Applications - DELEGATE_CLASS = decl.register(); - }); + // Launching Applications + DELEGATE_CLASS = decl.register(); + }); + } unsafe { DELEGATE_CLASS } } diff --git a/src/view/appkit.rs b/src/view/appkit.rs index 27b047e..85bc096 100644 --- a/src/view/appkit.rs +++ b/src/view/appkit.rs @@ -94,19 +94,24 @@ extern "C" fn update_layer(this: &Object, _: Sel) { pub(crate) fn register_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTView"; - INIT.call_once(|| unsafe { - let superclass = class!(NSView); - let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(NSView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - 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!(wantsUpdateLayer), 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!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); - decl.add_ivar::(BACKGROUND_COLOR); + decl.add_ivar::(BACKGROUND_COLOR); - VIEW_CLASS = decl.register(); - }); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/view/splitviewcontroller/ios.rs b/src/view/splitviewcontroller/ios.rs index fe2ab7b..bb4cf59 100644 --- a/src/view/splitviewcontroller/ios.rs +++ b/src/view/splitviewcontroller/ios.rs @@ -53,20 +53,30 @@ extern "C" fn did_disappear(this: &mut Object, _: Sel, animated pub(crate) fn register_view_controller_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTViewController"; - INIT.call_once(|| unsafe { - let superclass = class!(UIViewController); - let mut decl = ClassDecl::new("RSTViewController", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIViewController); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); - decl.add_ivar::(VIEW_DELEGATE_PTR); + decl.add_ivar::(VIEW_DELEGATE_PTR); - decl.add_method(sel!(viewWillAppear:), will_appear:: as extern "C" fn(&mut Object, _, BOOL)); - decl.add_method(sel!(viewDidAppear:), did_appear:: as extern "C" fn(&mut Object, _, BOOL)); - decl.add_method(sel!(viewWillDisappear:), will_disappear:: as extern "C" fn(&mut Object, _, BOOL)); - decl.add_method(sel!(viewDidDisappear:), did_disappear:: as extern "C" fn(&mut Object, _, BOOL)); - - VIEW_CLASS = decl.register(); - }); + decl.add_method(sel!(viewWillAppear:), will_appear:: as extern "C" fn(&mut Object, _, BOOL)); + decl.add_method(sel!(viewDidAppear:), did_appear:: as extern "C" fn(&mut Object, _, BOOL)); + decl.add_method( + sel!(viewWillDisappear:), + will_disappear:: as extern "C" fn(&mut Object, _, BOOL) + ); + decl.add_method( + sel!(viewDidDisappear:), + did_disappear:: as extern "C" fn(&mut Object, _, BOOL) + ); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/view/uikit.rs b/src/view/uikit.rs index 4b697d9..54015ce 100644 --- a/src/view/uikit.rs +++ b/src/view/uikit.rs @@ -16,12 +16,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR}; pub(crate) fn register_view_class() -> *const Class { static mut VIEW_CLASS: *const Class = 0 as *const Class; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTView"; - INIT.call_once(|| unsafe { - let superclass = class!(UIView); - let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); - VIEW_CLASS = decl.register(); - }); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { VIEW_CLASS = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = class!(UIView); + let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap(); + VIEW_CLASS = decl.register(); + }); + } unsafe { VIEW_CLASS } } diff --git a/src/webview/process_pool.rs b/src/webview/process_pool.rs index 8b5c630..718b292 100644 --- a/src/webview/process_pool.rs +++ b/src/webview/process_pool.rs @@ -28,17 +28,22 @@ extern "C" fn download_delegate(this: &Object, _: Sel) -> id { pub fn register_process_pool() -> *const Object { static mut PROCESS_POOL: *const Object = 0 as *const Object; static INIT: Once = Once::new(); + const CLASS_NAME: &str = "RSTWebViewProcessPool"; - INIT.call_once(|| unsafe { - let superclass = Class::get("WKProcessPool").unwrap(); - let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap(); + if let Some(c) = Class::get(CLASS_NAME) { + unsafe { PROCESS_POOL = c }; + } else { + INIT.call_once(|| unsafe { + let superclass = Class::get("WKProcessPool").unwrap(); + let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap(); - //decl.add_ivar::(DOWNLOAD_DELEGATE_PTR); - decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id); + //decl.add_ivar::(DOWNLOAD_DELEGATE_PTR); + decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id); - //PROCESS_POOL = decl.register(); - PROCESS_POOL = msg_send![decl.register(), new]; - }); + //PROCESS_POOL = decl.register(); + PROCESS_POOL = msg_send![decl.register(), new]; + }); + } unsafe { PROCESS_POOL } }