sgl

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