From da31beb62f5f4cca055c265b6fcdbcbbf59be113 Mon Sep 17 00:00:00 2001 From: bung87 Date: Wed, 2 Oct 2024 23:00:01 +0800 Subject: [PATCH] delegates --- src/crowngui/platforms/macos/app_delegate.nim | 14 +++++++----- .../platforms/macos/navigation_delegate.nim | 8 +++++-- src/crowngui/platforms/macos/types.nim | 3 ++- src/crowngui/platforms/macos/ui_delegate.nim | 8 +++++-- src/crowngui/platforms/macos/webview.nim | 22 ++++++++++--------- .../platforms/macos/window_delegate.nim | 3 +++ .../platforms/macos/windowcontroller.nim | 6 ++++- src/crowngui/webview.nim | 18 ++++++--------- 8 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/crowngui/platforms/macos/app_delegate.nim b/src/crowngui/platforms/macos/app_delegate.nim index 2631122..bc48dee 100644 --- a/src/crowngui/platforms/macos/app_delegate.nim +++ b/src/crowngui/platforms/macos/app_delegate.nim @@ -4,7 +4,11 @@ import darwin / [app_kit, foundation, objc/runtime] import ../../types import ./bundle -proc applicationOpenFile(self: ID; cmd: SEL; sender: NSApplication; openFile: NSString): Bool {.cdecl.} = +type MyAppDelegate* = ptr object of NSObject + +proc setDelegate*(s: NSApplication, d: NSObject) {.objc: "setDelegate:".} + +proc applicationOpenFile(self: MyAppDelegate; cmd: SEL; sender: NSApplication; openFile: NSString): Bool {.cdecl.} = let path = cast[cstring](objc_msgSend(cast[ID](openFile), $$"UTF8String")) var cls = self.getClass() var ivar = cls.getIvar("webview") @@ -12,12 +16,12 @@ proc applicationOpenFile(self: ID; cmd: SEL; sender: NSApplication; openFile: NS if wv.onOpenFile != nil: return cast[Bool](wv.onOpenFile(wv, $path)) -proc applicationShouldTerminateAfterLastWindowClosed(self: ID; cmd: SEL; notification: ID): bool {.cdecl.} = +proc applicationShouldTerminateAfterLastWindowClosed(self: MyAppDelegate; cmd: SEL; notification: ID): bool {.cdecl.} = # return true, so will not stay in dock and wait for reactivation return true # applicationWillFinishLaunching: -> application:openFile: -> applicationDidFinishLaunching: -proc applicationWillFinishLaunching(self: ID; cmd: SEL; notification: ID): void {.cdecl.} = +proc applicationWillFinishLaunching(self: MyAppDelegate; cmd: SEL; notification: ID): void {.cdecl.} = when not defined(release): echo "applicationWillFinishLaunching" @@ -29,7 +33,7 @@ proc on_application_did_finish_launching(delegate: ID; app: ID) {.objcr.}= [app activateIgnoringOtherApps: YES] # set_up_window() -proc applicationDidFinishLaunching(self: ID; cmd: SEL; notification: ID): void {.cdecl.} = +proc applicationDidFinishLaunching(self: MyAppDelegate; cmd: SEL; notification: ID): void {.cdecl.} = when not defined(release): echo "applicationDidFinishLaunching" # var w = getAssociatedObject(self, cast[pointer]($$"webview")) @@ -39,7 +43,7 @@ proc applicationDidFinishLaunching(self: ID; cmd: SEL; notification: ID): void { let app = [notification $$"object"] on_application_did_finish_launching(self, app) -proc applicationWillBecomeActive(self: ID; cmd: SEL; notification: ID): void {.cdecl.} = +proc applicationWillBecomeActive(self: MyAppDelegate; cmd: SEL; notification: ID): void {.cdecl.} = # close button pressed, stay in dock. then press from dock to activate app. when not defined(release): echo "applicationWillBecomeActive" diff --git a/src/crowngui/platforms/macos/navigation_delegate.nim b/src/crowngui/platforms/macos/navigation_delegate.nim index ffe665b..8e5c28b 100644 --- a/src/crowngui/platforms/macos/navigation_delegate.nim +++ b/src/crowngui/platforms/macos/navigation_delegate.nim @@ -1,9 +1,13 @@ import objc_runtime -import darwin / [objc/blocks] +import darwin / [objc/blocks, web_kit] const WKNavigationActionPolicyDownload = 2 const WKNavigationResponsePolicyAllow = 1 +type MyWKNavigationDelegate* = ptr object of NSObject + +proc setNavigationDelegate*(s: WKWebview, d: NSObject) {.objc: "setNavigationDelegate:".} + proc make_nav_policy_decision(self: Id; cmd: SEL; webView: Id; response: Id; decisionHandler: Block[proc (): void]) = objcr: @@ -14,7 +18,7 @@ proc make_nav_policy_decision(self: Id; cmd: SEL; webView: Id; response: Id; proc registerWKNavigationDelegate*(): ObjcClass = result = allocateClassPair( - getClass("NSObject"), "PrivWKNavigationDelegate", 0) + getClass("NSObject"), "MyWKNavigationDelegate", 0) discard addProtocol(result, getProtocol("WKNavigationDelegate")) discard addMethod( result, diff --git a/src/crowngui/platforms/macos/types.nim b/src/crowngui/platforms/macos/types.nim index 0a21ddd..d8d4de0 100644 --- a/src/crowngui/platforms/macos/types.nim +++ b/src/crowngui/platforms/macos/types.nim @@ -3,8 +3,9 @@ import darwin/app_kit/nswindow import darwin/web_kit/wkwebview type + MyNSWindowDelegate* = ptr object of NSObject WebviewPrivObj* = object pool*: ID window*: NSWindow webview*: WKWebView - windowDelegate*: ID + windowDelegate*: MyNSWindowDelegate diff --git a/src/crowngui/platforms/macos/ui_delegate.nim b/src/crowngui/platforms/macos/ui_delegate.nim index b9d664d..e83c617 100644 --- a/src/crowngui/platforms/macos/ui_delegate.nim +++ b/src/crowngui/platforms/macos/ui_delegate.nim @@ -1,9 +1,13 @@ import objc_runtime -import darwin / [app_kit, foundation, objc/runtime] +import darwin / [app_kit, web_kit, foundation, objc/runtime] import ./internal_dialogs +type MyUIDelegate* = ptr object of NSObject + +proc setUIDelegate*(s: WKWebview, d: NSObject) {.objc: "setUIDelegate:".} + proc registerUIDelegate*(): ObjcClass = - result = allocateClassPair(getClass("NSObject"), "PrivWKUIDelegate", 0) + result = allocateClassPair(getClass("NSObject"), "MyWKUIDelegate", 0) discard addProtocol(result, getProtocol("WKUIDelegate")) discard addMethod(result, $$"webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:", diff --git a/src/crowngui/platforms/macos/webview.nim b/src/crowngui/platforms/macos/webview.nim index ad8aaeb..35498d8 100644 --- a/src/crowngui/platforms/macos/webview.nim +++ b/src/crowngui/platforms/macos/webview.nim @@ -76,8 +76,8 @@ proc webview_init*(w: Webview): cint {.objcr.} = # [processPool "_setDownloadDelegate": downloadDelegate] # [config setProcessPool: processPool] - var PrivNSWindowDelegate = registerWindowDelegate() - w.priv.windowDelegate = [PrivNSWindowDelegate new] + var MyNSWindowDelegateClass = registerWindowDelegate() + w.priv.windowDelegate = cast[MyNSWindowDelegate](createInstance(MyNSWindowDelegateClass, 0)) setAssociatedObject(w.priv.windowDelegate, cast[pointer]($$"webview"), (Id)(w), OBJC_ASSOCIATION_ASSIGN) @@ -89,20 +89,22 @@ proc webview_init*(w: Webview): cint {.objcr.} = w.priv.window.initWithContentRect(frameRect, cast[NSWindowStyleMask](style), NSBackingStoreBuffered, NO) [w.priv.window autorelease] w.priv.window.setTitle(@($w.title)) - let send = cast[proc(self:ID; sel: SEL; t: ID){.cdecl,gcsafe.}](objc_msgSend) - send(w.priv.window, $$"setDelegate:", w.priv.windowDelegate) + + w.priv.window.setDelegate(w.priv.windowDelegate) w.priv.window.center() - var PrivWKUIDelegate = registerUIDelegate() - var uiDel = [PrivWKUIDelegate new] + var MyWKUIDelegateClass = registerUIDelegate() + var uiDel = cast[MyUIDelegate](createInstance(MyWKUIDelegateClass, 0)) - var PrivWKNavigationDelegate = registerWKNavigationDelegate() - var navDel = [PrivWKNavigationDelegate new] + var MyWKNavigationDelegateClass = registerWKNavigationDelegate() + var navDel = cast[MyWKNavigationDelegate](createInstance(MyWKNavigationDelegateClass, 0)) w.priv.webview = WKWebView.alloc() discard initWithFrameAndConfiguration(w.priv.webview, frameRect, config) - send(w.priv.webview, $$"setUIDelegate:", uiDel) - send(w.priv.webview, $$"setNavigationDelegate:", navDel) + + w.priv.webview.setUIDelegate(uiDel) + w.priv.webview.setNavigationDelegate(navDel) + let url = $(w.url) case w.entryType of EntryType.html: diff --git a/src/crowngui/platforms/macos/window_delegate.nim b/src/crowngui/platforms/macos/window_delegate.nim index 481a31c..2b87f59 100644 --- a/src/crowngui/platforms/macos/window_delegate.nim +++ b/src/crowngui/platforms/macos/window_delegate.nim @@ -2,6 +2,9 @@ import objc_runtime import darwin / [app_kit, objc/runtime] import ../../types + +proc setDelegate*(s: NSWindow, d: NSObject) {.objc: "setDelegate:".} + proc webview_window_will_close(self: Id; cmd: SEL; notification: Id) = var w = getAssociatedObject(self, cast[pointer]($$"webview")) var wv = cast[Webview](w) diff --git a/src/crowngui/platforms/macos/windowcontroller.nim b/src/crowngui/platforms/macos/windowcontroller.nim index dbea192..ce5f37a 100644 --- a/src/crowngui/platforms/macos/windowcontroller.nim +++ b/src/crowngui/platforms/macos/windowcontroller.nim @@ -2,6 +2,10 @@ import objc_runtime import darwin / [app_kit, foundation, objc/runtime] +type MyWindowController* = ptr object of NSObject + +proc setDelegate*(s: NSWindow, d: NSObject) {.objc: "setDelegate:".} + when false: proc awakeFromNib(self: ID; cmd: SEL; ): void {.cdecl.} = objcr: @@ -22,7 +26,7 @@ when false: [self registerForDraggedTypes: tid] return self -proc draggingEntered(self: ID; cmd: SEL; sender: NSDraggingInfo): NSDragOperation {.cdecl.} = +proc draggingEntered(self: MyWindowController; cmd: SEL; sender: NSDraggingInfo): NSDragOperation {.cdecl.} = return NSDragOperationCopy proc registerWindowController*(): ObjcClass = diff --git a/src/crowngui/webview.nim b/src/crowngui/webview.nim index 7db419b..961fb49 100644 --- a/src/crowngui/webview.nim +++ b/src/crowngui/webview.nim @@ -214,19 +214,15 @@ proc newWebView*(path: static[string] = ""; entryType:static[EntryType]; title = entryType1 = EntryType.html var webview = webView(title, entry, entryType1, width, height, resizable, debug, callback) when defined(macosx): - let MyAppDelegate = registerAppDelegate() - let WindowController = registerWindowController() - let send1 = cast[proc(self: NSWindow; sel: SEL; c: ID){.cdecl,gcsafe.}](objc_msgSend) - let send2 = cast[proc(self: NSApplication; sel: SEL; c: ID){.cdecl,gcsafe.}](objc_msgSend) + let MyAppDelegateClass = registerAppDelegate() + let MyWindowControllerClass = registerWindowController() objcr: - var appDel = [MyAppDelegate new] - var windowController = [WindowController new] - # [webview.priv.window setDelegate: windowController] - send1(webview.priv.window, $$"setDelegate:", windowController) - # [app setDelegate: appDel] - send2(cast[NSApplication](NSApp), $$"setDelegate:", appDel) - let ivar: Ivar = getIvar(MyAppDelegate, "webview") + var appDel = cast[MyAppDelegate](createInstance(MyAppDelegateClass, 0)) + var windowController = cast[MyWindowController](createInstance(MyWindowControllerClass, 0)) # [MyWindowController new] + webview.priv.window.setDelegate(windowController) + cast[NSApplication](NSApp).setDelegate(appDel) + let ivar: Ivar = getIvar(MyAppDelegateClass, "webview") setIvar(appDel, ivar, cast[ID](webview)) createMenu()