summaryrefslogtreecommitdiff
path: root/new/window_darwin.m
blob: b0cab113d5aec0c6a34467fe3ec648e51a7dad28 (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
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
// 6 april 2015
#import "uipriv_darwin.h"

// TODO
// - free chilld containers properly

@interface uiWindowDelegate : NSObject <NSWindowDelegate>
@property (assign) NSWindow *w;
@property uiParent *content;
@property int (*onClosing)(uiWindow *, void *);
@property void *onClosingData;
@property uiWindow *uiw;
@end

@implementation uiWindowDelegate

uiLogObjCClassAllocations

- (BOOL)windowShouldClose:(id)win
{
	// return exact constants to be safe
	if ((*(self.onClosing))(self.uiw, self.onClosingData))
		return YES;
	return NO;
}

// after this method returns we assume the window will be released (see below), so we can go too
- (void)windowWillClose:(NSNotification *)note
{
	[self.w setDelegate:nil];		// see http://stackoverflow.com/a/29523141/3408572

	// when we reach this point, we need to ensure that all the window's children are destroyed (for OS parity)
	// because we need to set the content view's superview to the destroyed controls view to trigger deletion, we need to do this manually
	// first, replace the current content view...
	[self.w setContentView:[[NSView alloc] initWithFrame:NSZeroRect]];
	// ...then, trigger the deletion
	[destroyedControlsView addSubview:((NSView *) uiParentHandle(self.content))];

	uiFree(self.uiw);
	[self release];
}

@end

struct uiWindow {
	uiWindowDelegate *d;
	int margined;
};

static int defaultOnClosing(uiWindow *w, void *data)
{
	return 1;
}

uiWindow *uiNewWindow(char *title, int width, int height)
{
	uiWindowDelegate *d;

	d = [uiWindowDelegate new];

	d.w = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height)
		styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
		backing:NSBackingStoreBuffered
		defer:YES];
	[d.w setTitle:toNSString(title)];

	// we do not want substitutions
	// text fields, labels, etc. take their smart quotes and other autocorrect settings from their parent window, which provides a shared "field editor"
	// so we have to turn them off here
	// thanks akempgen in irc.freenode.net/#macdev
	// for some reason, this selector returns NSText but is documented to return NSTextView...
	// NOTE: if you disagree with me about disabling substitutions, start a github issue with why and I'll be happy to consider it
	disableAutocorrect((NSTextView *) [d.w fieldEditor:YES forObject:nil]);

	// this is what will destroy the window on close
	[d.w setReleasedWhenClosed:YES];

	d.content = uiNewParent(0);
	[d.w setContentView:((NSView *) uiParentHandle(d.content))];

	d.onClosing = defaultOnClosing;
	[d.w setDelegate:d];

	d.uiw = uiNew(uiWindow);
	d.uiw->d = d;
	return d.uiw;
}

#define D w->d

void uiWindowDestroy(uiWindow *w)
{
	[D.w close];
}

uintptr_t uiWindowHandle(uiWindow *w)
{
	return (uintptr_t) (D.w);
}

char *uiWindowTitle(uiWindow *w)
{
	return uiDarwinNSStringToText([D.w title]);
}

void uiWindowSetTitle(uiWindow *w, const char *title)
{
	[D.w setTitle:toNSString(title)];
}

void uiWindowShow(uiWindow *w)
{
	[D.w makeKeyAndOrderFront:D.w];
}

void uiWindowHide(uiWindow *w)
{
	[D.w orderOut:D.w];
}

void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
	D.onClosing = f;
	D.onClosingData = data;
}

void uiWindowSetChild(uiWindow *w, uiControl *c)
{
	uiParentSetChild(D.content, c);
}

int uiWindowMargined(uiWindow *w)
{
	return w->margined;
}

void uiWindowSetMargined(uiWindow *w, int margined)
{
	w->margined = margined;
	if (w->margined)
		uiParentSetMargins(D.content, macXMargin, macYMargin, macXMargin, macYMargin);
	else
		uiParentSetMargins(D.content, 0, 0, 0, 0);
	uiParentUpdate(D.content);
}