123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636 |
- #include "tauri-cocoa-webview.h"
- #include "tauri.h"
- #define NSAlertStyleWarning 0
- #define NSAlertStyleCritical 2
- #define NSWindowStyleMaskResizable 8
- #define NSWindowStyleMaskMiniaturizable 4
- #define NSWindowStyleMaskTitled 1
- #define NSWindowStyleMaskClosable 2
- #define NSWindowStyleMaskFullScreen (1 << 14)
- #define NSViewWidthSizable 2
- #define NSViewHeightSizable 16
- #define NSBackingStoreBuffered 2
- #define NSEventMaskAny ULONG_MAX
- #define NSEventModifierFlagCommand (1 << 20)
- #define NSEventModifierFlagOption (1 << 19)
- #define NSAlertStyleInformational 1
- #define NSAlertFirstButtonReturn 1000
- #define WKNavigationActionPolicyDownload 2
- #define NSModalResponseOK 1
- #define WKNavigationActionPolicyDownload 2
- #define WKNavigationResponsePolicyAllow 1
- #define WKUserScriptInjectionTimeAtDocumentStart 0
- #define NSApplicationActivationPolicyRegular 0
- static id get_nsstring(const char *c_str) {
- return objc_msgSend((id)objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"), c_str);
- }
- static id create_menu_item(id title, const char *action, const char *key) {
- id item =
- objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
- objc_msgSend(item, sel_registerName("initWithTitle:action:keyEquivalent:"),
- title, sel_registerName(action), get_nsstring(key));
- objc_msgSend(item, sel_registerName("autorelease"));
- return item;
- }
- static void webview_window_will_close(id self, SEL cmd, id notification) {
- struct webview *w =
- (struct webview *)objc_getAssociatedObject(self, "webview");
- webview_terminate(w);
- }
- static void webview_external_invoke(id self, SEL cmd, id contentController,
- id message) {
- struct webview *w =
- (struct webview *)objc_getAssociatedObject(contentController, "webview");
- if (w == NULL || w->external_invoke_cb == NULL) {
- return;
- }
- w->external_invoke_cb(w, (const char *)objc_msgSend(
- objc_msgSend(message, sel_registerName("body")),
- sel_registerName("UTF8String")));
- }
- static void run_open_panel(id self, SEL cmd, id webView, id parameters,
- id frame, void (^completionHandler)(id)) {
- id openPanel = objc_msgSend((id)objc_getClass("NSOpenPanel"),
- sel_registerName("openPanel"));
- objc_msgSend(
- openPanel, sel_registerName("setAllowsMultipleSelection:"),
- objc_msgSend(parameters, sel_registerName("allowsMultipleSelection")));
- objc_msgSend(openPanel, sel_registerName("setCanChooseFiles:"), 1);
- objc_msgSend(
- openPanel, sel_registerName("beginWithCompletionHandler:"), ^(id result) {
- if (result == (id)NSModalResponseOK) {
- completionHandler(objc_msgSend(openPanel, sel_registerName("URLs")));
- } else {
- completionHandler(nil);
- }
- });
- }
- static void run_save_panel(id self, SEL cmd, id download, id filename,
- void (^completionHandler)(int allowOverwrite,
- id destination)) {
- id savePanel = objc_msgSend((id)objc_getClass("NSSavePanel"),
- sel_registerName("savePanel"));
- objc_msgSend(savePanel, sel_registerName("setCanCreateDirectories:"), 1);
- objc_msgSend(savePanel, sel_registerName("setNameFieldStringValue:"),
- filename);
- objc_msgSend(savePanel, sel_registerName("beginWithCompletionHandler:"),
- ^(id result) {
- if (result == (id)NSModalResponseOK) {
- id url = objc_msgSend(savePanel, sel_registerName("URL"));
- id path = objc_msgSend(url, sel_registerName("path"));
- completionHandler(1, path);
- } else {
- completionHandler(NO, nil);
- }
- });
- }
- static void run_confirmation_panel(id self, SEL cmd, id webView, id message,
- id frame, void (^completionHandler)(bool)) {
- id alert =
- objc_msgSend((id)objc_getClass("NSAlert"), sel_registerName("new"));
- objc_msgSend(alert, sel_registerName("setIcon:"),
- objc_msgSend((id)objc_getClass("NSImage"),
- sel_registerName("imageNamed:"),
- get_nsstring("NSCaution")));
- objc_msgSend(alert, sel_registerName("setShowsHelp:"), 0);
- objc_msgSend(alert, sel_registerName("setInformativeText:"), message);
- objc_msgSend(alert, sel_registerName("addButtonWithTitle:"),
- get_nsstring("OK"));
- objc_msgSend(alert, sel_registerName("addButtonWithTitle:"),
- get_nsstring("Cancel"));
- if (objc_msgSend(alert, sel_registerName("runModal")) ==
- (id)NSAlertFirstButtonReturn) {
- completionHandler(true);
- } else {
- completionHandler(false);
- }
- objc_msgSend(alert, sel_registerName("release"));
- }
- static void run_alert_panel(id self, SEL cmd, id webView, id message, id frame,
- void (^completionHandler)(void)) {
- id alert =
- objc_msgSend((id)objc_getClass("NSAlert"), sel_registerName("new"));
- objc_msgSend(alert, sel_registerName("setIcon:"),
- objc_msgSend((id)objc_getClass("NSImage"),
- sel_registerName("imageNamed:"),
- get_nsstring("NSCaution")));
- objc_msgSend(alert, sel_registerName("setShowsHelp:"), 0);
- objc_msgSend(alert, sel_registerName("setInformativeText:"), message);
- objc_msgSend(alert, sel_registerName("addButtonWithTitle:"),
- get_nsstring("OK"));
- objc_msgSend(alert, sel_registerName("runModal"));
- objc_msgSend(alert, sel_registerName("release"));
- completionHandler();
- }
- static void download_failed(id self, SEL cmd, id download, id error) {
- printf("%s",
- (const char *)objc_msgSend(
- objc_msgSend(error, sel_registerName("localizedDescription")),
- sel_registerName("UTF8String")));
- }
- static void make_nav_policy_decision(id self, SEL cmd, id webView, id response,
- void (^decisionHandler)(int)) {
- if (objc_msgSend(response, sel_registerName("canShowMIMEType")) == 0) {
- decisionHandler(WKNavigationActionPolicyDownload);
- } else {
- decisionHandler(WKNavigationResponsePolicyAllow);
- }
- }
- WEBVIEW_API int webview_init(struct webview *w) {
- w->priv.pool = objc_msgSend((id)objc_getClass("NSAutoreleasePool"),
- sel_registerName("new"));
- objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication"));
- Class __WKScriptMessageHandler = objc_allocateClassPair(
- objc_getClass("NSObject"), "__WKScriptMessageHandler", 0);
- class_addMethod(
- __WKScriptMessageHandler,
- sel_registerName("userContentController:didReceiveScriptMessage:"),
- (IMP)webview_external_invoke, "v@:@@");
- objc_registerClassPair(__WKScriptMessageHandler);
- id scriptMessageHandler =
- objc_msgSend((id)__WKScriptMessageHandler, sel_registerName("new"));
- /***
- _WKDownloadDelegate is an undocumented/private protocol with methods called
- from WKNavigationDelegate
- References:
- https://github.com/WebKit/webkit/blob/master/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.h
- https://github.com/WebKit/webkit/blob/master/Source/WebKit/UIProcess/API/Cocoa/_WKDownloadDelegate.h
- https://github.com/WebKit/webkit/blob/master/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm
- ***/
- Class __WKDownloadDelegate = objc_allocateClassPair(
- objc_getClass("NSObject"), "__WKDownloadDelegate", 0);
- class_addMethod(
- __WKDownloadDelegate,
- sel_registerName("_download:decideDestinationWithSuggestedFilename:"
- "completionHandler:"),
- (IMP)run_save_panel, "v@:@@?");
- class_addMethod(__WKDownloadDelegate,
- sel_registerName("_download:didFailWithError:"),
- (IMP)download_failed, "v@:@@");
- objc_registerClassPair(__WKDownloadDelegate);
- id downloadDelegate =
- objc_msgSend((id)__WKDownloadDelegate, sel_registerName("new"));
- Class __WKPreferences = objc_allocateClassPair(objc_getClass("WKPreferences"),
- "__WKPreferences", 0);
- objc_property_attribute_t type = {"T", "c"};
- objc_property_attribute_t ownership = {"N", ""};
- objc_property_attribute_t attrs[] = {type, ownership};
- class_replaceProperty(__WKPreferences, "developerExtrasEnabled", attrs, 2);
- objc_registerClassPair(__WKPreferences);
- id wkPref = objc_msgSend((id)__WKPreferences, sel_registerName("new"));
- objc_msgSend(wkPref, sel_registerName("setValue:forKey:"),
- objc_msgSend((id)objc_getClass("NSNumber"),
- sel_registerName("numberWithBool:"), !!w->debug),
- objc_msgSend((id)objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"),
- "developerExtrasEnabled"));
- id userController = objc_msgSend((id)objc_getClass("WKUserContentController"),
- sel_registerName("new"));
- objc_setAssociatedObject(userController, "webview", (id)(w),
- OBJC_ASSOCIATION_ASSIGN);
- objc_msgSend(
- userController, sel_registerName("addScriptMessageHandler:name:"),
- scriptMessageHandler,
- objc_msgSend((id)objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"), "invoke"));
- /***
- In order to maintain compatibility with the other 'webviews' we need to
- override window.external.invoke to call
- webkit.messageHandlers.invoke.postMessage
- ***/
- id windowExternalOverrideScript = objc_msgSend(
- (id)objc_getClass("WKUserScript"), sel_registerName("alloc"));
- objc_msgSend(
- windowExternalOverrideScript,
- sel_registerName("initWithSource:injectionTime:forMainFrameOnly:"),
- get_nsstring("window.external = this; invoke = function(arg){ "
- "webkit.messageHandlers.invoke.postMessage(arg); };"),
- WKUserScriptInjectionTimeAtDocumentStart, 0);
- objc_msgSend(userController, sel_registerName("addUserScript:"),
- windowExternalOverrideScript);
- id config = objc_msgSend((id)objc_getClass("WKWebViewConfiguration"),
- sel_registerName("new"));
- id processPool = objc_msgSend(config, sel_registerName("processPool"));
- objc_msgSend(processPool, sel_registerName("_setDownloadDelegate:"),
- downloadDelegate);
- objc_msgSend(config, sel_registerName("setProcessPool:"), processPool);
- objc_msgSend(config, sel_registerName("setUserContentController:"),
- userController);
- objc_msgSend(config, sel_registerName("setPreferences:"), wkPref);
- Class __NSWindowDelegate = objc_allocateClassPair(objc_getClass("NSObject"),
- "__NSWindowDelegate", 0);
- class_addProtocol(__NSWindowDelegate, objc_getProtocol("NSWindowDelegate"));
- class_replaceMethod(__NSWindowDelegate, sel_registerName("windowWillClose:"),
- (IMP)webview_window_will_close, "v@:@");
- objc_registerClassPair(__NSWindowDelegate);
- w->priv.windowDelegate =
- objc_msgSend((id)__NSWindowDelegate, sel_registerName("new"));
- objc_setAssociatedObject(w->priv.windowDelegate, "webview", (id)(w),
- OBJC_ASSOCIATION_ASSIGN);
- id nsTitle =
- objc_msgSend((id)objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"), w->title);
- CGRect r = CGRectMake(0, 0, w->width, w->height);
- unsigned int style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskMiniaturizable;
- if (w->resizable) {
- style = style | NSWindowStyleMaskResizable;
- }
- w->priv.window =
- objc_msgSend((id)objc_getClass("NSWindow"), sel_registerName("alloc"));
- objc_msgSend(w->priv.window,
- sel_registerName("initWithContentRect:styleMask:backing:defer:"),
- r, style, NSBackingStoreBuffered, 0);
- objc_msgSend(w->priv.window, sel_registerName("autorelease"));
- objc_msgSend(w->priv.window, sel_registerName("setTitle:"), nsTitle);
- objc_msgSend(w->priv.window, sel_registerName("setDelegate:"),
- w->priv.windowDelegate);
- objc_msgSend(w->priv.window, sel_registerName("center"));
- Class __WKUIDelegate =
- objc_allocateClassPair(objc_getClass("NSObject"), "__WKUIDelegate", 0);
- class_addProtocol(__WKUIDelegate, objc_getProtocol("WKUIDelegate"));
- class_addMethod(__WKUIDelegate,
- sel_registerName("webView:runOpenPanelWithParameters:"
- "initiatedByFrame:completionHandler:"),
- (IMP)run_open_panel, "v@:@@@?");
- class_addMethod(__WKUIDelegate,
- sel_registerName("webView:runJavaScriptAlertPanelWithMessage:"
- "initiatedByFrame:completionHandler:"),
- (IMP)run_alert_panel, "v@:@@@?");
- class_addMethod(
- __WKUIDelegate,
- sel_registerName("webView:runJavaScriptConfirmPanelWithMessage:"
- "initiatedByFrame:completionHandler:"),
- (IMP)run_confirmation_panel, "v@:@@@?");
- objc_registerClassPair(__WKUIDelegate);
- id uiDel = objc_msgSend((id)__WKUIDelegate, sel_registerName("new"));
- Class __WKNavigationDelegate = objc_allocateClassPair(
- objc_getClass("NSObject"), "__WKNavigationDelegate", 0);
- class_addProtocol(__WKNavigationDelegate,
- objc_getProtocol("WKNavigationDelegate"));
- class_addMethod(
- __WKNavigationDelegate,
- sel_registerName(
- "webView:decidePolicyForNavigationResponse:decisionHandler:"),
- (IMP)make_nav_policy_decision, "v@:@@?");
- objc_registerClassPair(__WKNavigationDelegate);
- id navDel = objc_msgSend((id)__WKNavigationDelegate, sel_registerName("new"));
- w->priv.webview =
- objc_msgSend((id)objc_getClass("WKWebView"), sel_registerName("alloc"));
- objc_msgSend(w->priv.webview,
- sel_registerName("initWithFrame:configuration:"), r, config);
- objc_msgSend(w->priv.webview, sel_registerName("setUIDelegate:"), uiDel);
- objc_msgSend(w->priv.webview, sel_registerName("setNavigationDelegate:"),
- navDel);
- id nsURL = objc_msgSend((id)objc_getClass("NSURL"),
- sel_registerName("URLWithString:"),
- get_nsstring(webview_check_url(w->url)));
- objc_msgSend(w->priv.webview, sel_registerName("loadRequest:"),
- objc_msgSend((id)objc_getClass("NSURLRequest"),
- sel_registerName("requestWithURL:"), nsURL));
- objc_msgSend(w->priv.webview, sel_registerName("setAutoresizesSubviews:"), 1);
- objc_msgSend(w->priv.webview, sel_registerName("setAutoresizingMask:"),
- (NSViewWidthSizable | NSViewHeightSizable));
- objc_msgSend(objc_msgSend(w->priv.window, sel_registerName("contentView")),
- sel_registerName("addSubview:"), w->priv.webview);
- objc_msgSend(w->priv.window, sel_registerName("orderFrontRegardless"));
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("setActivationPolicy:"),
- NSApplicationActivationPolicyRegular);
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("finishLaunching"));
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("activateIgnoringOtherApps:"), 1);
- id menubar =
- objc_msgSend((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
- objc_msgSend(menubar, sel_registerName("initWithTitle:"), get_nsstring(""));
- objc_msgSend(menubar, sel_registerName("autorelease"));
- id appName = objc_msgSend(objc_msgSend((id)objc_getClass("NSProcessInfo"),
- sel_registerName("processInfo")),
- sel_registerName("processName"));
- id appMenuItem =
- objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
- objc_msgSend(appMenuItem,
- sel_registerName("initWithTitle:action:keyEquivalent:"), appName,
- NULL, get_nsstring(""));
- id appMenu =
- objc_msgSend((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
- objc_msgSend(appMenu, sel_registerName("initWithTitle:"), appName);
- objc_msgSend(appMenu, sel_registerName("autorelease"));
- objc_msgSend(appMenuItem, sel_registerName("setSubmenu:"), appMenu);
- objc_msgSend(menubar, sel_registerName("addItem:"), appMenuItem);
- id title =
- objc_msgSend(get_nsstring("Hide "),
- sel_registerName("stringByAppendingString:"), appName);
- id item = create_menu_item(title, "hide:", "h");
- objc_msgSend(appMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Hide Others"),
- "hideOtherApplications:", "h");
- objc_msgSend(item, sel_registerName("setKeyEquivalentModifierMask:"),
- (NSEventModifierFlagOption | NSEventModifierFlagCommand));
- objc_msgSend(appMenu, sel_registerName("addItem:"), item);
- item =
- create_menu_item(get_nsstring("Show All"), "unhideAllApplications:", "");
- objc_msgSend(appMenu, sel_registerName("addItem:"), item);
- objc_msgSend(appMenu, sel_registerName("addItem:"),
- objc_msgSend((id)objc_getClass("NSMenuItem"),
- sel_registerName("separatorItem")));
- title = objc_msgSend(get_nsstring("Quit "),
- sel_registerName("stringByAppendingString:"), appName);
- item = create_menu_item(title, "terminate:", "q");
- objc_msgSend(appMenu, sel_registerName("addItem:"), item);
- id editMenuItem =
- objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
- objc_msgSend(editMenuItem,
- sel_registerName("initWithTitle:action:keyEquivalent:"), get_nsstring("Edit"),
- NULL, get_nsstring(""));
- /***
- Edit menu
- ***/
- id editMenu =
- objc_msgSend((id)objc_getClass("NSMenu"), sel_registerName("alloc"));
- objc_msgSend(editMenu, sel_registerName("initWithTitle:"), get_nsstring("Edit"));
- objc_msgSend(editMenu, sel_registerName("autorelease"));
- objc_msgSend(editMenuItem, sel_registerName("setSubmenu:"), editMenu);
- objc_msgSend(menubar, sel_registerName("addItem:"), editMenuItem);
- item = create_menu_item(get_nsstring("Undo"), "undo:", "z");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Redo"), "redo:", "y");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("separatorItem"));
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Cut"), "cut:", "x");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Copy"), "copy:", "c");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Paste"), "paste:", "v");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- item = create_menu_item(get_nsstring("Select All"), "selectAll:", "a");
- objc_msgSend(editMenu, sel_registerName("addItem:"), item);
- /***
- Finalize menubar
- ***/
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("setMainMenu:"), menubar);
- w->priv.should_exit = 0;
- return 0;
- }
- WEBVIEW_API int webview_loop(struct webview *w, int blocking) {
- id until = (blocking ? objc_msgSend((id)objc_getClass("NSDate"),
- sel_registerName("distantFuture"))
- : objc_msgSend((id)objc_getClass("NSDate"),
- sel_registerName("distantPast")));
- id event = objc_msgSend(
- objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"),
- ULONG_MAX, until,
- objc_msgSend((id)objc_getClass("NSString"),
- sel_registerName("stringWithUTF8String:"),
- "kCFRunLoopDefaultMode"),
- true);
- if (event) {
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("sendEvent:"), event);
- }
- return w->priv.should_exit;
- }
- WEBVIEW_API int webview_eval(struct webview *w, const char *js) {
- objc_msgSend(w->priv.webview,
- sel_registerName("evaluateJavaScript:completionHandler:"),
- get_nsstring(js), NULL);
- return 0;
- }
- WEBVIEW_API void webview_set_title(struct webview *w, const char *title) {
- objc_msgSend(w->priv.window, sel_registerName("setTitle"),
- get_nsstring(title));
- }
- WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) {
- unsigned long windowStyleMask = (unsigned long)objc_msgSend(
- w->priv.window, sel_registerName("styleMask"));
- int b = (((windowStyleMask & NSWindowStyleMaskFullScreen) ==
- NSWindowStyleMaskFullScreen)
- ? 1
- : 0);
- if (b != fullscreen) {
- objc_msgSend(w->priv.window, sel_registerName("toggleFullScreen:"), NULL);
- }
- }
- WEBVIEW_API void webview_set_color(struct webview *w, uint8_t r, uint8_t g,
- uint8_t b, uint8_t a) {
- id color = objc_msgSend((id)objc_getClass("NSColor"),
- sel_registerName("colorWithRed:green:blue:alpha:"),
- (float)r / 255.0, (float)g / 255.0, (float)b / 255.0,
- (float)a / 255.0);
- objc_msgSend(w->priv.window, sel_registerName("setBackgroundColor:"), color);
- if (0.5 >= ((r / 255.0 * 299.0) + (g / 255.0 * 587.0) + (b / 255.0 * 114.0)) /
- 1000.0) {
- objc_msgSend(w->priv.window, sel_registerName("setAppearance:"),
- objc_msgSend((id)objc_getClass("NSAppearance"),
- sel_registerName("appearanceNamed:"),
- get_nsstring("NSAppearanceNameVibrantDark")));
- } else {
- objc_msgSend(w->priv.window, sel_registerName("setAppearance:"),
- objc_msgSend((id)objc_getClass("NSAppearance"),
- sel_registerName("appearanceNamed:"),
- get_nsstring("NSAppearanceNameVibrantLight")));
- }
- objc_msgSend(w->priv.window, sel_registerName("setOpaque:"), 0);
- objc_msgSend(w->priv.window,
- sel_registerName("setTitlebarAppearsTransparent:"), 1);
- objc_msgSend(w->priv.webview, sel_registerName("_setDrawsBackground:"), 0);
- }
- WEBVIEW_API void webview_dialog(struct webview *w,
- enum webview_dialog_type dlgtype, int flags,
- const char *title, const char *arg,
- char *result, size_t resultsz) {
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
- dlgtype == WEBVIEW_DIALOG_TYPE_SAVE) {
- id panel = (id)objc_getClass("NSSavePanel");
- if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN) {
- id openPanel = objc_msgSend((id)objc_getClass("NSOpenPanel"),
- sel_registerName("openPanel"));
- if (flags & WEBVIEW_DIALOG_FLAG_DIRECTORY) {
- objc_msgSend(openPanel, sel_registerName("setCanChooseFiles:"), 0);
- objc_msgSend(openPanel, sel_registerName("setCanChooseDirectories:"),
- 1);
- } else {
- objc_msgSend(openPanel, sel_registerName("setCanChooseFiles:"), 1);
- objc_msgSend(openPanel, sel_registerName("setCanChooseDirectories:"),
- 0);
- }
- objc_msgSend(openPanel, sel_registerName("setResolvesAliases:"), 0);
- objc_msgSend(openPanel, sel_registerName("setAllowsMultipleSelection:"),
- 0);
- panel = openPanel;
- } else {
- panel = objc_msgSend((id)objc_getClass("NSSavePanel"),
- sel_registerName("savePanel"));
- }
- objc_msgSend(panel, sel_registerName("setCanCreateDirectories:"), 1);
- objc_msgSend(panel, sel_registerName("setShowsHiddenFiles:"), 1);
- objc_msgSend(panel, sel_registerName("setExtensionHidden:"), 0);
- objc_msgSend(panel, sel_registerName("setCanSelectHiddenExtension:"), 0);
- objc_msgSend(panel, sel_registerName("setTreatsFilePackagesAsDirectories:"),
- 1);
- objc_msgSend(
- panel, sel_registerName("beginSheetModalForWindow:completionHandler:"),
- w->priv.window, ^(id result) {
- objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("stopModalWithCode:"), result);
- });
- if (objc_msgSend(objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication")),
- sel_registerName("runModalForWindow:"),
- panel) == (id)NSModalResponseOK) {
- id url = objc_msgSend(panel, sel_registerName("URL"));
- id path = objc_msgSend(url, sel_registerName("path"));
- const char *filename =
- (const char *)objc_msgSend(path, sel_registerName("UTF8String"));
- strlcpy(result, filename, resultsz);
- }
- } else if (dlgtype == WEBVIEW_DIALOG_TYPE_ALERT) {
- id a = objc_msgSend((id)objc_getClass("NSAlert"), sel_registerName("new"));
- switch (flags & WEBVIEW_DIALOG_FLAG_ALERT_MASK) {
- case WEBVIEW_DIALOG_FLAG_INFO:
- objc_msgSend(a, sel_registerName("setAlertStyle:"),
- NSAlertStyleInformational);
- break;
- case WEBVIEW_DIALOG_FLAG_WARNING:
- printf("Warning\n");
- objc_msgSend(a, sel_registerName("setAlertStyle:"), NSAlertStyleWarning);
- break;
- case WEBVIEW_DIALOG_FLAG_ERROR:
- printf("Error\n");
- objc_msgSend(a, sel_registerName("setAlertStyle:"), NSAlertStyleCritical);
- break;
- }
- objc_msgSend(a, sel_registerName("setShowsHelp:"), 0);
- objc_msgSend(a, sel_registerName("setShowsSuppressionButton:"), 0);
- objc_msgSend(a, sel_registerName("setMessageText:"), get_nsstring(title));
- objc_msgSend(a, sel_registerName("setInformativeText:"), get_nsstring(arg));
- objc_msgSend(a, sel_registerName("addButtonWithTitle:"),
- get_nsstring("OK"));
- objc_msgSend(a, sel_registerName("runModal"));
- objc_msgSend(a, sel_registerName("release"));
- }
- }
- static void webview_dispatch_cb(void *arg) {
- struct webview_dispatch_arg *context = (struct webview_dispatch_arg *)arg;
- (context->fn)(context->w, context->arg);
- free(context);
- }
- WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
- void *arg) {
- struct webview_dispatch_arg *context = (struct webview_dispatch_arg *)malloc(
- sizeof(struct webview_dispatch_arg));
- context->w = w;
- context->arg = arg;
- context->fn = fn;
- dispatch_async_f(dispatch_get_main_queue(), context, webview_dispatch_cb);
- }
- WEBVIEW_API void webview_terminate(struct webview *w) {
- w->priv.should_exit = 1;
- }
- WEBVIEW_API void webview_exit(struct webview *w) {
- id app = objc_msgSend((id)objc_getClass("NSApplication"),
- sel_registerName("sharedApplication"));
- objc_msgSend(app, sel_registerName("terminate:"), app);
- }
- WEBVIEW_API void webview_print_log(const char *s) { printf("%s\n", s); }
|