sgl

view src/wsys_cocoa.m @ 31:124195562f7e

FUCKING AUTORELEASE POOL
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 03 Jul 2011 04:33:32 +0300
parents 171aa71b97e7
children fc2dba4c5a5f
line source
1 /* SimplyGL window system module for Cocoa */
2 /* mac-framework: -framework Cocoa */
4 #include "config.h"
6 #ifdef USE_WSYS_MODULE_COCOA
8 #import <Cocoa/Cocoa.h>
9 #include "sgl.h"
10 #include "wsys.h"
11 #include "log.h"
13 #define APPLE_SUCKS() sgl_log("%s called\n", __func__)
15 @interface OpenGLView : NSOpenGLView
16 {
17 int foo;
18 }
20 -(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf;
22 -(void) drawRect: (NSRect) rect;
23 -(void) reshape;
24 /*-(void) keyDown: (NSEvent*) ev;
25 -(void) keyUp: (NSEvent*) ev;
26 -(void) mouseDown: (NSEvent*) ev;
27 -(void) mouseUp: (NSEvent*) ev;
28 -(void) rightMouseDown: (NSEvent*) ev;
29 -(void) rightMouseUp: (NSEvent*) ev;
30 -(void) otherMouseDown: (NSEvent*) ev;
31 -(void) otherMouseUp: (NSEvent*) ev;
32 -(void) mouseDragged: (NSEvent*) ev;
33 -(void) rightMouseDragged: (NSEvent*) ev;
34 -(void) otherMouseDragged: (NSEvent*) ev;*/
36 -(BOOL) acceptsFirstResponder;
37 @end
40 @interface AppDelegate : NSObject
41 {
42 int foo;
43 }
45 -(void) applicationWillFinishLaunching: (NSNotification*) notification;
46 -(void) applicationDidFinishLaunching: (NSNotification*) notification;
48 -(void) windowDidExpose: (NSNotification*) notification;
49 -(void) windowDidResize: (NSNotification*) notification;
51 -(BOOL) applicationShouldTerminate: (NSApplication*) app;
52 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) app;
53 -(void) applicationWillTerminate: (NSNotification*) notification;
54 -(BOOL) windowShouldClose: (id) win;
55 -(void) windowWillClose: (NSNotification*) notification;
56 @end
59 struct window {
60 int wid;
61 int width, height;
62 NSWindow *win;
63 OpenGLView *view;
64 NSOpenGLContext *ctx;
65 int needs_redisplay;
66 struct window *next;
67 };
70 static int init(void);
71 static void shutdown(void);
73 /* video mode switching */
74 static int set_vidmode(int xsz, int ysz);
75 static int get_vidmode(int *xsz, int *ysz);
77 /* create/destroy windows */
78 static int create_window(int xsz, int ysz, unsigned int flags);
79 static void close_window(int wid);
81 /* window management */
82 static int set_active(int wid);
83 static struct window *find_window(int wid);
84 static int activate_window(struct window *win);
85 static int set_title(const char *str);
86 static void redisplay(void);
87 static void swap_buffers(void);
89 static int get_modifiers(void);
91 /* event handling and friends */
92 static void set_event(int idx, int enable);
93 static int process_events(void);
95 static void fill_attr(NSOpenGLPixelFormatAttribute *attr, unsigned int flags);
98 static struct wsys_module ws = {
99 "cocoa", 0,
100 init,
101 shutdown,
102 set_vidmode,
103 get_vidmode,
104 create_window,
105 close_window,
106 set_active,
107 set_title,
108 redisplay,
109 swap_buffers,
110 get_modifiers,
111 set_event,
112 process_events,
113 0
114 };
116 static struct window *winlist, *active_win;
117 static int quit_main_loop;
119 static NSAutoreleasePool *global_pool;
121 void sgl_register_cocoa(void)
122 {
123 sgl_register_module(&ws);
124 }
127 @implementation OpenGLView
129 -(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf
130 {
131 APPLE_SUCKS();
132 self = [super initWithFrame: frame pixelFormat: pf];
133 return self;
134 }
136 -(void) drawRect: (NSRect) rect
137 {
138 APPLE_SUCKS();
139 sgl_display_callback_t func = sgl_get_callback(SGL_DISPLAY);
140 if(func) {
141 func();
142 }
143 }
145 -(void) reshape
146 {
147 APPLE_SUCKS();
148 NSSize sz;
149 sgl_reshape_callback_t func;
151 sz = [self bounds].size;
153 if((func = sgl_get_callback(SGL_RESHAPE)) && (sz.width != active_win->width ||
154 sz.height != active_win->height)) {
155 active_win->width = sz.width;
156 active_win->height = sz.height;
157 func(sz.width, sz.height);
158 }
159 }
161 -(BOOL) acceptsFirstResponder
162 {
163 APPLE_SUCKS();
164 return YES;
165 }
166 @end
168 @implementation AppDelegate
169 -(void) applicationWillFinishLaunching: (NSNotification*) notification
170 {
171 APPLE_SUCKS();
172 }
174 -(void) applicationDidFinishLaunching: (NSNotification*) notification
175 {
176 APPLE_SUCKS();
177 }
179 -(void) windowDidExpose: (NSNotification*) notification
180 {
181 APPLE_SUCKS();
182 }
184 -(void) windowDidResize: (NSNotification*) notification
185 {
186 APPLE_SUCKS();
187 }
189 -(BOOL) applicationShouldTerminate: (NSApplication*) app
190 {
191 APPLE_SUCKS();
192 return NSTerminateNow;
193 }
195 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) app
196 {
197 APPLE_SUCKS();
198 return YES;
199 }
201 -(void) applicationWillTerminate: (NSNotification*) notification
202 {
203 APPLE_SUCKS();
204 }
206 -(BOOL) windowShouldClose: (id) win
207 {
208 APPLE_SUCKS();
209 return YES;
210 }
212 -(void) windowWillClose: (NSNotification*) notification
213 {
214 APPLE_SUCKS();
215 /*[NSApp terminate: nil];*/
216 }
217 @end
219 static int init(void)
220 {
221 APPLE_SUCKS();
222 AppDelegate *delegate;
224 global_pool = [[NSAutoreleasePool alloc] init];
226 [NSApplication sharedApplication];
228 delegate = [[AppDelegate alloc] init];
229 [NSApp setDelegate: delegate];
230 return 0;
231 }
233 static void shutdown(void)
234 {
235 APPLE_SUCKS();
236 while(winlist) {
237 close_window(winlist->wid);
238 }
240 quit_main_loop = 1;
241 [NSApp setDelegate: nil];
242 [global_pool drain];
243 }
246 /* video mode switching */
247 static int set_vidmode(int xsz, int ysz)
248 {
249 return 0; /* TODO */
250 }
252 static int get_vidmode(int *xsz, int *ysz)
253 {
254 return 0; /* TODO */
255 }
258 /* create/destroy windows */
259 static int create_window(int xsz, int ysz, unsigned int flags)
260 {
261 APPLE_SUCKS();
262 NSAutoreleasePool *pool;
263 NSWindow *nswin;
264 NSRect rect;
265 OpenGLView *view;
266 NSOpenGLPixelFormat *pf;
267 NSOpenGLPixelFormatAttribute attr[32];
268 unsigned int style;
269 struct window *win;
270 static int next_id = 1;
272 if(!(win = malloc(sizeof *win))) {
273 return -1;
274 }
276 pool = [[NSAutoreleasePool alloc] init];
278 /* create the view */
279 fill_attr(attr, flags);
280 pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes: attr] autorelease];
281 view = [[OpenGLView alloc] initWithFrame: rect pixelFormat: pf];
283 /* create the window and attach the OpenGL view */
284 rect.origin.x = rect.origin.y = 0;
285 rect.size.width = xsz;
286 rect.size.height = ysz;
288 style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask |
289 NSResizableWindowMask;
291 nswin = [[NSWindow alloc] initWithContentRect: rect styleMask: style
292 backing: NSBackingStoreBuffered defer: YES];
294 [nswin setTitle: @"OpenGL/Cocoa"];
295 [nswin setReleasedWhenClosed: YES];
296 [nswin setContentView: view];
297 [nswin makeFirstResponder: view];
298 [nswin makeKeyAndOrderFront: nil];
299 [view release];
301 win->win = nswin;
302 win->view = view;
303 win->ctx = [view openGLContext];
304 win->wid = next_id++;
305 win->needs_redisplay = 1;
306 win->next = winlist;
307 winlist = win;
309 if(!active_win) {
310 activate_window(win);
311 }
313 [pool drain];
314 return win->wid;
315 }
317 static void close_window(int wid)
318 {
319 APPLE_SUCKS();
320 struct window *win, *prev, dummy;
321 sgl_close_callback_t close_func;
323 dummy.next = win = winlist;
324 prev = &dummy;
326 while(win) {
327 if(win->wid == wid) {
328 if(!(close_func = sgl_get_callback(SGL_CLOSE))) {
329 close_func(wid);
330 }
331 [win->win close];
333 prev->next = win->next;
335 if(!dummy.next) {
336 winlist = 0;
337 }
339 if(active_win == win) {
340 activate_window(winlist);
341 }
342 free(win);
343 break;
344 }
345 prev = win;
346 win = win->next;
347 }
349 if(!winlist) {
350 shutdown();
351 }
352 }
355 /* window management */
356 static int set_active(int wid)
357 {
358 struct window *win = find_window(wid);
359 return activate_window(win);
360 }
362 static struct window *find_window(int wid)
363 {
364 struct window *win = winlist;
366 while(win) {
367 if(win->wid == wid) {
368 return win;
369 }
370 win = win->next;
371 }
372 return 0;
373 }
375 static int activate_window(struct window *win)
376 {
377 if(!win) {
378 return -1;
379 }
380 [win->ctx makeCurrentContext];
381 active_win = win;
382 return 0;
383 }
385 static int set_title(const char *str)
386 {
387 NSString *nsstr;
389 nsstr = [[NSString alloc] initWithCString: str encoding: NSASCIIStringEncoding];
390 [active_win->win setTitle: nsstr];
391 [nsstr release];
392 return 0;
393 }
395 static void redisplay(void)
396 {
397 active_win->needs_redisplay = 1;
398 }
400 static void swap_buffers(void)
401 {
402 [active_win->ctx flushBuffer];
403 }
406 static int get_modifiers(void)
407 {
408 return 0; /* TODO */
409 }
412 /* event handling and friends */
413 static void set_event(int idx, int enable)
414 {
415 }
417 static int process_events(void)
418 {
419 NSAutoreleasePool *pool;
420 NSRunLoop *runloop;
421 NSDate *block, *nonblock, *limdate;
423 sgl_idle_callback_t idle;
424 sgl_display_callback_t disp;
425 struct window *win;
427 pool = [[NSAutoreleasePool alloc] init];
429 idle = sgl_get_callback(SGL_IDLE);
430 disp = sgl_get_callback(SGL_DISPLAY);
432 win = winlist;
433 while(win) {
434 if(win->needs_redisplay && disp) {
435 activate_window(win);
436 disp();
437 win->needs_redisplay = 0;
438 }
439 win = win->next;
440 }
442 runloop = [[NSRunLoop currentRunLoop] retain];
443 block = [runloop limitDateForMode: NSDefaultRunLoopMode];
444 nonblock = [[NSDate distantPast] retain];
445 limdate = idle ? nonblock : block;
447 while(!quit_main_loop) {
448 NSEvent *ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: limdate
449 inMode: NSDefaultRunLoopMode dequeue: YES];
450 if(!ev) break;
452 [NSApp sendEvent: ev];
453 if(limdate == block) {
454 limdate = nonblock;
455 }
456 }
458 if(idle) {
459 idle();
460 }
462 [runloop release];
463 [pool drain];
465 /*sgl_log("%s returning: %d\n", __func__, quit_main_loop ? -1 : 0);*/
466 return quit_main_loop ? -1 : 0;
467 }
469 static void fill_attr(NSOpenGLPixelFormatAttribute *attr, unsigned int flags)
470 {
471 int i = 0;
473 /* this is very important. makes pixelformat selection behave like GLX
474 * where any non-zero value will denote "choose highest possible". This
475 * is pretty much what we intend, as the user doesn't actually pass any
476 * of these numbers.
477 */
478 attr[i++] = NSOpenGLPFAMaximumPolicy;
480 attr[i++] = NSOpenGLPFAColorSize;
481 attr[i++] = 1;
483 if(flags & SGL_DOUBLE) {
484 attr[i++] = NSOpenGLPFADoubleBuffer;
485 }
486 if(flags & SGL_DEPTH) {
487 attr[i++] = NSOpenGLPFADepthSize;
488 attr[i++] = 1;
489 }
490 if(flags & SGL_STENCIL) {
491 attr[i++] = NSOpenGLPFAStencilSize;
492 attr[i++] = 8; /* max-policy has no effect on stencil selection */
493 }
494 if(flags & SGL_STEREO) {
495 attr[i++] = NSOpenGLPFAStereo;
496 }
497 if(flags & SGL_MULTISAMPLE) {
498 attr[i++] = NSOpenGLPFASampleBuffers;
499 attr[i++] = 1;
500 attr[i++] = NSOpenGLPFASamples;
501 attr[i++] = 4; /* TODO don't hardcode, query */
502 }
503 attr[i++] = 0;
504 }
506 #else
507 int sgl_wsys_cocoa_silence_the_fucking_empty_file_warnings;
508 #endif /* USE_WSYS_MODULE_COCOA */