aboutsummaryrefslogtreecommitdiff
path: root/core/sys/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'core/sys/darwin')
-rw-r--r--core/sys/darwin/Foundation/NSApplication.odin609
-rw-r--r--core/sys/darwin/Foundation/NSArray.odin42
-rw-r--r--core/sys/darwin/Foundation/NSAutoreleasePool.odin33
-rw-r--r--core/sys/darwin/Foundation/NSBlock.odin120
-rw-r--r--core/sys/darwin/Foundation/NSBundle.odin191
-rw-r--r--core/sys/darwin/Foundation/NSColor.odin149
-rw-r--r--core/sys/darwin/Foundation/NSData.odin24
-rw-r--r--core/sys/darwin/Foundation/NSDate.odin19
-rw-r--r--core/sys/darwin/Foundation/NSDictionary.odin50
-rw-r--r--core/sys/darwin/Foundation/NSEnumerator.odin50
-rw-r--r--core/sys/darwin/Foundation/NSError.odin88
-rw-r--r--core/sys/darwin/Foundation/NSEvent.odin466
-rw-r--r--core/sys/darwin/Foundation/NSLock.odin53
-rw-r--r--core/sys/darwin/Foundation/NSMenu.odin103
-rw-r--r--core/sys/darwin/Foundation/NSNotification.odin60
-rw-r--r--core/sys/darwin/Foundation/NSNumber.odin154
-rw-r--r--core/sys/darwin/Foundation/NSObject.odin91
-rw-r--r--core/sys/darwin/Foundation/NSOpenPanel.odin31
-rw-r--r--core/sys/darwin/Foundation/NSPanel.odin9
-rw-r--r--core/sys/darwin/Foundation/NSPasteboard.odin5
-rw-r--r--core/sys/darwin/Foundation/NSRange.odin22
-rw-r--r--core/sys/darwin/Foundation/NSSavePanel.odin9
-rw-r--r--core/sys/darwin/Foundation/NSScreen.odin33
-rw-r--r--core/sys/darwin/Foundation/NSSet.odin27
-rw-r--r--core/sys/darwin/Foundation/NSString.odin140
-rw-r--r--core/sys/darwin/Foundation/NSTypes.odin61
-rw-r--r--core/sys/darwin/Foundation/NSURL.odin30
-rw-r--r--core/sys/darwin/Foundation/NSUndoManager.odin5
-rw-r--r--core/sys/darwin/Foundation/NSUserActivity.odin5
-rw-r--r--core/sys/darwin/Foundation/NSUserDefaults.odin14
-rw-r--r--core/sys/darwin/Foundation/NSWindow.odin714
-rw-r--r--core/sys/darwin/Foundation/objc.odin81
32 files changed, 3488 insertions, 0 deletions
diff --git a/core/sys/darwin/Foundation/NSApplication.odin b/core/sys/darwin/Foundation/NSApplication.odin
new file mode 100644
index 000000000..d332345f9
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSApplication.odin
@@ -0,0 +1,609 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+
+import "base:intrinsics"
+import "base:runtime"
+import "core:strings"
+
+RunLoopMode :: ^String
+
+@(link_prefix="NS")
+foreign Foundation {
+ RunLoopCommonModes: RunLoopMode
+ DefaultRunLoopMode: RunLoopMode
+ EventTrackingRunLoopMode: RunLoopMode
+ ModalPanelRunLoopMode: RunLoopMode
+}
+
+ActivationPolicy :: enum UInteger {
+ Regular = 0,
+ Accessory = 1,
+ Prohibited = 2,
+}
+
+ApplicationTerminateReply :: enum UInteger {
+ TerminateCancel = 0,
+ TerminateNow = 1,
+ TerminateLater = 2,
+}
+
+ApplicationPrintReply :: enum UInteger {
+ PrintingCancelled = 0,
+ PrintingSuccess = 1,
+ PrintingReplyLater = 2,
+ PrintingFailure = 3,
+}
+
+ApplicationPresentationOptionFlag :: enum UInteger {
+ AutoHideDock = 0,
+ HideDock = 1,
+ AutoHideMenuBar = 2,
+ HideMenuBar = 3,
+ DisableAppleMenu = 4,
+ DisableProcessSwitching = 5,
+ DisableForceQuit = 6,
+ DisableSessionTermination = 7,
+ DisableHideApplication = 8,
+ DisableMenuBarTransparency = 9,
+ FullScreen = 10,
+ AutoHideToolbar = 11,
+ DisableCursorLocationAssistance = 12,
+}
+ApplicationPresentationOptions :: distinct bit_set[ApplicationPresentationOptionFlag; UInteger]
+ApplicationPresentationOptionsDefault :: ApplicationPresentationOptions {}
+ApplicationPresentationOptionsAutoHideDock :: ApplicationPresentationOptions {.AutoHideDock}
+ApplicationPresentationOptionsHideDock :: ApplicationPresentationOptions {.HideDock}
+ApplicationPresentationOptionsAutoHideMenuBar :: ApplicationPresentationOptions {.AutoHideMenuBar}
+ApplicationPresentationOptionsHideMenuBar :: ApplicationPresentationOptions {.HideMenuBar}
+ApplicationPresentationOptionsDisableAppleMenu :: ApplicationPresentationOptions {.DisableAppleMenu}
+ApplicationPresentationOptionsDisableProcessSwitching :: ApplicationPresentationOptions {.DisableProcessSwitching}
+ApplicationPresentationOptionsDisableForceQuit :: ApplicationPresentationOptions {.DisableForceQuit}
+ApplicationPresentationOptionsDisableSessionTermination :: ApplicationPresentationOptions {.DisableSessionTermination}
+ApplicationPresentationOptionsDisableHideApplication :: ApplicationPresentationOptions {.DisableHideApplication}
+ApplicationPresentationOptionsDisableMenuBarTransparency :: ApplicationPresentationOptions {.DisableMenuBarTransparency}
+ApplicationPresentationOptionsFullScreen :: ApplicationPresentationOptions {.FullScreen}
+ApplicationPresentationOptionsAutoHideToolbar :: ApplicationPresentationOptions {.AutoHideToolbar}
+ApplicationPresentationOptionsDisableCursorLocationAssistance :: ApplicationPresentationOptions {.DisableCursorLocationAssistance}
+
+@(objc_class="NSApplication")
+Application :: struct {using _: Object}
+
+@(objc_type=Application, objc_name="sharedApplication", objc_is_class_method=true)
+Application_sharedApplication :: proc "c" () -> ^Application {
+ return msgSend(^Application, Application, "sharedApplication")
+}
+
+@(objc_type=Application, objc_name="setActivationPolicy")
+Application_setActivationPolicy :: proc "c" (self: ^Application, activationPolicy: ActivationPolicy) -> BOOL {
+ return msgSend(BOOL, self, "setActivationPolicy:", activationPolicy)
+}
+
+@(deprecated="Use NSApplication method activate instead.")
+@(objc_type=Application, objc_name="activateIgnoringOtherApps")
+Application_activateIgnoringOtherApps :: proc "c" (self: ^Application, ignoreOtherApps: BOOL) {
+ msgSend(nil, self, "activateIgnoringOtherApps:", ignoreOtherApps)
+}
+
+@(objc_type=Application, objc_name="activate")
+Application_activate :: proc "c" (self: ^Application) {
+ msgSend(nil, self, "activate")
+}
+
+@(objc_type=Application, objc_name="setTitle")
+Application_setTitle :: proc "c" (self: ^Application, title: ^String) {
+ msgSend(nil, self, "setTitle", title)
+}
+
+@(objc_type=Application, objc_name="setMainMenu")
+Application_setMainMenu :: proc "c" (self: ^Application, menu: ^Menu) {
+ msgSend(nil, self, "setMainMenu:", menu)
+}
+
+@(objc_type=Application, objc_name="windows")
+Application_windows :: proc "c" (self: ^Application) -> ^Array {
+ return msgSend(^Array, self, "windows")
+}
+
+@(objc_type=Application, objc_name="run")
+Application_run :: proc "c" (self: ^Application) {
+ msgSend(nil, self, "run")
+}
+
+@(objc_type=Application, objc_name="terminate")
+Application_terminate :: proc "c" (self: ^Application, sender: ^Object) {
+ msgSend(nil, self, "terminate:", sender)
+}
+
+@(objc_type=Application, objc_name="isRunning")
+Application_isRunning :: proc "c" (self: ^Application) -> BOOL {
+ return msgSend(BOOL, self, "isRunning")
+}
+
+@(objc_type=Application, objc_name="currentEvent")
+Application_currentEvent :: proc "c" (self: ^Application) -> ^Event {
+ return msgSend(^Event, self, "currentEvent")
+}
+
+@(objc_type=Application, objc_name="nextEventMatchingMask")
+Application_nextEventMatchingMask :: proc "c" (self: ^Application, mask: EventMask, expiration: ^Date, in_mode: RunLoopMode, dequeue: BOOL) -> ^Event {
+ return msgSend(^Event, self, "nextEventMatchingMask:untilDate:inMode:dequeue:", mask, expiration, in_mode, dequeue)
+}
+
+@(objc_type=Application, objc_name="sendEvent")
+Application_sendEvent :: proc "c" (self: ^Application, event: ^Event) {
+ msgSend(Event, self, "sendEvent:", event)
+}
+@(objc_type=Application, objc_name="updateWindows")
+Application_updateWindows :: proc "c" (self: ^Application) {
+ msgSend(nil, self, "updateWindows")
+}
+
+
+@(objc_class="NSRunningApplication")
+RunningApplication :: struct {using _: Object}
+
+@(objc_type=RunningApplication, objc_name="currentApplication", objc_is_class_method=true)
+RunningApplication_currentApplication :: proc "c" () -> ^RunningApplication {
+ return msgSend(^RunningApplication, RunningApplication, "currentApplication")
+}
+
+@(objc_type=RunningApplication, objc_name="localizedName")
+RunningApplication_localizedName :: proc "c" (self: ^RunningApplication) -> ^String {
+ return msgSend(^String, self, "localizedName")
+}
+
+ApplicationDelegateTemplate :: struct {
+ // Launching Applications
+ applicationWillFinishLaunching: proc(notification: ^Notification),
+ applicationDidFinishLaunching: proc(notification: ^Notification),
+ // Managing Active Status
+ applicationWillBecomeActive: proc(notification: ^Notification),
+ applicationDidBecomeActive: proc(notification: ^Notification),
+ applicationWillResignActive: proc(notification: ^Notification),
+ applicationDidResignActive: proc(notification: ^Notification),
+ // Terminating Applications
+ applicationShouldTerminate: proc(sender: ^Application) -> ApplicationTerminateReply,
+ applicationShouldTerminateAfterLastWindowClosed: proc(sender: ^Application) -> BOOL,
+ applicationWillTerminate: proc(notification: ^Notification),
+ // Hiding Applications
+ applicationWillHide: proc(notification: ^Notification),
+ applicationDidHide: proc(notification: ^Notification),
+ applicationWillUnhide: proc(notification: ^Notification),
+ applicationDidUnhide: proc(notification: ^Notification),
+ // Managing Windows
+ applicationWillUpdate: proc(notification: ^Notification),
+ applicationDidUpdate: proc(notification: ^Notification),
+ applicationShouldHandleReopenHasVisibleWindows: proc(sender: ^Application, flag: BOOL) -> BOOL,
+ // Managing the Dock Menu
+ applicationDockMenu: proc(sender: ^Application) -> ^Menu,
+ // Localizing Keyboard Shortcuts
+ applicationShouldAutomaticallyLocalizeKeyEquivalents: proc(application: ^Application) -> BOOL,
+ // Displaying Errors
+ applicationWillPresentError: proc(application: ^Application, error: ^Error) -> ^Error,
+ // Managing the Screen
+ applicationDidChangeScreenParameters: proc(notification: ^Notification),
+ // Continuing User Activities
+ applicationWillContinueUserActivityWithType: proc(application: ^Application, userActivityType: ^String) -> BOOL,
+ applicationContinueUserActivityRestorationHandler: proc(application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL,
+ applicationDidFailToContinueUserActivityWithTypeError: proc(application: ^Application, userActivityType: ^String, error: ^Error),
+ applicationDidUpdateUserActivity: proc(application: ^Application, userActivity: ^UserActivity),
+ // Handling Push Notifications
+ applicationDidRegisterForRemoteNotificationsWithDeviceToken: proc(application: ^Application, deviceToken: ^Data),
+ applicationDidFailToRegisterForRemoteNotificationsWithError: proc(application: ^Application, error: ^Error),
+ applicationDidReceiveRemoteNotification: proc(application: ^Application, userInfo: ^Dictionary),
+ // Handling CloudKit Invitations
+ // TODO: if/when we have cloud kit bindings implement
+ // applicationUserDidAcceptCloudKitShareWithMetadata: proc(application: ^Application, metadata: ^CKShareMetadata),
+ // Handling SiriKit Intents
+ // TODO: if/when we have siri kit bindings implement
+ // applicationHandlerForIntent: proc(application: ^Application, intent: ^INIntent) -> id,
+ // Opening Files
+ applicationOpenURLs: proc(application: ^Application, urls: ^Array),
+ applicationOpenFile: proc(sender: ^Application, filename: ^String) -> BOOL,
+ applicationOpenFileWithoutUI: proc(sender: id, filename: ^String) -> BOOL,
+ applicationOpenTempFile: proc(sender: ^Application, filename: ^String) -> BOOL,
+ applicationOpenFiles: proc(sender: ^Application, filenames: ^Array),
+ applicationShouldOpenUntitledFile: proc(sender: ^Application) -> BOOL,
+ applicationOpenUntitledFile: proc(sender: ^Application) -> BOOL,
+ // Printing
+ applicationPrintFile: proc(sender: ^Application, filename: ^String) -> BOOL,
+ applicationPrintFilesWithSettingsShowPrintPanels: proc(application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply,
+ // Restoring Application State
+ applicationSupportsSecureRestorableState: proc(app: ^Application) -> BOOL,
+ applicationProtectedDataDidBecomeAvailable: proc(notification: ^Notification),
+ applicationProtectedDataWillBecomeUnavailable: proc(notification: ^Notification),
+ applicationWillEncodeRestorableState: proc(app: ^Application, coder: ^Coder),
+ applicationDidDecodeRestorableState: proc(app: ^Application, coder: ^Coder),
+ // Handling Changes to the Occlusion State
+ applicationDidChangeOcclusionState: proc(notification: ^Notification),
+ // Scripting Your App
+ applicationDelegateHandlesKey: proc(sender: ^Application, key: ^String) -> BOOL,
+}
+
+ApplicationDelegate :: struct { using _: Object }
+_ApplicationDelegateInternal :: struct {
+ using _: ApplicationDelegateTemplate,
+ _context: runtime.Context,
+}
+
+application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTemplate, class_name: string, delegate_context: Maybe(runtime.Context)) -> ^ApplicationDelegate {
+ class := objc_allocateClassPair(intrinsics.objc_find_class("NSObject"), strings.clone_to_cstring(class_name, context.temp_allocator), 0); if class == nil {
+ // Class already registered
+ return nil
+ }
+ if template.applicationWillFinishLaunching != nil {
+ applicationWillFinishLaunching :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillFinishLaunching(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillFinishLaunching:"), auto_cast applicationWillFinishLaunching, "v@:@")
+ }
+ if template.applicationDidFinishLaunching != nil {
+ applicationDidFinishLaunching :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidFinishLaunching(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidFinishLaunching:"), auto_cast applicationDidFinishLaunching, "v@:@")
+ }
+ if template.applicationWillBecomeActive != nil {
+ applicationWillBecomeActive :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillBecomeActive(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillBecomeActive:"), auto_cast applicationWillBecomeActive, "v@:@")
+ }
+ if template.applicationDidBecomeActive != nil {
+ applicationDidBecomeActive :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidBecomeActive(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidBecomeActive:"), auto_cast applicationDidBecomeActive, "v@:@")
+ }
+ if template.applicationWillResignActive != nil {
+ applicationWillResignActive :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillResignActive(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillResignActive:"), auto_cast applicationWillResignActive, "v@:@")
+ }
+ if template.applicationDidResignActive != nil {
+ applicationDidResignActive :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidResignActive(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidResignActive:"), auto_cast applicationDidResignActive, "v@:@")
+ }
+ if template.applicationShouldTerminate != nil {
+ applicationShouldTerminate :: proc "c" (self: id, sender: ^Application) -> ApplicationTerminateReply {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationShouldTerminate(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminate:"), auto_cast applicationShouldTerminate, _UINTEGER_ENCODING+"@:@")
+ }
+ if template.applicationShouldTerminateAfterLastWindowClosed != nil {
+ applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, sender: ^Application) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationShouldTerminateAfterLastWindowClosed(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast applicationShouldTerminateAfterLastWindowClosed, "B@:@")
+ }
+ if template.applicationWillTerminate != nil {
+ applicationWillTerminate :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillTerminate(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillTerminate:"), auto_cast applicationWillTerminate, "v@:@")
+ }
+ if template.applicationWillHide != nil {
+ applicationWillHide :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillHide(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillHide:"), auto_cast applicationWillHide, "v@:@")
+ }
+ if template.applicationDidHide != nil {
+ applicationDidHide :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidHide(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidHide:"), auto_cast applicationDidHide, "v@:@")
+ }
+ if template.applicationWillUnhide != nil {
+ applicationWillUnhide :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillUnhide(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillUnhide:"), auto_cast applicationWillUnhide, "v@:@")
+ }
+ if template.applicationDidUnhide != nil {
+ applicationDidUnhide :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidUnhide(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidUnhide:"), auto_cast applicationDidUnhide, "v@:@")
+ }
+ if template.applicationWillUpdate != nil {
+ applicationWillUpdate :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillUpdate(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationWillUpdate:"), auto_cast applicationWillUpdate, "v@:@")
+ }
+ if template.applicationDidUpdate != nil {
+ applicationDidUpdate :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidUpdate(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidUpdate:"), auto_cast applicationDidUpdate, "v@:@")
+ }
+ if template.applicationShouldHandleReopenHasVisibleWindows != nil {
+ applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, sender: ^Application, flag: BOOL) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationShouldHandleReopenHasVisibleWindows(sender, flag)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationShouldHandleReopen:hasVisibleWindows:"), auto_cast applicationShouldHandleReopenHasVisibleWindows, "B@:@B")
+ }
+ if template.applicationDockMenu != nil {
+ applicationDockMenu :: proc "c" (self: id, sender: ^Application) -> ^Menu {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationDockMenu(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDockMenu:"), auto_cast applicationDockMenu, "@@:@")
+ }
+ if template.applicationShouldAutomaticallyLocalizeKeyEquivalents != nil {
+ applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, application: ^Application) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationShouldAutomaticallyLocalizeKeyEquivalents(application)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationShouldAutomaticallyLocalizeKeyEquivalents:"), auto_cast applicationShouldAutomaticallyLocalizeKeyEquivalents, "B@:@")
+ }
+ if template.applicationWillPresentError != nil {
+ applicationWillPresentError :: proc "c" (self: id, application: ^Application, error: ^Error) -> ^Error {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationWillPresentError(application, error)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:willPresentError:"), auto_cast applicationWillPresentError, "@@:@@")
+ }
+ if template.applicationDidChangeScreenParameters != nil {
+ applicationDidChangeScreenParameters :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidChangeScreenParameters(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeScreenParameters:"), auto_cast applicationDidChangeScreenParameters, "v@:@")
+ }
+ if template.applicationWillContinueUserActivityWithType != nil {
+ applicationWillContinueUserActivityWithType :: proc "c" (self: id, application: ^Application, userActivityType: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationWillContinueUserActivityWithType(application, userActivityType)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:willContinueUserActivityWithType:"), auto_cast applicationWillContinueUserActivityWithType, "B@:@@")
+ }
+ if template.applicationContinueUserActivityRestorationHandler != nil {
+ applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationContinueUserActivityRestorationHandler(application, userActivity, restorationHandler)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:continueUserActivity:restorationHandler:"), auto_cast applicationContinueUserActivityRestorationHandler, "B@:@@?")
+ }
+ if template.applicationDidFailToContinueUserActivityWithTypeError != nil {
+ applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, application: ^Application, userActivityType: ^String, error: ^Error) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidFailToContinueUserActivityWithTypeError(application, userActivityType, error)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didFailToContinueUserActivityWithType:error:"), auto_cast applicationDidFailToContinueUserActivityWithTypeError, "v@:@@@")
+ }
+ if template.applicationDidUpdateUserActivity != nil {
+ applicationDidUpdateUserActivity :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidUpdateUserActivity(application, userActivity)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didUpdateUserActivity:"), auto_cast applicationDidUpdateUserActivity, "v@:@@")
+ }
+ if template.applicationDidRegisterForRemoteNotificationsWithDeviceToken != nil {
+ applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, application: ^Application, deviceToken: ^Data) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidRegisterForRemoteNotificationsWithDeviceToken(application, deviceToken)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didRegisterForRemoteNotificationsWithDeviceToken:"), auto_cast applicationDidRegisterForRemoteNotificationsWithDeviceToken, "v@:@@")
+ }
+ if template.applicationDidFailToRegisterForRemoteNotificationsWithError != nil {
+ applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, application: ^Application, error: ^Error) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidFailToRegisterForRemoteNotificationsWithError(application, error)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didFailToRegisterForRemoteNotificationsWithError:"), auto_cast applicationDidFailToRegisterForRemoteNotificationsWithError, "v@:@@")
+ }
+ if template.applicationDidReceiveRemoteNotification != nil {
+ applicationDidReceiveRemoteNotification :: proc "c" (self: id, application: ^Application, userInfo: ^Dictionary) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidReceiveRemoteNotification(application, userInfo)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didReceiveRemoteNotification:"), auto_cast applicationDidReceiveRemoteNotification, "v@:@@")
+ }
+ // if template.applicationUserDidAcceptCloudKitShareWithMetadata != nil {
+ // applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, application: ^Application, metadata: ^CKShareMetadata) {
+ // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ // context = del._context
+ // del.applicationUserDidAcceptCloudKitShareWithMetadata(application, metadata)
+ // }
+ // class_addMethod(class, intrinsics.objc_find_selector("application:userDidAcceptCloudKitShareWithMetadata:"), auto_cast applicationUserDidAcceptCloudKitShareWithMetadata, "v@:@@")
+ // }
+ // if template.applicationHandlerForIntent != nil {
+ // applicationHandlerForIntent :: proc "c" (self: id, application: ^Application, intent: ^INIntent) -> id {
+ // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ // context = del._context
+ // return del.applicationHandlerForIntent(application, intent)
+ // }
+ // class_addMethod(class, intrinsics.objc_find_selector("application:handlerForIntent:"), auto_cast applicationHandlerForIntent, "@@:@@")
+ // }
+ if template.applicationOpenURLs != nil {
+ applicationOpenURLs :: proc "c" (self: id, application: ^Application, urls: ^Array) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationOpenURLs(application, urls)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:openURLs:"), auto_cast applicationOpenURLs, "v@:@@")
+ }
+ if template.applicationOpenFile != nil {
+ applicationOpenFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationOpenFile(sender, filename)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:openFile:"), auto_cast applicationOpenFile, "B@:@@")
+ }
+ if template.applicationOpenFileWithoutUI != nil {
+ applicationOpenFileWithoutUI :: proc "c" (self: id, sender: id, filename: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationOpenFileWithoutUI(sender, filename)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:openFileWithoutUI:"), auto_cast applicationOpenFileWithoutUI, "B@:@@")
+ }
+ if template.applicationOpenTempFile != nil {
+ applicationOpenTempFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationOpenTempFile(sender, filename)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:openTempFile:"), auto_cast applicationOpenTempFile, "B@:@@")
+ }
+ if template.applicationOpenFiles != nil {
+ applicationOpenFiles :: proc "c" (self: id, sender: ^Application, filenames: ^Array) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationOpenFiles(sender, filenames)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:openFiles:"), auto_cast applicationOpenFiles, "v@:@@")
+ }
+ if template.applicationShouldOpenUntitledFile != nil {
+ applicationShouldOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationShouldOpenUntitledFile(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationShouldOpenUntitledFile:"), auto_cast applicationShouldOpenUntitledFile, "B@:@")
+ }
+ if template.applicationOpenUntitledFile != nil {
+ applicationOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationOpenUntitledFile(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationOpenUntitledFile:"), auto_cast applicationOpenUntitledFile, "B@:@")
+ }
+ if template.applicationPrintFile != nil {
+ applicationPrintFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationPrintFile(sender, filename)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:printFile:"), auto_cast applicationPrintFile, "B@:@@")
+ }
+ if template.applicationPrintFilesWithSettingsShowPrintPanels != nil {
+ applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationPrintFilesWithSettingsShowPrintPanels(application, fileNames, printSettings, showPrintPanels)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:printFiles:withSettings:showPrintPanels:"), auto_cast applicationPrintFilesWithSettingsShowPrintPanels, _UINTEGER_ENCODING+"@:@@@B")
+ }
+ if template.applicationSupportsSecureRestorableState != nil {
+ applicationSupportsSecureRestorableState :: proc "c" (self: id, app: ^Application) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationSupportsSecureRestorableState(app)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationSupportsSecureRestorableState:"), auto_cast applicationSupportsSecureRestorableState, "B@:@")
+ }
+ if template.applicationProtectedDataDidBecomeAvailable != nil {
+ applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationProtectedDataDidBecomeAvailable(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataDidBecomeAvailable:"), auto_cast applicationProtectedDataDidBecomeAvailable, "v@:@")
+ }
+ if template.applicationProtectedDataWillBecomeUnavailable != nil {
+ applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationProtectedDataWillBecomeUnavailable(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataWillBecomeUnavailable:"), auto_cast applicationProtectedDataWillBecomeUnavailable, "v@:@")
+ }
+ if template.applicationWillEncodeRestorableState != nil {
+ applicationWillEncodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationWillEncodeRestorableState(app, coder)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:willEncodeRestorableState:"), auto_cast applicationWillEncodeRestorableState, "v@:@@")
+ }
+ if template.applicationDidDecodeRestorableState != nil {
+ applicationDidDecodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidDecodeRestorableState(app, coder)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:didDecodeRestorableState:"), auto_cast applicationDidDecodeRestorableState, "v@:@@")
+ }
+ if template.applicationDidChangeOcclusionState != nil {
+ applicationDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.applicationDidChangeOcclusionState(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeOcclusionState:"), auto_cast applicationDidChangeOcclusionState, "v@:@")
+ }
+ if template.applicationDelegateHandlesKey != nil {
+ applicationDelegateHandlesKey :: proc "c" (self: id, sender: ^Application, key: ^String) -> BOOL {
+ del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.applicationDelegateHandlesKey(sender, key)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("application:delegateHandlesKey:"), auto_cast applicationDelegateHandlesKey, "B@:@@")
+ }
+
+ objc_registerClassPair(class)
+ del := class_createInstance(class, size_of(_ApplicationDelegateInternal))
+ del_internal := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(del)
+ del_internal^ = {
+ template,
+ delegate_context.(runtime.Context) or_else runtime.default_context(),
+ }
+ return cast(^ApplicationDelegate)del
+}
+
+@(objc_type=Application, objc_name="setDelegate")
+Application_setDelegate :: proc "c" (self: ^Application, delegate: ^ApplicationDelegate) {
+ msgSend(nil, self, "setDelegate:", delegate)
+}
diff --git a/core/sys/darwin/Foundation/NSArray.odin b/core/sys/darwin/Foundation/NSArray.odin
new file mode 100644
index 000000000..b238f63f8
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSArray.odin
@@ -0,0 +1,42 @@
+package objc_Foundation
+
+import "base:intrinsics"
+
+@(objc_class="NSArray")
+Array :: struct {
+ using _: Copying(Array),
+}
+
+@(objc_type=Array, objc_name="alloc", objc_is_class_method=true)
+Array_alloc :: proc "c" () -> ^Array {
+ return msgSend(^Array, Array, "alloc")
+}
+
+@(objc_type=Array, objc_name="init")
+Array_init :: proc "c" (self: ^Array) -> ^Array {
+ return msgSend(^Array, self, "init")
+}
+
+@(objc_type=Array, objc_name="initWithObjects")
+Array_initWithObjects :: proc "c" (self: ^Array, objects: [^]^Object, count: UInteger) -> ^Array {
+ return msgSend(^Array, self, "initWithObjects:count:", objects, count)
+}
+
+@(objc_type=Array, objc_name="initWithCoder")
+Array_initWithCoder :: proc "c" (self: ^Array, coder: ^Coder) -> ^Array {
+ return msgSend(^Array, self, "initWithCoder:", coder)
+}
+
+@(objc_type=Array, objc_name="object")
+Array_object :: proc "c" (self: ^Array, index: UInteger) -> ^Object {
+ return msgSend(^Object, self, "objectAtIndex:", index)
+}
+@(objc_type=Array, objc_name="objectAs")
+Array_objectAs :: proc "c" (self: ^Array, index: UInteger, $T: typeid) -> T where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
+ return (T)(Array_object(self, index))
+}
+
+@(objc_type=Array, objc_name="count")
+Array_count :: proc "c" (self: ^Array) -> UInteger {
+ return msgSend(UInteger, self, "count")
+}
diff --git a/core/sys/darwin/Foundation/NSAutoreleasePool.odin b/core/sys/darwin/Foundation/NSAutoreleasePool.odin
new file mode 100644
index 000000000..8eb3657b6
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSAutoreleasePool.odin
@@ -0,0 +1,33 @@
+package objc_Foundation
+
+@(objc_class="NSAutoreleasePool")
+AutoreleasePool :: struct {using _: Object}
+
+@(objc_type=AutoreleasePool, objc_name="alloc", objc_is_class_method=true)
+AutoreleasePool_alloc :: proc "c" () -> ^AutoreleasePool {
+ return msgSend(^AutoreleasePool, AutoreleasePool, "alloc")
+}
+
+@(objc_type=AutoreleasePool, objc_name="init")
+AutoreleasePool_init :: proc "c" (self: ^AutoreleasePool) -> ^AutoreleasePool {
+ return msgSend(^AutoreleasePool, self, "init")
+}
+
+@(objc_type=AutoreleasePool, objc_name="drain")
+AutoreleasePool_drain :: proc "c" (self: ^AutoreleasePool) {
+ msgSend(nil, self, "drain")
+}
+@(objc_type=AutoreleasePool, objc_name="addObject")
+AutoreleasePool_addObject :: proc "c" (self: ^AutoreleasePool, obj: ^Object) {
+ msgSend(nil, self, "addObject:", obj)
+}
+@(objc_type=AutoreleasePool, objc_name="showPools")
+AutoreleasePool_showPools :: proc "c" (self: ^AutoreleasePool, obj: ^Object) {
+ msgSend(nil, self, "showPools")
+}
+
+
+@(deferred_out=AutoreleasePool_drain)
+scoped_autoreleasepool :: proc "c" () -> ^AutoreleasePool {
+ return AutoreleasePool.alloc()->init()
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSBlock.odin b/core/sys/darwin/Foundation/NSBlock.odin
new file mode 100644
index 000000000..b9d94bfee
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSBlock.odin
@@ -0,0 +1,120 @@
+package objc_Foundation
+
+import "base:intrinsics"
+import "base:builtin"
+import "core:mem"
+
+@(objc_class="NSBlock")
+Block :: struct {using _: Object}
+
+@(objc_type=Block, objc_name="createGlobal", objc_is_class_method=true)
+Block_createGlobal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
+ return Block_createInternal(true, user_data, user_proc, allocator)
+}
+@(objc_type=Block, objc_name="createLocal", objc_is_class_method=true)
+Block_createLocal :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr)) -> ^Block {
+ b, _ := Block_createInternal(false, user_data, user_proc, {})
+ return b
+}
+@(objc_type=Block, objc_name="createGlobalWithParam", objc_is_class_method=true)
+Block_createGlobalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator := context.allocator) -> (^Block, mem.Allocator_Error) #optional_allocator_error {
+ return Block_createInternalWithParam(true, user_data, user_proc, allocator)
+}
+@(objc_type=Block, objc_name="createLocalWithParam", objc_is_class_method=true)
+Block_createLocalWithParam :: proc (user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T)) -> ^Block {
+ b, _ := Block_createInternalWithParam(false, user_data, user_proc, {})
+ return b
+}
+
+@(private)
+Internal_Block_Literal_Base :: struct {
+ isa: ^intrinsics.objc_class,
+ flags: u32,
+ reserved: u32,
+ invoke: rawptr, // contains a pointer to a proc "c" (^Internal_Block_Literal, ...)
+ descriptor: ^Block_Descriptor,
+}
+
+@(private)
+Internal_Block_Literal :: struct {
+ using base: Internal_Block_Literal_Base,
+ // Imported Variables
+ user_proc: rawptr, // contains a pointer to a proc "c" (user_data: rawptr, ...)
+ user_data: rawptr,
+}
+
+@(private)
+Block_Descriptor :: struct {
+ reserved: uint,
+ size: uint,
+ copy_helper: proc "c" (dst, src: rawptr),
+ dispose_helper: proc "c" (src: rawptr),
+ signature: cstring,
+}
+
+@(private)
+global_block_descriptor := Block_Descriptor{
+ reserved = 0,
+ size = size_of(Internal_Block_Literal),
+}
+
+foreign import libSystem "system:System.framework"
+foreign libSystem {
+ _NSConcreteGlobalBlock: intrinsics.objc_class
+ _NSConcreteStackBlock: intrinsics.objc_class
+}
+
+@(private="file")
+internal_block_literal_make :: proc (is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr, allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
+ _init :: proc(bl: ^Internal_Block_Literal, is_global: bool, user_data: rawptr, user_proc: rawptr, invoke: rawptr) {
+ // Set to true on blocks that have captures (and thus are not true
+ // global blocks) but are known not to escape for various other
+ // reasons. For backward compatibility with old runtimes, whenever
+ // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
+ // non-escaping block returns the original block and releasing such a
+ // block is a no-op, which is exactly how global blocks are handled.
+ BLOCK_IS_NOESCAPE :: (1 << 23)|BLOCK_IS_GLOBAL
+
+ BLOCK_HAS_COPY_DISPOSE :: 1 << 25
+ BLOCK_HAS_CTOR :: 1 << 26 // helpers have C++ code
+ BLOCK_IS_GLOBAL :: 1 << 28
+ BLOCK_HAS_STRET :: 1 << 29 // IFF BLOCK_HAS_SIGNATURE
+ BLOCK_HAS_SIGNATURE :: 1 << 30
+
+ bl.isa = is_global ? &_NSConcreteGlobalBlock : &_NSConcreteStackBlock
+ bl.flags = BLOCK_IS_GLOBAL if is_global else 0
+ bl.invoke = invoke
+ bl.descriptor = &global_block_descriptor
+ bl.user_proc = auto_cast user_proc
+ bl.user_data = user_data
+ }
+ if is_global {
+ bl := builtin.new (Internal_Block_Literal, allocator) or_return
+ _init(bl, true, user_data, user_proc, invoke)
+ return auto_cast bl, .None
+ } else {
+ // malloc blocks are created by calling 'copy' on a stack block
+ bl: Internal_Block_Literal
+ _init(&bl, false, user_data, user_proc, invoke)
+ return auto_cast copy(cast(^Copying(Block))(&bl)), .None
+ }
+}
+
+@(private="file")
+Block_createInternal :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
+ invoke :: proc "c" (bl: ^Internal_Block_Literal) {
+ user_proc := (proc "c" (rawptr))(bl.user_proc)
+ user_proc(bl.user_data)
+ }
+ return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
+}
+
+@(private="file")
+Block_createInternalWithParam :: proc (is_global: bool, user_data: rawptr, user_proc: proc "c" (user_data: rawptr, t: $T), allocator: mem.Allocator) -> (b: ^Block, err: mem.Allocator_Error) {
+ invoke :: proc "c" (bl: ^Internal_Block_Literal, t: T) {
+ user_proc := (proc "c" (rawptr, T))(bl.user_proc)
+ user_proc(bl.user_data, t)
+ }
+ return internal_block_literal_make(is_global, user_data, auto_cast user_proc, auto_cast invoke, allocator)
+}
+
diff --git a/core/sys/darwin/Foundation/NSBundle.odin b/core/sys/darwin/Foundation/NSBundle.odin
new file mode 100644
index 000000000..25fc8df32
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSBundle.odin
@@ -0,0 +1,191 @@
+package objc_Foundation
+
+@(objc_class="NSBundle")
+Bundle :: struct { using _: Object }
+
+@(objc_type=Bundle, objc_name="mainBundle", objc_is_class_method=true)
+Bundle_mainBundle :: proc "c" () -> ^Bundle {
+ return msgSend(^Bundle, Bundle, "mainBundle")
+}
+
+@(objc_type=Bundle, objc_name="bundleWithPath", objc_is_class_method=true)
+Bundle_bundleWithPath :: proc "c" (path: ^String) -> ^Bundle {
+ return msgSend(^Bundle, Bundle, "bundleWithPath:", path)
+}
+
+@(objc_type=Bundle, objc_name="bundleWithURL", objc_is_class_method=true)
+Bundle_bundleWithURL :: proc "c" (url: ^URL) -> ^Bundle {
+ return msgSend(^Bundle, Bundle, "bundleWithUrl:", url)
+}
+
+
+@(objc_type=Bundle, objc_name="alloc", objc_is_class_method=true)
+Bundle_alloc :: proc "c" () -> ^Bundle {
+ return msgSend(^Bundle, Bundle, "alloc")
+}
+
+@(objc_type=Bundle, objc_name="init")
+Bundle_init :: proc "c" (self: ^Bundle) -> ^Bundle {
+ return msgSend(^Bundle, self, "init")
+}
+
+@(objc_type=Bundle, objc_name="initWithPath")
+Bundle_initWithPath :: proc "c" (self: ^Bundle, path: ^String) -> ^Bundle {
+ return msgSend(^Bundle, self, "initWithPath:", path)
+}
+
+@(objc_type=Bundle, objc_name="initWithURL")
+Bundle_initWithURL :: proc "c" (self: ^Bundle, url: ^URL) -> ^Bundle {
+ return msgSend(^Bundle, self, "initWithUrl:", url)
+}
+
+@(objc_type=Bundle, objc_name="allBundles")
+Bundle_allBundles :: proc "c" () -> (all: ^Array) {
+ return msgSend(type_of(all), Bundle, "allBundles")
+}
+
+@(objc_type=Bundle, objc_name="allFrameworks")
+Bundle_allFrameworks :: proc "c" () -> (all: ^Array) {
+ return msgSend(type_of(all), Bundle, "allFrameworks")
+}
+
+@(objc_type=Bundle, objc_name="load")
+Bundle_load :: proc "c" (self: ^Bundle) -> BOOL {
+ return msgSend(BOOL, self, "load")
+}
+@(objc_type=Bundle, objc_name="unload")
+Bundle_unload :: proc "c" (self: ^Bundle) -> BOOL {
+ return msgSend(BOOL, self, "unload")
+}
+
+@(objc_type=Bundle, objc_name="isLoaded")
+Bundle_isLoaded :: proc "c" (self: ^Bundle) -> BOOL {
+ return msgSend(BOOL, self, "isLoaded")
+}
+
+@(objc_type=Bundle, objc_name="preflightAndReturnError")
+Bundle_preflightAndReturnError :: proc "contextless" (self: ^Bundle) -> (ok: BOOL, error: ^Error) {
+ ok = msgSend(BOOL, self, "preflightAndReturnError:", &error)
+ return
+}
+
+@(objc_type=Bundle, objc_name="loadAndReturnError")
+Bundle_loadAndReturnError :: proc "contextless" (self: ^Bundle) -> (ok: BOOL, error: ^Error) {
+ ok = msgSend(BOOL, self, "loadAndReturnError:", &error)
+ return
+}
+
+@(objc_type=Bundle, objc_name="bundleURL")
+Bundle_bundleURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "bundleURL")
+}
+
+@(objc_type=Bundle, objc_name="resourceURL")
+Bundle_resourceURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "resourceURL")
+}
+
+@(objc_type=Bundle, objc_name="executableURL")
+Bundle_executableURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "executableURL")
+}
+
+@(objc_type=Bundle, objc_name="URLForAuxiliaryExecutable")
+Bundle_URLForAuxiliaryExecutable :: proc "c" (self: ^Bundle, executableName: ^String) -> ^URL {
+ return msgSend(^URL, self, "URLForAuxiliaryExecutable:", executableName)
+}
+
+@(objc_type=Bundle, objc_name="privateFrameworksURL")
+Bundle_privateFrameworksURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "privateFrameworksURL")
+}
+
+@(objc_type=Bundle, objc_name="sharedFrameworksURL")
+Bundle_sharedFrameworksURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "sharedFrameworksURL")
+}
+
+@(objc_type=Bundle, objc_name="sharedSupportURL")
+Bundle_sharedSupportURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "sharedSupportURL")
+}
+
+@(objc_type=Bundle, objc_name="builtInPlugInsURL")
+Bundle_builtInPlugInsURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "builtInPlugInsURL")
+}
+
+@(objc_type=Bundle, objc_name="appStoreReceiptURL")
+Bundle_appStoreReceiptURL :: proc "c" (self: ^Bundle) -> ^URL {
+ return msgSend(^URL, self, "appStoreReceiptURL")
+}
+
+@(objc_type=Bundle, objc_name="bundlePath")
+Bundle_bundlePath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "bundlePath")
+}
+
+@(objc_type=Bundle, objc_name="resourcePath")
+Bundle_resourcePath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "resourcePath")
+}
+
+@(objc_type=Bundle, objc_name="executablePath")
+Bundle_executablePath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "executablePath")
+}
+
+@(objc_type=Bundle, objc_name="PathForAuxiliaryExecutable")
+Bundle_PathForAuxiliaryExecutable :: proc "c" (self: ^Bundle, executableName: ^String) -> ^String {
+ return msgSend(^String, self, "PathForAuxiliaryExecutable:", executableName)
+}
+
+@(objc_type=Bundle, objc_name="privateFrameworksPath")
+Bundle_privateFrameworksPath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "privateFrameworksPath")
+}
+
+@(objc_type=Bundle, objc_name="sharedFrameworksPath")
+Bundle_sharedFrameworksPath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "sharedFrameworksPath")
+}
+
+@(objc_type=Bundle, objc_name="sharedSupportPath")
+Bundle_sharedSupportPath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "sharedSupportPath")
+}
+
+@(objc_type=Bundle, objc_name="builtInPlugInsPath")
+Bundle_builtInPlugInsPath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "builtInPlugInsPath")
+}
+
+@(objc_type=Bundle, objc_name="appStoreReceiptPath")
+Bundle_appStoreReceiptPath :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "appStoreReceiptPath")
+}
+
+@(objc_type=Bundle, objc_name="bundleIdentifier")
+Bundle_bundleIdentifier :: proc "c" (self: ^Bundle) -> ^String {
+ return msgSend(^String, self, "bundleIdentifier")
+}
+
+@(objc_type=Bundle, objc_name="infoDictionary")
+Bundle_infoDictionary :: proc "c" (self: ^Bundle) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "infoDictionary")
+}
+
+@(objc_type=Bundle, objc_name="localizedInfoDictionary")
+Bundle_localizedInfoDictionary :: proc "c" (self: ^Bundle) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "localizedInfoDictionary")
+}
+
+@(objc_type=Bundle, objc_name="objectForInfoDictionaryKey")
+Bundle_objectForInfoDictionaryKey :: proc "c" (self: ^Bundle, key: ^String) -> ^Object {
+ return msgSend(^Object, self, "objectForInfoDictionaryKey:", key)
+}
+
+@(objc_type=Bundle, objc_name="localizedStringForKey")
+Bundle_localizedStringForKey :: proc "c" (self: ^Bundle, key: ^String, value: ^String = nil, tableName: ^String = nil) -> ^String {
+ return msgSend(^String, self, "localizedStringForKey:value:table:", key, value, tableName)
+}
diff --git a/core/sys/darwin/Foundation/NSColor.odin b/core/sys/darwin/Foundation/NSColor.odin
new file mode 100644
index 000000000..453b33144
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSColor.odin
@@ -0,0 +1,149 @@
+package objc_Foundation
+
+@(objc_class="NSColorSpace")
+ColorSpace :: struct {using _: Object}
+
+@(objc_class="NSColor")
+Color :: struct {using _: Object}
+
+@(objc_type=Color, objc_name="colorWithSRGBRed", objc_is_class_method=true)
+Color_colorWithSRGBRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithSRGBRed:green:blue:alpha:", red, green, blue, alpha)
+}
+
+@(objc_type=Color, objc_name="colorWithCalibratedHue", objc_is_class_method=true)
+Color_colorWithCalibratedHue :: proc "c" (hue, saturation, brightness, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithCalibratedHue:hue:saturation:brightness:alpha:", hue, saturation, brightness, alpha)
+}
+@(objc_type=Color, objc_name="colorWithCalibratedRed", objc_is_class_method=true)
+Color_colorWithCalibratedRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithCalibratedRed:green:blue:alpha:", red, green, blue, alpha)
+}
+@(objc_type=Color, objc_name="colorWithCalibratedWhite", objc_is_class_method=true)
+Color_colorWithCalibratedWhite :: proc "c" (white, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithCalibratedWhite:alpha:", white, alpha)
+}
+
+@(objc_type=Color, objc_name="colorWithDeviceCyan", objc_is_class_method=true)
+Color_colorWithDeviceCyan :: proc "c" (cyan, magenta, yellow, black, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithDeviceCyan:magenta:yellow:black:", cyan, magenta, yellow, black)
+}
+@(objc_type=Color, objc_name="colorWithDeviceHue", objc_is_class_method=true)
+Color_colorWithDeviceHue :: proc "c" (hue, saturation, brightness, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithDeviceHue:hue:saturation:brightness:alpha:", hue, saturation, brightness, alpha)
+}
+@(objc_type=Color, objc_name="colorWithDeviceRed", objc_is_class_method=true)
+Color_colorWithDeviceRed :: proc "c" (red, green, blue, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithDeviceRed:green:blue:alpha:", red, green, blue, alpha)
+}
+@(objc_type=Color, objc_name="colorWithDeviceWhite", objc_is_class_method=true)
+Color_colorWithDeviceWhite :: proc "c" (white, alpha: Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithDeviceWhite:alpha:", white, alpha)
+}
+
+
+@(objc_type=Color, objc_name="blackColor", objc_is_class_method=true)
+Color_blackColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "blackColor")
+}
+
+@(objc_type=Color, objc_name="whiteColor", objc_is_class_method=true)
+Color_whiteColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "whiteColor")
+}
+
+@(objc_type=Color, objc_name="redColor", objc_is_class_method=true)
+Color_redColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "redColor")
+}
+
+@(objc_type=Color, objc_name="greenColor", objc_is_class_method=true)
+Color_greenColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "greenColor")
+}
+
+@(objc_type=Color, objc_name="orangeColor", objc_is_class_method=true)
+Color_orangeColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "orangeColor")
+}
+
+@(objc_type=Color, objc_name="purpleColor", objc_is_class_method=true)
+Color_purpleColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "purpleColor")
+}
+
+@(objc_type=Color, objc_name="cyanColor", objc_is_class_method=true)
+Color_cyanColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "cyanColor")
+}
+
+@(objc_type=Color, objc_name="blueColor", objc_is_class_method=true)
+Color_blueColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "blueColor")
+}
+
+@(objc_type=Color, objc_name="magentaColor", objc_is_class_method=true)
+Color_magentaColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "magentaColor")
+}
+
+@(objc_type=Color, objc_name="yellowColor", objc_is_class_method=true)
+Color_yellowColor :: proc "c" () -> ^Color {
+ return msgSend(^Color, Color, "yellowColor")
+}
+
+
+@(objc_type=Color, objc_name="getCMYKA")
+Color_getCMYKA :: proc "c" (self: ^Color) -> (cyan, magenta, yellow, black, alpha: Float) {
+ msgSend(nil, Color, "getCyan:magenta:yellow:black:alpha:", &cyan, &magenta, &yellow, &black, &alpha)
+ return
+}
+@(objc_type=Color, objc_name="getHSBA")
+Color_getHSBA :: proc "c" (self: ^Color) -> (hue, saturation, brightness, alpha: Float) {
+ msgSend(nil, Color, "getHue:saturation:brightness:alpha:", &hue, &saturation, &brightness, &alpha)
+ return
+}
+@(objc_type=Color, objc_name="getRGBA")
+Color_getRGBA :: proc "c" (self: ^Color) -> (red, green, blue, alpha: Float) {
+ msgSend(nil, Color, "getRed:green:blue:alpha:", &red, &green, &blue, &alpha)
+ return
+}
+@(objc_type=Color, objc_name="getWhiteAlpha")
+Color_getWhiteAlpha :: proc "c" (self: ^Color) -> (white, alpha: Float) {
+ msgSend(nil, Color, "getWhite:alpha:", &white, &alpha)
+ return
+}
+
+
+@(objc_type=Color, objc_name="colorWithColorSpace", objc_is_class_method=true)
+Color_colorWithColorSpace :: proc "c" (space: ^ColorSpace, components: []Float) -> ^Color {
+ return msgSend(^Color, Color, "colorWithColorSpace:components:count", space, raw_data(components), Integer(len(components)))
+}
+
+
+@(objc_type=Color, objc_name="colorSpaceName")
+Color_colorSpaceName :: proc "c" (self: ^Color) -> ^String {
+ return msgSend(^String, self, "colorSpaceName")
+}
+
+@(objc_type=Color, objc_name="colorSpace")
+Color_colorSpace :: proc "c" (self: ^Color) -> ^ColorSpace {
+ return msgSend(^ColorSpace, self, "colorSpace")
+}
+
+@(objc_type=Color, objc_name="colorUsingColorSpaceName")
+Color_colorUsingColorSpaceName :: proc "c" (self: ^Color, colorSpace: ^String, device: ^Dictionary = nil) -> ^Color {
+ if device != nil {
+ return msgSend(^Color, self, "colorUsingColorSpaceName:device:", colorSpace, device)
+ }
+ return msgSend(^Color, self, "colorUsingColorSpaceName:", colorSpace)
+}
+
+@(objc_type=Color, objc_name="numberOfComponents")
+Color_numberOfComponents :: proc "c" (self: ^Color) -> Integer {
+ return msgSend(Integer, self, "numberOfComponents")
+}
+@(objc_type=Color, objc_name="getComponents")
+Color_getComponents :: proc "c" (self: ^Color, components: [^]Float) {
+ msgSend(nil, self, "getComponents:", components)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSData.odin b/core/sys/darwin/Foundation/NSData.odin
new file mode 100644
index 000000000..04c1ce25d
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSData.odin
@@ -0,0 +1,24 @@
+package objc_Foundation
+
+@(objc_class="NSData")
+Data :: struct {using _: Copying(Data)}
+
+@(objc_type=Data, objc_name="alloc", objc_is_class_method=true)
+Data_alloc :: proc "c" () -> ^Data {
+ return msgSend(^Data, Data, "alloc")
+}
+
+@(objc_type=Data, objc_name="init")
+Data_init :: proc "c" (self: ^Data) -> ^Data {
+ return msgSend(^Data, self, "init")
+}
+
+@(objc_type=Data, objc_name="mutableBytes")
+Data_mutableBytes :: proc "c" (self: ^Data) -> rawptr {
+ return msgSend(rawptr, self, "mutableBytes")
+}
+
+@(objc_type=Data, objc_name="length")
+Data_length :: proc "c" (self: ^Data) -> UInteger {
+ return msgSend(UInteger, self, "length")
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSDate.odin b/core/sys/darwin/Foundation/NSDate.odin
new file mode 100644
index 000000000..f8096c698
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSDate.odin
@@ -0,0 +1,19 @@
+package objc_Foundation
+
+@(objc_class="NSDate")
+Date :: struct {using _: Copying(Date)}
+
+@(objc_type=Date, objc_name="alloc", objc_is_class_method=true)
+Date_alloc :: proc "c" () -> ^Date {
+ return msgSend(^Date, Date, "alloc")
+}
+
+@(objc_type=Date, objc_name="init")
+Date_init :: proc "c" (self: ^Date) -> ^Date {
+ return msgSend(^Date, self, "init")
+}
+
+@(objc_type=Date, objc_name="dateWithTimeIntervalSinceNow")
+Date_dateWithTimeIntervalSinceNow :: proc "c" (secs: TimeInterval) -> ^Date {
+ return msgSend(^Date, Date, "dateWithTimeIntervalSinceNow:", secs)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSDictionary.odin b/core/sys/darwin/Foundation/NSDictionary.odin
new file mode 100644
index 000000000..8af58cf62
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSDictionary.odin
@@ -0,0 +1,50 @@
+package objc_Foundation
+
+@(objc_class="NSDictionary")
+Dictionary :: struct {using _: Copying(Dictionary)}
+
+@(objc_type=Dictionary, objc_name="dictionary", objc_is_class_method=true)
+Dictionary_dictionary :: proc "c" () -> ^Dictionary {
+ return msgSend(^Dictionary, Dictionary, "dictionary")
+}
+
+@(objc_type=Dictionary, objc_name="dictionaryWithObject", objc_is_class_method=true)
+Dictionary_dictionaryWithObject :: proc "c" (object: ^Object, forKey: ^Object) -> ^Dictionary {
+ return msgSend(^Dictionary, Dictionary, "dictionaryWithObject:forKey:", object, forKey)
+}
+
+@(objc_type=Dictionary, objc_name="dictionaryWithObjects", objc_is_class_method=true)
+Dictionary_dictionaryWithObjects :: proc "c" (objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
+ return msgSend(^Dictionary, Dictionary, "dictionaryWithObjects:forKeys:count", objects, forKeys, count)
+}
+
+
+@(objc_type=Dictionary, objc_name="alloc", objc_is_class_method=true)
+Dictionary_alloc :: proc "c" () -> ^Dictionary {
+ return msgSend(^Dictionary, Dictionary, "alloc")
+}
+
+@(objc_type=Dictionary, objc_name="init")
+Dictionary_init :: proc "c" (self: ^Dictionary) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "init")
+}
+
+@(objc_type=Dictionary, objc_name="initWithObjects")
+Dictionary_initWithObjects :: proc "c" (self: ^Dictionary, objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "initWithObjects:forKeys:count", objects, forKeys, count)
+}
+
+@(objc_type=Dictionary, objc_name="objectForKey")
+Dictionary_objectForKey :: proc "c" (self: ^Dictionary, key: ^Object) -> ^Object {
+ return msgSend(^Dictionary, self, "objectForKey:", key)
+}
+
+@(objc_type=Dictionary, objc_name="count")
+Dictionary_count :: proc "c" (self: ^Dictionary) -> UInteger {
+ return msgSend(UInteger, self, "count")
+}
+
+@(objc_type=Dictionary, objc_name="keyEnumerator")
+Dictionary_keyEnumerator :: proc "c" (self: ^Dictionary, $KeyType: typeid) -> (enumerator: ^Enumerator(KeyType)) {
+ return msgSend(type_of(enumerator), self, "keyEnumerator")
+}
diff --git a/core/sys/darwin/Foundation/NSEnumerator.odin b/core/sys/darwin/Foundation/NSEnumerator.odin
new file mode 100644
index 000000000..52f3f49d7
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSEnumerator.odin
@@ -0,0 +1,50 @@
+package objc_Foundation
+
+import "core:c"
+import "base:intrinsics"
+
+FastEnumerationState :: struct #packed {
+ state: c.ulong,
+ itemsPtr: [^]^Object,
+ mutationsPtr: [^]c.ulong,
+ extra: [5]c.ulong,
+}
+
+@(objc_class="NSFastEnumeration")
+FastEnumeration :: struct {using _: Object}
+
+@(objc_class="NSEnumerator")
+Enumerator :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
+ using _: FastEnumeration,
+}
+
+
+@(objc_type=FastEnumeration, objc_name="alloc", objc_is_class_method=true)
+FastEnumeration_alloc :: proc "c" () -> ^FastEnumeration {
+ return msgSend(^FastEnumeration, FastEnumeration, "alloc")
+}
+
+@(objc_type=FastEnumeration, objc_name="init")
+FastEnumeration_init :: proc "c" (self: ^FastEnumeration) -> ^FastEnumeration {
+ return msgSend(^FastEnumeration, self, "init")
+}
+
+
+@(objc_type=FastEnumeration, objc_name="countByEnumerating")
+FastEnumeration_countByEnumerating :: proc "c" (self: ^FastEnumeration, state: ^FastEnumerationState, buffer: [^]^Object, len: UInteger) -> UInteger {
+ return msgSend(UInteger, self, "countByEnumeratingWithState:objects:count:", state, buffer, len)
+}
+
+Enumerator_nextObject :: proc "c" (self: ^$E/Enumerator($T)) -> T {
+ return msgSend(T, self, "nextObject")
+}
+
+Enumerator_allObjects :: proc "c" (self: ^$E/Enumerator($T)) -> (all: ^Array) {
+ return msgSend(type_of(all), self, "allObjects")
+}
+
+Enumerator_iterator :: proc "contextless" (self: ^$E/Enumerator($T)) -> (obj: T, ok: bool) {
+ obj = msgSend(T, self, "nextObject")
+ ok = obj != nil
+ return
+}
diff --git a/core/sys/darwin/Foundation/NSError.odin b/core/sys/darwin/Foundation/NSError.odin
new file mode 100644
index 000000000..1657befe2
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSError.odin
@@ -0,0 +1,88 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+
+ErrorDomain :: ^String
+
+foreign Foundation {
+ @(linkage="weak") CocoaErrorDomain: ErrorDomain
+ @(linkage="weak") POSIXErrorDomain: ErrorDomain
+ @(linkage="weak") OSStatusErrorDomain: ErrorDomain
+ @(linkage="weak") MachErrorDomain: ErrorDomain
+}
+
+ErrorUserInfoKey :: ^String
+
+foreign Foundation {
+ @(linkage="weak") UnderlyingErrorKey: ErrorUserInfoKey
+ @(linkage="weak") LocalizedDescriptionKey: ErrorUserInfoKey
+ @(linkage="weak") LocalizedFailureReasonErrorKey: ErrorUserInfoKey
+ @(linkage="weak") LocalizedRecoverySuggestionErrorKey: ErrorUserInfoKey
+ @(linkage="weak") LocalizedRecoveryOptionsErrorKey: ErrorUserInfoKey
+ @(linkage="weak") RecoveryAttempterErrorKey: ErrorUserInfoKey
+ @(linkage="weak") HelpAnchorErrorKey: ErrorUserInfoKey
+ @(linkage="weak") DebugDescriptionErrorKey: ErrorUserInfoKey
+ @(linkage="weak") LocalizedFailureErrorKey: ErrorUserInfoKey
+ @(linkage="weak") StringEncodingErrorKey: ErrorUserInfoKey
+ @(linkage="weak") URLErrorKey: ErrorUserInfoKey
+ @(linkage="weak") FilePathErrorKey: ErrorUserInfoKey
+}
+
+@(objc_class="NSError")
+Error :: struct { using _: Copying(Error) }
+
+
+@(objc_type=Error, objc_name="alloc", objc_is_class_method=true)
+Error_alloc :: proc "c" () -> ^Error {
+ return msgSend(^Error, Error, "alloc")
+}
+
+@(objc_type=Error, objc_name="init")
+Error_init :: proc "c" (self: ^Error) -> ^Error {
+ return msgSend(^Error, self, "init")
+}
+
+@(objc_type=Error, objc_name="errorWithDomain", objc_is_class_method=true)
+Error_errorWithDomain :: proc "c" (domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
+ return msgSend(^Error, Error, "errorWithDomain:code:userInfo:", domain, code, userInfo)
+}
+
+@(objc_type=Error, objc_name="initWithDomain")
+Error_initWithDomain :: proc "c" (self: ^Error, domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
+ return msgSend(^Error, self, "initWithDomain:code:userInfo:", domain, code, userInfo)
+}
+
+@(objc_type=Error, objc_name="code")
+Error_code :: proc "c" (self: ^Error) -> Integer {
+ return msgSend(Integer, self, "code")
+}
+
+@(objc_type=Error, objc_name="domain")
+Error_domain :: proc "c" (self: ^Error) -> ErrorDomain {
+ return msgSend(ErrorDomain, self, "domain")
+}
+
+@(objc_type=Error, objc_name="userInfo")
+Error_userInfo :: proc "c" (self: ^Error) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "userInfo")
+}
+
+@(objc_type=Error, objc_name="localizedDescription")
+Error_localizedDescription :: proc "c" (self: ^Error) -> ^String {
+ return msgSend(^String, self, "localizedDescription")
+}
+
+@(objc_type=Error, objc_name="localizedRecoveryOptions")
+Error_localizedRecoveryOptions :: proc "c" (self: ^Error) -> (options: ^Array) {
+ return msgSend(type_of(options), self, "localizedRecoveryOptions")
+}
+
+@(objc_type=Error, objc_name="localizedRecoverySuggestion")
+Error_localizedRecoverySuggestion :: proc "c" (self: ^Error) -> ^String {
+ return msgSend(^String, self, "localizedRecoverySuggestion")
+}
+
+@(objc_type=Error, objc_name="localizedFailureReason")
+Error_localizedFailureReason :: proc "c" (self: ^Error) -> ^String {
+ return msgSend(^String, self, "localizedFailureReason")
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSEvent.odin b/core/sys/darwin/Foundation/NSEvent.odin
new file mode 100644
index 000000000..b9f247230
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSEvent.odin
@@ -0,0 +1,466 @@
+package objc_Foundation
+
+@(objc_class="NSEvent")
+Event :: struct {using _: Object}
+
+
+
+EventMask :: distinct bit_set[EventType; UInteger]
+EventMaskAny :: ~EventMask{}
+
+when size_of(UInteger) == 4 {
+ // We don't support a 32-bit darwin system but this is mostly to shut up the type checker for the time being
+ EventType :: enum UInteger {
+ LeftMouseDown = 1,
+ LeftMouseUp = 2,
+ RightMouseDown = 3,
+ RightMouseUp = 4,
+ MouseMoved = 5,
+ LeftMouseDragged = 6,
+ RightMouseDragged = 7,
+ MouseEntered = 8,
+ MouseExited = 9,
+ KeyDown = 10,
+ KeyUp = 11,
+ FlagsChanged = 12,
+ AppKitDefined = 13,
+ SystemDefined = 14,
+ ApplicationDefined = 15,
+ Periodic = 16,
+ CursorUpdate = 17,
+ Rotate = 18,
+ BeginGesture = 19,
+ EndGesture = 20,
+ ScrollWheel = 22,
+ TabletPoint = 23,
+ TabletProximity = 24,
+ OtherMouseDown = 25,
+ OtherMouseUp = 26,
+ OtherMouseDragged = 27,
+ Gesture = 29,
+ Magnify = 30,
+ Swipe = 31,
+ }
+} else {
+ EventType :: enum UInteger {
+ LeftMouseDown = 1,
+ LeftMouseUp = 2,
+ RightMouseDown = 3,
+ RightMouseUp = 4,
+ MouseMoved = 5,
+ LeftMouseDragged = 6,
+ RightMouseDragged = 7,
+ MouseEntered = 8,
+ MouseExited = 9,
+ KeyDown = 10,
+ KeyUp = 11,
+ FlagsChanged = 12,
+ AppKitDefined = 13,
+ SystemDefined = 14,
+ ApplicationDefined = 15,
+ Periodic = 16,
+ CursorUpdate = 17,
+ Rotate = 18,
+ BeginGesture = 19,
+ EndGesture = 20,
+ ScrollWheel = 22,
+ TabletPoint = 23,
+ TabletProximity = 24,
+ OtherMouseDown = 25,
+ OtherMouseUp = 26,
+ OtherMouseDragged = 27,
+ Gesture = 29,
+ Magnify = 30,
+ Swipe = 31,
+ SmartMagnify = 32,
+ QuickLook = 33,
+ Pressure = 34,
+ DirectTouch = 37,
+ ChangeMode = 38,
+ }
+}
+
+EventPhase :: distinct bit_set[EventPhaseFlag; UInteger]
+EventPhaseFlag :: enum UInteger {
+ Began = 0,
+ Stationary = 1,
+ Changed = 2,
+ Ended = 3,
+ Cancelled = 4,
+ MayBegin = 5,
+}
+EventPhaseNone :: EventPhase{}
+EventPhaseBegan :: EventPhase{.Began}
+EventPhaseStationary :: EventPhase{.Stationary}
+EventPhaseChanged :: EventPhase{.Changed}
+EventPhaseEnded :: EventPhase{.Ended}
+EventPhaseCancelled :: EventPhase{.Cancelled}
+EventPhaseMayBegin :: EventPhase{.MayBegin}
+
+/* pointer types for NSTabletProximity events or mouse events with subtype NSTabletProximityEventSubtype*/
+PointingDeviceType :: enum UInteger {
+ Unknown = 0,
+ Pen = 1,
+ Cursor = 2,
+ Eraser = 3,
+}
+
+// Defined in Carbon.framework Events.h
+kVK :: enum {
+ ANSI_A = 0x00,
+ ANSI_S = 0x01,
+ ANSI_D = 0x02,
+ ANSI_F = 0x03,
+ ANSI_H = 0x04,
+ ANSI_G = 0x05,
+ ANSI_Z = 0x06,
+ ANSI_X = 0x07,
+ ANSI_C = 0x08,
+ ANSI_V = 0x09,
+ ANSI_B = 0x0B,
+ ANSI_Q = 0x0C,
+ ANSI_W = 0x0D,
+ ANSI_E = 0x0E,
+ ANSI_R = 0x0F,
+ ANSI_Y = 0x10,
+ ANSI_T = 0x11,
+ ANSI_1 = 0x12,
+ ANSI_2 = 0x13,
+ ANSI_3 = 0x14,
+ ANSI_4 = 0x15,
+ ANSI_6 = 0x16,
+ ANSI_5 = 0x17,
+ ANSI_Equal = 0x18,
+ ANSI_9 = 0x19,
+ ANSI_7 = 0x1A,
+ ANSI_Minus = 0x1B,
+ ANSI_8 = 0x1C,
+ ANSI_0 = 0x1D,
+ ANSI_RightBracket = 0x1E,
+ ANSI_O = 0x1F,
+ ANSI_U = 0x20,
+ ANSI_LeftBracket = 0x21,
+ ANSI_I = 0x22,
+ ANSI_P = 0x23,
+ ANSI_L = 0x25,
+ ANSI_J = 0x26,
+ ANSI_Quote = 0x27,
+ ANSI_K = 0x28,
+ ANSI_Semicolon = 0x29,
+ ANSI_Backslash = 0x2A,
+ ANSI_Comma = 0x2B,
+ ANSI_Slash = 0x2C,
+ ANSI_N = 0x2D,
+ ANSI_M = 0x2E,
+ ANSI_Period = 0x2F,
+ ANSI_Grave = 0x32,
+ ANSI_KeypadDecimal = 0x41,
+ ANSI_KeypadMultiply = 0x43,
+ ANSI_KeypadPlus = 0x45,
+ ANSI_KeypadClear = 0x47,
+ ANSI_KeypadDivide = 0x4B,
+ ANSI_KeypadEnter = 0x4C,
+ ANSI_KeypadMinus = 0x4E,
+ ANSI_KeypadEquals = 0x51,
+ ANSI_Keypad0 = 0x52,
+ ANSI_Keypad1 = 0x53,
+ ANSI_Keypad2 = 0x54,
+ ANSI_Keypad3 = 0x55,
+ ANSI_Keypad4 = 0x56,
+ ANSI_Keypad5 = 0x57,
+ ANSI_Keypad6 = 0x58,
+ ANSI_Keypad7 = 0x59,
+ ANSI_Keypad8 = 0x5B,
+ ANSI_Keypad9 = 0x5C,
+ Return = 0x24,
+ Tab = 0x30,
+ Space = 0x31,
+ Delete = 0x33,
+ Escape = 0x35,
+ Command = 0x37,
+ Shift = 0x38,
+ CapsLock = 0x39,
+ Option = 0x3A,
+ Control = 0x3B,
+ RightCommand = 0x36,
+ RightShift = 0x3C,
+ RightOption = 0x3D,
+ RightControl = 0x3E,
+ Function = 0x3F,
+ F17 = 0x40,
+ VolumeUp = 0x48,
+ VolumeDown = 0x49,
+ Mute = 0x4A,
+ F18 = 0x4F,
+ F19 = 0x50,
+ F20 = 0x5A,
+ F5 = 0x60,
+ F6 = 0x61,
+ F7 = 0x62,
+ F3 = 0x63,
+ F8 = 0x64,
+ F9 = 0x65,
+ F11 = 0x67,
+ F13 = 0x69,
+ F16 = 0x6A,
+ F14 = 0x6B,
+ F10 = 0x6D,
+ F12 = 0x6F,
+ F15 = 0x71,
+ Help = 0x72,
+ Home = 0x73,
+ PageUp = 0x74,
+ ForwardDelete = 0x75,
+ F4 = 0x76,
+ End = 0x77,
+ F2 = 0x78,
+ PageDown = 0x79,
+ F1 = 0x7A,
+ LeftArrow = 0x7B,
+ RightArrow = 0x7C,
+ DownArrow = 0x7D,
+ UpArrow = 0x7E,
+ JIS_Yen = 0x5D,
+ JIS_Underscore = 0x5E,
+ JIS_KeypadComma = 0x5F,
+ JIS_Eisu = 0x66,
+ JIS_Kana = 0x68,
+ ISO_Section = 0x0A,
+}
+
+
+/* these messages are valid for all events */
+
+@(objc_type=Event, objc_name="type")
+Event_type :: proc "c" (self: ^Event) -> EventType {
+ return msgSend(EventType, self, "type")
+}
+@(objc_type=Event, objc_name="modifierFlags")
+Event_modifierFlags :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "modifierFlags")
+}
+@(objc_type=Event, objc_name="timestamp")
+Event_timestamp :: proc "c" (self: ^Event) -> TimeInterval {
+ return msgSend(TimeInterval, self, "timestamp")
+}
+@(objc_type=Event, objc_name="window")
+Event_window :: proc "c" (self: ^Event) -> ^Window {
+ return msgSend(^Window, self, "window")
+}
+@(objc_type=Event, objc_name="windowNumber")
+Event_windowNumber :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "windowNumber")
+}
+
+/* these messages are valid for all mouse down/up/drag events */
+
+@(objc_type=Event, objc_name="clickCount")
+Event_clickCount :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "clickCount")
+}
+
+// for NSOtherMouse events, but will return valid constants for NSLeftMouse and NSRightMouse
+@(objc_type=Event, objc_name="buttonNumber")
+Event_buttonNumber :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "buttonNumber")
+}
+
+/* these messages are valid for all mouse down/up/drag and enter/exit events */
+@(objc_type=Event, objc_name="eventNumber")
+Event_eventNumber :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "eventNumber")
+}
+
+/* -pressure is valid for all mouse down/up/drag events, and is also valid for NSTabletPoint events on 10.4 or later */
+@(objc_type=Event, objc_name="pressure")
+Event_pressure :: proc "c" (self: ^Event) -> f32 {
+ return msgSend(f32, self, "pressure")
+}
+
+/* -locationInWindow is valid for all mouse-related events */
+@(objc_type=Event, objc_name="locationInWindow")
+Event_locationInWindow :: proc "c" (self: ^Event) -> Point {
+ return msgSend(Point, self, "locationInWindow")
+}
+
+
+@(objc_type=Event, objc_name="deltaX")
+Event_deltaX :: proc "c" (self: ^Event) -> Float {
+ return msgSend(Float, self, "deltaX")
+}
+@(objc_type=Event, objc_name="deltaY")
+Event_deltaY :: proc "c" (self: ^Event) -> Float {
+ return msgSend(Float, self, "deltaY")
+}
+@(objc_type=Event, objc_name="deltaZ")
+Event_deltaZ :: proc "c" (self: ^Event) -> Float {
+ return msgSend(Float, self, "deltaZ")
+}
+@(objc_type=Event, objc_name="delta")
+Event_delta :: proc "c" (self: ^Event) -> (x, y, z: Float) {
+ x = self->deltaX()
+ y = self->deltaY()
+ z = self->deltaZ()
+ return
+}
+
+@(objc_type=Event, objc_name="hasPreciseScrollingDeltas")
+Event_hasPreciseScrollingDeltas :: proc "c" (self: ^Event) -> BOOL {
+ return msgSend(BOOL, self, "hasPreciseScrollingDeltas")
+}
+
+
+@(objc_type=Event, objc_name="scrollingDeltaX")
+Event_scrollingDeltaX :: proc "c" (self: ^Event) -> Float {
+ return msgSend(Float, self, "scrollingDeltaX")
+}
+@(objc_type=Event, objc_name="scrollingDeltaY")
+Event_scrollingDeltaY :: proc "c" (self: ^Event) -> Float {
+ return msgSend(Float, self, "scrollingDeltaY")
+}
+@(objc_type=Event, objc_name="scrollingDelta")
+Event_scrollingDelta :: proc "c" (self: ^Event) -> (x, y: Float) {
+ x = self->scrollingDeltaX()
+ y = self->scrollingDeltaY()
+ return
+}
+
+
+
+@(objc_type=Event, objc_name="momentumPhase")
+Event_momentumPhase :: proc "c" (self: ^Event) -> EventPhase {
+ return msgSend(EventPhase, self, "momentumPhase")
+}
+@(objc_type=Event, objc_name="phase")
+Event_phase :: proc "c" (self: ^Event) -> EventPhase {
+ return msgSend(EventPhase, self, "phase")
+}
+
+
+@(objc_type=Event, objc_name="isDirectionInvertedFromDevice")
+Event_isDirectionInvertedFromDevice :: proc "c" (self: ^Event) -> BOOL {
+ return msgSend(BOOL, self, "isDirectionInvertedFromDevice")
+}
+
+@(objc_type=Event, objc_name="characters")
+Event_characters :: proc "c" (self: ^Event) -> ^String {
+ return msgSend(^String, self, "characters")
+}
+@(objc_type=Event, objc_name="charactersIgnoringModifiers")
+Event_charactersIgnoringModifiers :: proc "c" (self: ^Event) -> ^String {
+ return msgSend(^String, self, "charactersIgnoringModifiers")
+}
+@(objc_type=Event, objc_name="isARepeat")
+Event_isARepeat :: proc "c" (self: ^Event) -> BOOL {
+ return msgSend(BOOL, self, "isARepeat")
+}
+
+@(objc_type=Event, objc_name="keyCode")
+Event_keyCode :: proc "c" (self: ^Event) -> u16 {
+ return msgSend(u16, self, "keyCode")
+}
+
+@(objc_type=Event, objc_name="subtype")
+Event_subtype :: proc "c" (self: ^Event) -> i16 {
+ return msgSend(i16, self, "subtype")
+}
+
+@(objc_type=Event, objc_name="data1")
+Event_data1 :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "data1")
+}
+@(objc_type=Event, objc_name="data2")
+Event_data2 :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "data2")
+}
+
+
+@(objc_type=Event, objc_name="absoluteX")
+Event_absoluteX :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "absoluteX")
+}
+@(objc_type=Event, objc_name="absoluteY")
+Event_absoluteY :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "absoluteY")
+}
+@(objc_type=Event, objc_name="absoluteZ")
+Event_absoluteZ :: proc "c" (self: ^Event) -> Integer {
+ return msgSend(Integer, self, "absoluteZ")
+}
+
+@(objc_type=Event, objc_name="absolute")
+Event_absolute :: proc "c" (self: ^Event) -> (x, y, z: Integer) {
+ x = self->absoluteX()
+ y = self->absoluteY()
+ z = self->absoluteZ()
+ return
+}
+
+
+@(objc_type=Event, objc_name="buttonMask")
+Event_buttonMask :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "buttonMask")
+}
+
+@(objc_type=Event, objc_name="tilt")
+tilt :: proc "c" (self: ^Event) -> Point {
+ return msgSend(Point, self, "tilt")
+}
+
+@(objc_type=Event, objc_name="tangentialPressure")
+Event_tangentialPressure :: proc "c" (self: ^Event) -> f32 {
+ return msgSend(f32, self, "tangentialPressure")
+}
+
+@(objc_type=Event, objc_name="vendorDefined")
+Event_vendorDefined :: proc "c" (self: ^Event) -> id {
+ return msgSend(id, self, "vendorDefined")
+}
+
+
+@(objc_type=Event, objc_name="vendorID")
+Event_vendorID :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "vendorID")
+}
+@(objc_type=Event, objc_name="tabletID")
+Event_tabletID :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "tabletID")
+}
+@(objc_type=Event, objc_name="pointingDeviceID")
+Event_pointingDeviceID :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "pointingDeviceID")
+}
+@(objc_type=Event, objc_name="systemTabletID")
+Event_systemTabletID :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "systemTabletID")
+}
+@(objc_type=Event, objc_name="vendorPointingDeviceType")
+Event_vendorPointingDeviceType :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "vendorPointingDeviceType")
+}
+@(objc_type=Event, objc_name="pointingDeviceSerialNumber")
+Event_pointingDeviceSerialNumber :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "pointingDeviceSerialNumber")
+}
+@(objc_type=Event, objc_name="uniqueID")
+Event_uniqueID :: proc "c" (self: ^Event) -> u64 {
+ return msgSend(u64, self, "uniqueID")
+}
+@(objc_type=Event, objc_name="capabilityMask")
+Event_capabilityMask :: proc "c" (self: ^Event) -> UInteger {
+ return msgSend(UInteger, self, "capabilityMask")
+}
+@(objc_type=Event, objc_name="pointingDeviceType")
+Event_pointingDeviceType :: proc "c" (self: ^Event) -> PointingDeviceType {
+ return msgSend(PointingDeviceType, self, "pointingDeviceType")
+}
+@(objc_type=Event, objc_name="isEnteringProximity")
+Event_isEnteringProximity :: proc "c" (self: ^Event) -> BOOL {
+ return msgSend(BOOL, self, "isEnteringProximity")
+}
+
+
+@(objc_type=Event, objc_name="isSwipeTrackingFromScrollEventsEnabled")
+Event_isSwipeTrackingFromScrollEventsEnabled :: proc "c" (self: ^Event) -> BOOL {
+ return msgSend(BOOL, self, "isSwipeTrackingFromScrollEventsEnabled")
+}
diff --git a/core/sys/darwin/Foundation/NSLock.odin b/core/sys/darwin/Foundation/NSLock.odin
new file mode 100644
index 000000000..168380669
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSLock.odin
@@ -0,0 +1,53 @@
+package objc_Foundation
+
+Locking :: struct($T: typeid) {using _: Object}
+
+Locking_lock :: proc "c" (self: ^Locking($T)) {
+ msgSend(nil, self, "lock")
+}
+Locking_unlock :: proc "c" (self: ^Locking($T)) {
+ msgSend(nil, self, "unlock")
+}
+
+@(objc_class="NSCondition")
+Condition :: struct {using _: Locking(Condition) }
+
+
+@(objc_type=Condition, objc_name="alloc", objc_is_class_method=true)
+Condition_alloc :: proc "c" () -> ^Condition {
+ return msgSend(^Condition, Condition, "alloc")
+}
+
+@(objc_type=Condition, objc_name="init")
+Condition_init :: proc "c" (self: ^Condition) -> ^Condition {
+ return msgSend(^Condition, self, "init")
+}
+
+@(objc_type=Condition, objc_name="wait")
+Condition_wait :: proc "c" (self: ^Condition) {
+ msgSend(nil, self, "wait")
+}
+
+@(objc_type=Condition, objc_name="waitUntilDate")
+Condition_waitUntilDate :: proc "c" (self: ^Condition, limit: ^Date) -> BOOL {
+ return msgSend(BOOL, self, "waitUntilDate:", limit)
+}
+
+@(objc_type=Condition, objc_name="signal")
+Condition_signal :: proc "c" (self: ^Condition) {
+ msgSend(nil, self, "signal")
+}
+
+@(objc_type=Condition, objc_name="broadcast")
+Condition_broadcast :: proc "c" (self: ^Condition) {
+ msgSend(nil, self, "broadcast")
+}
+
+@(objc_type=Condition, objc_name="lock")
+Condition_lock :: proc "c" (self: ^Condition) {
+ msgSend(nil, self, "lock")
+}
+@(objc_type=Condition, objc_name="unlock")
+Condition_unlock :: proc "c" (self: ^Condition) {
+ msgSend(nil, self, "unlock")
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSMenu.odin b/core/sys/darwin/Foundation/NSMenu.odin
new file mode 100644
index 000000000..79da36601
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSMenu.odin
@@ -0,0 +1,103 @@
+package objc_Foundation
+
+import "base:builtin"
+import "base:intrinsics"
+
+KeyEquivalentModifierFlag :: enum UInteger {
+ CapsLock = 16, // Set if Caps Lock key is pressed.
+ Shift = 17, // Set if Shift key is pressed.
+ Control = 18, // Set if Control key is pressed.
+ Option = 19, // Set if Option or Alternate key is pressed.
+ Command = 20, // Set if Command key is pressed.
+ NumericPad = 21, // Set if any key in the numeric keypad is pressed.
+ Help = 22, // Set if the Help key is pressed.
+ Function = 23, // Set if any function key is pressed.
+}
+KeyEquivalentModifierMask :: distinct bit_set[KeyEquivalentModifierFlag; UInteger]
+
+// Used to retrieve only the device-independent modifier flags, allowing applications to mask off the device-dependent modifier flags, including event coalescing information.
+KeyEventModifierFlagDeviceIndependentFlagsMask := transmute(KeyEquivalentModifierMask)_KeyEventModifierFlagDeviceIndependentFlagsMask
+@(private) _KeyEventModifierFlagDeviceIndependentFlagsMask := UInteger(0xffff0000)
+
+
+MenuItemCallback :: proc "c" (unused: rawptr, name: SEL, sender: ^Object)
+
+
+@(objc_class="NSMenuItem")
+MenuItem :: struct {using _: Object}
+
+@(objc_type=MenuItem, objc_name="alloc", objc_is_class_method=true)
+MenuItem_alloc :: proc "c" () -> ^MenuItem {
+ return msgSend(^MenuItem, MenuItem, "alloc")
+}
+@(objc_type=MenuItem, objc_name="registerActionCallback", objc_is_class_method=true)
+MenuItem_registerActionCallback :: proc "c" (name: cstring, callback: MenuItemCallback) -> SEL {
+ s := string(name)
+ n := len(s)
+ sel: SEL
+ if n > 0 && s[n-1] != ':' {
+ col_name := intrinsics.alloca(n+2, 1)
+ builtin.copy(col_name[:n], s)
+ col_name[n] = ':'
+ col_name[n+1] = 0
+ sel = sel_registerName(cstring(col_name))
+ } else {
+ sel = sel_registerName(name)
+ }
+ if callback != nil {
+ class_addMethod(intrinsics.objc_find_class("NSObject"), sel, auto_cast callback, "v@:@")
+ }
+ return sel
+}
+
+@(objc_type=MenuItem, objc_name="init")
+MenuItem_init :: proc "c" (self: ^MenuItem) -> ^MenuItem {
+ return msgSend(^MenuItem, self, "init")
+}
+
+@(objc_type=MenuItem, objc_name="setKeyEquivalentModifierMask")
+MenuItem_setKeyEquivalentModifierMask :: proc "c" (self: ^MenuItem, modifierMask: KeyEquivalentModifierMask) {
+ msgSend(nil, self, "setKeyEquivalentModifierMask:", modifierMask)
+}
+
+@(objc_type=MenuItem, objc_name="keyEquivalentModifierMask")
+MenuItem_keyEquivalentModifierMask :: proc "c" (self: ^MenuItem) -> KeyEquivalentModifierMask {
+ return msgSend(KeyEquivalentModifierMask, self, "keyEquivalentModifierMask")
+}
+
+@(objc_type=MenuItem, objc_name="setSubmenu")
+MenuItem_setSubmenu :: proc "c" (self: ^MenuItem, submenu: ^Menu) {
+ msgSend(nil, self, "setSubmenu:", submenu)
+}
+
+
+
+
+@(objc_class="NSMenu")
+Menu :: struct {using _: Object}
+
+@(objc_type=Menu, objc_name="alloc", objc_is_class_method=true)
+Menu_alloc :: proc "c" () -> ^Menu {
+ return msgSend(^Menu, Menu, "alloc")
+}
+
+@(objc_type=Menu, objc_name="init")
+Menu_init :: proc "c" (self: ^Menu) -> ^Menu {
+ return msgSend(^Menu, self, "init")
+}
+
+@(objc_type=Menu, objc_name="initWithTitle")
+Menu_initWithTitle :: proc "c" (self: ^Menu, title: ^String) -> ^Menu {
+ return msgSend(^Menu, self, "initWithTitle:", title)
+}
+
+
+@(objc_type=Menu, objc_name="addItem")
+Menu_addItem :: proc "c" (self: ^Menu, item: ^MenuItem) {
+ msgSend(nil, self, "addItem:", item)
+}
+
+@(objc_type=Menu, objc_name="addItemWithTitle")
+Menu_addItemWithTitle :: proc "c" (self: ^Menu, title: ^String, selector: SEL, keyEquivalent: ^String) -> ^MenuItem {
+ return msgSend(^MenuItem, self, "addItemWithTitle:action:keyEquivalent:", title, selector, keyEquivalent)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSNotification.odin b/core/sys/darwin/Foundation/NSNotification.odin
new file mode 100644
index 000000000..f766d0cab
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSNotification.odin
@@ -0,0 +1,60 @@
+package objc_Foundation
+
+@(objc_class="NSNotification")
+Notification :: struct{using _: Object}
+
+
+@(objc_type=Notification, objc_name="alloc", objc_is_class_method=true)
+Notification_alloc :: proc "c" () -> ^Notification {
+ return msgSend(^Notification, Notification, "alloc")
+}
+
+@(objc_type=Notification, objc_name="init")
+Notification_init :: proc "c" (self: ^Notification) -> ^Notification {
+ return msgSend(^Notification, self, "init")
+}
+
+@(objc_type=Notification, objc_name="name")
+Notification_name :: proc "c" (self: ^Notification) -> ^String {
+ return msgSend(^String, self, "name")
+}
+
+@(objc_type=Notification, objc_name="object")
+Notification_object :: proc "c" (self: ^Notification) -> ^Object {
+ return msgSend(^Object, self, "object")
+}
+
+@(objc_type=Notification, objc_name="userInfo")
+Notification_userInfo :: proc "c" (self: ^Notification) -> ^Dictionary {
+ return msgSend(^Dictionary, self, "userInfo")
+}
+
+NotificationName :: ^String
+
+@(objc_class="NSNotificationCenter")
+NotificationCenter :: struct{using _: Object}
+
+
+@(objc_type=NotificationCenter, objc_name="alloc", objc_is_class_method=true)
+NotificationCenter_alloc :: proc "c" () -> ^NotificationCenter {
+ return msgSend(^NotificationCenter, NotificationCenter, "alloc")
+}
+
+@(objc_type=NotificationCenter, objc_name="init")
+NotificationCenter_init :: proc "c" (self: ^NotificationCenter) -> ^NotificationCenter {
+ return msgSend(^NotificationCenter, self, "init")
+}
+
+@(objc_type=NotificationCenter, objc_name="defaultCenter", objc_is_class_method=true)
+NotificationCenter_defaultCenter :: proc "c" () -> ^NotificationCenter {
+ return msgSend(^NotificationCenter, NotificationCenter, "defaultCenter")
+}
+
+@(objc_type=NotificationCenter, objc_name="addObserver")
+NotificationCenter_addObserverName :: proc "c" (self: ^NotificationCenter, name: NotificationName, pObj: ^Object, pQueue: rawptr, block: ^Block) -> ^Object {
+ return msgSend(^Object, self, "addObserverName:object:queue:block:", name, pObj, pQueue, block)
+}
+@(objc_type=NotificationCenter, objc_name="removeObserver")
+NotificationCenter_removeObserver :: proc "c" (self: ^NotificationCenter, pObserver: ^Object) {
+ msgSend(nil, self, "removeObserver:", pObserver)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSNumber.odin b/core/sys/darwin/Foundation/NSNumber.odin
new file mode 100644
index 000000000..b3124885f
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSNumber.odin
@@ -0,0 +1,154 @@
+package objc_Foundation
+
+import "core:c"
+_ :: c
+when ODIN_OS == .Darwin {
+ #assert(size_of(c.long) == size_of(int))
+ #assert(size_of(c.ulong) == size_of(uint))
+}
+
+@(objc_class="NSValue")
+Value :: struct{using _: Copying(Value)}
+
+@(objc_type=Value, objc_name="alloc", objc_is_class_method=true)
+Value_alloc :: proc "c" () -> ^Value {
+ return msgSend(^Value, Value, "alloc")
+}
+
+@(objc_type=Value, objc_name="init")
+Value_init :: proc "c" (self: ^Value) -> ^Value {
+ return msgSend(^Value, self, "init")
+}
+
+@(objc_type=Value, objc_name="valueWithBytes", objc_is_class_method=true)
+Value_valueWithBytes :: proc "c" (value: rawptr, type: cstring) -> ^Value {
+ return msgSend(^Value, Value, "valueWithBytes:objCType:", value, type)
+}
+
+@(objc_type=Value, objc_name="valueWithPointer", objc_is_class_method=true)
+Value_valueWithPointer :: proc "c" (pointer: rawptr) -> ^Value {
+ return msgSend(^Value, Value, "valueWithPointer:", pointer)
+}
+
+@(objc_type=Value, objc_name="initWithBytes")
+Value_initWithBytes :: proc "c" (self: ^Value, value: rawptr, type: cstring) -> ^Value {
+ return msgSend(^Value, self, "initWithBytes:objCType:", value, type)
+}
+
+@(objc_type=Value, objc_name="initWithCoder")
+Value_initWithCoder :: proc "c" (self: ^Value, coder: ^Coder) -> ^Value {
+ return msgSend(^Value, self, "initWithCoder:", coder)
+}
+
+@(objc_type=Value, objc_name="getValue")
+Value_getValue :: proc "c" (self: ^Value, value: rawptr, size: UInteger) {
+ msgSend(nil, self, "getValue:size:", value, size)
+}
+
+
+@(objc_type=Value, objc_name="objCType")
+Value_objCType :: proc "c" (self: ^Value) -> cstring {
+ return msgSend(cstring, self, "objCType")
+}
+
+@(objc_type=Value, objc_name="isEqualToValue")
+Value_isEqualToValue :: proc "c" (self, other: ^Value) -> BOOL {
+ return msgSend(BOOL, self, "isEqualToValue:", other)
+}
+
+@(objc_type=Value, objc_name="pointerValue")
+Value_pointerValue :: proc "c" (self: ^Value) -> rawptr {
+ return msgSend(rawptr, self, "pointerValue")
+}
+
+
+@(objc_class="NSNumber")
+Number :: struct{using _: Copying(Number), using _: Value}
+
+@(objc_type=Number, objc_name="alloc", objc_is_class_method=true)
+Number_alloc :: proc "c" () -> ^Number {
+ return msgSend(^Number, Number, "alloc")
+}
+
+@(objc_type=Number, objc_name="init")
+Number_init :: proc "c" (self: ^Number) -> ^Number {
+ return msgSend(^Number, self, "init")
+}
+
+@(objc_type=Number, objc_name="numberWithI8", objc_is_class_method=true) Number_numberWithI8 :: proc "c" (value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) }
+@(objc_type=Number, objc_name="numberWithU8", objc_is_class_method=true) Number_numberWithU8 :: proc "c" (value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) }
+@(objc_type=Number, objc_name="numberWithI16", objc_is_class_method=true) Number_numberWithI16 :: proc "c" (value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) }
+@(objc_type=Number, objc_name="numberWithU16", objc_is_class_method=true) Number_numberWithU16 :: proc "c" (value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) }
+@(objc_type=Number, objc_name="numberWithI32", objc_is_class_method=true) Number_numberWithI32 :: proc "c" (value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) }
+@(objc_type=Number, objc_name="numberWithU32", objc_is_class_method=true) Number_numberWithU32 :: proc "c" (value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) }
+@(objc_type=Number, objc_name="numberWithInt", objc_is_class_method=true) Number_numberWithInt :: proc "c" (value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) }
+@(objc_type=Number, objc_name="numberWithUint", objc_is_class_method=true) Number_numberWithUint :: proc "c" (value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) }
+@(objc_type=Number, objc_name="numberWithU64", objc_is_class_method=true) Number_numberWithU64 :: proc "c" (value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) }
+@(objc_type=Number, objc_name="numberWithI64", objc_is_class_method=true) Number_numberWithI64 :: proc "c" (value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) }
+@(objc_type=Number, objc_name="numberWithF32", objc_is_class_method=true) Number_numberWithF32 :: proc "c" (value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) }
+@(objc_type=Number, objc_name="numberWithF64", objc_is_class_method=true) Number_numberWithF64 :: proc "c" (value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) }
+@(objc_type=Number, objc_name="numberWithBool", objc_is_class_method=true) Number_numberWithBool :: proc "c" (value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) }
+
+@(objc_type=Number, objc_name="number", objc_is_class_method=true)
+Number_number :: proc{
+ Number_numberWithI8,
+ Number_numberWithU8,
+ Number_numberWithI16,
+ Number_numberWithU16,
+ Number_numberWithI32,
+ Number_numberWithU32,
+ Number_numberWithInt,
+ Number_numberWithUint,
+ Number_numberWithU64,
+ Number_numberWithI64,
+ Number_numberWithF32,
+ Number_numberWithF64,
+ Number_numberWithBool,
+}
+
+@(objc_type=Number, objc_name="initWithI8") Number_initWithI8 :: proc "c" (self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) }
+@(objc_type=Number, objc_name="initWithU8") Number_initWithU8 :: proc "c" (self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) }
+@(objc_type=Number, objc_name="initWithI16") Number_initWithI16 :: proc "c" (self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) }
+@(objc_type=Number, objc_name="initWithU16") Number_initWithU16 :: proc "c" (self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) }
+@(objc_type=Number, objc_name="initWithI32") Number_initWithI32 :: proc "c" (self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) }
+@(objc_type=Number, objc_name="initWithU32") Number_initWithU32 :: proc "c" (self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) }
+@(objc_type=Number, objc_name="initWithInt") Number_initWithInt :: proc "c" (self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) }
+@(objc_type=Number, objc_name="initWithUint") Number_initWithUint :: proc "c" (self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) }
+@(objc_type=Number, objc_name="initWithU64") Number_initWithU64 :: proc "c" (self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) }
+@(objc_type=Number, objc_name="initWithI64") Number_initWithI64 :: proc "c" (self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) }
+@(objc_type=Number, objc_name="initWithF32") Number_initWithF32 :: proc "c" (self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) }
+@(objc_type=Number, objc_name="initWithF64") Number_initWithF64 :: proc "c" (self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) }
+@(objc_type=Number, objc_name="initWithBool") Number_initWithBool :: proc "c" (self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) }
+
+
+@(objc_type=Number, objc_name="i8Value") Number_i8Value :: proc "c" (self: ^Number) -> i8 { return msgSend(i8, self, "charValue") }
+@(objc_type=Number, objc_name="u8Value") Number_u8Value :: proc "c" (self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") }
+@(objc_type=Number, objc_name="i16Value") Number_i16Value :: proc "c" (self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") }
+@(objc_type=Number, objc_name="u16Value") Number_u16Value :: proc "c" (self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") }
+@(objc_type=Number, objc_name="i32Value") Number_i32Value :: proc "c" (self: ^Number) -> i32 { return msgSend(i32, self, "intValue") }
+@(objc_type=Number, objc_name="u32Value") Number_u32Value :: proc "c" (self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") }
+@(objc_type=Number, objc_name="intValue") Number_intValue :: proc "c" (self: ^Number) -> int { return msgSend(int, self, "longValue") }
+@(objc_type=Number, objc_name="uintValue") Number_uintValue :: proc "c" (self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") }
+@(objc_type=Number, objc_name="u64Value") Number_u64Value :: proc "c" (self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") }
+@(objc_type=Number, objc_name="i64Value") Number_i64Value :: proc "c" (self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") }
+@(objc_type=Number, objc_name="f32Value") Number_f32Value :: proc "c" (self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") }
+@(objc_type=Number, objc_name="f64Value") Number_f64Value :: proc "c" (self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") }
+@(objc_type=Number, objc_name="boolValue") Number_boolValue :: proc "c" (self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") }
+@(objc_type=Number, objc_name="integerValue") Number_integerValue :: proc "c" (self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") }
+@(objc_type=Number, objc_name="uintegerValue") Number_uintegerValue :: proc "c" (self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") }
+@(objc_type=Number, objc_name="stringValue") Number_stringValue :: proc "c" (self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") }
+
+@(objc_type=Number, objc_name="compare")
+Number_compare :: proc "c" (self, other: ^Number) -> ComparisonResult {
+ return msgSend(ComparisonResult, self, "compare:", other)
+}
+
+@(objc_type=Number, objc_name="isEqualToNumber")
+Number_isEqualToNumber :: proc "c" (self, other: ^Number) -> BOOL {
+ return msgSend(BOOL, self, "isEqualToNumber:", other)
+}
+
+@(objc_type=Number, objc_name="descriptionWithLocale")
+Number_descriptionWithLocale :: proc "c" (self: ^Number, locale: ^Object) -> ^String {
+ return msgSend(^String, self, "descriptionWithLocale:", locale)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSObject.odin b/core/sys/darwin/Foundation/NSObject.odin
new file mode 100644
index 000000000..31ece47a1
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSObject.odin
@@ -0,0 +1,91 @@
+package objc_Foundation
+
+import "base:intrinsics"
+
+methodSignatureForSelector :: proc "c" (obj: ^Object, selector: SEL) -> rawptr {
+ return msgSend(rawptr, obj, "methodSignatureForSelector:", selector)
+}
+
+respondsToSelector :: proc "c" (obj: ^Object, selector: SEL) -> BOOL {
+ return msgSend(BOOL, obj, "respondsToSelector:", selector)
+}
+
+msgSendSafeCheck :: proc "c" (obj: ^Object, selector: SEL) -> BOOL {
+ return respondsToSelector(obj, selector) || methodSignatureForSelector(obj, selector) != nil
+}
+
+
+@(objc_class="NSObject")
+Object :: struct {using _: intrinsics.objc_object}
+
+@(objc_class="NSObject")
+Copying :: struct($T: typeid) {using _: Object}
+
+alloc :: proc "c" ($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
+ return msgSend(^T, T, "alloc")
+}
+@(objc_type=Object, objc_name="init")
+init :: proc "c" (self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
+ return msgSend(^T, self, "init")
+}
+@(objc_type=Object, objc_name="copy")
+copy :: proc "c" (self: ^Copying($T)) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
+ return msgSend(^T, self, "copy")
+}
+
+new :: proc "c" ($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
+ return init(alloc(T))
+}
+
+@(objc_type=Object, objc_name="retain")
+retain :: proc "c" (self: ^Object) {
+ _ = msgSend(^Object, self, "retain")
+}
+@(objc_type=Object, objc_name="release")
+release :: proc "c" (self: ^Object) {
+ msgSend(nil, self, "release")
+}
+@(objc_type=Object, objc_name="autorelease")
+autorelease :: proc "c" (self: ^Object) {
+ msgSend(nil, self, "autorelease")
+}
+@(objc_type=Object, objc_name="retainCount")
+retainCount :: proc "c" (self: ^Object) -> UInteger {
+ return msgSend(UInteger, self, "retainCount")
+}
+@(objc_type=Object, objc_name="class")
+class :: proc "c" (self: ^Object) -> Class {
+ return msgSend(Class, self, "class")
+}
+
+@(objc_type=Object, objc_name="hash")
+hash :: proc "c" (self: ^Object) -> UInteger {
+ return msgSend(UInteger, self, "hash")
+}
+
+@(objc_type=Object, objc_name="isEqual")
+isEqual :: proc "c" (self, pObject: ^Object) -> BOOL {
+ return msgSend(BOOL, self, "isEqual:", pObject)
+}
+
+@(objc_type=Object, objc_name="description")
+description :: proc "c" (self: ^Object) -> ^String {
+ return msgSend(^String, self, "description")
+}
+
+@(objc_type=Object, objc_name="debugDescription")
+debugDescription :: proc "c" (self: ^Object) -> ^String {
+ if msgSendSafeCheck(self, intrinsics.objc_find_selector("debugDescription")) {
+ return msgSend(^String, self, "debugDescription")
+ }
+ return nil
+}
+
+bridgingCast :: proc "c" ($T: typeid, obj: ^Object) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
+ return (T)(obj)
+}
+
+
+@(objc_class="NSCoder")
+Coder :: struct {using _: Object}
+// TODO(bill): Implement all the methods for this massive type \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSOpenPanel.odin b/core/sys/darwin/Foundation/NSOpenPanel.odin
new file mode 100644
index 000000000..ac5f9674e
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSOpenPanel.odin
@@ -0,0 +1,31 @@
+package objc_Foundation
+
+@(objc_class="NSOpenPanel")
+OpenPanel :: struct{ using _: SavePanel }
+
+@(objc_type=OpenPanel, objc_name="openPanel", objc_is_class_method=true)
+OpenPanel_openPanel :: proc "c" () -> ^OpenPanel {
+ return msgSend(^OpenPanel, OpenPanel, "openPanel")
+}
+
+@(objc_type=OpenPanel, objc_name="URLs")
+OpenPanel_URLs :: proc "c" (self: ^OpenPanel) -> ^Array {
+ return msgSend(^Array, self, "URLs")
+}
+
+@(objc_type=OpenPanel, objc_name="setCanChooseFiles")
+OpenPanel_setCanChooseFiles :: proc "c" (self: ^OpenPanel, setting: BOOL) {
+ msgSend(nil, self, "setCanChooseFiles:", setting)
+}
+@(objc_type=OpenPanel, objc_name="setCanChooseDirectories")
+OpenPanel_setCanChooseDirectories :: proc "c" (self: ^OpenPanel, setting: BOOL) {
+ msgSend(nil, self, "setCanChooseDirectories:", setting)
+}
+@(objc_type=OpenPanel, objc_name="setResolvesAliases")
+OpenPanel_setResolvesAliases :: proc "c" (self: ^OpenPanel, setting: BOOL) {
+ msgSend(nil, self, "setResolvesAliases:", setting)
+}
+@(objc_type=OpenPanel, objc_name="setAllowsMultipleSelection")
+OpenPanel_setAllowsMultipleSelection :: proc "c" (self: ^OpenPanel, setting: BOOL) {
+ msgSend(nil, self, "setAllowsMultipleSelection:", setting)
+}
diff --git a/core/sys/darwin/Foundation/NSPanel.odin b/core/sys/darwin/Foundation/NSPanel.odin
new file mode 100644
index 000000000..4bdf08cdb
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSPanel.odin
@@ -0,0 +1,9 @@
+package objc_Foundation
+
+ModalResponse :: enum UInteger {
+ Cancel = 0,
+ OK = 1,
+}
+
+@(objc_class="NSPanel")
+Panel :: struct{ using _: Window }
diff --git a/core/sys/darwin/Foundation/NSPasteboard.odin b/core/sys/darwin/Foundation/NSPasteboard.odin
new file mode 100644
index 000000000..74cf7d172
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSPasteboard.odin
@@ -0,0 +1,5 @@
+package objc_Foundation
+
+@(objc_class="NSPasteboard")
+Pasteboard :: struct {using _: Object}
+// TODO: implement NSPasteboard
diff --git a/core/sys/darwin/Foundation/NSRange.odin b/core/sys/darwin/Foundation/NSRange.odin
new file mode 100644
index 000000000..dcb100e91
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSRange.odin
@@ -0,0 +1,22 @@
+package objc_Foundation
+
+Range :: struct {
+ location: UInteger,
+ length: UInteger,
+}
+
+Range_Make :: proc "c" (loc, len: UInteger) -> Range {
+ return Range{loc, len}
+}
+
+Range_Equal :: proc "c" (a, b: Range) -> BOOL {
+ return a == b
+}
+
+Range_LocationInRange :: proc "c" (self: Range, loc: UInteger) -> BOOL {
+ return !((loc < self.location) && ((loc - self.location) < self.length))
+}
+
+Range_Max :: proc "c" (self: Range) -> UInteger {
+ return self.location + self.length
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSSavePanel.odin b/core/sys/darwin/Foundation/NSSavePanel.odin
new file mode 100644
index 000000000..8e4d7a07b
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSSavePanel.odin
@@ -0,0 +1,9 @@
+package objc_Foundation
+
+@(objc_class="NSSavePanel")
+SavePanel :: struct{ using _: Panel }
+
+@(objc_type=SavePanel, objc_name="runModal")
+SavePanel_runModal :: proc "c" (self: ^SavePanel) -> ModalResponse {
+ return msgSend(ModalResponse, self, "runModal")
+}
diff --git a/core/sys/darwin/Foundation/NSScreen.odin b/core/sys/darwin/Foundation/NSScreen.odin
new file mode 100644
index 000000000..a8fe44aa5
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSScreen.odin
@@ -0,0 +1,33 @@
+package objc_Foundation
+
+@(objc_class="NSScreen")
+Screen :: struct {using _: Object}
+
+@(objc_type=Screen, objc_name="mainScreen")
+Screen_mainScreen :: proc "c" () -> ^Screen {
+ return msgSend(^Screen, Screen, "mainScreen")
+}
+@(objc_type=Screen, objc_name="deepestScreen")
+Screen_deepestScreen :: proc "c" () -> ^Screen {
+ return msgSend(^Screen, Screen, "deepestScreen")
+}
+@(objc_type=Screen, objc_name="screens")
+Screen_screens :: proc "c" () -> ^Array {
+ return msgSend(^Array, Screen, "screens")
+}
+@(objc_type=Screen, objc_name="frame")
+Screen_frame :: proc "c" (self: ^Screen) -> Rect {
+ return msgSend(Rect, self, "frame")
+}
+@(objc_type=Screen, objc_name="depth")
+Screen_depth :: proc "c" (self: ^Screen) -> Depth {
+ return msgSend(Depth, self, "depth")
+}
+@(objc_type=Screen, objc_name="visibleFrame")
+Screen_visibleFrame :: proc "c" (self: ^Screen) -> Rect {
+ return msgSend(Rect, self, "visibleFrame")
+}
+@(objc_type=Screen, objc_name="colorSpace")
+Screen_colorSpace :: proc "c" (self: ^Screen) -> ^ColorSpace {
+ return msgSend(^ColorSpace, self, "colorSpace")
+}
diff --git a/core/sys/darwin/Foundation/NSSet.odin b/core/sys/darwin/Foundation/NSSet.odin
new file mode 100644
index 000000000..7fb8db6c2
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSSet.odin
@@ -0,0 +1,27 @@
+package objc_Foundation
+
+@(objc_class="NSSet")
+Set :: struct {using _: Copying(Set)}
+
+
+@(objc_type=Set, objc_name="alloc", objc_is_class_method=true)
+Set_alloc :: proc "c" () -> ^Set {
+ return msgSend(^Set, Set, "alloc")
+}
+
+@(objc_type=Set, objc_name="init")
+Set_init :: proc "c" (self: ^Set) -> ^Set {
+ return msgSend(^Set, self, "init")
+}
+
+
+@(objc_type=Set, objc_name="initWithObjects")
+Set_initWithObjects :: proc "c" (self: ^Set, objects: [^]^Object, count: UInteger) -> ^Set {
+ return msgSend(^Set, self, "initWithObjects:count:", objects, count)
+}
+
+
+@(objc_type=Set, objc_name="initWithCoder")
+Set_initWithCoder :: proc "c" (self: ^Set, coder: ^Coder) -> ^Set {
+ return msgSend(^Set, self, "initWithCoder:", coder)
+}
diff --git a/core/sys/darwin/Foundation/NSString.odin b/core/sys/darwin/Foundation/NSString.odin
new file mode 100644
index 000000000..d3c6c454d
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSString.odin
@@ -0,0 +1,140 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+
+@(objc_class="NSString")
+String :: struct {using _: Copying(String)}
+
+StringEncoding :: enum UInteger {
+ ASCII = 1,
+ NEXTSTEP = 2,
+ JapaneseEUC = 3,
+ UTF8 = 4,
+ ISOLatin1 = 5,
+ Symbol = 6,
+ NonLossyASCII = 7,
+ ShiftJIS = 8,
+ ISOLatin2 = 9,
+ Unicode = 10,
+ WindowsCP1251 = 11,
+ WindowsCP1252 = 12,
+ WindowsCP1253 = 13,
+ WindowsCP1254 = 14,
+ WindowsCP1250 = 15,
+ ISO2022JP = 21,
+ MacOSRoman = 30,
+
+ UTF16 = Unicode,
+
+ UTF16BigEndian = 0x90000100,
+ UTF16LittleEndian = 0x94000100,
+
+ UTF32 = 0x8c000100,
+ UTF32BigEndian = 0x98000100,
+ UTF32LittleEndian = 0x9c000100,
+}
+
+StringCompareOptions :: distinct bit_set[StringCompareOption; UInteger]
+StringCompareOption :: enum UInteger {
+ CaseInsensitive = 0,
+ LiteralSearch = 1,
+ BackwardsSearch = 2,
+ AnchoredSearch = 3,
+ NumericSearch = 6,
+ DiacriticInsensitive = 7,
+ WidthInsensitive = 8,
+ ForcedOrdering = 9,
+ RegularExpression = 10,
+}
+
+unichar :: distinct u16
+
+@(link_prefix="NS", default_calling_convention="c")
+foreign Foundation {
+ StringFromClass :: proc(cls: Class) -> ^String ---
+}
+
+AT :: MakeConstantString
+MakeConstantString :: proc "c" (#const c: cstring) -> ^String {
+ foreign Foundation {
+ __CFStringMakeConstantString :: proc "c" (c: cstring) -> ^String ---
+ }
+ return __CFStringMakeConstantString(c)
+}
+
+
+@(objc_type=String, objc_name="alloc", objc_is_class_method=true)
+String_alloc :: proc "c" () -> ^String {
+ return msgSend(^String, String, "alloc")
+}
+
+@(objc_type=String, objc_name="init")
+String_init :: proc "c" (self: ^String) -> ^String {
+ return msgSend(^String, self, "init")
+}
+
+
+@(objc_type=String, objc_name="initWithString")
+String_initWithString :: proc "c" (self: ^String, other: ^String) -> ^String {
+ return msgSend(^String, self, "initWithString:", other)
+}
+
+@(objc_type=String, objc_name="initWithCString")
+String_initWithCString :: proc "c" (self: ^String, pString: cstring, encoding: StringEncoding) -> ^String {
+ return msgSend(^String, self, "initWithCstring:encoding:", pString, encoding)
+}
+
+@(objc_type=String, objc_name="initWithBytesNoCopy")
+String_initWithBytesNoCopy :: proc "c" (self: ^String, pBytes: rawptr, length: UInteger, encoding: StringEncoding, freeWhenDone: bool) -> ^String {
+ return msgSend(^String, self, "initWithBytesNoCopy:length:encoding:freeWhenDone:", pBytes, length, encoding, freeWhenDone)
+}
+
+@(objc_type=String, objc_name="initWithOdinString")
+String_initWithOdinString :: proc "c" (self: ^String, str: string) -> ^String {
+ return String_initWithBytesNoCopy(self, raw_data(str), UInteger(len(str)), .UTF8, false)
+}
+
+@(objc_type=String, objc_name="characterAtIndex")
+String_characterAtIndex :: proc "c" (self: ^String, index: UInteger) -> unichar {
+ return msgSend(unichar, self, "characterAtIndex:", index)
+}
+
+@(objc_type=String, objc_name="length")
+String_length :: proc "c" (self: ^String) -> UInteger {
+ return msgSend(UInteger, self, "length")
+}
+
+@(objc_type=String, objc_name="cstringUsingEncoding")
+String_cstringUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> cstring {
+ return msgSend(cstring, self, "cStringUsingEncoding:", encoding)
+}
+
+@(objc_type=String, objc_name="UTF8String")
+String_UTF8String :: proc "c" (self: ^String) -> cstring {
+ return msgSend(cstring, self, "UTF8String")
+}
+
+@(objc_type=String, objc_name="odinString")
+String_odinString :: proc "c" (self: ^String) -> string {
+ return string(String_UTF8String(self))
+}
+
+@(objc_type=String, objc_name="maximumLengthOfBytesUsingEncoding")
+String_maximumLengthOfBytesUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> UInteger {
+ return msgSend(UInteger, self, "maximumLengthOfBytesUsingEncoding:", encoding)
+}
+
+@(objc_type=String, objc_name="lengthOfBytesUsingEncoding")
+String_lengthOfBytesUsingEncoding :: proc "c" (self: ^String, encoding: StringEncoding) -> UInteger {
+ return msgSend(UInteger, self, "lengthOfBytesUsingEncoding:", encoding)
+}
+
+@(objc_type=String, objc_name="isEqualToString")
+String_isEqualToString :: proc "c" (self, other: ^String) -> BOOL {
+ return msgSend(BOOL, self, "isEqualToString:", other)
+}
+
+@(objc_type=String, objc_name="rangeOfString")
+String_rangeOfString :: proc "c" (self, other: ^String, options: StringCompareOptions) -> Range {
+ return msgSend(Range, self, "rangeOfString:options:", other, options)
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSTypes.odin b/core/sys/darwin/Foundation/NSTypes.odin
new file mode 100644
index 000000000..fbd883a8f
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSTypes.odin
@@ -0,0 +1,61 @@
+package objc_Foundation
+
+import "base:intrinsics"
+
+@(private) msgSend :: intrinsics.objc_send
+
+id :: ^intrinsics.objc_object
+SEL :: ^intrinsics.objc_selector
+Class :: ^intrinsics.objc_class
+
+TimeInterval :: distinct f64
+Integer :: distinct int
+UInteger :: distinct uint
+
+IntegerMax :: max(Integer)
+Integermin :: min(Integer)
+UIntegerMax :: max(UInteger)
+
+BOOL :: bool // TODO(bill): should this be `distinct`?
+YES :: true
+NO :: false
+
+OperatingSystemVersion :: struct #packed {
+ majorVersion: Integer,
+ minorVersion: Integer,
+ patchVersion: Integer,
+}
+
+ComparisonResult :: enum Integer {
+ OrderedAscending = -1,
+ OrderedSame = 0,
+ OrderedDescending = 1,
+}
+
+NotFound :: IntegerMax
+
+Float :: distinct (f32 when size_of(uint) == 4 else f64)
+
+Point :: struct {
+ x: Float,
+ y: Float,
+}
+
+Size :: struct {
+ width: Float,
+ height: Float,
+}
+
+when size_of(UInteger) == 8 {
+ _UINTEGER_ENCODING :: "Q"
+} else {
+ _UINTEGER_ENCODING :: "I"
+}
+
+when size_of(Float) == 8 {
+ _POINT_ENCODING :: "{CGPoint=dd}"
+ _SIZE_ENCODING :: "{CGSize=dd}"
+} else {
+ _POINT_ENCODING :: "{NSPoint=ff}"
+ _SIZE_ENCODING :: "{NSSize=ff}"
+} \ No newline at end of file
diff --git a/core/sys/darwin/Foundation/NSURL.odin b/core/sys/darwin/Foundation/NSURL.odin
new file mode 100644
index 000000000..9e9081219
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSURL.odin
@@ -0,0 +1,30 @@
+package objc_Foundation
+
+@(objc_class="NSURL")
+URL :: struct{using _: Copying(URL)}
+
+
+@(objc_type=URL, objc_name="alloc", objc_is_class_method=true)
+URL_alloc :: proc "c" () -> ^URL {
+ return msgSend(^URL, URL, "alloc")
+}
+
+@(objc_type=URL, objc_name="init")
+URL_init :: proc "c" (self: ^URL) -> ^URL {
+ return msgSend(^URL, self, "init")
+}
+
+@(objc_type=URL, objc_name="initWithString")
+URL_initWithString :: proc "c" (self: ^URL, value: ^String) -> ^URL {
+ return msgSend(^URL, self, "initWithString:", value)
+}
+
+@(objc_type=URL, objc_name="initFileURLWithPath")
+URL_initFileURLWithPath :: proc "c" (self: ^URL, path: ^String) -> ^URL {
+ return msgSend(^URL, self, "initFileURLWithPath:", path)
+}
+
+@(objc_type=URL, objc_name="fileSystemRepresentation")
+URL_fileSystemRepresentation :: proc "c" (self: ^URL) -> cstring {
+ return msgSend(cstring, self, "fileSystemRepresentation")
+}
diff --git a/core/sys/darwin/Foundation/NSUndoManager.odin b/core/sys/darwin/Foundation/NSUndoManager.odin
new file mode 100644
index 000000000..16411dcb4
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSUndoManager.odin
@@ -0,0 +1,5 @@
+package objc_Foundation
+
+@(objc_class="NSUndoManager")
+UndoManager :: struct {using _: Object}
+// TODO: implement NSUndoManager
diff --git a/core/sys/darwin/Foundation/NSUserActivity.odin b/core/sys/darwin/Foundation/NSUserActivity.odin
new file mode 100644
index 000000000..3b2f956ee
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSUserActivity.odin
@@ -0,0 +1,5 @@
+package objc_Foundation
+
+@(objc_class="NSUserActivity")
+UserActivity :: struct {using _: Object}
+// TODO: implement NSUserActivity
diff --git a/core/sys/darwin/Foundation/NSUserDefaults.odin b/core/sys/darwin/Foundation/NSUserDefaults.odin
new file mode 100644
index 000000000..a8a6d7545
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSUserDefaults.odin
@@ -0,0 +1,14 @@
+package objc_Foundation
+
+@(objc_class="NSUserDefaults")
+UserDefaults :: struct { using _: Object }
+
+@(objc_type=UserDefaults, objc_name="standardUserDefaults", objc_is_class_method=true)
+UserDefaults_standardUserDefaults :: proc "c" () -> ^UserDefaults {
+ return msgSend(^UserDefaults, UserDefaults, "standardUserDefaults")
+}
+
+@(objc_type=UserDefaults, objc_name="setBoolForKey")
+UserDefaults_setBoolForKey :: proc "c" (self: ^UserDefaults, value: BOOL, name: ^String) {
+ msgSend(nil, self, "setBool:forKey:", value, name)
+}
diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin
new file mode 100644
index 000000000..7159a7c3a
--- /dev/null
+++ b/core/sys/darwin/Foundation/NSWindow.odin
@@ -0,0 +1,714 @@
+package objc_Foundation
+
+import "core:strings"
+import "base:runtime"
+import "base:intrinsics"
+
+Rect :: struct {
+ using origin: Point,
+ using size: Size,
+}
+
+Depth :: enum UInteger {
+ onehundredtwentyeightBitRGB = 544,
+ sixtyfourBitRGB = 528,
+ twentyfourBitRGB = 520,
+}
+
+when size_of(Float) == 8 {
+ _RECT_ENCODING :: "{CGRect="+_POINT_ENCODING+_SIZE_ENCODING+"}"
+} else {
+ _RECT_ENCODING :: "{NSRect="+_POINT_ENCODING+_SIZE_ENCODING+"}"
+}
+
+WindowStyleFlag :: enum UInteger {
+ Titled = 0,
+ Closable = 1,
+ Miniaturizable = 2,
+ Resizable = 3,
+ TexturedBackground = 8,
+ UnifiedTitleAndToolbar = 12,
+ FullScreen = 14,
+ FullSizeContentView = 15,
+ UtilityWindow = 4,
+ DocModalWindow = 6,
+ NonactivatingPanel = 7,
+ HUDWindow = 13,
+}
+WindowStyleMask :: distinct bit_set[WindowStyleFlag; UInteger]
+WindowStyleMaskBorderless :: WindowStyleMask{}
+WindowStyleMaskTitled :: WindowStyleMask{.Titled}
+WindowStyleMaskClosable :: WindowStyleMask{.Closable}
+WindowStyleMaskMiniaturizable :: WindowStyleMask{.Miniaturizable}
+WindowStyleMaskResizable :: WindowStyleMask{.Resizable}
+WindowStyleMaskTexturedBackground :: WindowStyleMask{.TexturedBackground}
+WindowStyleMaskUnifiedTitleAndToolbar :: WindowStyleMask{.UnifiedTitleAndToolbar}
+WindowStyleMaskFullScreen :: WindowStyleMask{.FullScreen}
+WindowStyleMaskFullSizeContentView :: WindowStyleMask{.FullSizeContentView}
+WindowStyleMaskUtilityWindow :: WindowStyleMask{.UtilityWindow}
+WindowStyleMaskDocModalWindow :: WindowStyleMask{.DocModalWindow}
+WindowStyleMaskNonactivatingPanel :: WindowStyleMask{.NonactivatingPanel}
+WindowStyleMaskHUDWindow :: WindowStyleMask{.HUDWindow}
+
+BackingStoreType :: enum UInteger {
+ Retained = 0,
+ Nonretained = 1,
+ Buffered = 2,
+}
+
+WindowDelegateTemplate :: struct {
+ // Managing Sheets
+ windowWillPositionSheetUsingRect: proc(window: ^Window, sheet: ^Window, rect: Rect) -> Rect,
+ windowWillBeginSheet: proc(notification: ^Notification),
+ windowDidEndSheet: proc(notification: ^Notification),
+ // Sizing Windows
+ windowWillResizeToSize: proc(sender: ^Window, frameSize: Size) -> Size,
+ windowDidResize: proc(notification: ^Notification),
+ windowWillStartLiveResize: proc(noitifcation: ^Notification),
+ windowDidEndLiveResize: proc(notification: ^Notification),
+ // Minimizing Windows
+ windowWillMiniaturize: proc(notification: ^Notification),
+ windowDidMiniaturize: proc(notification: ^Notification),
+ windowDidDeminiaturize: proc(notification: ^Notification),
+ // Zooming window
+ windowWillUseStandardFrameDefaultFrame: proc(window: ^Window, newFrame: Rect) -> Rect,
+ windowShouldZoomToFrame: proc(window: ^Window, newFrame: Rect) -> BOOL,
+ // Managing Full-Screen Presentation
+ windowWillUseFullScreenContentSize: proc(window: ^Window, proposedSize: Size) -> Size,
+ windowWillUseFullScreenPresentationOptions: proc(window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions,
+ windowWillEnterFullScreen: proc(notification: ^Notification),
+ windowDidEnterFullScreen: proc(notification: ^Notification),
+ windowWillExitFullScreen: proc(notification: ^Notification),
+ windowDidExitFullScreen: proc(notification: ^Notification),
+ // Custom Full-Screen Presentation Animations
+ customWindowsToEnterFullScreenForWindow: proc(window: ^Window) -> ^Array,
+ customWindowsToEnterFullScreenForWindowOnScreen: proc(window: ^Window, screen: ^Screen) -> ^Array,
+ windowStartCustomAnimationToEnterFullScreenWithDuration: proc(window: ^Window, duration: TimeInterval),
+ windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration: proc(window: ^Window, screen: ^Screen, duration: TimeInterval),
+ windowDidFailToEnterFullScreen: proc(window: ^Window),
+ customWindowsToExitFullScreenForWindow: proc(window: ^Window) -> ^Array,
+ windowStartCustomAnimationToExitFullScreenWithDuration: proc(window: ^Window, duration: TimeInterval),
+ windowDidFailToExitFullScreen: proc(window: ^Window),
+ // Moving Windows
+ windowWillMove: proc(notification: ^Notification),
+ windowDidMove: proc(notification: ^Notification),
+ windowDidChangeScreen: proc(notification: ^Notification),
+ windowDidChangeScreenProfile: proc(notification: ^Notification),
+ windowDidChangeBackingProperties: proc(notification: ^Notification),
+ // Closing Windows
+ windowShouldClose: proc(sender: ^Window) -> BOOL,
+ windowWillClose: proc(notification: ^Notification),
+ // Managing Key Status
+ windowDidBecomeKey: proc(notification: ^Notification),
+ windowDidResignKey: proc(notification: ^Notification),
+ // Managing Main Status
+ windowDidBecomeMain: proc(notification: ^Notification),
+ windowDidResignMain: proc(notification: ^Notification),
+ // Managing Field Editors
+ windowWillReturnFieldEditorToObject: proc(sender: ^Window, client: id) -> id,
+ // Updating Windows
+ windowDidUpdate: proc (notification: ^Notification),
+ // Exposing Windows
+ windowDidExpose: proc (notification: ^Notification),
+ // Managing Occlusion State
+ windowDidChangeOcclusionState: proc(notification: ^Notification),
+ // Dragging Windows
+ windowShouldDragDocumentWithEventFromWithPasteboard: proc(window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL,
+ // Getting the Undo Manager
+ windowWillReturnUndoManager: proc(window: ^Window) -> ^UndoManager,
+ // Managing Titles
+ windowShouldPopUpDocumentPathMenu: proc(window: ^Window, menu: ^Menu) -> BOOL,
+ // Managing Restorable State
+ windowWillEncodeRestorableState: proc(window: ^Window, state: ^Coder),
+ windowDidEncodeRestorableState: proc(window: ^Window, state: ^Coder),
+ // Managing Presentation in Version Browsers
+ windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize: proc(window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size,
+ windowWillEnterVersionBrowser: proc(notification: ^Notification),
+ windowDidEnterVersionBrowser: proc(notification: ^Notification),
+ windowWillExitVersionBrowser: proc(notification: ^Notification),
+ windowDidExitVersionBrowser: proc(notification: ^Notification),
+}
+
+
+WindowDelegate :: struct { using _: Object } // This is not the same as NSWindowDelegate
+_WindowDelegateInternal :: struct {
+ using _: WindowDelegateTemplate,
+ _context: runtime.Context,
+}
+
+window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, class_name: string, delegate_context: Maybe(runtime.Context)) -> ^WindowDelegate {
+ class := objc_allocateClassPair(intrinsics.objc_find_class("NSObject"), strings.clone_to_cstring(class_name, context.temp_allocator), 0); if class == nil {
+ // Class already registered
+ return nil
+ }
+ if template.windowWillPositionSheetUsingRect != nil {
+ windowWillPositionSheetUsingRect :: proc "c" (self: id, window: ^Window, sheet: ^Window, rect: Rect) -> Rect {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillPositionSheetUsingRect(window, sheet, rect)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:willPositionSheet:usingRect:"), auto_cast windowWillPositionSheetUsingRect, _RECT_ENCODING+"@:@@"+_RECT_ENCODING)
+ }
+ if template.windowWillBeginSheet != nil {
+ windowWillBeginSheet :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillBeginSheet(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillBeginSheet:"), auto_cast windowWillBeginSheet, "v@:@")
+ }
+ if template.windowDidEndSheet != nil {
+ windowDidEndSheet :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidEndSheet(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidEndSheet:"), auto_cast windowDidEndSheet, "v@:@")
+ }
+ if template.windowWillResizeToSize != nil {
+ windowWillResizeToSize :: proc "c" (self: id, sender: ^Window, frameSize: Size) -> Size {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillResizeToSize(sender, frameSize)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillResize:toSize:"), auto_cast windowWillResizeToSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING)
+ }
+ if template.windowDidResize != nil {
+ windowDidResize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidResize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidResize:"), auto_cast windowDidResize, "v@:@")
+ }
+ if template.windowWillStartLiveResize != nil {
+ windowWillStartLiveResize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillStartLiveResize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillStartLiveResize:"), auto_cast windowWillStartLiveResize, "v@:@")
+ }
+ if template.windowDidEndLiveResize != nil {
+ windowDidEndLiveResize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidEndLiveResize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidEndLiveResize:"), auto_cast windowDidEndLiveResize, "v@:@")
+ }
+ if template.windowWillMiniaturize != nil {
+ windowWillMiniaturize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillMiniaturize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillMiniaturize:"), auto_cast windowWillMiniaturize, "v@:@")
+ }
+ if template.windowDidMiniaturize != nil {
+ windowDidMiniaturize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidMiniaturize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidMiniaturize:"), auto_cast windowDidMiniaturize, "v@:@")
+ }
+ if template.windowDidDeminiaturize != nil {
+ windowDidDeminiaturize :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidDeminiaturize(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidDeminiaturize:"), auto_cast windowDidDeminiaturize, "v@:@")
+ }
+ if template.windowWillUseStandardFrameDefaultFrame != nil {
+ windowWillUseStandardFrameDefaultFrame :: proc(self: id, window: ^Window, newFrame: Rect) -> Rect {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillUseStandardFrameDefaultFrame(window, newFrame)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillUseStandardFrame:defaultFrame:"), auto_cast windowWillUseStandardFrameDefaultFrame, _RECT_ENCODING+"@:@"+_RECT_ENCODING)
+ }
+ if template.windowShouldZoomToFrame != nil {
+ windowShouldZoomToFrame :: proc "c" (self: id, window: ^Window, newFrame: Rect) -> BOOL {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowShouldZoomToFrame(window, newFrame)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowShouldZoom:toFrame:"), auto_cast windowShouldZoomToFrame, "B@:@"+_RECT_ENCODING)
+ }
+ if template.windowWillUseFullScreenContentSize != nil {
+ windowWillUseFullScreenContentSize :: proc "c" (self: id, window: ^Window, proposedSize: Size) -> Size {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillUseFullScreenContentSize(window, proposedSize)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenContentSize:"), auto_cast windowWillUseFullScreenContentSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING)
+ }
+ if template.windowWillUseFullScreenPresentationOptions != nil {
+ windowWillUseFullScreenPresentationOptions :: proc(self: id, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillUseFullScreenPresentationOptions(window, proposedOptions)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenPresentationOptions:"), auto_cast windowWillUseFullScreenPresentationOptions, _UINTEGER_ENCODING+"@:@"+_UINTEGER_ENCODING)
+ }
+ if template.windowWillEnterFullScreen != nil {
+ windowWillEnterFullScreen :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillEnterFullScreen(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterFullScreen:"), auto_cast windowWillEnterFullScreen, "v@:@")
+ }
+ if template.windowDidEnterFullScreen != nil {
+ windowDidEnterFullScreen :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidEnterFullScreen(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterFullScreen:"), auto_cast windowDidEnterFullScreen, "v@:@")
+ }
+ if template.windowWillExitFullScreen != nil {
+ windowWillExitFullScreen :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillExitFullScreen(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillExitFullScreen:"), auto_cast windowWillExitFullScreen, "v@:@")
+ }
+ if template.windowDidExitFullScreen != nil {
+ windowDidExitFullScreen :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidExitFullScreen(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidExitFullScreen:"), auto_cast windowDidExitFullScreen, "v@:@")
+ }
+ if template.customWindowsToEnterFullScreenForWindow != nil {
+ customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.customWindowsToEnterFullScreenForWindow(window)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:"), auto_cast customWindowsToEnterFullScreenForWindow, "@@:@")
+ }
+ if template.customWindowsToEnterFullScreenForWindowOnScreen != nil {
+ customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, window: ^Window, screen: ^Screen) -> ^Array {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.customWindowsToEnterFullScreenForWindowOnScreen(window, screen)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:onScreen:"), auto_cast customWindowsToEnterFullScreenForWindowOnScreen, "@@:@@")
+ }
+ if template.windowStartCustomAnimationToEnterFullScreenWithDuration != nil {
+ windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowStartCustomAnimationToEnterFullScreenWithDuration(window, duration)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenWithDuration, "v@:@@")
+ }
+ if template.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration != nil {
+ windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, window: ^Window, screen: ^Screen, duration: TimeInterval) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration(window, screen, duration)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenOnScreen:withDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration, "v@:@@d")
+ }
+ if template.windowDidFailToEnterFullScreen != nil {
+ windowDidFailToEnterFullScreen :: proc "c" (self: id, window: ^Window) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidFailToEnterFullScreen(window)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToEnterFullScreen:"), auto_cast windowDidFailToEnterFullScreen, "v@:@")
+ }
+ if template.customWindowsToExitFullScreenForWindow != nil {
+ customWindowsToExitFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.customWindowsToExitFullScreenForWindow(window)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("customWindowsToExitFullScreenForWindow:"), auto_cast customWindowsToExitFullScreenForWindow, "@@:@")
+ }
+ if template.windowStartCustomAnimationToExitFullScreenWithDuration != nil {
+ windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowStartCustomAnimationToExitFullScreenWithDuration(window, duration)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToExitFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToExitFullScreenWithDuration, "v@:@d")
+ }
+ if template.windowDidFailToExitFullScreen != nil {
+ windowDidFailToExitFullScreen :: proc "c" (self: id, window: ^Window) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidFailToExitFullScreen(window)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToExitFullScreen:"), auto_cast windowDidFailToExitFullScreen, "v@:@")
+ }
+ if template.windowWillMove != nil {
+ windowWillMove :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillMove(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillMove:"), auto_cast windowWillMove, "v@:@")
+ }
+ if template.windowDidMove != nil {
+ windowDidMove :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidMove(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidMove:"), auto_cast windowDidMove, "v@:@")
+ }
+ if template.windowDidChangeScreen != nil {
+ windowDidChangeScreen :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidChangeScreen(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreen:"), auto_cast windowDidChangeScreen, "v@:@")
+ }
+ if template.windowDidChangeScreenProfile != nil {
+ windowDidChangeScreenProfile :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidChangeScreenProfile(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreenProfile:"), auto_cast windowDidChangeScreenProfile, "v@:@")
+ }
+ if template.windowDidChangeBackingProperties != nil {
+ windowDidChangeBackingProperties :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidChangeBackingProperties(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeBackingProperties:"), auto_cast windowDidChangeBackingProperties, "v@:@")
+ }
+ if template.windowShouldClose != nil {
+ windowShouldClose :: proc "c" (self:id, sender: ^Window) -> BOOL {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowShouldClose(sender)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowShouldClose:"), auto_cast windowShouldClose, "B@:@")
+ }
+ if template.windowWillClose != nil {
+ windowWillClose :: proc "c" (self:id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillClose(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillClose:"), auto_cast windowWillClose, "v@:@")
+ }
+ if template.windowDidBecomeKey != nil {
+ windowDidBecomeKey :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidBecomeKey(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeKey:"), auto_cast windowDidBecomeKey, "v@:@")
+ }
+ if template.windowDidResignKey != nil {
+ windowDidResignKey :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidResignKey(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidResignKey:"), auto_cast windowDidResignKey, "v@:@")
+ }
+ if template.windowDidBecomeMain != nil {
+ windowDidBecomeMain :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidBecomeMain(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeMain:"), auto_cast windowDidBecomeMain, "v@:@")
+ }
+ if template.windowDidResignMain != nil {
+ windowDidResignMain :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidResignMain(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidResignMain:"), auto_cast windowDidResignMain, "v@:@")
+ }
+ if template.windowWillReturnFieldEditorToObject != nil {
+ windowWillReturnFieldEditorToObject :: proc "c" (self:id, sender: ^Window, client: id) -> id {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillReturnFieldEditorToObject(sender, client)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnFieldEditor:toObject:"), auto_cast windowWillReturnFieldEditorToObject, "@@:@@")
+ }
+ if template.windowDidUpdate != nil {
+ windowDidUpdate :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidUpdate(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidUpdate:"), auto_cast windowDidUpdate, "v@:@")
+ }
+ if template.windowDidExpose != nil {
+ windowDidExpose :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidExpose(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidExpose:"), auto_cast windowDidExpose, "v@:@")
+ }
+ if template.windowDidChangeOcclusionState != nil {
+ windowDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidChangeOcclusionState(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeOcclusionState:"), auto_cast windowDidChangeOcclusionState, "v@:@")
+ }
+ if template.windowShouldDragDocumentWithEventFromWithPasteboard != nil {
+ windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowShouldDragDocumentWithEventFromWithPasteboard(window, event, dragImageLocation, pasteboard)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:shouldDragDocumentWithEvent:from:withPasteboard:"), auto_cast windowShouldDragDocumentWithEventFromWithPasteboard, "B@:@@"+_POINT_ENCODING+"@")
+ }
+ if template.windowWillReturnUndoManager != nil {
+ windowWillReturnUndoManager :: proc "c" (self: id, window: ^Window) -> ^UndoManager {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillReturnUndoManager(window)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnUndoManager:"), auto_cast windowWillReturnUndoManager, "@@:@")
+ }
+ if template.windowShouldPopUpDocumentPathMenu != nil {
+ windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, window: ^Window, menu: ^Menu) -> BOOL {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowShouldPopUpDocumentPathMenu(window, menu)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:shouldPopUpDocumentPathMenu:"), auto_cast windowShouldPopUpDocumentPathMenu, "B@:@@")
+ }
+ if template.windowWillEncodeRestorableState != nil {
+ windowWillEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillEncodeRestorableState(window, state)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:willEncodeRestorableState:"), auto_cast windowWillEncodeRestorableState, "v@:@@")
+ }
+ if template.windowDidEncodeRestorableState != nil {
+ windowDidEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidEncodeRestorableState(window, state)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:didDecodeRestorableState:"), auto_cast windowDidEncodeRestorableState, "v@:@@")
+ }
+ if template.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize != nil {
+ windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ return del.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize(window, maxPreferredFrameSize, maxPreferredFrameSize)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("window:willResizeForVersionBrowserWithMaxPreferredSize:maxAllowedSize:"), auto_cast windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING+_SIZE_ENCODING)
+ }
+ if template.windowWillEnterVersionBrowser != nil {
+ windowWillEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillEnterVersionBrowser(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterVersionBrowser:"), auto_cast windowWillEnterVersionBrowser, "v@:@")
+ }
+ if template.windowDidEnterVersionBrowser != nil {
+ windowDidEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidEnterVersionBrowser(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterVersionBrowser:"), auto_cast windowDidEnterVersionBrowser, "v@:@")
+ }
+ if template.windowWillExitVersionBrowser != nil {
+ windowWillExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowWillExitVersionBrowser(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowWillExitVersionBrowser:"), auto_cast windowWillExitVersionBrowser, "v@:@")
+ }
+ if template.windowDidExitVersionBrowser != nil {
+ windowDidExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) {
+ del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self)
+ context = del._context
+ del.windowDidExitVersionBrowser(notification)
+ }
+ class_addMethod(class, intrinsics.objc_find_selector("windowDidExitVersionBrowser:"), auto_cast windowDidExitVersionBrowser, "v@:@")
+ }
+
+ objc_registerClassPair(class)
+ del := class_createInstance(class, size_of(_WindowDelegateInternal))
+ del_internal := cast(^_WindowDelegateInternal)object_getIndexedIvars(del)
+ del_internal^ = {
+ template,
+ delegate_context.(runtime.Context) or_else runtime.default_context(),
+ }
+
+ return cast(^WindowDelegate)del
+}
+
+@(objc_class="CALayer")
+Layer :: struct { using _: Object }
+
+@(objc_type=Layer, objc_name="contentsScale")
+Layer_contentsScale :: proc "c" (self: ^Layer) -> Float {
+ return msgSend(Float, self, "contentsScale")
+}
+@(objc_type=Layer, objc_name="setContentsScale")
+Layer_setContentsScale :: proc "c" (self: ^Layer, scale: Float) {
+ msgSend(nil, self, "setContentsScale:", scale)
+}
+@(objc_type=Layer, objc_name="frame")
+Layer_frame :: proc "c" (self: ^Layer) -> Rect {
+ return msgSend(Rect, self, "frame")
+}
+@(objc_type=Layer, objc_name="addSublayer")
+Layer_addSublayer :: proc "c" (self: ^Layer, layer: ^Layer) {
+ msgSend(nil, self, "addSublayer:", layer)
+}
+
+@(objc_class="NSResponder")
+Responder :: struct {using _: Object}
+
+@(objc_class="NSView")
+View :: struct {using _: Responder}
+
+
+@(objc_type=View, objc_name="initWithFrame")
+View_initWithFrame :: proc "c" (self: ^View, frame: Rect) -> ^View {
+ return msgSend(^View, self, "initWithFrame:", frame)
+}
+@(objc_type=View, objc_name="bounds")
+View_bounds :: proc "c" (self: ^View) -> Rect {
+ return msgSend(Rect, self, "bounds")
+}
+@(objc_type=View, objc_name="layer")
+View_layer :: proc "c" (self: ^View) -> ^Layer {
+ return msgSend(^Layer, self, "layer")
+}
+@(objc_type=View, objc_name="setLayer")
+View_setLayer :: proc "c" (self: ^View, layer: ^Layer) {
+ msgSend(nil, self, "setLayer:", layer)
+}
+@(objc_type=View, objc_name="wantsLayer")
+View_wantsLayer :: proc "c" (self: ^View) -> BOOL {
+ return msgSend(BOOL, self, "wantsLayer")
+}
+@(objc_type=View, objc_name="setWantsLayer")
+View_setWantsLayer :: proc "c" (self: ^View, wantsLayer: BOOL) {
+ msgSend(nil, self, "setWantsLayer:", wantsLayer)
+}
+@(objc_type=View, objc_name="convertPointFromView")
+View_convertPointFromView :: proc "c" (self: ^View, point: Point, view: ^View) -> Point {
+ return msgSend(Point, self, "convertPoint:fromView:", point, view)
+}
+
+@(objc_class="NSWindow")
+Window :: struct {using _: Responder}
+
+@(objc_type=Window, objc_name="alloc", objc_is_class_method=true)
+Window_alloc :: proc "c" () -> ^Window {
+ return msgSend(^Window, Window, "alloc")
+}
+
+@(objc_type=Window, objc_name="initWithContentRect")
+Window_initWithContentRect :: proc (self: ^Window, contentRect: Rect, styleMask: WindowStyleMask, backing: BackingStoreType, doDefer: BOOL) -> ^Window {
+ self := self
+ // HACK: due to a compiler bug, the generated calling code does not
+ // currently work for this message. Has to do with passing a struct along
+ // with other parameters, so we don't send the rect here.
+ // Omiting the rect argument here actually works, because of how the C
+ // calling conventions are defined.
+ self = msgSend(^Window, self, "initWithContentRect:styleMask:backing:defer:", styleMask, backing, doDefer)
+
+ // apply the contentRect now, since we did not pass it to the init call
+ msgSend(nil, self, "setContentSize:", contentRect.size)
+ msgSend(nil, self, "setFrameOrigin:", contentRect.origin)
+ return self
+}
+@(objc_type=Window, objc_name="contentView")
+Window_contentView :: proc "c" (self: ^Window) -> ^View {
+ return msgSend(^View, self, "contentView")
+}
+@(objc_type=Window, objc_name="setContentView")
+Window_setContentView :: proc "c" (self: ^Window, content_view: ^View) {
+ msgSend(nil, self, "setContentView:", content_view)
+}
+@(objc_type=Window, objc_name="contentLayoutRect")
+Window_contentLayoutRect :: proc "c" (self: ^Window) -> Rect {
+ return msgSend(Rect, self, "contentLayoutRect")
+}
+@(objc_type=Window, objc_name="frame")
+Window_frame :: proc "c" (self: ^Window) -> Rect {
+ return msgSend(Rect, self, "frame")
+}
+@(objc_type=Window, objc_name="setFrame")
+Window_setFrame :: proc "c" (self: ^Window, frame: Rect) {
+ msgSend(nil, self, "setFrame:", frame)
+}
+@(objc_type=Window, objc_name="opaque")
+Window_opaque :: proc "c" (self: ^Window) -> BOOL {
+ return msgSend(BOOL, self, "opaque")
+}
+@(objc_type=Window, objc_name="setOpaque")
+Window_setOpaque :: proc "c" (self: ^Window, ok: BOOL) {
+ msgSend(nil, self, "setOpaque:", ok)
+}
+@(objc_type=Window, objc_name="backgroundColor")
+Window_backgroundColor :: proc "c" (self: ^Window) -> ^Color {
+ return msgSend(^Color, self, "backgroundColor")
+}
+@(objc_type=Window, objc_name="setBackgroundColor")
+Window_setBackgroundColor :: proc "c" (self: ^Window, color: ^Color) {
+ msgSend(nil, self, "setBackgroundColor:", color)
+}
+@(objc_type=Window, objc_name="makeKeyAndOrderFront")
+Window_makeKeyAndOrderFront :: proc "c" (self: ^Window, key: ^Object) {
+ msgSend(nil, self, "makeKeyAndOrderFront:", key)
+}
+@(objc_type=Window, objc_name="setTitle")
+Window_setTitle :: proc "c" (self: ^Window, title: ^String) {
+ msgSend(nil, self, "setTitle:", title)
+}
+@(objc_type=Window, objc_name="setTitlebarAppearsTransparent")
+Window_setTitlebarAppearsTransparent :: proc "c" (self: ^Window, ok: BOOL) {
+ msgSend(nil, self, "setTitlebarAppearsTransparent:", ok)
+}
+@(objc_type=Window, objc_name="setMovable")
+Window_setMovable :: proc "c" (self: ^Window, ok: BOOL) {
+ msgSend(nil, self, "setMovable:", ok)
+}
+@(objc_type=Window, objc_name="setMovableByWindowBackground")
+Window_setMovableByWindowBackground :: proc "c" (self: ^Window, ok: BOOL) {
+ msgSend(nil, self, "setMovableByWindowBackground:", ok)
+}
+@(objc_type=Window, objc_name="setStyleMask")
+Window_setStyleMask :: proc "c" (self: ^Window, style_mask: WindowStyleMask) {
+ msgSend(nil, self, "setStyleMask:", style_mask)
+}
+@(objc_type=Window, objc_name="close")
+Window_close :: proc "c" (self: ^Window) {
+ msgSend(nil, self, "close")
+}
+@(objc_type=Window, objc_name="setDelegate")
+Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) {
+ msgSend(nil, self, "setDelegate:", delegate)
+}
+@(objc_type=Window, objc_name="backingScaleFactor")
+Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float {
+ return msgSend(Float, self, "backingScaleFactor")
+}
diff --git a/core/sys/darwin/Foundation/objc.odin b/core/sys/darwin/Foundation/objc.odin
new file mode 100644
index 000000000..673996cbe
--- /dev/null
+++ b/core/sys/darwin/Foundation/objc.odin
@@ -0,0 +1,81 @@
+package objc_Foundation
+
+foreign import "system:Foundation.framework"
+// NOTE: Most of our bindings are reliant on Cocoa (everything under appkit) so just unconditionally import it
+@(require) foreign import "system:Cocoa.framework"
+
+import "base:intrinsics"
+import "core:c"
+
+IMP :: proc "c" (object: id, sel: SEL, #c_vararg args: ..any) -> id
+
+foreign Foundation {
+ objc_lookUpClass :: proc "c" (name: cstring) -> Class ---
+ sel_registerName :: proc "c" (name: cstring) -> SEL ---
+ objc_allocateClassPair :: proc "c" (superclass : Class, name : cstring, extraBytes : c.size_t) -> Class ---
+ objc_registerClassPair :: proc "c" (cls : Class) ---
+
+ class_addMethod :: proc "c" (cls: Class, name: SEL, imp: IMP, types: cstring) -> BOOL ---
+ class_getInstanceMethod :: proc "c" (cls: Class, name: SEL) -> Method ---
+ class_createInstance :: proc "c" (cls: Class, extraBytes: c.size_t) -> id ---
+
+ method_setImplementation :: proc "c" (method: Method, imp: IMP) ---
+ object_getIndexedIvars :: proc(obj: id) -> rawptr ---
+}
+
+
+@(objc_class="NSZone")
+Zone :: struct {using _: Object}
+
+@(link_prefix="NS")
+foreign Foundation {
+ AllocateObject :: proc "c" (aClass: Class, extraBytes: UInteger, zone: ^Zone) -> id ---
+ DeallocateObject :: proc "c" (object: id) ---
+}
+
+Method :: ^objc_method
+objc_method :: struct {
+ method_name: SEL,
+ method_types: cstring,
+ method_imp: IMP,
+}
+objc_method_list :: struct {}
+
+objc_ivar :: struct {}
+objc_ivar_list :: struct {}
+
+objc_cache :: struct {
+ mask: u32,
+ occupied: u32,
+ buckets: [1]Method,
+}
+
+objc_protocol_list :: struct {
+ next: ^objc_protocol_list,
+ count: c.int,
+ list: [1]^Protocol,
+}
+
+@(objc_class="Protocol")
+Protocol :: struct{using _: intrinsics.objc_object}
+
+objc_object_internals :: struct {
+ isa: ^objc_class_internals,
+}
+
+
+objc_class_internals :: struct {
+ isa: Class,
+ super_class: Class,
+ name: cstring,
+ version: c.long,
+ info: c.long,
+ instance_size: c.long,
+ ivars: ^objc_ivar_list,
+
+ methodLists: ^^objc_method_list,
+
+ cache: rawptr,
+ protocols: rawptr,
+
+}