sgl

annotate src/wsys_cocoa.m @ 19:12ce0cef7ebf

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