sgl

annotate src/wsys_cocoa.m @ 30:6242b03e7191

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