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.
This commit is contained in:
Alexander Czernay 2023-04-16 10:47:32 +02:00
parent 1d76dce75f
commit 2803922f3a
24 changed files with 626 additions and 478 deletions

View file

@ -12,12 +12,17 @@ use objc::runtime::Class;
pub(crate) fn register_app_class() -> *const Class { pub(crate) fn register_app_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; static mut APP_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTApplication";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSApplication); unsafe { APP_CLASS = c };
let decl = ClassDecl::new("RSTApplication", superclass).unwrap(); } else {
APP_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSApplication);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
APP_CLASS = decl.register();
});
}
unsafe { APP_CLASS } unsafe { APP_CLASS }
} }

View file

@ -297,173 +297,178 @@ extern "C" fn delegate_handles_key<T: AppDelegate>(this: &Object, _: Sel, _: id,
pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class { pub(crate) fn register_app_delegate_class<T: AppDelegate + AppDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTAppDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSObject); unsafe { DELEGATE_CLASS = c };
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap(); } else {
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(APP_PTR); decl.add_ivar::<usize>(APP_PTR);
// Launching Applications // Launching Applications
decl.add_method( decl.add_method(
sel!(applicationWillFinishLaunching:), sel!(applicationWillFinishLaunching:),
will_finish_launching::<T> as extern "C" fn(&Object, _, _) will_finish_launching::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationDidFinishLaunching:), sel!(applicationDidFinishLaunching:),
did_finish_launching::<T> as extern "C" fn(&Object, _, _) did_finish_launching::<T> as extern "C" fn(&Object, _, _)
); );
// Managing Active Status // Managing Active Status
decl.add_method( decl.add_method(
sel!(applicationWillBecomeActive:), sel!(applicationWillBecomeActive:),
will_become_active::<T> as extern "C" fn(&Object, _, _) will_become_active::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationDidBecomeActive:), sel!(applicationDidBecomeActive:),
did_become_active::<T> as extern "C" fn(&Object, _, _) did_become_active::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationWillResignActive:), sel!(applicationWillResignActive:),
will_resign_active::<T> as extern "C" fn(&Object, _, _) will_resign_active::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationDidResignActive:), sel!(applicationDidResignActive:),
did_resign_active::<T> as extern "C" fn(&Object, _, _) did_resign_active::<T> as extern "C" fn(&Object, _, _)
); );
// Terminating Applications // Terminating Applications
decl.add_method( decl.add_method(
sel!(applicationShouldTerminate:), sel!(applicationShouldTerminate:),
should_terminate::<T> as extern "C" fn(&Object, _, _) -> NSUInteger should_terminate::<T> as extern "C" fn(&Object, _, _) -> NSUInteger
); );
decl.add_method( decl.add_method(
sel!(applicationWillTerminate:), sel!(applicationWillTerminate:),
will_terminate::<T> as extern "C" fn(&Object, _, _) will_terminate::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationShouldTerminateAfterLastWindowClosed:), sel!(applicationShouldTerminateAfterLastWindowClosed:),
should_terminate_after_last_window_closed::<T> as extern "C" fn(&Object, _, _) -> BOOL should_terminate_after_last_window_closed::<T> as extern "C" fn(&Object, _, _) -> BOOL
); );
// Hiding Applications // Hiding Applications
decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationWillHide:), will_hide::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationDidHide:), did_hide::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationWillUnhide:), will_unhide::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationDidUnhide:), did_unhide::<T> as extern "C" fn(&Object, _, _));
// Managing Windows // Managing Windows
decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationWillUpdate:), will_update::<T> as extern "C" fn(&Object, _, _));
decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _)); decl.add_method(sel!(applicationDidUpdate:), did_update::<T> as extern "C" fn(&Object, _, _));
decl.add_method( decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:), sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL should_handle_reopen::<T> as extern "C" fn(&Object, _, _, BOOL) -> BOOL
); );
// Dock Menu // Dock Menu
decl.add_method( decl.add_method(
sel!(applicationDockMenu:), sel!(applicationDockMenu:),
dock_menu::<T> as extern "C" fn(&Object, _, _) -> id dock_menu::<T> as extern "C" fn(&Object, _, _) -> id
); );
// Displaying Errors // Displaying Errors
decl.add_method( decl.add_method(
sel!(application:willPresentError:), sel!(application:willPresentError:),
will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id will_present_error::<T> as extern "C" fn(&Object, _, _, id) -> id
); );
// Managing the Screen // Managing the Screen
decl.add_method( decl.add_method(
sel!(applicationDidChangeScreenParameters:), sel!(applicationDidChangeScreenParameters:),
did_change_screen_parameters::<T> as extern "C" fn(&Object, _, _) did_change_screen_parameters::<T> as extern "C" fn(&Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(applicationDidChangeOcclusionState:), sel!(applicationDidChangeOcclusionState:),
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _) did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _)
); );
// User Activities // User Activities
decl.add_method( decl.add_method(
sel!(application:willContinueUserActivityWithType:), sel!(application:willContinueUserActivityWithType:),
will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL will_continue_user_activity_with_type::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(application:continueUserActivity:restorationHandler:), sel!(application:continueUserActivity:restorationHandler:),
continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) -> BOOL continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(application:didFailToContinueUserActivityWithType:error:), sel!(application:didFailToContinueUserActivityWithType:error:),
failed_to_continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id) failed_to_continue_user_activity::<T> as extern "C" fn(&Object, _, _, id, id)
); );
decl.add_method( decl.add_method(
sel!(application:didUpdateUserActivity:), sel!(application:didUpdateUserActivity:),
did_update_user_activity::<T> as extern "C" fn(&Object, _, _, id) did_update_user_activity::<T> as extern "C" fn(&Object, _, _, id)
); );
// Handling push notifications // Handling push notifications
decl.add_method( decl.add_method(
sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:), sel!(application:didRegisterForRemoteNotificationsWithDeviceToken:),
registered_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id) registered_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
); );
decl.add_method( decl.add_method(
sel!(application:didFailToRegisterForRemoteNotificationsWithError:), sel!(application:didFailToRegisterForRemoteNotificationsWithError:),
failed_to_register_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id) failed_to_register_for_remote_notifications::<T> as extern "C" fn(&Object, _, _, id)
); );
decl.add_method( decl.add_method(
sel!(application:didReceiveRemoteNotification:), sel!(application:didReceiveRemoteNotification:),
did_receive_remote_notification::<T> as extern "C" fn(&Object, _, _, id) did_receive_remote_notification::<T> as extern "C" fn(&Object, _, _, id)
); );
// CloudKit // CloudKit
#[cfg(feature = "cloudkit")] #[cfg(feature = "cloudkit")]
decl.add_method( decl.add_method(
sel!(application:userDidAcceptCloudKitShareWithMetadata:), sel!(application:userDidAcceptCloudKitShareWithMetadata:),
accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id) accepted_cloudkit_share::<T> as extern "C" fn(&Object, _, _, id)
); );
// Opening Files // Opening Files
decl.add_method( decl.add_method(
sel!(application:openURLs:), sel!(application:openURLs:),
open_urls::<T> as extern "C" fn(&Object, _, _, id) open_urls::<T> as extern "C" fn(&Object, _, _, id)
); );
decl.add_method( decl.add_method(
sel!(application:openFileWithoutUI:), sel!(application:openFileWithoutUI:),
open_file_without_ui::<T> as extern "C" fn(&Object, _, _, id) -> BOOL open_file_without_ui::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(applicationShouldOpenUntitledFile:), sel!(applicationShouldOpenUntitledFile:),
should_open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL should_open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(applicationOpenUntitledFile:), sel!(applicationOpenUntitledFile:),
open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL open_untitled_file::<T> as extern "C" fn(&Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(application:openTempFile:), sel!(application:openTempFile:),
open_temp_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL open_temp_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
// Printing // Printing
decl.add_method( decl.add_method(
sel!(application:printFile:), sel!(application:printFile:),
print_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL print_file::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(application:printFiles:withSettings:showPrintPanels:), sel!(application:printFiles:withSettings:showPrintPanels:),
print_files::<T> as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger print_files::<T> as extern "C" fn(&Object, _, id, id, id, BOOL) -> NSUInteger
); );
// @TODO: Restoring Application State // @TODO: Restoring Application State
// Depends on NSCoder support, which is... welp. // Depends on NSCoder support, which is... welp.
// Scripting // Scripting
decl.add_method( decl.add_method(
sel!(application:delegateHandlesKey:), sel!(application:delegateHandlesKey:),
delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL delegate_handles_key::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
DELEGATE_CLASS = decl.register(); DELEGATE_CLASS = decl.register();
}); });
}
unsafe { DELEGATE_CLASS } unsafe { DELEGATE_CLASS }
} }

View file

@ -316,17 +316,22 @@ extern "C" fn fire_block_action(this: &Object, _: Sel, _item: id) {
pub(crate) fn register_menu_item_class() -> *const Class { pub(crate) fn register_menu_item_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; static mut APP_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "CacaoMenuItem";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSMenuItem); unsafe { APP_CLASS = c };
let mut decl = ClassDecl::new("CacaoMenuItem", superclass).unwrap(); } else {
decl.add_ivar::<usize>(BLOCK_PTR); INIT.call_once(|| unsafe {
let superclass = class!(NSMenuItem);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(BLOCK_PTR);
decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _)); decl.add_method(sel!(dealloc), dealloc_cacao_menuitem as extern "C" fn(&Object, _));
decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id)); decl.add_method(sel!(fireBlockAction:), fire_block_action as extern "C" fn(&Object, _, id));
APP_CLASS = decl.register(); APP_CLASS = decl.register();
}); });
}
unsafe { APP_CLASS } unsafe { APP_CLASS }
} }

View file

@ -14,13 +14,18 @@ use crate::appkit::window::{WindowDelegate, WINDOW_DELEGATE_PTR};
pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class { pub(crate) fn register_window_controller_class<T: WindowDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTWindowController";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSWindowController); unsafe { DELEGATE_CLASS = c };
let mut decl = ClassDecl::new("RSTWindowController", superclass).unwrap(); } else {
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR); INIT.call_once(|| unsafe {
DELEGATE_CLASS = decl.register(); let superclass = class!(NSWindowController);
}); let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(WINDOW_DELEGATE_PTR);
DELEGATE_CLASS = decl.register();
});
}
unsafe { DELEGATE_CLASS } unsafe { DELEGATE_CLASS }
} }

View file

@ -345,12 +345,18 @@ impl Drop for Button {
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTButton";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSButton); unsafe {
let decl = ClassDecl::new("RSTButton", superclass).unwrap(); VIEW_CLASS = c;
VIEW_CLASS = decl.register(); }
}); } else {
INIT.call_once(|| unsafe {
let superclass = class!(NSButton);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -261,107 +261,112 @@ extern "C" fn color_with_system_effect(this: &Object, _: Sel, effect: NSInteger)
pub(crate) fn register_class() -> *const Class { pub(crate) fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "CacaoDynamicColor";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSColor); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("CacaoDynamicColor", superclass).unwrap(); } 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. // These methods all need to be forwarded, so let's hook them up.
decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id); decl.add_method(sel!(colorSpace), color_space as extern "C" fn(&Object, _) -> id);
decl.add_method( decl.add_method(
sel!(colorUsingColorSpace:), sel!(colorUsingColorSpace:),
color_using_color_space as extern "C" fn(&Object, _, id) -> id 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!(colorSpaceName), color_space_name as extern "C" fn(&Object, _) -> id);
decl.add_method( decl.add_method(
sel!(colorUsingColorSpaceName:), sel!(colorUsingColorSpaceName:),
color_using_color_space_name as extern "C" fn(&Object, _, id) -> id color_using_color_space_name as extern "C" fn(&Object, _, id) -> id
); );
decl.add_method( decl.add_method(
sel!(numberOfComponents), sel!(numberOfComponents),
number_of_components as extern "C" fn(&Object, _) -> NSInteger 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!(getComponents:), get_components as extern "C" fn(&Object, _, CGFloat));
decl.add_method( decl.add_method(
sel!(getRed:green:blue:alpha:), sel!(getRed:green:blue:alpha:),
get_rgba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) 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!(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!(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!(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!(hueComponent), hue_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method( decl.add_method(
sel!(saturationComponent), sel!(saturationComponent),
saturation_component as extern "C" fn(&Object, _) -> CGFloat saturation_component as extern "C" fn(&Object, _) -> CGFloat
); );
decl.add_method( decl.add_method(
sel!(brightnessComponent), sel!(brightnessComponent),
brightness_component as extern "C" fn(&Object, _) -> CGFloat brightness_component as extern "C" fn(&Object, _) -> CGFloat
); );
decl.add_method( decl.add_method(
sel!(getHue:saturation:brightness:alpha:), sel!(getHue:saturation:brightness:alpha:),
get_hsba as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat) 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!(whiteComponent), white_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method( decl.add_method(
sel!(getWhite:alpha:), sel!(getWhite:alpha:),
get_white as extern "C" fn(&Object, _, CGFloat, CGFloat) 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!(cyanComponent), cyan_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method( decl.add_method(
sel!(magentaComponent), sel!(magentaComponent),
magenta_component as extern "C" fn(&Object, _) -> CGFloat magenta_component as extern "C" fn(&Object, _) -> CGFloat
); );
decl.add_method( decl.add_method(
sel!(yellowComponent), sel!(yellowComponent),
yellow_component as extern "C" fn(&Object, _) -> CGFloat 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!(blackComponent), black_component as extern "C" fn(&Object, _) -> CGFloat);
decl.add_method( decl.add_method(
sel!(getCyan:magenta:yellow:black:alpha:), sel!(getCyan:magenta:yellow:black:alpha:),
get_cmyk as extern "C" fn(&Object, _, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat) 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!(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!(setStroke), set_stroke as extern "C" fn(&Object, _));
decl.add_method(sel!(setFill), set_fill 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!(set), call_set as extern "C" fn(&Object, _));
decl.add_method( decl.add_method(
sel!(highlightWithLevel:), sel!(highlightWithLevel:),
highlight_with_level as extern "C" fn(&Object, _, CGFloat) -> id highlight_with_level as extern "C" fn(&Object, _, CGFloat) -> id
); );
decl.add_method( decl.add_method(
sel!(shadowWithLevel:), sel!(shadowWithLevel:),
shadow_with_level as extern "C" fn(&Object, _, CGFloat) -> id shadow_with_level as extern "C" fn(&Object, _, CGFloat) -> id
); );
decl.add_method( decl.add_method(
sel!(colorWithAlphaComponent:), sel!(colorWithAlphaComponent:),
color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id color_with_alpha_component as extern "C" fn(&Object, _, CGFloat) -> id
); );
decl.add_method( decl.add_method(
sel!(blendedColorWithFraction:ofColor:), sel!(blendedColorWithFraction:ofColor:),
blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id blended_color as extern "C" fn(&Object, _, CGFloat, id) -> id
); );
decl.add_method( decl.add_method(
sel!(colorWithSystemEffect:), sel!(colorWithSystemEffect:),
color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id color_with_system_effect as extern "C" fn(&Object, _, NSInteger) -> id
); );
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST); decl.add_ivar::<id>(AQUA_LIGHT_COLOR_NORMAL_CONTRAST);
decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST); decl.add_ivar::<id>(AQUA_LIGHT_COLOR_HIGH_CONTRAST);
decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST); decl.add_ivar::<id>(AQUA_DARK_COLOR_NORMAL_CONTRAST);
decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST); decl.add_ivar::<id>(AQUA_DARK_COLOR_HIGH_CONTRAST);
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -25,15 +25,20 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
pub(crate) fn register_image_view_class() -> *const Class { pub(crate) fn register_image_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTImageView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSImageView); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("RSTImageView", superclass).unwrap(); } 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 } unsafe { VIEW_CLASS }
} }

View file

@ -15,12 +15,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
pub(crate) fn register_image_view_class() -> *const Class { pub(crate) fn register_image_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTImageView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIImageView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTImageView", superclass).expect("Failed to get RSTVIEW"); } else {
VIEW_CLASS = decl.register(); 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 } unsafe { VIEW_CLASS }
} }

View file

@ -54,12 +54,17 @@ extern "C" fn text_should_end_editing<T: TextFieldDelegate>(this: &mut Object, _
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTTextInputField";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSTextField); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("RSTTextInputField", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSTextField);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -97,16 +97,23 @@ extern "C" fn perform<F: Fn() + 'static>(this: &mut Object, _: Sel, _sender: id)
pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class { pub(crate) fn register_invoker_class<F: Fn() + 'static>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTTargetActionHandler";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSObject); unsafe {
let mut decl = ClassDecl::new("RSTTargetActionHandler", superclass).unwrap(); VIEW_CLASS = c;
}
} else {
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(ACTION_CALLBACK_PTR); decl.add_ivar::<usize>(ACTION_CALLBACK_PTR);
decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id)); decl.add_method(sel!(perform:), perform::<F> as extern "C" fn(&mut Object, _, id));
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -187,12 +187,17 @@ extern "C" fn dragging_exited<T: ListViewDelegate>(this: &mut Object, _: Sel, in
pub(crate) fn register_listview_class() -> *const Class { pub(crate) fn register_listview_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &'static str = "RSTListView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSTableView); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("RSTListView", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSTableView);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -109,15 +109,20 @@ extern "C" fn dealloc<T: ViewDelegate>(this: &Object, _: Sel) {
pub(crate) fn register_listview_row_class() -> *const Class { pub(crate) fn register_listview_row_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTTableViewRow";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTTableViewRow", superclass).unwrap(); } 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 } 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<T: ViewDelegate>() -> *const Class { pub(crate) fn register_listview_row_class_with_delegate<T: ViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTableViewRowWithDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTableViewRowWithDelegate", superclass).unwrap(); } 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 // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR); decl.add_ivar::<usize>(LISTVIEW_ROW_DELEGATE_PTR);
decl.add_ivar::<id>(BACKGROUND_COLOR); decl.add_ivar::<id>(BACKGROUND_COLOR);
decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); decl.add_method(sel!(isFlipped), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _)); decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
// Drag and drop operations (e.g, accepting files) // Drag and drop operations (e.g, accepting files)
decl.add_method( decl.add_method(
sel!(draggingEntered:), sel!(draggingEntered:),
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
); );
decl.add_method( decl.add_method(
sel!(prepareForDragOperation:), sel!(prepareForDragOperation:),
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(performDragOperation:), sel!(performDragOperation:),
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(concludeDragOperation:), sel!(concludeDragOperation:),
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _) conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(draggingExited:), sel!(draggingExited:),
dragging_exited::<T> as extern "C" fn(&mut Object, _, _) dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
); );
// Cleanup // Cleanup
decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _)); decl.add_method(sel!(dealloc), dealloc::<T> as extern "C" fn(&Object, _));
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -16,12 +16,17 @@ use crate::utils::load;
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(UIView);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }
@ -31,15 +36,18 @@ pub(crate) fn register_view_class() -> *const Class {
pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class { pub(crate) fn register_view_class_with_delegate<T: ViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTViewWithDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTViewWithDelegate", superclass).unwrap(); } else {
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR); INIT.call_once(|| unsafe {
VIEW_CLASS = decl.register(); let superclass = class!(UIView);
}); let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
unsafe { VIEW_CLASS = decl.register();
VIEW_CLASS });
} }
unsafe { VIEW_CLASS }
} }

View file

@ -79,12 +79,17 @@ extern "C" fn dragging_exited<T: ScrollViewDelegate>(this: &mut Object, _: Sel,
pub(crate) fn register_scrollview_class() -> *const Class { pub(crate) fn register_scrollview_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &'static str = "RSTScrollView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSScrollView); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("RSTScrollView", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSScrollView);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }
@ -94,41 +99,46 @@ pub(crate) fn register_scrollview_class() -> *const Class {
pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class { pub(crate) fn register_scrollview_class_with_delegate<T: ScrollViewDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &'static str = "RSTScrollViewWithDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSScrollView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTScrollViewWithDelegate", superclass).unwrap(); } 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 // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR); decl.add_ivar::<usize>(SCROLLVIEW_DELEGATE_PTR);
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) // Drag and drop operations (e.g, accepting files)
decl.add_method( decl.add_method(
sel!(draggingEntered:), sel!(draggingEntered:),
dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger dragging_entered::<T> as extern "C" fn(&mut Object, _, _) -> NSUInteger
); );
decl.add_method( decl.add_method(
sel!(prepareForDragOperation:), sel!(prepareForDragOperation:),
prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL prepare_for_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(performDragOperation:), sel!(performDragOperation:),
perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL perform_drag_operation::<T> as extern "C" fn(&mut Object, _, _) -> BOOL
); );
decl.add_method( decl.add_method(
sel!(concludeDragOperation:), sel!(concludeDragOperation:),
conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _) conclude_drag_operation::<T> as extern "C" fn(&mut Object, _, _)
); );
decl.add_method( decl.add_method(
sel!(draggingExited:), sel!(draggingExited:),
dragging_exited::<T> as extern "C" fn(&mut Object, _, _) dragging_exited::<T> as extern "C" fn(&mut Object, _, _)
); );
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -270,12 +270,17 @@ impl Drop for Select {
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "CacaoSelect";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSPopUpButton); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("CacaoSelect", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSPopUpButton);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -180,12 +180,19 @@ impl Drop for Switch {
fn register_class() -> *const Class { fn register_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTSwitch";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSButton); unsafe {
let decl = ClassDecl::new("RSTSwitch", superclass).unwrap(); VIEW_CLASS = c;
VIEW_CLASS = decl.register(); }
}); } else {
INIT.call_once(|| unsafe {
let superclass = class!(NSButton);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -25,12 +25,17 @@ use crate::utils::load;
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTTextField";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSTextField); unsafe { VIEW_CLASS = c };
let decl = ClassDecl::new("RSTTextField", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(NSTextField);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }
@ -40,17 +45,22 @@ pub(crate) fn register_view_class() -> *const Class {
pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class { pub(crate) fn register_view_class_with_delegate<T: LabelDelegate>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTTextFieldWithDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTTextFieldWithDelegate", superclass).unwrap(); } 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 // A pointer to the "view controller" on the Rust side. It's expected that this doesn't
// move. // move.
decl.add_ivar::<usize>(LABEL_DELEGATE_PTR); decl.add_ivar::<usize>(LABEL_DELEGATE_PTR);
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -12,12 +12,17 @@ use objc::runtime::Class;
pub(crate) fn register_app_class() -> *const Class { pub(crate) fn register_app_class() -> *const Class {
static mut APP_CLASS: *const Class = 0 as *const Class; static mut APP_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTApplication";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIApplication); unsafe { APP_CLASS = c };
let decl = ClassDecl::new("RSTApplication", superclass).unwrap(); } else {
APP_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(UIApplication);
let decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
APP_CLASS = decl.register();
});
}
unsafe { APP_CLASS } unsafe { APP_CLASS }
} }

View file

@ -51,29 +51,34 @@ extern "C" fn configuration_for_scene_session<T: AppDelegate>(this: &Object, _:
pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class { pub(crate) fn register_app_delegate_class<T: AppDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTAppDelegate";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSObject); unsafe { DELEGATE_CLASS = c };
let mut decl = ClassDecl::new("RSTAppDelegate", superclass).unwrap(); } else {
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
// Launching Applications // Launching Applications
decl.add_method( decl.add_method(
sel!(application:didFinishLaunchingWithOptions:), sel!(application:didFinishLaunchingWithOptions:),
did_finish_launching::<T> as extern "C" fn(&Object, _, _, id) -> BOOL did_finish_launching::<T> as extern "C" fn(&Object, _, _, id) -> BOOL
); );
// Scenes // Scenes
decl.add_method( decl.add_method(
sel!(application:configurationForConnectingSceneSession:options:), sel!(application:configurationForConnectingSceneSession:options:),
configuration_for_scene_session::<T> as extern "C" fn(&Object, _, _, id, id) -> id configuration_for_scene_session::<T> as extern "C" fn(&Object, _, _, id, id) -> id
); );
/*decl.add_method( /*decl.add_method(
sel!(application:didDiscardSceneSessions:), sel!(application:didDiscardSceneSessions:),
did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id) did_discard_scene_sessions::<T> as extern "C" fn(&Object, _, _, id)
);*/ );*/
DELEGATE_CLASS = decl.register(); DELEGATE_CLASS = decl.register();
}); });
}
unsafe { DELEGATE_CLASS } unsafe { DELEGATE_CLASS }
} }

View file

@ -62,30 +62,35 @@ extern "C" fn scene_will_connect_to_session_with_options<T: WindowSceneDelegate>
pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class { pub(crate) fn register_window_scene_delegate_class<T: WindowSceneDelegate, F: Fn() -> Box<T>>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class; static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTWindowSceneDelegate";
use objc::runtime::{class_addProtocol, Protocol}; if let Some(c) = Class::get(CLASS_NAME) {
INIT.call_once(|| unsafe { unsafe { DELEGATE_CLASS = c };
let superclass = class!(UIResponder); } else {
let mut decl = ClassDecl::new("RSTWindowSceneDelegate", superclass).unwrap(); 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 // A spot to hold a pointer to
decl.add_ivar::<usize>(WINDOW_SCENE_PTR); decl.add_ivar::<usize>(WINDOW_SCENE_PTR);
decl.add_protocol(p); decl.add_protocol(p);
// Override the `init` call to handle creating and attaching a WindowSceneDelegate. // Override the `init` call to handle creating and attaching a WindowSceneDelegate.
decl.add_method(sel!(init), init::<T, F> as extern "C" fn(&mut Object, _) -> id); decl.add_method(sel!(init), init::<T, F> as extern "C" fn(&mut Object, _) -> id);
// UIWindowSceneDelegate API // UIWindowSceneDelegate API
decl.add_method( decl.add_method(
sel!(scene:willConnectToSession:options:), sel!(scene:willConnectToSession:options:),
scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _) scene_will_connect_to_session_with_options::<T> as extern "C" fn(&Object, _, _, _, _)
); );
// Launching Applications // Launching Applications
DELEGATE_CLASS = decl.register(); DELEGATE_CLASS = decl.register();
}); });
}
unsafe { DELEGATE_CLASS } unsafe { DELEGATE_CLASS }
} }

View file

@ -94,19 +94,24 @@ extern "C" fn update_layer(this: &Object, _: Sel) {
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(NSView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); } 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);
decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _)); decl.add_method(sel!(updateLayer), update_layer as extern "C" fn(&Object, _));
decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL); decl.add_method(sel!(wantsUpdateLayer), enforce_normalcy as extern "C" fn(&Object, _) -> BOOL);
decl.add_ivar::<id>(BACKGROUND_COLOR); decl.add_ivar::<id>(BACKGROUND_COLOR);
VIEW_CLASS = decl.register(); VIEW_CLASS = decl.register();
}); });
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -53,20 +53,30 @@ extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel, animated
pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>() -> *const Class { pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTViewController";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIViewController); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTViewController", superclass).unwrap(); } else {
INIT.call_once(|| unsafe {
let superclass = class!(UIViewController);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR); decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(sel!(viewWillAppear:), will_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(sel!(viewDidAppear:), did_appear::<T> as extern "C" fn(&mut Object, _, BOOL));
decl.add_method(sel!(viewWillDisappear:), will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)); decl.add_method(
decl.add_method(sel!(viewDidDisappear:), did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)); sel!(viewWillDisappear:),
will_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
VIEW_CLASS = decl.register(); );
}); decl.add_method(
sel!(viewDidDisappear:),
did_disappear::<T> as extern "C" fn(&mut Object, _, BOOL)
);
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -16,12 +16,17 @@ use crate::view::{ViewDelegate, VIEW_DELEGATE_PTR};
pub(crate) fn register_view_class() -> *const Class { pub(crate) fn register_view_class() -> *const Class {
static mut VIEW_CLASS: *const Class = 0 as *const Class; static mut VIEW_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTView";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = class!(UIView); unsafe { VIEW_CLASS = c };
let mut decl = ClassDecl::new("RSTView", superclass).unwrap(); } else {
VIEW_CLASS = decl.register(); INIT.call_once(|| unsafe {
}); let superclass = class!(UIView);
let mut decl = ClassDecl::new(CLASS_NAME, superclass).unwrap();
VIEW_CLASS = decl.register();
});
}
unsafe { VIEW_CLASS } unsafe { VIEW_CLASS }
} }

View file

@ -28,17 +28,22 @@ extern "C" fn download_delegate(this: &Object, _: Sel) -> id {
pub fn register_process_pool() -> *const Object { pub fn register_process_pool() -> *const Object {
static mut PROCESS_POOL: *const Object = 0 as *const Object; static mut PROCESS_POOL: *const Object = 0 as *const Object;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
const CLASS_NAME: &str = "RSTWebViewProcessPool";
INIT.call_once(|| unsafe { if let Some(c) = Class::get(CLASS_NAME) {
let superclass = Class::get("WKProcessPool").unwrap(); unsafe { PROCESS_POOL = c };
let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap(); } else {
INIT.call_once(|| unsafe {
let superclass = Class::get("WKProcessPool").unwrap();
let mut decl = ClassDecl::new("RSTWebViewProcessPool", superclass).unwrap();
//decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR); //decl.add_ivar::<id>(DOWNLOAD_DELEGATE_PTR);
decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id); decl.add_method(sel!(_downloadDelegate), download_delegate as extern "C" fn(&Object, _) -> id);
//PROCESS_POOL = decl.register(); //PROCESS_POOL = decl.register();
PROCESS_POOL = msg_send![decl.register(), new]; PROCESS_POOL = msg_send![decl.register(), new];
}); });
}
unsafe { PROCESS_POOL } unsafe { PROCESS_POOL }
} }