sgl

annotate src/wsys_cocoa.m @ 17:ee7b3a898b6b

fooing with cocoa
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 25 Jun 2011 05:17:16 +0300
parents a16b34ac3f2a
children 33acb6b2d7a4
rev   line source
nuclear@13 1 /* mac-framework: -framework Cocoa */
nuclear@13 2
nuclear@13 3 #include "config.h"
nuclear@13 4
nuclear@13 5 #ifdef USE_WSYS_MODULE_COCOA
nuclear@13 6
nuclear@13 7 #import <Cocoa/Cocoa.h>
nuclear@13 8 #include "sgl.h"
nuclear@15 9 #include "wsys.h"
nuclear@13 10
nuclear@13 11 @interface OpenGLView : NSOpenGLView
nuclear@13 12 {
nuclear@15 13 int foo;
nuclear@13 14 }
nuclear@13 15
nuclear@17 16 -(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf;
nuclear@13 17
nuclear@13 18 -(void) drawRect: (NSRect) rect;
nuclear@13 19 -(void) reshape;
nuclear@13 20 /*-(void) keyDown: (NSEvent*) ev;
nuclear@13 21 -(void) keyUp: (NSEvent*) ev;
nuclear@13 22 -(void) mouseDown: (NSEvent*) ev;
nuclear@13 23 -(void) mouseUp: (NSEvent*) ev;
nuclear@13 24 -(void) rightMouseDown: (NSEvent*) ev;
nuclear@13 25 -(void) rightMouseUp: (NSEvent*) ev;
nuclear@13 26 -(void) otherMouseDown: (NSEvent*) ev;
nuclear@13 27 -(void) otherMouseUp: (NSEvent*) ev;
nuclear@13 28 -(void) mouseDragged: (NSEvent*) ev;
nuclear@13 29 -(void) rightMouseDragged: (NSEvent*) ev;
nuclear@13 30 -(void) otherMouseDragged: (NSEvent*) ev;*/
nuclear@13 31
nuclear@13 32 -(BOOL) acceptsFirstResponder;
nuclear@13 33 @end
nuclear@13 34
nuclear@17 35
nuclear@17 36 @interface AppDelegate : NSObject
nuclear@17 37 {
nuclear@17 38 int foo;
nuclear@17 39 }
nuclear@17 40 -(BOOL) applicationShouldTerminate: (NSApplication*) app;
nuclear@17 41 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*)app;
nuclear@17 42 @end
nuclear@17 43
nuclear@17 44
nuclear@13 45 struct window {
nuclear@13 46 int wid;
nuclear@15 47 int width, height;
nuclear@13 48 NSWindow *win;
nuclear@13 49 OpenGLView *view;
nuclear@15 50 NSOpenGLContext *ctx;
nuclear@15 51 int needs_redisplay;
nuclear@13 52 struct window *next;
nuclear@13 53 };
nuclear@13 54
nuclear@13 55
nuclear@13 56 static int init(void);
nuclear@13 57 static void shutdown(void);
nuclear@13 58
nuclear@13 59 /* video mode switching */
nuclear@13 60 static int set_vidmode(int xsz, int ysz);
nuclear@13 61 static int get_vidmode(int *xsz, int *ysz);
nuclear@13 62
nuclear@13 63 /* create/destroy windows */
nuclear@13 64 static int create_window(int xsz, int ysz, unsigned int flags);
nuclear@13 65 static void close_window(int wid);
nuclear@13 66
nuclear@13 67 /* window management */
nuclear@13 68 static int set_active(int wid);
nuclear@13 69 static struct window *find_window(int wid);
nuclear@13 70 static int activate_window(struct window *win);
nuclear@13 71 static int set_title(const char *str);
nuclear@13 72 static void redisplay(void);
nuclear@13 73 static void swap_buffers(void);
nuclear@13 74
nuclear@13 75 static int get_modifiers(void);
nuclear@13 76
nuclear@13 77 /* event handling and friends */
nuclear@13 78 static void set_event(int idx, int enable);
nuclear@13 79 static int process_events(void);
nuclear@17 80
nuclear@17 81 static void fill_attr(NSOpenGLPixelFormatAttribute *attr, unsigned int flags);
nuclear@13 82
nuclear@13 83
nuclear@13 84 static struct wsys_module ws = {
nuclear@13 85 "cocoa", 0,
nuclear@13 86 init,
nuclear@13 87 shutdown,
nuclear@13 88 set_vidmode,
nuclear@13 89 get_vidmode,
nuclear@13 90 create_window,
nuclear@13 91 close_window,
nuclear@13 92 set_active,
nuclear@13 93 set_title,
nuclear@13 94 redisplay,
nuclear@13 95 swap_buffers,
nuclear@13 96 get_modifiers,
nuclear@13 97 set_event,
nuclear@13 98 process_events,
nuclear@13 99 0
nuclear@13 100 };
nuclear@13 101
nuclear@13 102 static struct window *winlist, *active_win;
nuclear@17 103 static int quit_main_loop;
nuclear@13 104
nuclear@13 105
nuclear@13 106 void sgl_register_cocoa(void)
nuclear@13 107 {
nuclear@15 108 sgl_register_module(&ws);
nuclear@13 109 }
nuclear@13 110
nuclear@13 111
nuclear@13 112 @implementation OpenGLView
nuclear@13 113
nuclear@17 114 -(id) initWithFrame: (NSRect) frame pixelFormat: (NSOpenGLPixelFormat*) pf
nuclear@17 115 {
nuclear@17 116 self = [super initWithFrame: frame pixelFormat: pf];
nuclear@17 117 return self;
nuclear@17 118 }
nuclear@17 119
nuclear@13 120 -(void) drawRect: (NSRect) rect
nuclear@13 121 {
nuclear@13 122 sgl_display_callback_t func = sgl_get_callback(SGL_DISPLAY);
nuclear@13 123 if(func) {
nuclear@13 124 func();
nuclear@13 125 }
nuclear@13 126 }
nuclear@13 127
nuclear@13 128 -(void) reshape
nuclear@13 129 {
nuclear@15 130 NSSize sz;
nuclear@15 131 sgl_reshape_callback_t func;
nuclear@15 132
nuclear@15 133 sz = [self bounds].size;
nuclear@15 134
nuclear@15 135 if((func = sgl_get_callback(SGL_RESHAPE)) && (sz.width != active_win->width ||
nuclear@15 136 sz.height != active_win->height)) {
nuclear@15 137 active_win->width = sz.width;
nuclear@15 138 active_win->height = sz.height;
nuclear@15 139 func(sz.width, sz.height);
nuclear@13 140 }
nuclear@13 141 }
nuclear@13 142
nuclear@13 143 -(BOOL) acceptsFirstResponder
nuclear@13 144 {
nuclear@13 145 return YES;
nuclear@13 146 }
nuclear@13 147 @end
nuclear@13 148
nuclear@17 149 @implementation AppDelegate
nuclear@17 150 -(BOOL) applicationShouldTerminate: (NSApplication*) app
nuclear@17 151 {
nuclear@17 152 return NSTerminateNow;
nuclear@17 153 }
nuclear@17 154
nuclear@17 155 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) app
nuclear@17 156 {
nuclear@17 157 return YES;
nuclear@17 158 }
nuclear@17 159
nuclear@17 160 -(void) applicationWillTerminate: (NSNotification*) notification
nuclear@17 161 {
nuclear@17 162 printf("applicationWillTerminate\n");
nuclear@17 163 }
nuclear@17 164
nuclear@17 165 -(BOOL) windowShouldClose: (id) win
nuclear@17 166 {
nuclear@17 167 return YES;
nuclear@17 168 }
nuclear@17 169
nuclear@17 170 -(void) windowWillClose: (NSNotification*) notification
nuclear@17 171 {
nuclear@17 172 [NSApp terminate: nil];
nuclear@17 173 }
nuclear@17 174 @end
nuclear@17 175
nuclear@13 176 static int init(void)
nuclear@13 177 {
nuclear@17 178 AppDelegate *delegate;
nuclear@17 179
nuclear@17 180 [NSApplication sharedApplication];
nuclear@17 181
nuclear@17 182 delegate = [[AppDelegate alloc] init];
nuclear@17 183 [NSApp setDelegate: delegate];
nuclear@15 184 return 0;
nuclear@13 185 }
nuclear@13 186
nuclear@13 187 static void shutdown(void)
nuclear@13 188 {
nuclear@13 189 while(winlist) {
nuclear@13 190 struct window *win = winlist;
nuclear@13 191 winlist = winlist->next;
nuclear@13 192
nuclear@13 193 /* TODO destroy window */
nuclear@13 194 free(win);
nuclear@13 195 }
nuclear@17 196
nuclear@17 197 quit_main_loop = 1;
nuclear@13 198 }
nuclear@13 199
nuclear@13 200
nuclear@13 201 /* video mode switching */
nuclear@13 202 static int set_vidmode(int xsz, int ysz)
nuclear@13 203 {
nuclear@13 204 return 0; /* TODO */
nuclear@13 205 }
nuclear@13 206
nuclear@13 207 static int get_vidmode(int *xsz, int *ysz)
nuclear@13 208 {
nuclear@13 209 return 0; /* TODO */
nuclear@13 210 }
nuclear@13 211
nuclear@13 212
nuclear@13 213 /* create/destroy windows */
nuclear@13 214 static int create_window(int xsz, int ysz, unsigned int flags)
nuclear@13 215 {
nuclear@17 216 NSAutoreleasePool *pool;
nuclear@13 217 NSWindow *nswin;
nuclear@13 218 NSRect rect;
nuclear@15 219 OpenGLView *view;
nuclear@17 220 NSOpenGLPixelFormat *pf;
nuclear@17 221 NSOpenGLPixelFormatAttribute attr[32];
nuclear@13 222 unsigned int style;
nuclear@13 223 struct window *win;
nuclear@13 224 static int next_id = 1;
nuclear@13 225
nuclear@13 226 if(!(win = malloc(sizeof *win))) {
nuclear@13 227 return -1;
nuclear@13 228 }
nuclear@13 229
nuclear@17 230 pool = [[NSAutoreleasePool alloc] init];
nuclear@17 231
nuclear@17 232 /* create the view */
nuclear@17 233 fill_attr(attr, flags);
nuclear@17 234 pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes: attr] autorelease];
nuclear@17 235 view = [[OpenGLView alloc] initWithFrame: rect pixelFormat: pf];
nuclear@17 236
nuclear@13 237 /* create the window and attach the OpenGL view */
nuclear@13 238 rect.origin.x = rect.origin.y = 0;
nuclear@13 239 rect.size.width = xsz;
nuclear@13 240 rect.size.height = ysz;
nuclear@13 241
nuclear@13 242 style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask |
nuclear@13 243 NSResizableWindowMask;
nuclear@13 244
nuclear@13 245 nswin = [[NSWindow alloc] initWithContentRect: rect styleMask: style
nuclear@13 246 backing: NSBackingStoreBuffered defer: YES];
nuclear@17 247
nuclear@17 248 [nswin setTitle: @"OpenGL/Cocoa"];
nuclear@17 249 [nswin setReleasedWhenClosed: YES];
nuclear@13 250 [nswin setContentView: view];
nuclear@17 251 [nswin makeFirstResponder: view];
nuclear@17 252 [nswin makeKeyAndOrderFront: nil];
nuclear@13 253 [view release];
nuclear@13 254
nuclear@13 255 win->win = nswin;
nuclear@13 256 win->view = view;
nuclear@15 257 win->ctx = [view openGLContext];
nuclear@13 258 win->wid = next_id++;
nuclear@15 259 win->needs_redisplay = 1;
nuclear@13 260 win->next = winlist;
nuclear@13 261 winlist = win;
nuclear@13 262
nuclear@15 263 if(!active_win) {
nuclear@15 264 activate_window(win);
nuclear@15 265 }
nuclear@17 266
nuclear@17 267 [pool drain];
nuclear@13 268 return win->wid;
nuclear@13 269 }
nuclear@13 270
nuclear@13 271 static void close_window(int wid)
nuclear@13 272 {
nuclear@13 273 struct window *win, *prev, dummy;
nuclear@13 274 sgl_close_callback_t close_func;
nuclear@13 275
nuclear@13 276 dummy.next = win = winlist;
nuclear@13 277 prev = &dummy;
nuclear@13 278
nuclear@13 279 while(win) {
nuclear@13 280 if(win->wid == wid) {
nuclear@13 281 if(!(close_func = sgl_get_callback(SGL_CLOSE))) {
nuclear@13 282 close_func(wid);
nuclear@13 283 }
nuclear@13 284 [win->win close];
nuclear@13 285
nuclear@13 286 if(active_win == win) {
nuclear@13 287 activate_window(winlist);
nuclear@13 288 }
nuclear@13 289
nuclear@13 290 prev->next = win->next;
nuclear@13 291 free(win);
nuclear@13 292 return;
nuclear@13 293 }
nuclear@13 294 prev = win;
nuclear@13 295 win = win->next;
nuclear@13 296 }
nuclear@13 297 }
nuclear@13 298
nuclear@13 299
nuclear@13 300 /* window management */
nuclear@13 301 static int set_active(int wid)
nuclear@13 302 {
nuclear@15 303 struct window *win = find_window(wid);
nuclear@15 304 return activate_window(win);
nuclear@13 305 }
nuclear@13 306
nuclear@13 307 static struct window *find_window(int wid)
nuclear@13 308 {
nuclear@13 309 struct window *win = winlist;
nuclear@13 310
nuclear@13 311 while(win) {
nuclear@15 312 if(win->wid == wid) {
nuclear@13 313 return win;
nuclear@13 314 }
nuclear@13 315 win = win->next;
nuclear@13 316 }
nuclear@13 317 return 0;
nuclear@13 318 }
nuclear@13 319
nuclear@13 320 static int activate_window(struct window *win)
nuclear@13 321 {
nuclear@13 322 if(!win) {
nuclear@13 323 return -1;
nuclear@13 324 }
nuclear@13 325 [win->ctx makeCurrentContext];
nuclear@13 326 active_win = win;
nuclear@13 327 return 0;
nuclear@13 328 }
nuclear@13 329
nuclear@13 330 static int set_title(const char *str)
nuclear@13 331 {
nuclear@13 332 NSString *nsstr;
nuclear@13 333
nuclear@13 334 nsstr = [[NSString alloc] initWithCString: str encoding: NSASCIIStringEncoding];
nuclear@13 335 [active_win->win setTitle: nsstr];
nuclear@13 336 [nsstr release];
nuclear@15 337 return 0;
nuclear@13 338 }
nuclear@13 339
nuclear@13 340 static void redisplay(void)
nuclear@13 341 {
nuclear@15 342 active_win->needs_redisplay = 1;
nuclear@13 343 }
nuclear@13 344
nuclear@13 345 static void swap_buffers(void)
nuclear@13 346 {
nuclear@15 347 [active_win->ctx flushBuffer];
nuclear@13 348 }
nuclear@13 349
nuclear@13 350
nuclear@13 351 static int get_modifiers(void)
nuclear@13 352 {
nuclear@13 353 return 0; /* TODO */
nuclear@13 354 }
nuclear@13 355
nuclear@13 356
nuclear@13 357 /* event handling and friends */
nuclear@13 358 static void set_event(int idx, int enable)
nuclear@13 359 {
nuclear@13 360 }
nuclear@13 361
nuclear@13 362 static int process_events(void)
nuclear@13 363 {
nuclear@13 364 NSAutoreleasePool *pool;
nuclear@17 365 NSRunLoop *runloop;
nuclear@17 366 NSDate *block, *nonblock, *limdate;
nuclear@17 367
nuclear@14 368 sgl_idle_callback_t idle;
nuclear@15 369 sgl_display_callback_t disp;
nuclear@15 370 struct window *win;
nuclear@15 371 int res = 0;
nuclear@13 372
nuclear@13 373 pool = [[NSAutoreleasePool alloc] init];
nuclear@13 374
nuclear@15 375 idle = sgl_get_callback(SGL_IDLE);
nuclear@15 376 disp = sgl_get_callback(SGL_DISPLAY);
nuclear@15 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@17 391 limdate = idle ? nonblock : block;
nuclear@17 392
nuclear@17 393 while(!quit_main_loop) {
nuclear@17 394 NSEvent *ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: limdate
nuclear@17 395 inMode: NSDefaultRunLoopMode dequeue: YES];
nuclear@17 396 if(!ev) break;
nuclear@17 397
nuclear@17 398 [NSApp sendEvent: ev];
nuclear@17 399 if(limdate == block) {
nuclear@17 400 limdate = nonblock;
nuclear@13 401 }
nuclear@13 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@13 450 #endif /* USE_WSYS_MODULE_COCOA */