sgl

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