Forráskód Böngészése

(almost) Fully implement NSApplicationDelegate

Lucas Perlind 2 éve
szülő
commit
fed65742df

+ 468 - 30
vendor/darwin/Foundation/NSApplication.odin

@@ -1,6 +1,8 @@
 package objc_Foundation
 
 import "core:intrinsics"
+import "core:runtime"
+import "core:strings"
 
 ActivationPolicy :: enum UInteger {
 	Regular    = 0,
@@ -8,12 +10,17 @@ ActivationPolicy :: enum UInteger {
 	Prohibited = 2,
 }
 
-ApplicationDelegate :: struct {
-	willFinishLaunching:                  proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
-	didFinishLaunching:                   proc "c" (self: ^ApplicationDelegate, notification: ^Notification),
-	shouldTerminateAfterLastWindowClosed: proc "c" (self: ^ApplicationDelegate, sender: ^Application) -> BOOL,
+ApplicationTerminateReply :: enum UInteger {
+	TerminateCancel = 0,
+	TerminateNow = 1,
+	TerminateLater = 2,
+}
 
-	user_data: rawptr,
+ApplicationPrintReply :: enum UInteger {
+	PrintingCancelled = 0,
+	PrintingSuccess = 1,
+	PrintingReplyLater = 2,
+	PrintingFailure = 3,
 }
 
 @(objc_class="NSApplication")
@@ -24,30 +31,6 @@ Application_sharedApplication :: proc() -> ^Application {
 	return msgSend(^Application, Application, "sharedApplication")
 }
 
-@(objc_type=Application, objc_name="setDelegate")
-Application_setDelegate :: proc(self: ^Application, delegate: ^ApplicationDelegate) {
-	willFinishLaunching :: proc "c" (self: ^Value, _: SEL, notification: ^Notification) {
-		del := (^ApplicationDelegate)(self->pointerValue())
-		del->willFinishLaunching(notification)
-	}
-	didFinishLaunching :: proc "c" (self: ^Value, _: SEL, notification: ^Notification) {
-		del := (^ApplicationDelegate)(self->pointerValue())
-		del->didFinishLaunching(notification)
-	}
-	shouldTerminateAfterLastWindowClosed :: proc "c" (self: ^Value, _: SEL, application: ^Application) -> BOOL {
-		del := (^ApplicationDelegate)(self->pointerValue())
-		return del->shouldTerminateAfterLastWindowClosed(application)
-	}
-
-	wrapper := Value.valueWithPointer(delegate)
-
-	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationWillFinishLaunching:"),                  auto_cast willFinishLaunching,                  "v@:@")
-	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationDidFinishLaunching:"),                   auto_cast didFinishLaunching,                   "v@:@")
-	class_addMethod(intrinsics.objc_find_class("NSValue"), intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast shouldTerminateAfterLastWindowClosed, "B@:@")
-
-	msgSend(nil, self, "setDelegate:", wrapper)
-}
-
 @(objc_type=Application, objc_name="setActivationPolicy")
 Application_setActivationPolicy :: proc(self: ^Application, activationPolicy: ActivationPolicy) -> BOOL {
 	return msgSend(BOOL, self, "setActivationPolicy:", activationPolicy)
@@ -92,4 +75,459 @@ RunningApplication_currentApplication :: proc() -> ^RunningApplication {
 @(objc_type=RunningApplication, objc_name="localizedName")
 RunningApplication_localizedName :: proc(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(notification: ^Notification, 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: proc(^Array)) -> 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: ^Application, 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, notification: ^Notification, flag: BOOL) -> BOOL {
+			del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self)
+			context = del._context
+			return del.applicationShouldHandleReopenHasVisibleWindows(notification, 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: proc(^Array)) -> 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: ^Application, 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(self: ^Application, delegate: ^ApplicationDelegate) {
+	msgSend(nil, self, "setDelegate:", delegate)
+}

+ 6 - 0
vendor/darwin/Foundation/NSTypes.odin

@@ -45,3 +45,9 @@ Size :: struct {
 	width:  Float,
 	height: Float,
 }
+
+when size_of(UInteger) == 8 {
+	_UINTEGER_ENCODING :: "Q"
+} else {
+	_UINTEGER_ENCODING :: "I"
+}

+ 5 - 0
vendor/darwin/Foundation/NSUserActivity.odin

@@ -0,0 +1,5 @@
+package objc_Foundation
+
+@(objc_class="NSUserActivity")
+UserActivity :: struct {using _: Object}
+// TODO: implement NSUserActivity

+ 2 - 0
vendor/darwin/Foundation/objc.odin

@@ -15,8 +15,10 @@ foreign Foundation {
 
 	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 ---
 }