sgl

annotate src/wsys_cocoa.m @ 32:fc2dba4c5a5f

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