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@16
|
7 #import <Foundation/Foundation.h>
|
nuclear@16
|
8 #import <AppKit/AppKit.h>
|
nuclear@16
|
9
|
nuclear@13
|
10 #include "sgl.h"
|
nuclear@15
|
11 #include "wsys.h"
|
nuclear@13
|
12
|
nuclear@16
|
13 @interface GLView : NSOpenGLView
|
nuclear@13
|
14 {
|
nuclear@16
|
15 struct window *win;
|
nuclear@13
|
16 }
|
nuclear@13
|
17
|
nuclear@16
|
18 -(id) initWithFrame: (NSRect) frameRect;
|
nuclear@13
|
19
|
nuclear@13
|
20 -(void) drawRect: (NSRect) rect;
|
nuclear@13
|
21 -(void) reshape;
|
nuclear@16
|
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@16
|
32 -(void) otherMouseDragged: (NSEvent*) ev;
|
nuclear@13
|
33
|
nuclear@13
|
34 -(BOOL) acceptsFirstResponder;
|
nuclear@13
|
35 @end
|
nuclear@13
|
36
|
nuclear@16
|
37 @interface AppDelegate
|
nuclear@16
|
38 {
|
nuclear@16
|
39 }
|
nuclear@16
|
40 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*)app;
|
nuclear@16
|
41 @end
|
nuclear@16
|
42
|
nuclear@13
|
43 struct window {
|
nuclear@13
|
44 int wid;
|
nuclear@15
|
45 int width, height;
|
nuclear@13
|
46 NSWindow *win;
|
nuclear@16
|
47 GLView *view;
|
nuclear@15
|
48 NSOpenGLContext *ctx;
|
nuclear@13
|
49 struct window *next;
|
nuclear@13
|
50 };
|
nuclear@13
|
51
|
nuclear@13
|
52
|
nuclear@13
|
53 static int init(void);
|
nuclear@13
|
54 static void shutdown(void);
|
nuclear@13
|
55
|
nuclear@13
|
56 /* video mode switching */
|
nuclear@13
|
57 static int set_vidmode(int xsz, int ysz);
|
nuclear@13
|
58 static int get_vidmode(int *xsz, int *ysz);
|
nuclear@13
|
59
|
nuclear@13
|
60 /* create/destroy windows */
|
nuclear@13
|
61 static int create_window(int xsz, int ysz, unsigned int flags);
|
nuclear@13
|
62 static void close_window(int wid);
|
nuclear@13
|
63
|
nuclear@13
|
64 /* window management */
|
nuclear@13
|
65 static int set_active(int wid);
|
nuclear@13
|
66 static struct window *find_window(int wid);
|
nuclear@13
|
67 static int activate_window(struct window *win);
|
nuclear@13
|
68 static int set_title(const char *str);
|
nuclear@13
|
69 static void redisplay(void);
|
nuclear@13
|
70 static void swap_buffers(void);
|
nuclear@13
|
71
|
nuclear@13
|
72 static int get_modifiers(void);
|
nuclear@13
|
73
|
nuclear@13
|
74 /* event handling and friends */
|
nuclear@13
|
75 static void set_event(int idx, int enable);
|
nuclear@13
|
76 static int process_events(void);
|
nuclear@13
|
77 static int handle_event(NSEvent *ev);
|
nuclear@13
|
78
|
nuclear@13
|
79
|
nuclear@13
|
80 static struct wsys_module ws = {
|
nuclear@13
|
81 "cocoa", 0,
|
nuclear@13
|
82 init,
|
nuclear@13
|
83 shutdown,
|
nuclear@13
|
84 set_vidmode,
|
nuclear@13
|
85 get_vidmode,
|
nuclear@13
|
86 create_window,
|
nuclear@13
|
87 close_window,
|
nuclear@13
|
88 set_active,
|
nuclear@13
|
89 set_title,
|
nuclear@13
|
90 redisplay,
|
nuclear@13
|
91 swap_buffers,
|
nuclear@13
|
92 get_modifiers,
|
nuclear@13
|
93 set_event,
|
nuclear@13
|
94 process_events,
|
nuclear@13
|
95 0
|
nuclear@13
|
96 };
|
nuclear@13
|
97
|
nuclear@13
|
98 static struct window *winlist, *active_win;
|
nuclear@16
|
99 static NSDate *block, *nonblock;
|
nuclear@16
|
100 static NSRunLoop *runloop;
|
nuclear@13
|
101
|
nuclear@13
|
102
|
nuclear@13
|
103 void sgl_register_cocoa(void)
|
nuclear@13
|
104 {
|
nuclear@15
|
105 sgl_register_module(&ws);
|
nuclear@13
|
106 }
|
nuclear@13
|
107
|
nuclear@13
|
108
|
nuclear@16
|
109 @implementation GLView
|
nuclear@16
|
110
|
nuclear@16
|
111 -(id) initWithFrame: (NSRect) frameRect
|
nuclear@16
|
112 {
|
nuclear@16
|
113 }
|
nuclear@13
|
114
|
nuclear@13
|
115 -(void) drawRect: (NSRect) rect
|
nuclear@13
|
116 {
|
nuclear@13
|
117 sgl_display_callback_t func = sgl_get_callback(SGL_DISPLAY);
|
nuclear@13
|
118 if(func) {
|
nuclear@13
|
119 func();
|
nuclear@13
|
120 }
|
nuclear@13
|
121 }
|
nuclear@13
|
122
|
nuclear@13
|
123 -(void) reshape
|
nuclear@13
|
124 {
|
nuclear@15
|
125 NSSize sz;
|
nuclear@15
|
126 sgl_reshape_callback_t func;
|
nuclear@15
|
127
|
nuclear@15
|
128 sz = [self bounds].size;
|
nuclear@15
|
129
|
nuclear@15
|
130 if((func = sgl_get_callback(SGL_RESHAPE)) && (sz.width != active_win->width ||
|
nuclear@15
|
131 sz.height != active_win->height)) {
|
nuclear@15
|
132 active_win->width = sz.width;
|
nuclear@15
|
133 active_win->height = sz.height;
|
nuclear@15
|
134 func(sz.width, sz.height);
|
nuclear@13
|
135 }
|
nuclear@13
|
136 }
|
nuclear@13
|
137
|
nuclear@13
|
138 -(BOOL) acceptsFirstResponder
|
nuclear@13
|
139 {
|
nuclear@13
|
140 return YES;
|
nuclear@13
|
141 }
|
nuclear@13
|
142 @end
|
nuclear@13
|
143
|
nuclear@16
|
144 @implementation AppDelegate : NSObject
|
nuclear@16
|
145 -(BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*)app
|
nuclear@16
|
146 {
|
nuclear@16
|
147 return YES;
|
nuclear@16
|
148 }
|
nuclear@16
|
149 @end
|
nuclear@16
|
150
|
nuclear@13
|
151 static int init(void)
|
nuclear@13
|
152 {
|
nuclear@16
|
153 if(NSApp) {
|
nuclear@16
|
154 sgl_log("wsys_cocoa: multiple calls to init\n");
|
nuclear@16
|
155 return 0;
|
nuclear@16
|
156 }
|
nuclear@16
|
157
|
nuclear@16
|
158 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
nuclear@16
|
159
|
nuclear@16
|
160 [NSApplication sharedApplication];
|
nuclear@16
|
161 [NSApp setDelegate: delegate];
|
nuclear@16
|
162
|
nuclear@16
|
163 runloop = [[NSRunLoop currentRunLoop] retain];
|
nuclear@16
|
164 block = [runloop limitDateForMode: NSDefaultRunLoopMode];
|
nuclear@16
|
165 nonblock = [[NSDate distantPast] retain];
|
nuclear@16
|
166
|
nuclear@16
|
167 [pool drain];
|
nuclear@15
|
168 return 0;
|
nuclear@13
|
169 }
|
nuclear@13
|
170
|
nuclear@13
|
171 static void shutdown(void)
|
nuclear@13
|
172 {
|
nuclear@13
|
173 while(winlist) {
|
nuclear@13
|
174 struct window *win = winlist;
|
nuclear@13
|
175 winlist = winlist->next;
|
nuclear@13
|
176
|
nuclear@16
|
177 [win->win close];
|
nuclear@13
|
178 free(win);
|
nuclear@13
|
179 }
|
nuclear@16
|
180
|
nuclear@16
|
181 [NSApp stop: nil];
|
nuclear@16
|
182 [NSApp terminate: nil];
|
nuclear@16
|
183 NSApp = 0;
|
nuclear@13
|
184 }
|
nuclear@13
|
185
|
nuclear@13
|
186
|
nuclear@13
|
187 /* video mode switching */
|
nuclear@13
|
188 static int set_vidmode(int xsz, int ysz)
|
nuclear@13
|
189 {
|
nuclear@13
|
190 return 0; /* TODO */
|
nuclear@13
|
191 }
|
nuclear@13
|
192
|
nuclear@13
|
193 static int get_vidmode(int *xsz, int *ysz)
|
nuclear@13
|
194 {
|
nuclear@13
|
195 return 0; /* TODO */
|
nuclear@13
|
196 }
|
nuclear@13
|
197
|
nuclear@13
|
198
|
nuclear@13
|
199 /* create/destroy windows */
|
nuclear@13
|
200 static int create_window(int xsz, int ysz, unsigned int flags)
|
nuclear@13
|
201 {
|
nuclear@13
|
202 NSWindow *nswin;
|
nuclear@13
|
203 NSRect rect;
|
nuclear@16
|
204 GLView *view;
|
nuclear@13
|
205 unsigned int style;
|
nuclear@13
|
206 static int next_id = 1;
|
nuclear@13
|
207
|
nuclear@13
|
208 if(!(win = malloc(sizeof *win))) {
|
nuclear@13
|
209 return -1;
|
nuclear@13
|
210 }
|
nuclear@13
|
211
|
nuclear@13
|
212 /* create the window and attach the OpenGL view */
|
nuclear@16
|
213 rect = NSMakeRect(0, 0, xsz, ysz);
|
nuclear@16
|
214 view = [[GLView alloc] initWithFrame: rect];
|
nuclear@13
|
215
|
nuclear@16
|
216 style = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask |
|
nuclear@16
|
217 NSMiniaturizableWindowMask;
|
nuclear@13
|
218
|
nuclear@13
|
219 nswin = [[NSWindow alloc] initWithContentRect: rect styleMask: style
|
nuclear@13
|
220 backing: NSBackingStoreBuffered defer: YES];
|
nuclear@16
|
221 [nswin setTitle: @"OpenGL/Cocoa"];
|
nuclear@16
|
222 [nswin setReleaseWhenClosed: YES];
|
nuclear@13
|
223 [nswin setContentView: view];
|
nuclear@16
|
224 [nswin makeFirstResponder: view];
|
nuclear@16
|
225 [nswin makeKeyAndOrderFront: nil];
|
nuclear@16
|
226
|
nuclear@16
|
227 [pool drain];
|
nuclear@13
|
228
|
nuclear@13
|
229 win->win = nswin;
|
nuclear@13
|
230 win->view = view;
|
nuclear@13
|
231 win->wid = next_id++;
|
nuclear@13
|
232 win->next = winlist;
|
nuclear@13
|
233 winlist = win;
|
nuclear@13
|
234
|
nuclear@15
|
235 if(!active_win) {
|
nuclear@15
|
236 activate_window(win);
|
nuclear@15
|
237 }
|
nuclear@13
|
238 return win->wid;
|
nuclear@13
|
239 }
|
nuclear@13
|
240
|
nuclear@13
|
241 static void close_window(int wid)
|
nuclear@13
|
242 {
|
nuclear@13
|
243 struct window *win, *prev, dummy;
|
nuclear@13
|
244 sgl_close_callback_t close_func;
|
nuclear@13
|
245
|
nuclear@13
|
246 dummy.next = win = winlist;
|
nuclear@13
|
247 prev = &dummy;
|
nuclear@13
|
248
|
nuclear@13
|
249 while(win) {
|
nuclear@13
|
250 if(win->wid == wid) {
|
nuclear@13
|
251 if(!(close_func = sgl_get_callback(SGL_CLOSE))) {
|
nuclear@13
|
252 close_func(wid);
|
nuclear@13
|
253 }
|
nuclear@13
|
254 [win->win close];
|
nuclear@13
|
255
|
nuclear@13
|
256 if(active_win == win) {
|
nuclear@13
|
257 activate_window(winlist);
|
nuclear@13
|
258 }
|
nuclear@13
|
259
|
nuclear@13
|
260 prev->next = win->next;
|
nuclear@13
|
261 free(win);
|
nuclear@13
|
262 return;
|
nuclear@13
|
263 }
|
nuclear@13
|
264 prev = win;
|
nuclear@13
|
265 win = win->next;
|
nuclear@13
|
266 }
|
nuclear@13
|
267 }
|
nuclear@13
|
268
|
nuclear@13
|
269
|
nuclear@13
|
270 /* window management */
|
nuclear@13
|
271 static int set_active(int wid)
|
nuclear@13
|
272 {
|
nuclear@15
|
273 struct window *win = find_window(wid);
|
nuclear@15
|
274 return activate_window(win);
|
nuclear@13
|
275 }
|
nuclear@13
|
276
|
nuclear@13
|
277 static struct window *find_window(int wid)
|
nuclear@13
|
278 {
|
nuclear@13
|
279 struct window *win = winlist;
|
nuclear@13
|
280
|
nuclear@13
|
281 while(win) {
|
nuclear@15
|
282 if(win->wid == wid) {
|
nuclear@13
|
283 return win;
|
nuclear@13
|
284 }
|
nuclear@13
|
285 win = win->next;
|
nuclear@13
|
286 }
|
nuclear@13
|
287 return 0;
|
nuclear@13
|
288 }
|
nuclear@13
|
289
|
nuclear@13
|
290 static int activate_window(struct window *win)
|
nuclear@13
|
291 {
|
nuclear@13
|
292 if(!win) {
|
nuclear@13
|
293 return -1;
|
nuclear@13
|
294 }
|
nuclear@13
|
295 [win->ctx makeCurrentContext];
|
nuclear@13
|
296 active_win = win;
|
nuclear@13
|
297 return 0;
|
nuclear@13
|
298 }
|
nuclear@13
|
299
|
nuclear@13
|
300 static int set_title(const char *str)
|
nuclear@13
|
301 {
|
nuclear@13
|
302 NSString *nsstr;
|
nuclear@13
|
303
|
nuclear@13
|
304 nsstr = [[NSString alloc] initWithCString: str encoding: NSASCIIStringEncoding];
|
nuclear@13
|
305 [active_win->win setTitle: nsstr];
|
nuclear@13
|
306 [nsstr release];
|
nuclear@15
|
307 return 0;
|
nuclear@13
|
308 }
|
nuclear@13
|
309
|
nuclear@13
|
310 static void redisplay(void)
|
nuclear@13
|
311 {
|
nuclear@15
|
312 active_win->needs_redisplay = 1;
|
nuclear@13
|
313 }
|
nuclear@13
|
314
|
nuclear@13
|
315 static void swap_buffers(void)
|
nuclear@13
|
316 {
|
nuclear@15
|
317 [active_win->ctx flushBuffer];
|
nuclear@13
|
318 }
|
nuclear@13
|
319
|
nuclear@13
|
320
|
nuclear@13
|
321 static int get_modifiers(void)
|
nuclear@13
|
322 {
|
nuclear@13
|
323 return 0; /* TODO */
|
nuclear@13
|
324 }
|
nuclear@13
|
325
|
nuclear@13
|
326
|
nuclear@13
|
327 /* event handling and friends */
|
nuclear@13
|
328 static void set_event(int idx, int enable)
|
nuclear@13
|
329 {
|
nuclear@13
|
330 }
|
nuclear@13
|
331
|
nuclear@13
|
332 static int process_events(void)
|
nuclear@13
|
333 {
|
nuclear@13
|
334 NSAutoreleasePool *pool;
|
nuclear@16
|
335 NSDate *limdate;
|
nuclear@14
|
336 sgl_idle_callback_t idle;
|
nuclear@16
|
337
|
nuclear@16
|
338 idle = sgl_get_callback(SGL_IDLE);
|
nuclear@13
|
339
|
nuclear@13
|
340 pool = [[NSAutoreleasePool alloc] init];
|
nuclear@16
|
341 limdate = idle ? nonblock : block;
|
nuclear@15
|
342
|
nuclear@13
|
343 for(;;) {
|
nuclear@16
|
344 NSEvent *ev = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: limdate
|
nuclear@16
|
345 inMode: NSDefaultRunLoopMode dequeue: YES];
|
nuclear@16
|
346 if(!ev) break;
|
nuclear@16
|
347
|
nuclear@16
|
348 [NSApp sendEvent: ev];
|
nuclear@16
|
349 if(limdate == block) {
|
nuclear@16
|
350 limdate = nonblock;
|
nuclear@13
|
351 }
|
nuclear@15
|
352 }
|
nuclear@15
|
353
|
nuclear@15
|
354 [pool drain];
|
nuclear@15
|
355 return 0;
|
nuclear@13
|
356 }
|
nuclear@13
|
357
|
nuclear@13
|
358 static int handle_event(NSEvent *ev)
|
nuclear@13
|
359 {
|
nuclear@14
|
360 switch([ev type]) {
|
nuclear@14
|
361 case NSKeyDown:
|
nuclear@14
|
362 case NSKeyUp:
|
nuclear@15
|
363 printf("key pressed\n");
|
nuclear@15
|
364 break;
|
nuclear@14
|
365
|
nuclear@15
|
366 default:
|
nuclear@15
|
367 break;
|
nuclear@15
|
368 }
|
nuclear@15
|
369 return 0;
|
nuclear@13
|
370 }
|
nuclear@13
|
371
|
nuclear@13
|
372 #endif /* USE_WSYS_MODULE_COCOA */
|