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