sgl

view src/wsys_cocoa.m @ 18:33acb6b2d7a4

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