1#import <Cocoa/Cocoa.h>
2#import <Carbon/Carbon.h>
3
4static NSWindow* nsParentWindow = nil;
5static NSWindow* nsWindow = nil;
6static NSView* nsView = nil;
7static bool cocoaApplication = false;
8static id oldDelegate = nil;
9static int widgetX = 0, widgetY = 0;
10
11@interface SdlCocoaWindow : NSWindow
12- (void)windowDidMove:(id)notification;
13- (void)windowWillMiniaturize:(NSNotification *)notification;
14- (void)windowDidDeminiaturize:(NSNotification *)notification;
15@end
16
17@implementation SdlCocoaWindow
18- (void)windowDidMove:(id)notification
19{
20	NSRect parentFrame = [nsParentWindow frame];
21	NSPoint point = NSMakePoint(parentFrame.origin.x + widgetX, parentFrame.origin.y + widgetY);
22
23	[self setFrameOrigin:point];
24}
25
26- (void)windowWillMiniaturize:(NSNotification *)notification
27{
28	[self setIsVisible:NO];
29}
30
31- (void)windowDidDeminiaturize:(NSNotification *)notification
32{
33	[self setIsVisible:YES];
34}
35@end
36
37void initSdlCocoaView(void* parent, int x, int y, int width, int height, bool carbonParent)
38{
39	printf("[SDL] Creating Cocoa view x: %d, y: %d, width: %d, height %d, carbon %d\n", x, y, width, height, carbonParent);
40
41	NSRect contentRect;
42
43	if (carbonParent)
44	{
45		contentRect = NSMakeRect(x, y, width, height);
46
47		if (!nsWindow)
48		{
49			// initWithWindowRef always returns the same result for the same WindowRef
50			nsWindow = [[NSWindow alloc] initWithWindowRef:(WindowRef)parent];
51
52			[nsWindow setContentView:[[[NSView alloc] initWithFrame:contentRect] autorelease]];
53		}
54	}
55	else
56	{
57		contentRect = NSMakeRect(0, 0, width, height);
58
59		if (!nsWindow)
60		{
61			nsWindow = [[SdlCocoaWindow alloc] initWithContentRect:contentRect styleMask:NSDocModalWindowMask backing:NSBackingStoreBuffered defer:NO];
62
63			nsParentWindow = (NSWindow*)parent;
64			widgetX = x;
65			widgetY = y;
66			oldDelegate = [nsParentWindow delegate];
67			cocoaApplication = true;
68
69			[nsWindow setLevel:NSFloatingWindowLevel];
70			[nsWindow setHasShadow:NO];
71
72			NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
73
74			[nc addObserver:nsWindow selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:nsParentWindow];
75			[nc addObserver:nsWindow selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification object:nsParentWindow];
76			[nc addObserver:nsWindow selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:nsParentWindow];
77		}
78	}
79
80	if (!nsView)
81	{
82		nsView = [[NSView alloc] initWithFrame:contentRect];
83
84		[[nsWindow contentView] addSubview:nsView];
85		[nsView release];
86
87		if (carbonParent)
88			[nsWindow orderOut:nil];	// very important, otherwise window won't be placed correctly on repeat showings
89		else
90		{
91			NSRect parentFrame = [nsParentWindow frame];
92			NSPoint point = NSMakePoint(parentFrame.origin.x + x, parentFrame.origin.y + y);
93
94			[nsWindow setFrameOrigin:point];
95		}
96
97		[nsWindow orderFront:nil];
98	}
99	else
100	{
101		[nsView setFrame:contentRect];
102		[[nsWindow contentView] setFrame:contentRect];
103	}
104
105	// finally, set SDL environment variables with all this nonsense
106	char SDL_windowhack[50];
107
108	sprintf(SDL_windowhack,"SDL_NSWindowPointer=%ld",(int)nsWindow);
109	putenv(SDL_windowhack);
110
111	sprintf(SDL_windowhack,"SDL_NSViewPointer=%ld",(int)nsView);
112	putenv(SDL_windowhack);
113}
114
115void destroyCocoaView(void)
116{
117	if (cocoaApplication)
118	{
119		[nsParentWindow setDelegate:oldDelegate];
120
121		// we're using a floating panel so it doesn't automatically get destroyed
122		[nsWindow release];
123
124		nsWindow = nil;
125		nsView = nil;
126		oldDelegate = nil;
127	}
128	else if (nsWindow)
129	{
130		// Reference count cannot fall below 2 because SDL releases the window when closing
131		// and again when reinitialising (even though this is our own window...).
132		if ([nsWindow retainCount] > 2)
133			[nsWindow release];
134
135		// SDL takes care of all the destroying...a little too much, so make sure our Carbon
136		// window is still displayed (via its Cocoa wrapper)
137		[nsWindow makeKeyAndOrderFront:nil];
138	}
139}
140