-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathwebview_darwin.h
101 lines (82 loc) · 3.63 KB
/
webview_darwin.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//
// ====================================================================
//
// This implementation uses Cocoa WKWebView backend on macOS. It is
// written using ObjC runtime and uses WKWebView class as a browser runtime.
// You should pass "-framework Webkit" flag to the compiler.
//
// ====================================================================
//
#include <CoreGraphics/CoreGraphics.h>
#include <objc/objc-runtime.h>
#include <iostream>
namespace webview {
#define CLASS(clazz) (id)objc_getClass(clazz)
#define METHOD(method) sel_registerName(method)
#define NSTR(string) ((id(*)(id, SEL, const char *))objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), string)
class cocoa_wkwebview_engine {
public:
cocoa_wkwebview_engine(int width,int height,bool hide,bool debug) {
m_app = ((id(*)(id, SEL))objc_msgSend)(CLASS("WebViewApp"), METHOD("alloc"));
m_app = ((id(*)(id, SEL,int,int,BOOL,BOOL))objc_msgSend)(m_app, METHOD("initApp:height:hide:debug:"),width,height,hide,debug);
Class cls = objc_allocateClassPair((Class)objc_getClass("NSObject"), "NSWebviewResponder", 0);
class_addProtocol(cls, objc_getProtocol("MessageDelegate"));
class_addMethod(cls, METHOD("onMessage:"),
(IMP)(+[](id self, SEL, id msg) {
auto w = (cocoa_wkwebview_engine *)objc_getAssociatedObject(self, "webview");
assert(w);
w->on_message(((const char *(*)(id, SEL))objc_msgSend)(((id(*)(id, SEL))objc_msgSend)(msg, METHOD("body")),METHOD("UTF8String")));
}),
"v@:@@");
objc_registerClassPair(cls);
id delegate = ((id(*)(id, SEL))objc_msgSend)((id)cls, METHOD("new"));
objc_setAssociatedObject(delegate, "webview", (id)this,OBJC_ASSOCIATION_ASSIGN);
((void (*)(id, SEL, id))objc_msgSend)(m_app, METHOD("setDelegate:"),delegate);
}
~cocoa_wkwebview_engine() { close(); }
void *window() { return (void *)m_app; }
void show() {
((void (*)(id, SEL))objc_msgSend)(m_app, METHOD("show"));
}
void hide() {
((void (*)(id, SEL))objc_msgSend)(m_app, METHOD("hide"));
}
void terminate() {
close();
((void (*)(id, SEL))objc_msgSend)(m_app, METHOD("terminate"));
}
void run() {
((void (*)(id, SEL))objc_msgSend)(m_app, METHOD("run"));
}
void dispatch(std::function<void()> f) {
dispatch_async_f(dispatch_get_main_queue(), new dispatch_fn_t(f),
(dispatch_function_t)([](void *arg) {
auto f = static_cast<dispatch_fn_t *>(arg);
(*f)();
delete f;
}));
}
void set_icon(const std::string icon) {
}
void set_title(const std::string title) {
((void (*)(id, SEL, id))objc_msgSend)(m_app, METHOD("setTitle:"),NSTR(title.c_str()));
}
void set_size(int width, int height, int hints) {
((void (*)(id, SEL, int,int,int))objc_msgSend)(m_app, METHOD("setSize:height:hints:"),width,height,hints);
}
void navigate(const std::string url) {
((void (*)(id, SEL, id))objc_msgSend)(m_app, METHOD("navigate:"),NSTR(url.c_str()));
}
void init(const std::string js) {
((void (*)(id, SEL, id))objc_msgSend)(m_app, METHOD("initJS:"),NSTR(js.c_str()));
}
void eval(const std::string js) {
((void (*)(id, SEL, id))objc_msgSend)(m_app, METHOD("evalJS:"),NSTR(js.c_str()));
}
private:
virtual void on_message(const std::string msg) = 0;
void close() { ((void (*)(id, SEL))objc_msgSend)(m_app, METHOD("close")); }
id m_app;
};
using browser_engine = cocoa_wkwebview_engine;
} // namespace webview