-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtiny.mm
170 lines (147 loc) · 5.63 KB
/
tiny.mm
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Trivial hyperminimal single-file demo of using CEF on Mac
// Launches and runs ok on osx 10.11 through 10.13
// For simplicity's sake, does not subclass NSApplication<CefAppProtocol>, so sometimes crashes on exit
// See cef-project/examples/shared/main_mac.mm for proper way to do it
// Written solely to explore problems related to
//
// To compile as minimal Cocoa app without CEF (useful for testing cocoa launching):
// clang++ -framework Cocoa tiny.mm -o tiny
// Thanks to
// http://www.cocoawithlove.com/2010/09/minimalist-cocoa-programming.html
// https://stackoverflow.com/questions/33345686/cocoa-application-menu-bar-not-clickable
//
// To compile as minimal Cocoa app with CEF:
// (FIXME: adjust or remove -I, -L, and -F options to taste, mine are strange)
// clang++ -DCEF -stdlib=libc++ --std=c++11 \
// -I $(cefdir) \
// -L $(cefdir)/$(kind)/lib \
// -F$(cefdir)/$(kind)/cefclient.app/Contents/Frameworks -framework Chromium\ Embedded\ Framework \
// -framework Cocoa tiny.mm -o tiny -l cef_dll_wrapper
// Code linearized from https://bitbucket.org/chromiumembedded/cef-project
//
// To use the alternative DIY event loop, add -DDIYRUN to the compile commandline.
//
// Dan Kegel
#import <Cocoa/Cocoa.h>
#ifdef CEF
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_client.h"
const char kStartupURL[] = "https://www.google.com";
class MyCefClient : public CefClient {
IMPLEMENT_REFCOUNTING (MyCefClient);
};
// Minimal implementation of CefApp for the browser process.
class BrowserApp : public CefApp, public CefBrowserProcessHandler {
public:
BrowserApp() {}
// CefApp methods:
CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE {
return this;
}
// CefBrowserProcessHandler methods:
void OnContextInitialized() OVERRIDE {
CefWindowInfo window_info;
CefBrowserHost::CreateBrowser(window_info, new MyCefClient(), kStartupURL, CefBrowserSettings(), NULL);
}
private:
IMPLEMENT_REFCOUNTING(BrowserApp);
DISALLOW_COPY_AND_ASSIGN(BrowserApp);
};
#endif
@interface SharedAppDelegate : NSObject <NSApplicationDelegate>
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
@end
@implementation SharedAppDelegate
// Called immediately before the event loop starts.
// Right place for setting up app level things.
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
[NSApplication sharedApplication];
id menubar = [[NSMenu new] autorelease];
id appMenuItem = [[NSMenuItem new] autorelease];
[menubar addItem:appMenuItem];
[NSApp setMainMenu:menubar];
id appMenu = [[NSMenu new] autorelease];
id appName = [[NSProcessInfo processInfo] processName];
id quitTitle = [@"Quit " stringByAppendingString:appName];
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:quitTitle
action:@selector(terminate:) keyEquivalent:@"q"]
autorelease];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
}
// Called when the event loop has been started,
// document double clicks have already been processed,
// but no events have been executed yet.
// Right place for setting up event loop level things.
-(void)applicationDidFinishLaunching:(NSNotification *)notification
{
[NSApplication sharedApplication];
// Push app to foreground
[NSApp activateIgnoringOtherApps:YES];
}
@end
// Four different styles of event loop
// 1) CEF DIYRUN - DIY runloop that calls CefDoMessageLoopWork()
// 2) DIYRUN - DIY runloop
// 3) CEF - CefRunMessageLoop()
// 4) - [NSApp run]
void runloop() {
#if defined(DIYRUN)
#if defined(CEF)
// CEF will call [NSAapp run] and break out of main loop when idle...
// so [run] will take care of finishLaunching for us.
// If you call finishLaunching here anyway, the app will abort with
// _createMenuRef called with existing principal MenuRef already associated with menu
#else
// If you omit this, applicationWillFinishLaunching won't be called, and menus won't work.
[NSApp finishLaunching];
#endif
// FIXME: sense quit somehow
while (true) {
NSEvent *event;
event = [NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate distantPast]
inMode: NSDefaultRunLoopMode
dequeue: YES];
if (event != nil)
[NSApp sendEvent:event];
#if defined(CEF)
// FIXME: use external message pump integration
CefDoMessageLoopWork();
#endif
// if you don't want to burn CPU, you could do this,
// but then you need to handle cef's schedulework messages.
//event = [NSApp nextEventMatchingMask: NSAnyEventMask
// untilDate: [NSDate distantFuture]
// inMode: NSDefaultRunLoopMode
// dequeue: NO];
}
#else
#if defined(CEF)
CefRunMessageLoop();
#else
[NSApp run];
#endif
#endif
}
int main(int argc, char **argv) {
[NSAutoreleasePool new];
[NSApplication sharedApplication];
// Newbie alert: new = alloc init.
// See https://stackoverflow.com/questions/719877/use-of-alloc-init-instead-of-new
SharedAppDelegate* delegate = [SharedAppDelegate new];
[NSApp setDelegate:delegate];
#ifdef CEF
// Go cef go!
CefMainArgs main_args(argc, argv);
CefRefPtr<CefApp> app = new BrowserApp();
CefSettings settings;
CefInitialize(main_args, settings, app, NULL);
#endif
runloop();
return 0;
}