Commit 5b0753e0d8dfca5a33edcd3cc1306bb5d0594005
1 parent
157777ef
initial Cocoa support (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1313 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
634 additions
and
2 deletions
Makefile.target
@@ -346,6 +346,10 @@ endif | @@ -346,6 +346,10 @@ endif | ||
346 | ifdef CONFIG_SDL | 346 | ifdef CONFIG_SDL |
347 | VL_OBJS+=sdl.o | 347 | VL_OBJS+=sdl.o |
348 | endif | 348 | endif |
349 | +ifdef CONFIG_COCOA | ||
350 | +VL_OBJS+=cocoa.o | ||
351 | +COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa | ||
352 | +endif | ||
349 | ifdef CONFIG_SLIRP | 353 | ifdef CONFIG_SLIRP |
350 | DEFINES+=-I$(SRC_PATH)/slirp | 354 | DEFINES+=-I$(SRC_PATH)/slirp |
351 | SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ | 355 | SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ |
@@ -373,7 +377,10 @@ VL_LDFLAGS+=-p | @@ -373,7 +377,10 @@ VL_LDFLAGS+=-p | ||
373 | endif | 377 | endif |
374 | 378 | ||
375 | $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a | 379 | $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a |
376 | - $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(VL_LIBS) | 380 | + $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) |
381 | + | ||
382 | +cocoa.o: cocoa.m | ||
383 | + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< | ||
377 | 384 | ||
378 | sdl.o: sdl.c keymaps.c sdl_keysym.h | 385 | sdl.o: sdl.c keymaps.c sdl_keysym.h |
379 | $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< | 386 | $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< |
cocoa.m
0 → 100644
1 | +/* | ||
2 | + * QEMU Cocoa display driver | ||
3 | + * | ||
4 | + * Copyright (c) 2005 Pierre d'Herbemont | ||
5 | + * many code/inspiration from SDL 1.2 code (LGPL) | ||
6 | + * | ||
7 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
8 | + * of this software and associated documentation files (the "Software"), to deal | ||
9 | + * in the Software without restriction, including without limitation the rights | ||
10 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
11 | + * copies of the Software, and to permit persons to whom the Software is | ||
12 | + * furnished to do so, subject to the following conditions: | ||
13 | + * | ||
14 | + * The above copyright notice and this permission notice shall be included in | ||
15 | + * all copies or substantial portions of the Software. | ||
16 | + * | ||
17 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
21 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
22 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
23 | + * THE SOFTWARE. | ||
24 | + */ | ||
25 | +/* | ||
26 | + Todo : x miniaturize window | ||
27 | + x center the window | ||
28 | + - save window position | ||
29 | + - handle keyboard event | ||
30 | + - handle mouse event | ||
31 | + - non 32 bpp support | ||
32 | + - full screen | ||
33 | + - mouse focus | ||
34 | + x simple graphical prompt to demo | ||
35 | + - better graphical prompt | ||
36 | +*/ | ||
37 | +#include "vl.h" | ||
38 | +#import <Cocoa/Cocoa.h> | ||
39 | + | ||
40 | +NSWindow *window = NULL; | ||
41 | +NSQuickDrawView *qd_view = NULL; | ||
42 | + | ||
43 | + | ||
44 | +int gArgc; | ||
45 | +char **gArgv; | ||
46 | +DisplayState current_ds; | ||
47 | + | ||
48 | +/* main defined in qemu/vl.c */ | ||
49 | +int qemu_main(int argc, char **argv); | ||
50 | + | ||
51 | +/* To deal with miniaturization */ | ||
52 | +@interface QemuWindow : NSWindow | ||
53 | +{ } | ||
54 | +@end | ||
55 | + | ||
56 | + | ||
57 | +/* | ||
58 | + ------------------------------------------------------ | ||
59 | + Qemu Video Driver | ||
60 | + ------------------------------------------------------ | ||
61 | +*/ | ||
62 | + | ||
63 | +/* | ||
64 | + ------------------------------------------------------ | ||
65 | + cocoa_update | ||
66 | + ------------------------------------------------------ | ||
67 | +*/ | ||
68 | +static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) | ||
69 | +{ | ||
70 | + //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); | ||
71 | + | ||
72 | + /* Use QDFlushPortBuffer() to flush content to display */ | ||
73 | + RgnHandle dirty = NewRgn (); | ||
74 | + RgnHandle temp = NewRgn (); | ||
75 | + | ||
76 | + SetEmptyRgn (dirty); | ||
77 | + | ||
78 | + /* Build the region of dirty rectangles */ | ||
79 | + MacSetRectRgn (temp, x, y, | ||
80 | + x + w, y + h); | ||
81 | + MacUnionRgn (dirty, temp, dirty); | ||
82 | + | ||
83 | + /* Flush the dirty region */ | ||
84 | + QDFlushPortBuffer ( [ qd_view qdPort ], dirty ); | ||
85 | + DisposeRgn (dirty); | ||
86 | + DisposeRgn (temp); | ||
87 | +} | ||
88 | + | ||
89 | +/* | ||
90 | + ------------------------------------------------------ | ||
91 | + cocoa_resize | ||
92 | + ------------------------------------------------------ | ||
93 | +*/ | ||
94 | +static void cocoa_resize(DisplayState *ds, int w, int h) | ||
95 | +{ | ||
96 | + const int device_bpp = 32; | ||
97 | + static void *screen_pixels; | ||
98 | + static int screen_pitch; | ||
99 | + NSRect contentRect; | ||
100 | + | ||
101 | + //printf("resizing to %d %d\n", w, h); | ||
102 | + | ||
103 | + contentRect = NSMakeRect (0, 0, w, h); | ||
104 | + if(window) | ||
105 | + { | ||
106 | + [window close]; | ||
107 | + [window release]; | ||
108 | + } | ||
109 | + window = [ [ QemuWindow alloc ] initWithContentRect:contentRect | ||
110 | + styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask | ||
111 | + backing:NSBackingStoreBuffered defer:NO]; | ||
112 | + if(!window) | ||
113 | + { | ||
114 | + fprintf(stderr, "(cocoa) can't create window\n"); | ||
115 | + exit(1); | ||
116 | + } | ||
117 | + | ||
118 | + if(qd_view) | ||
119 | + [qd_view release]; | ||
120 | + | ||
121 | + qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; | ||
122 | + | ||
123 | + if(!qd_view) | ||
124 | + { | ||
125 | + fprintf(stderr, "(cocoa) can't create qd_view\n"); | ||
126 | + exit(1); | ||
127 | + } | ||
128 | + | ||
129 | + [ window setAcceptsMouseMovedEvents:YES ]; | ||
130 | + [ window setTitle:@"Qemu" ]; | ||
131 | + [ window setReleasedWhenClosed:NO ]; | ||
132 | + | ||
133 | + /* Set screen to black */ | ||
134 | + [ window setBackgroundColor: [NSColor blackColor] ]; | ||
135 | + | ||
136 | + /* set window position */ | ||
137 | + [ window center ]; | ||
138 | + | ||
139 | + [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; | ||
140 | + [ [ window contentView ] addSubview:qd_view ]; | ||
141 | + [ qd_view release ]; | ||
142 | + [ window makeKeyAndOrderFront:nil ]; | ||
143 | + | ||
144 | + /* Careful here, the window seems to have to be onscreen to do that */ | ||
145 | + LockPortBits ( [ qd_view qdPort ] ); | ||
146 | + screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) ); | ||
147 | + screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) ); | ||
148 | + UnlockPortBits ( [ qd_view qdPort ] ); | ||
149 | + { | ||
150 | + int vOffset = [ window frame ].size.height - | ||
151 | + [ qd_view frame ].size.height - [ qd_view frame ].origin.y; | ||
152 | + | ||
153 | + int hOffset = [ qd_view frame ].origin.x; | ||
154 | + | ||
155 | + screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8); | ||
156 | + } | ||
157 | + ds->data = screen_pixels; | ||
158 | + ds->linesize = screen_pitch; | ||
159 | + ds->depth = device_bpp; | ||
160 | + ds->width = w; | ||
161 | + ds->height = h; | ||
162 | + | ||
163 | + current_ds = *ds; | ||
164 | +} | ||
165 | + | ||
166 | +/* | ||
167 | + ------------------------------------------------------ | ||
168 | + keymap conversion | ||
169 | + ------------------------------------------------------ | ||
170 | +*/ | ||
171 | + | ||
172 | +static int keymap[] = | ||
173 | +{ | ||
174 | + 30, //'a' 0x0 | ||
175 | + 31, //'s' | ||
176 | + 32, //'d' | ||
177 | + 33, //'f' | ||
178 | + 35, //'h' | ||
179 | + 34, //'g' | ||
180 | + 44, //'z' | ||
181 | + 45, //'x' | ||
182 | + 46, //'c' | ||
183 | + 47, //'v' | ||
184 | + 0, // 0 0x0a | ||
185 | + 48, //'b' | ||
186 | + 16, //'q' | ||
187 | + 17, //'w' | ||
188 | + 18, //'e' | ||
189 | + 19, //'r' | ||
190 | + 21, //'y' 0x10 | ||
191 | + 20, //'t' | ||
192 | + 2, //'1' | ||
193 | + 3, //'2' | ||
194 | + 4, //'3' | ||
195 | + 5, //'4' | ||
196 | + 7, //'6' | ||
197 | + 6, //'5' | ||
198 | + 0, //'=' | ||
199 | + 10, //'9' | ||
200 | + 8, //'7' 0x1A | ||
201 | + 0, //'-' | ||
202 | + 9, //'8' | ||
203 | + 11, //'0' | ||
204 | + 27, //']' | ||
205 | + 24, //'o' | ||
206 | + 22, //'u' 0x20 | ||
207 | + 26, //'[' | ||
208 | + 23, //'i' | ||
209 | + 25, //'p' | ||
210 | + 28, //'\n' | ||
211 | + 38, //'l' | ||
212 | + 36, //'j' | ||
213 | + 40, //'"' | ||
214 | + 37, //'k' | ||
215 | + 39, //';' | ||
216 | + 15, //'\t' 0x30 | ||
217 | + 0, //' ' | ||
218 | + 0, //'`' | ||
219 | + 14, //'<backspace>' | ||
220 | + 0, //'' 0x34 | ||
221 | + 0, //'<esc>' | ||
222 | + 0, //'<esc>' | ||
223 | + /* Not completed to finish see http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */ | ||
224 | +}; | ||
225 | + | ||
226 | +static int cocoa_keycode_to_qemu(int keycode) | ||
227 | +{ | ||
228 | + if(sizeof(keymap) <= keycode) | ||
229 | + { | ||
230 | + printf("(cocoa) warning unknow keycode 0x%x\n", keycode); | ||
231 | + return 0; | ||
232 | + } | ||
233 | + return keymap[keycode]; | ||
234 | +} | ||
235 | + | ||
236 | +/* | ||
237 | + ------------------------------------------------------ | ||
238 | + cocoa_refresh | ||
239 | + ------------------------------------------------------ | ||
240 | +*/ | ||
241 | +static void cocoa_refresh(DisplayState *ds) | ||
242 | +{ | ||
243 | + //printf("cocoa_refresh \n"); | ||
244 | + NSDate *distantPast; | ||
245 | + NSEvent *event; | ||
246 | + NSAutoreleasePool *pool; | ||
247 | + int grab = 1; | ||
248 | + | ||
249 | + pool = [ [ NSAutoreleasePool alloc ] init ]; | ||
250 | + distantPast = [ NSDate distantPast ]; | ||
251 | + | ||
252 | + if (is_active_console(vga_console)) | ||
253 | + vga_update_display(); | ||
254 | + do { | ||
255 | + event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast | ||
256 | + inMode: NSDefaultRunLoopMode dequeue:YES ]; | ||
257 | + if (event != nil) { | ||
258 | + switch ([event type]) { | ||
259 | + case NSKeyDown: | ||
260 | + if(grab) | ||
261 | + { | ||
262 | + int keycode = cocoa_keycode_to_qemu([event keyCode]); | ||
263 | + | ||
264 | + if (keycode & 0x80) | ||
265 | + kbd_put_keycode(0xe0); | ||
266 | + kbd_put_keycode(keycode & 0x7f); | ||
267 | + } | ||
268 | + break; | ||
269 | + case NSKeyUp: | ||
270 | + if(grab) | ||
271 | + { | ||
272 | + int keycode = cocoa_keycode_to_qemu([event keyCode]); | ||
273 | + | ||
274 | + if (keycode & 0x80) | ||
275 | + kbd_put_keycode(0xe0); | ||
276 | + kbd_put_keycode(keycode | 0x80); | ||
277 | + } | ||
278 | + break; | ||
279 | + case NSScrollWheel: | ||
280 | + | ||
281 | + case NSLeftMouseDown: | ||
282 | + case NSLeftMouseUp: | ||
283 | + | ||
284 | + case NSOtherMouseDown: | ||
285 | + case NSRightMouseDown: | ||
286 | + | ||
287 | + case NSOtherMouseUp: | ||
288 | + case NSRightMouseUp: | ||
289 | + | ||
290 | + case NSMouseMoved: | ||
291 | + case NSOtherMouseDragged: | ||
292 | + case NSRightMouseDragged: | ||
293 | + case NSLeftMouseDragged: | ||
294 | + | ||
295 | + default: [NSApp sendEvent:event]; | ||
296 | + } | ||
297 | + } | ||
298 | + } while(event != nil); | ||
299 | +} | ||
300 | + | ||
301 | +/* | ||
302 | + ------------------------------------------------------ | ||
303 | + cocoa_cleanup | ||
304 | + ------------------------------------------------------ | ||
305 | +*/ | ||
306 | + | ||
307 | +static void cocoa_cleanup(void) | ||
308 | +{ | ||
309 | + | ||
310 | +} | ||
311 | + | ||
312 | +/* | ||
313 | + ------------------------------------------------------ | ||
314 | + cocoa_display_init | ||
315 | + ------------------------------------------------------ | ||
316 | +*/ | ||
317 | + | ||
318 | +void cocoa_display_init(DisplayState *ds, int full_screen) | ||
319 | +{ | ||
320 | + ds->dpy_update = cocoa_update; | ||
321 | + ds->dpy_resize = cocoa_resize; | ||
322 | + ds->dpy_refresh = cocoa_refresh; | ||
323 | + | ||
324 | + cocoa_resize(ds, 640, 400); | ||
325 | + | ||
326 | + atexit(cocoa_cleanup); | ||
327 | +} | ||
328 | + | ||
329 | +/* | ||
330 | + ------------------------------------------------------ | ||
331 | + Interface with Cocoa | ||
332 | + ------------------------------------------------------ | ||
333 | +*/ | ||
334 | + | ||
335 | + | ||
336 | +/* | ||
337 | + ------------------------------------------------------ | ||
338 | + QemuWindow | ||
339 | + Some trick from SDL to use miniwindow | ||
340 | + ------------------------------------------------------ | ||
341 | +*/ | ||
342 | +static void QZ_SetPortAlphaOpaque () | ||
343 | +{ | ||
344 | + /* Assume 32 bit if( bpp == 32 )*/ | ||
345 | + if ( 1 ) { | ||
346 | + | ||
347 | + uint32_t *pixels = (uint32_t*) current_ds.data; | ||
348 | + uint32_t rowPixels = current_ds.linesize / 4; | ||
349 | + uint32_t i, j; | ||
350 | + | ||
351 | + for (i = 0; i < current_ds.height; i++) | ||
352 | + for (j = 0; j < current_ds.width; j++) { | ||
353 | + | ||
354 | + pixels[ (i * rowPixels) + j ] |= 0xFF000000; | ||
355 | + } | ||
356 | + } | ||
357 | +} | ||
358 | + | ||
359 | +@implementation QemuWindow | ||
360 | +- (void)miniaturize:(id)sender | ||
361 | +{ | ||
362 | + | ||
363 | + /* make the alpha channel opaque so anim won't have holes in it */ | ||
364 | + QZ_SetPortAlphaOpaque (); | ||
365 | + | ||
366 | + [ super miniaturize:sender ]; | ||
367 | + | ||
368 | +} | ||
369 | +- (void)display | ||
370 | +{ | ||
371 | + /* | ||
372 | + This method fires just before the window deminaturizes from the Dock. | ||
373 | + | ||
374 | + We'll save the current visible surface, let the window manager redraw any | ||
375 | + UI elements, and restore the SDL surface. This way, no expose event | ||
376 | + is required, and the deminiaturize works perfectly. | ||
377 | + */ | ||
378 | + | ||
379 | + /* make sure pixels are fully opaque */ | ||
380 | + QZ_SetPortAlphaOpaque (); | ||
381 | + | ||
382 | + /* save current visible SDL surface */ | ||
383 | + [ self cacheImageInRect:[ qd_view frame ] ]; | ||
384 | + | ||
385 | + /* let the window manager redraw controls, border, etc */ | ||
386 | + [ super display ]; | ||
387 | + | ||
388 | + /* restore visible SDL surface */ | ||
389 | + [ self restoreCachedImage ]; | ||
390 | +} | ||
391 | + | ||
392 | +@end | ||
393 | + | ||
394 | + | ||
395 | +/* | ||
396 | + ------------------------------------------------------ | ||
397 | + QemuCocoaGUIController | ||
398 | + NSApp's delegate - indeed main object | ||
399 | + ------------------------------------------------------ | ||
400 | +*/ | ||
401 | + | ||
402 | +@interface QemuCocoaGUIController : NSObject | ||
403 | +{ | ||
404 | +} | ||
405 | +- (void)applicationDidFinishLaunching: (NSNotification *) note; | ||
406 | +- (void)applicationWillTerminate:(NSNotification *)aNotification; | ||
407 | + | ||
408 | +- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; | ||
409 | + | ||
410 | +- (void)startEmulationWithArgc:(int)argc argv:(char**)argv; | ||
411 | +@end | ||
412 | + | ||
413 | +@implementation QemuCocoaGUIController | ||
414 | +/* Called when the internal event loop has just started running */ | ||
415 | +- (void)applicationDidFinishLaunching: (NSNotification *) note | ||
416 | +{ | ||
417 | + | ||
418 | + /* Do whatever we want here : set up a pc list... */ | ||
419 | + { | ||
420 | + NSOpenPanel *op = [[NSOpenPanel alloc] init]; | ||
421 | + | ||
422 | + cocoa_resize(¤t_ds, 640, 400); | ||
423 | + | ||
424 | + [op setPrompt:@"Boot image"]; | ||
425 | + | ||
426 | + [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; | ||
427 | + | ||
428 | + [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",nil] | ||
429 | + modalForWindow:window modalDelegate:self | ||
430 | + didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; | ||
431 | + } | ||
432 | + | ||
433 | + /* or Launch Qemu, with the global args */ | ||
434 | + //[self startEmulationWithArgc:gArgc argv:gArgv]; | ||
435 | +} | ||
436 | + | ||
437 | +- (void)applicationWillTerminate:(NSNotification *)aNotification | ||
438 | +{ | ||
439 | + printf("Application will terminate\n"); | ||
440 | + qemu_system_shutdown_request(); | ||
441 | + /* In order to avoid a crash */ | ||
442 | + exit(0); | ||
443 | +} | ||
444 | + | ||
445 | +- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo | ||
446 | +{ | ||
447 | + if(returnCode == NSCancelButton) | ||
448 | + { | ||
449 | + exit(0); | ||
450 | + } | ||
451 | + | ||
452 | + if(returnCode == NSOKButton) | ||
453 | + { | ||
454 | + char *bin = "qemu"; | ||
455 | + char *img = (char*)[ [ sheet filename ] cString]; | ||
456 | + | ||
457 | + char **argv = (char**)malloc( sizeof(char*)*3 ); | ||
458 | + | ||
459 | + asprintf(&argv[0], "%s", bin); | ||
460 | + asprintf(&argv[1], "-hda"); | ||
461 | + asprintf(&argv[2], "%s", img); | ||
462 | + | ||
463 | + printf("Using argc %d argv %s -hda %s\n", 3, bin, img); | ||
464 | + | ||
465 | + [self startEmulationWithArgc:3 argv:(char**)argv]; | ||
466 | + } | ||
467 | +} | ||
468 | + | ||
469 | +- (void)startEmulationWithArgc:(int)argc argv:(char**)argv | ||
470 | +{ | ||
471 | + int status; | ||
472 | + /* Launch Qemu */ | ||
473 | + printf("starting qemu...\n"); | ||
474 | + status = qemu_main (argc, argv); | ||
475 | + exit(status); | ||
476 | +} | ||
477 | +@end | ||
478 | + | ||
479 | +/* | ||
480 | + ------------------------------------------------------ | ||
481 | + Application Creation | ||
482 | + ------------------------------------------------------ | ||
483 | +*/ | ||
484 | + | ||
485 | +/* Dock Connection */ | ||
486 | +typedef struct CPSProcessSerNum | ||
487 | +{ | ||
488 | + UInt32 lo; | ||
489 | + UInt32 hi; | ||
490 | +} CPSProcessSerNum; | ||
491 | + | ||
492 | +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); | ||
493 | +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); | ||
494 | +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); | ||
495 | + | ||
496 | +/* Menu Creation */ | ||
497 | +static void setApplicationMenu(void) | ||
498 | +{ | ||
499 | + /* warning: this code is very odd */ | ||
500 | + NSMenu *appleMenu; | ||
501 | + NSMenuItem *menuItem; | ||
502 | + NSString *title; | ||
503 | + NSString *appName; | ||
504 | + | ||
505 | + appName = @"Qemu"; | ||
506 | + appleMenu = [[NSMenu alloc] initWithTitle:@""]; | ||
507 | + | ||
508 | + /* Add menu items */ | ||
509 | + title = [@"About " stringByAppendingString:appName]; | ||
510 | + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; | ||
511 | + | ||
512 | + [appleMenu addItem:[NSMenuItem separatorItem]]; | ||
513 | + | ||
514 | + title = [@"Hide " stringByAppendingString:appName]; | ||
515 | + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; | ||
516 | + | ||
517 | + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; | ||
518 | + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; | ||
519 | + | ||
520 | + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; | ||
521 | + | ||
522 | + [appleMenu addItem:[NSMenuItem separatorItem]]; | ||
523 | + | ||
524 | + title = [@"Quit " stringByAppendingString:appName]; | ||
525 | + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; | ||
526 | + | ||
527 | + | ||
528 | + /* Put menu into the menubar */ | ||
529 | + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; | ||
530 | + [menuItem setSubmenu:appleMenu]; | ||
531 | + [[NSApp mainMenu] addItem:menuItem]; | ||
532 | + | ||
533 | + /* Tell the application object that this is now the application menu */ | ||
534 | + [NSApp setAppleMenu:appleMenu]; | ||
535 | + | ||
536 | + /* Finally give up our references to the objects */ | ||
537 | + [appleMenu release]; | ||
538 | + [menuItem release]; | ||
539 | +} | ||
540 | + | ||
541 | +/* Create a window menu */ | ||
542 | +static void setupWindowMenu(void) | ||
543 | +{ | ||
544 | + NSMenu *windowMenu; | ||
545 | + NSMenuItem *windowMenuItem; | ||
546 | + NSMenuItem *menuItem; | ||
547 | + | ||
548 | + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; | ||
549 | + | ||
550 | + /* "Minimize" item */ | ||
551 | + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; | ||
552 | + [windowMenu addItem:menuItem]; | ||
553 | + [menuItem release]; | ||
554 | + | ||
555 | + /* Put menu into the menubar */ | ||
556 | + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; | ||
557 | + [windowMenuItem setSubmenu:windowMenu]; | ||
558 | + [[NSApp mainMenu] addItem:windowMenuItem]; | ||
559 | + | ||
560 | + /* Tell the application object that this is now the window menu */ | ||
561 | + [NSApp setWindowsMenu:windowMenu]; | ||
562 | + | ||
563 | + /* Finally give up our references to the objects */ | ||
564 | + [windowMenu release]; | ||
565 | + [windowMenuItem release]; | ||
566 | + | ||
567 | +} | ||
568 | + | ||
569 | +static void CustomApplicationMain (argc, argv) | ||
570 | +{ | ||
571 | + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | ||
572 | + QemuCocoaGUIController *gui_controller; | ||
573 | + CPSProcessSerNum PSN; | ||
574 | + | ||
575 | + [NSApplication sharedApplication]; | ||
576 | + | ||
577 | + if (!CPSGetCurrentProcess(&PSN)) | ||
578 | + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) | ||
579 | + if (!CPSSetFrontProcess(&PSN)) | ||
580 | + [NSApplication sharedApplication]; | ||
581 | + | ||
582 | + /* Set up the menubar */ | ||
583 | + [NSApp setMainMenu:[[NSMenu alloc] init]]; | ||
584 | + setApplicationMenu(); | ||
585 | + setupWindowMenu(); | ||
586 | + | ||
587 | + /* Create SDLMain and make it the app delegate */ | ||
588 | + gui_controller = [[QemuCocoaGUIController alloc] init]; | ||
589 | + [NSApp setDelegate:gui_controller]; | ||
590 | + | ||
591 | + /* Start the main event loop */ | ||
592 | + [NSApp run]; | ||
593 | + | ||
594 | + [gui_controller release]; | ||
595 | + [pool release]; | ||
596 | +} | ||
597 | + | ||
598 | +/* Real main of qemu-cocoa */ | ||
599 | +int main(int argc, char **argv) | ||
600 | +{ | ||
601 | + gArgc = argc; | ||
602 | + gArgv = argv; | ||
603 | + | ||
604 | + CustomApplicationMain (argc, argv); | ||
605 | + | ||
606 | + return 0; | ||
607 | +} |
configure
@@ -83,6 +83,7 @@ fmod_inc="" | @@ -83,6 +83,7 @@ fmod_inc="" | ||
83 | linux="no" | 83 | linux="no" |
84 | kqemu="no" | 84 | kqemu="no" |
85 | kernel_path="" | 85 | kernel_path="" |
86 | +cocoa="no" | ||
86 | 87 | ||
87 | # OS specific | 88 | # OS specific |
88 | targetos=`uname -s` | 89 | targetos=`uname -s` |
@@ -178,6 +179,8 @@ for opt do | @@ -178,6 +179,8 @@ for opt do | ||
178 | ;; | 179 | ;; |
179 | --kernel-path=*) kernel_path=${opt#--kernel-path=} | 180 | --kernel-path=*) kernel_path=${opt#--kernel-path=} |
180 | ;; | 181 | ;; |
182 | + --enable-cocoa) cocoa="yes" ; sdl="no" | ||
183 | + ;; | ||
181 | esac | 184 | esac |
182 | done | 185 | done |
183 | 186 | ||
@@ -403,6 +406,9 @@ echo "host big endian $bigendian" | @@ -403,6 +406,9 @@ echo "host big endian $bigendian" | ||
403 | echo "target list $target_list" | 406 | echo "target list $target_list" |
404 | echo "gprof enabled $gprof" | 407 | echo "gprof enabled $gprof" |
405 | echo "static build $static" | 408 | echo "static build $static" |
409 | +if test "$darwin" = "yes" ; then | ||
410 | + echo "Cocoa support $cocoa" | ||
411 | +fi | ||
406 | echo "SDL support $sdl" | 412 | echo "SDL support $sdl" |
407 | echo "SDL static link $sdl_static" | 413 | echo "SDL static link $sdl_static" |
408 | echo "mingw32 support $mingw32" | 414 | echo "mingw32 support $mingw32" |
@@ -676,6 +682,11 @@ if test "$target_user_only" = "no"; then | @@ -676,6 +682,11 @@ if test "$target_user_only" = "no"; then | ||
676 | fi | 682 | fi |
677 | fi | 683 | fi |
678 | 684 | ||
685 | +if test "$cocoa" = "yes" ; then | ||
686 | + echo "#define CONFIG_COCOA 1" >> $config_h | ||
687 | + echo "CONFIG_COCOA=yes" >> $config_mak | ||
688 | +fi | ||
689 | + | ||
679 | done # for target in $targets | 690 | done # for target in $targets |
680 | 691 | ||
681 | # build tree in object directory if source path is different from current one | 692 | # build tree in object directory if source path is different from current one |
vl.c
@@ -72,6 +72,11 @@ | @@ -72,6 +72,11 @@ | ||
72 | #endif | 72 | #endif |
73 | #endif /* CONFIG_SDL */ | 73 | #endif /* CONFIG_SDL */ |
74 | 74 | ||
75 | +#ifdef CONFIG_COCOA | ||
76 | +#undef main | ||
77 | +#define main qemu_main | ||
78 | +#endif /* CONFIG_COCOA */ | ||
79 | + | ||
75 | #include "disas.h" | 80 | #include "disas.h" |
76 | 81 | ||
77 | #include "exec-all.h" | 82 | #include "exec-all.h" |
@@ -3554,8 +3559,10 @@ int main(int argc, char **argv) | @@ -3554,8 +3559,10 @@ int main(int argc, char **argv) | ||
3554 | if (nographic) { | 3559 | if (nographic) { |
3555 | dumb_display_init(ds); | 3560 | dumb_display_init(ds); |
3556 | } else { | 3561 | } else { |
3557 | -#ifdef CONFIG_SDL | 3562 | +#if defined(CONFIG_SDL) |
3558 | sdl_display_init(ds, full_screen); | 3563 | sdl_display_init(ds, full_screen); |
3564 | +#elif defined(CONFIG_COCOA) | ||
3565 | + cocoa_display_init(ds, full_screen); | ||
3559 | #else | 3566 | #else |
3560 | dumb_display_init(ds); | 3567 | dumb_display_init(ds); |
3561 | #endif | 3568 | #endif |