2 * QEMU Cocoa display driver
4 * Copyright (c) 2005 Pierre d'Herbemont
5 * many code/inspiration from SDL 1.2 code (LGPL)
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
26 Todo : x miniaturize window
28 - save window position
29 - handle keyboard event
34 x simple graphical prompt to demo
35 - better graphical prompt
38 #import <Cocoa/Cocoa.h>
40 #include "qemu-common.h"
44 NSWindow *window = NULL;
45 NSQuickDrawView *qd_view = NULL;
50 DisplayState current_ds;
53 int modifiers_state[256];
55 /* main defined in qemu/vl.c */
56 int qemu_main(int argc, char **argv);
58 /* To deal with miniaturization */
59 @interface QemuWindow : NSWindow
65 ------------------------------------------------------
67 ------------------------------------------------------
71 ------------------------------------------------------
73 ------------------------------------------------------
75 static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
77 //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
79 /* Use QDFlushPortBuffer() to flush content to display */
80 RgnHandle dirty = NewRgn ();
81 RgnHandle temp = NewRgn ();
85 /* Build the region of dirty rectangles */
86 MacSetRectRgn (temp, x, y,
88 MacUnionRgn (dirty, temp, dirty);
90 /* Flush the dirty region */
91 QDFlushPortBuffer ( [ qd_view qdPort ], dirty );
97 ------------------------------------------------------
99 ------------------------------------------------------
101 static void cocoa_resize(DisplayState *ds, int w, int h)
103 const int device_bpp = 32;
104 static void *screen_pixels;
105 static int screen_pitch;
108 //printf("resizing to %d %d\n", w, h);
110 contentRect = NSMakeRect (0, 0, w, h);
116 window = [ [ QemuWindow alloc ] initWithContentRect:contentRect
117 styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
118 backing:NSBackingStoreBuffered defer:NO];
121 fprintf(stderr, "(cocoa) can't create window\n");
128 qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
132 fprintf(stderr, "(cocoa) can't create qd_view\n");
136 [ window setAcceptsMouseMovedEvents:YES ];
137 [ window setTitle:@"Qemu" ];
138 [ window setReleasedWhenClosed:NO ];
140 /* Set screen to black */
141 [ window setBackgroundColor: [NSColor blackColor] ];
143 /* set window position */
146 [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
147 [ [ window contentView ] addSubview:qd_view ];
149 [ window makeKeyAndOrderFront:nil ];
151 /* Careful here, the window seems to have to be onscreen to do that */
152 LockPortBits ( [ qd_view qdPort ] );
153 screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) );
154 screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) );
155 UnlockPortBits ( [ qd_view qdPort ] );
157 int vOffset = [ window frame ].size.height -
158 [ qd_view frame ].size.height - [ qd_view frame ].origin.y;
160 int hOffset = [ qd_view frame ].origin.x;
162 screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
164 ds->data = screen_pixels;
165 ds->linesize = screen_pitch;
166 ds->depth = device_bpp;
169 #ifdef __LITTLE_ENDIAN__
179 ------------------------------------------------------
181 ------------------------------------------------------
186 // SdlI macI macH SdlH 104xtH 104xtC sdl
187 30, // 0 0x00 0x1e A QZ_a
188 31, // 1 0x01 0x1f S QZ_s
189 32, // 2 0x02 0x20 D QZ_d
190 33, // 3 0x03 0x21 F QZ_f
191 35, // 4 0x04 0x23 H QZ_h
192 34, // 5 0x05 0x22 G QZ_g
193 44, // 6 0x06 0x2c Z QZ_z
194 45, // 7 0x07 0x2d X QZ_x
195 46, // 8 0x08 0x2e C QZ_c
196 47, // 9 0x09 0x2f V QZ_v
197 0, // 10 0x0A Undefined
198 48, // 11 0x0B 0x30 B QZ_b
199 16, // 12 0x0C 0x10 Q QZ_q
200 17, // 13 0x0D 0x11 W QZ_w
201 18, // 14 0x0E 0x12 E QZ_e
202 19, // 15 0x0F 0x13 R QZ_r
203 21, // 16 0x10 0x15 Y QZ_y
204 20, // 17 0x11 0x14 T QZ_t
205 2, // 18 0x12 0x02 1 QZ_1
206 3, // 19 0x13 0x03 2 QZ_2
207 4, // 20 0x14 0x04 3 QZ_3
208 5, // 21 0x15 0x05 4 QZ_4
209 7, // 22 0x16 0x07 6 QZ_6
210 6, // 23 0x17 0x06 5 QZ_5
211 13, // 24 0x18 0x0d = QZ_EQUALS
212 10, // 25 0x19 0x0a 9 QZ_9
213 8, // 26 0x1A 0x08 7 QZ_7
214 12, // 27 0x1B 0x0c - QZ_MINUS
215 9, // 28 0x1C 0x09 8 QZ_8
216 11, // 29 0x1D 0x0b 0 QZ_0
217 27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET
218 24, // 31 0x1F 0x18 O QZ_o
219 22, // 32 0x20 0x16 U QZ_u
220 26, // 33 0x21 0x1a [ QZ_LEFTBRACKET
221 23, // 34 0x22 0x17 I QZ_i
222 25, // 35 0x23 0x19 P QZ_p
223 28, // 36 0x24 0x1c ENTER QZ_RETURN
224 38, // 37 0x25 0x26 L QZ_l
225 36, // 38 0x26 0x24 J QZ_j
226 40, // 39 0x27 0x28 ' QZ_QUOTE
227 37, // 40 0x28 0x25 K QZ_k
228 39, // 41 0x29 0x27 ; QZ_SEMICOLON
229 43, // 42 0x2A 0x2b \ QZ_BACKSLASH
230 51, // 43 0x2B 0x33 , QZ_COMMA
231 53, // 44 0x2C 0x35 / QZ_SLASH
232 49, // 45 0x2D 0x31 N QZ_n
233 50, // 46 0x2E 0x32 M QZ_m
234 52, // 47 0x2F 0x34 . QZ_PERIOD
235 15, // 48 0x30 0x0f TAB QZ_TAB
236 57, // 49 0x31 0x39 SPACE QZ_SPACE
237 41, // 50 0x32 0x29 ` QZ_BACKQUOTE
238 14, // 51 0x33 0x0e BKSP QZ_BACKSPACE
239 0, // 52 0x34 Undefined
240 1, // 53 0x35 0x01 ESC QZ_ESCAPE
241 0, // 54 0x36 QZ_RMETA
242 0, // 55 0x37 QZ_LMETA
243 42, // 56 0x38 0x2a L SHFT QZ_LSHIFT
244 58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK
245 56, // 58 0x3A 0x38 L ALT QZ_LALT
246 29, // 59 0x3B 0x1d L CTRL QZ_LCTRL
247 54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT
248 184,// 61 0x3D 0xb8 E0,38 R ALT QZ_RALT
249 157,// 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL
250 0, // 63 0x3F Undefined
251 0, // 64 0x40 Undefined
252 0, // 65 0x41 Undefined
253 0, // 66 0x42 Undefined
254 55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY
255 0, // 68 0x44 Undefined
256 78, // 69 0x45 0x4e KP + QZ_KP_PLUS
257 0, // 70 0x46 Undefined
258 69, // 71 0x47 0x45 NUM QZ_NUMLOCK
259 0, // 72 0x48 Undefined
260 0, // 73 0x49 Undefined
261 0, // 74 0x4A Undefined
262 181,// 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE
263 152,// 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER
264 0, // 77 0x4D undefined
265 74, // 78 0x4E 0x4a KP - QZ_KP_MINUS
266 0, // 79 0x4F Undefined
267 0, // 80 0x50 Undefined
268 0, // 81 0x51 QZ_KP_EQUALS
269 82, // 82 0x52 0x52 KP 0 QZ_KP0
270 79, // 83 0x53 0x4f KP 1 QZ_KP1
271 80, // 84 0x54 0x50 KP 2 QZ_KP2
272 81, // 85 0x55 0x51 KP 3 QZ_KP3
273 75, // 86 0x56 0x4b KP 4 QZ_KP4
274 76, // 87 0x57 0x4c KP 5 QZ_KP5
275 77, // 88 0x58 0x4d KP 6 QZ_KP6
276 71, // 89 0x59 0x47 KP 7 QZ_KP7
277 0, // 90 0x5A Undefined
278 72, // 91 0x5B 0x48 KP 8 QZ_KP8
279 73, // 92 0x5C 0x49 KP 9 QZ_KP9
280 0, // 93 0x5D Undefined
281 0, // 94 0x5E Undefined
282 0, // 95 0x5F Undefined
283 63, // 96 0x60 0x3f F5 QZ_F5
284 64, // 97 0x61 0x40 F6 QZ_F6
285 65, // 98 0x62 0x41 F7 QZ_F7
286 61, // 99 0x63 0x3d F3 QZ_F3
287 66, // 100 0x64 0x42 F8 QZ_F8
288 67, // 101 0x65 0x43 F9 QZ_F9
289 0, // 102 0x66 Undefined
290 87, // 103 0x67 0x57 F11 QZ_F11
291 0, // 104 0x68 Undefined
292 183,// 105 0x69 0xb7 QZ_PRINT
293 0, // 106 0x6A Undefined
294 70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK
295 0, // 108 0x6C Undefined
296 68, // 109 0x6D 0x44 F10 QZ_F10
297 0, // 110 0x6E Undefined
298 88, // 111 0x6F 0x58 F12 QZ_F12
299 0, // 112 0x70 Undefined
300 110,// 113 0x71 0x0 QZ_PAUSE
301 210,// 114 0x72 0xd2 E0,52 INSERT QZ_INSERT
302 199,// 115 0x73 0xc7 E0,47 HOME QZ_HOME
303 201,// 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP
304 211,// 117 0x75 0xd3 E0,53 DELETE QZ_DELETE
305 62, // 118 0x76 0x3e F4 QZ_F4
306 207,// 119 0x77 0xcf E0,4f END QZ_END
307 60, // 120 0x78 0x3c F2 QZ_F2
308 209,// 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN
309 59, // 122 0x7A 0x3b F1 QZ_F1
310 203,// 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT
311 205,// 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT
312 208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN
313 200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP
314 /* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
316 /* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
318 219 // 0xdb e0,5b L GUI
319 220 // 0xdc e0,5c R GUI
320 221 // 0xdd e0,5d APPS
321 // E0,2A,E0,37 PRNT SCRN
322 // E1,1D,45,E1,9D,C5 PAUSE
325 222 // 0xde E0, 5E Power
326 223 // 0xdf E0, 5F Sleep
327 227 // 0xe3 E0, 63 Wake
328 // Windows Multimedia Scan Codes
329 153 // 0x99 E0, 19 Next Track
330 144 // 0x90 E0, 10 Previous Track
331 164 // 0xa4 E0, 24 Stop
332 162 // 0xa2 E0, 22 Play/Pause
333 160 // 0xa0 E0, 20 Mute
334 176 // 0xb0 E0, 30 Volume Up
335 174 // 0xae E0, 2E Volume Down
336 237 // 0xed E0, 6D Media Select
337 236 // 0xec E0, 6C E-Mail
338 161 // 0xa1 E0, 21 Calculator
339 235 // 0xeb E0, 6B My Computer
340 229 // 0xe5 E0, 65 WWW Search
341 178 // 0xb2 E0, 32 WWW Home
342 234 // 0xea E0, 6A WWW Back
343 233 // 0xe9 E0, 69 WWW Forward
344 232 // 0xe8 E0, 68 WWW Stop
345 231 // 0xe7 E0, 67 WWW Refresh
346 230 // 0xe6 E0, 66 WWW Favorites
350 int cocoa_keycode_to_qemu(int keycode)
352 if((sizeof(keymap)/sizeof(int)) <= keycode)
354 printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
357 return keymap[keycode];
361 ------------------------------------------------------
363 ------------------------------------------------------
365 static void cocoa_refresh(DisplayState *ds)
367 //printf("cocoa_refresh \n");
370 NSAutoreleasePool *pool;
372 pool = [ [ NSAutoreleasePool alloc ] init ];
373 distantPast = [ NSDate distantPast ];
378 event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
379 inMode: NSDefaultRunLoopMode dequeue:YES ];
381 switch ([event type]) {
384 int keycode = cocoa_keycode_to_qemu([event keyCode]);
388 if (keycode == 58 || keycode == 69) {
389 /* emulate caps lock and num lock keydown and keyup */
390 kbd_put_keycode(keycode);
391 kbd_put_keycode(keycode | 0x80);
392 } else if (is_graphic_console()) {
394 kbd_put_keycode(0xe0);
395 if (modifiers_state[keycode] == 0) {
397 kbd_put_keycode(keycode & 0x7f);
398 modifiers_state[keycode] = 1;
401 kbd_put_keycode(keycode | 0x80);
402 modifiers_state[keycode] = 0;
407 /* release Mouse grab when pressing ctrl+alt */
408 if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask))
410 [window setTitle: @"QEMU"];
412 CGAssociateMouseAndMouseCursorPosition ( TRUE );
420 int keycode = cocoa_keycode_to_qemu([event keyCode]);
422 /* handle command Key Combos */
423 if ([event modifierFlags] & NSCommandKeyMask) {
424 switch ([event keyCode]) {
427 /* switch to windowed View */
433 /* handle control + alt Key Combos */
434 if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
437 case 0x02 ... 0x0a: /* '1' to '9' keys */
438 console_select(keycode - 0x02);
442 /* handle standard key events */
443 if (is_graphic_console()) {
444 if (keycode & 0x80) //check bit for e0 in front
445 kbd_put_keycode(0xe0);
446 kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
447 /* handle monitor key events */
451 switch([event keyCode]) {
453 keysym = QEMU_KEY_HOME;
456 keysym = QEMU_KEY_DELETE;
459 keysym = QEMU_KEY_END;
462 keysym = QEMU_KEY_LEFT;
465 keysym = QEMU_KEY_RIGHT;
468 keysym = QEMU_KEY_DOWN;
471 keysym = QEMU_KEY_UP;
475 NSString *ks = [event characters];
478 keysym = [ks characterAtIndex:0];
482 kbd_put_keysym(keysym);
490 int keycode = cocoa_keycode_to_qemu([event keyCode]);
491 if (is_graphic_console()) {
493 kbd_put_keycode(0xe0);
494 kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
501 int dx = [event deltaX];
502 int dy = [event deltaY];
503 int dz = [event deltaZ];
505 kbd_mouse_event(dx, dy, dz, buttons);
509 case NSLeftMouseDown:
513 /* leftclick+command simulates rightclick */
514 if ([event modifierFlags] & NSCommandKeyMask) {
515 buttons |= MOUSE_EVENT_RBUTTON;
517 buttons |= MOUSE_EVENT_LBUTTON;
519 kbd_mouse_event(0, 0, 0, buttons);
521 [NSApp sendEvent: event];
525 case NSLeftMouseDragged:
527 int dx = [event deltaX];
528 int dy = [event deltaY];
529 int dz = [event deltaZ];
531 if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) { //leftclick+command simulates rightclick
532 buttons |= MOUSE_EVENT_RBUTTON;
534 buttons |= MOUSE_EVENT_LBUTTON;
536 kbd_mouse_event(dx, dy, dz, buttons);
542 kbd_mouse_event(0, 0, 0, 0);
544 [window setTitle: @"QEMU (Press ctrl + alt to release Mouse)"];
546 CGAssociateMouseAndMouseCursorPosition ( FALSE );
548 //[NSApp sendEvent: event];
552 case NSRightMouseDown:
556 buttons |= MOUSE_EVENT_RBUTTON;
557 kbd_mouse_event(0, 0, 0, buttons);
559 [NSApp sendEvent: event];
563 case NSRightMouseDragged:
565 int dx = [event deltaX];
566 int dy = [event deltaY];
567 int dz = [event deltaZ];
569 buttons |= MOUSE_EVENT_RBUTTON;
570 kbd_mouse_event(dx, dy, dz, buttons);
576 kbd_mouse_event(0, 0, 0, 0);
578 [NSApp sendEvent: event];
582 case NSOtherMouseDragged:
584 int dx = [event deltaX];
585 int dy = [event deltaY];
586 int dz = [event deltaZ];
588 buttons |= MOUSE_EVENT_MBUTTON;
589 kbd_mouse_event(dx, dy, dz, buttons);
593 case NSOtherMouseDown:
596 buttons |= MOUSE_EVENT_MBUTTON;
597 kbd_mouse_event(0, 0, 0, buttons);
599 [NSApp sendEvent:event];
605 kbd_mouse_event(0, 0, 0, 0);
607 [NSApp sendEvent: event];
613 int dz = [event deltaY];
614 kbd_mouse_event(0, 0, -dz, 0);
618 default: [NSApp sendEvent:event];
621 } while(event != nil);
625 ------------------------------------------------------
627 ------------------------------------------------------
630 static void cocoa_cleanup(void)
636 ------------------------------------------------------
638 ------------------------------------------------------
641 void cocoa_display_init(DisplayState *ds, int full_screen)
643 ds->dpy_update = cocoa_update;
644 ds->dpy_resize = cocoa_resize;
645 ds->dpy_refresh = cocoa_refresh;
647 cocoa_resize(ds, 640, 400);
649 atexit(cocoa_cleanup);
653 ------------------------------------------------------
655 ------------------------------------------------------
660 ------------------------------------------------------
662 Some trick from SDL to use miniwindow
663 ------------------------------------------------------
665 static void QZ_SetPortAlphaOpaque ()
667 /* Assume 32 bit if( bpp == 32 )*/
670 uint32_t *pixels = (uint32_t*) current_ds.data;
671 uint32_t rowPixels = current_ds.linesize / 4;
674 for (i = 0; i < current_ds.height; i++)
675 for (j = 0; j < current_ds.width; j++) {
677 pixels[ (i * rowPixels) + j ] |= 0xFF000000;
682 @implementation QemuWindow
683 - (void)miniaturize:(id)sender
686 /* make the alpha channel opaque so anim won't have holes in it */
687 QZ_SetPortAlphaOpaque ();
689 [ super miniaturize:sender ];
695 This method fires just before the window deminaturizes from the Dock.
697 We'll save the current visible surface, let the window manager redraw any
698 UI elements, and restore the SDL surface. This way, no expose event
699 is required, and the deminiaturize works perfectly.
702 /* make sure pixels are fully opaque */
703 QZ_SetPortAlphaOpaque ();
705 /* save current visible SDL surface */
706 [ self cacheImageInRect:[ qd_view frame ] ];
708 /* let the window manager redraw controls, border, etc */
711 /* restore visible SDL surface */
712 [ self restoreCachedImage ];
719 ------------------------------------------------------
720 QemuCocoaGUIController
721 NSApp's delegate - indeed main object
722 ------------------------------------------------------
725 @interface QemuCocoaGUIController : NSObject
728 - (void)applicationDidFinishLaunching: (NSNotification *) note;
729 - (void)applicationWillTerminate:(NSNotification *)aNotification;
731 - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
733 - (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
736 @implementation QemuCocoaGUIController
737 /* Called when the internal event loop has just started running */
738 - (void)applicationDidFinishLaunching: (NSNotification *) note
741 /* Display an open dialog box if no argument were passed or
742 if qemu was launched from the finder ( the Finder passes "-psn" ) */
744 if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
746 NSOpenPanel *op = [[NSOpenPanel alloc] init];
748 cocoa_resize(¤t_ds, 640, 400);
750 [op setPrompt:@"Boot image"];
752 [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
754 [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
755 modalForWindow:window modalDelegate:self
756 didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
760 /* or Launch Qemu, with the global args */
761 [self startEmulationWithArgc:gArgc argv:gArgv];
765 - (void)applicationWillTerminate:(NSNotification *)aNotification
767 printf("Application will terminate\n");
768 qemu_system_shutdown_request();
769 /* In order to avoid a crash */
773 - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
775 if(returnCode == NSCancelButton)
780 if(returnCode == NSOKButton)
783 char *img = (char*)[ [ sheet filename ] cString];
785 char **argv = (char**)malloc( sizeof(char*)*3 );
787 asprintf(&argv[0], "%s", bin);
788 asprintf(&argv[1], "-hda");
789 asprintf(&argv[2], "%s", img);
791 printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
793 [self startEmulationWithArgc:3 argv:(char**)argv];
797 - (void)startEmulationWithArgc:(int)argc argv:(char**)argv
801 printf("starting qemu...\n");
802 status = qemu_main (argc, argv);
808 ------------------------------------------------------
810 ------------------------------------------------------
813 /* Dock Connection */
814 typedef struct CPSProcessSerNum
820 extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
821 extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
822 extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
825 static void setApplicationMenu(void)
827 /* warning: this code is very odd */
829 NSMenuItem *menuItem;
834 appleMenu = [[NSMenu alloc] initWithTitle:@""];
837 title = [@"About " stringByAppendingString:appName];
838 [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
840 [appleMenu addItem:[NSMenuItem separatorItem]];
842 title = [@"Hide " stringByAppendingString:appName];
843 [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
845 menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
846 [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
848 [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
850 [appleMenu addItem:[NSMenuItem separatorItem]];
852 title = [@"Quit " stringByAppendingString:appName];
853 [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
856 /* Put menu into the menubar */
857 menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
858 [menuItem setSubmenu:appleMenu];
859 [[NSApp mainMenu] addItem:menuItem];
861 /* Tell the application object that this is now the application menu */
862 [NSApp setAppleMenu:appleMenu];
864 /* Finally give up our references to the objects */
869 /* Create a window menu */
870 static void setupWindowMenu(void)
873 NSMenuItem *windowMenuItem;
874 NSMenuItem *menuItem;
876 windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
878 /* "Minimize" item */
879 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
880 [windowMenu addItem:menuItem];
883 /* Put menu into the menubar */
884 windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
885 [windowMenuItem setSubmenu:windowMenu];
886 [[NSApp mainMenu] addItem:windowMenuItem];
888 /* Tell the application object that this is now the window menu */
889 [NSApp setWindowsMenu:windowMenu];
891 /* Finally give up our references to the objects */
892 [windowMenu release];
893 [windowMenuItem release];
896 static void CustomApplicationMain(void)
898 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
899 QemuCocoaGUIController *gui_controller;
900 CPSProcessSerNum PSN;
902 [NSApplication sharedApplication];
904 if (!CPSGetCurrentProcess(&PSN))
905 if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
906 if (!CPSSetFrontProcess(&PSN))
907 [NSApplication sharedApplication];
909 /* Set up the menubar */
910 [NSApp setMainMenu:[[NSMenu alloc] init]];
911 setApplicationMenu();
914 /* Create SDLMain and make it the app delegate */
915 gui_controller = [[QemuCocoaGUIController alloc] init];
916 [NSApp setDelegate:gui_controller];
918 /* Start the main event loop */
921 [gui_controller release];
925 /* Real main of qemu-cocoa */
926 int main(int argc, char **argv)
931 CustomApplicationMain();