summaryrefslogtreecommitdiff
path: root/delegateuitask_darwin.m
blob: 5d2ec9e6925ff390d5252d3989b1f714f8852162 (plain)
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
// 13 may 2014

#include "objc_darwin.h"
#include "delegateuitask_darwin.h"
#include "_cgo_export.h"
#include <Foundation/NSObject.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSNotification.h>
#include <AppKit/NSApplication.h>
#include <AppKit/NSWindow.h>
#include <Foundation/NSAutoreleasePool.h>

@interface appDelegate : NSObject
@end

@implementation appDelegate

- (void)uitask:(NSValue *)fp
{
	appDelegate_uitask([fp pointerValue]);
}

- (BOOL)windowShouldClose:(id)win
{
	appDelegate_windowShouldClose(win);
	return NO;		// don't close
}

- (void)windowDidResize:(NSNotification *)n
{
	appDelegate_windowDidResize([n object]);
}

- (void)buttonClicked:(id)button
{
	appDelegate_buttonClicked(button);
}

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
{
	appDelegate_applicationShouldTerminate();
	return NSTerminateCancel;
}

@end

id makeAppDelegate(void)
{
	return [appDelegate new];
}

id windowGetContentView(id window)
{
	return [((NSWindow *) window) contentView];
}

BOOL initCocoa(id appDelegate)
{
	[NSApplication sharedApplication];
	if ([NSApp setActivationPolicy:NSApplicationActivationPolicyRegular] != YES)
		return NO;
	[NSApp activateIgnoringOtherApps:YES];		// TODO actually do C.NO here? Russ Cox does YES in his devdraw; the docs say the Finder does NO
	[NSApp setDelegate:appDelegate];
	return YES;
}

void douitask(id appDelegate, void *p)
{
	NSAutoreleasePool *pool;
	NSValue *fp;

	// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
	pool = [NSAutoreleasePool new];
	fp = [NSValue valueWithPointer:p];
	[appDelegate performSelectorOnMainThread:@selector(uitask:)
		withObject:fp
		waitUntilDone:YES];			// wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
	[pool release];
}

void breakMainLoop(void)
{
	// -[NSApplication stop:] stops the event loop; it won't do a clean termination, but we're not too concerned with that (at least not on the other platforms either so)
	// we can't call -[NSApplication terminate:] because that will just quit the program, ensuring we never leave ui.Go()
	[NSApp stop:NSApp];
	// simply calling -[NSApplication stop:] is not good enough, as the stop flag is only checked when an event comes in
	// we have to create a "proper" event; a blank event will just throw an exception
	[NSApp postEvent:makeDummyEvent()		// TODO inline this
		atStart:NO];			// not at start, just in case there are other events pending (TODO is this correct?)
}

void cocoaMainLoop(void)
{
	[NSApp run];
}