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 */
|