]>
Commit | Line | Data |
---|---|---|
5b0753e0 FB |
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 | */ | |
da4dbf74 | 37 | |
5b0753e0 FB |
38 | #import <Cocoa/Cocoa.h> |
39 | ||
da4dbf74 FB |
40 | #include "vl.h" |
41 | ||
5b0753e0 FB |
42 | NSWindow *window = NULL; |
43 | NSQuickDrawView *qd_view = NULL; | |
44 | ||
45 | ||
46 | int gArgc; | |
47 | char **gArgv; | |
48 | DisplayState current_ds; | |
49 | ||
50 | /* main defined in qemu/vl.c */ | |
51 | int qemu_main(int argc, char **argv); | |
52 | ||
53 | /* To deal with miniaturization */ | |
54 | @interface QemuWindow : NSWindow | |
55 | { } | |
56 | @end | |
57 | ||
58 | ||
59 | /* | |
60 | ------------------------------------------------------ | |
61 | Qemu Video Driver | |
62 | ------------------------------------------------------ | |
63 | */ | |
64 | ||
65 | /* | |
66 | ------------------------------------------------------ | |
67 | cocoa_update | |
68 | ------------------------------------------------------ | |
69 | */ | |
70 | static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) | |
71 | { | |
72 | //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); | |
73 | ||
74 | /* Use QDFlushPortBuffer() to flush content to display */ | |
75 | RgnHandle dirty = NewRgn (); | |
76 | RgnHandle temp = NewRgn (); | |
77 | ||
78 | SetEmptyRgn (dirty); | |
79 | ||
80 | /* Build the region of dirty rectangles */ | |
81 | MacSetRectRgn (temp, x, y, | |
82 | x + w, y + h); | |
83 | MacUnionRgn (dirty, temp, dirty); | |
84 | ||
85 | /* Flush the dirty region */ | |
86 | QDFlushPortBuffer ( [ qd_view qdPort ], dirty ); | |
87 | DisposeRgn (dirty); | |
88 | DisposeRgn (temp); | |
89 | } | |
90 | ||
91 | /* | |
92 | ------------------------------------------------------ | |
93 | cocoa_resize | |
94 | ------------------------------------------------------ | |
95 | */ | |
96 | static void cocoa_resize(DisplayState *ds, int w, int h) | |
97 | { | |
98 | const int device_bpp = 32; | |
99 | static void *screen_pixels; | |
100 | static int screen_pitch; | |
101 | NSRect contentRect; | |
102 | ||
103 | //printf("resizing to %d %d\n", w, h); | |
104 | ||
105 | contentRect = NSMakeRect (0, 0, w, h); | |
106 | if(window) | |
107 | { | |
108 | [window close]; | |
109 | [window release]; | |
110 | } | |
111 | window = [ [ QemuWindow alloc ] initWithContentRect:contentRect | |
112 | styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask | |
113 | backing:NSBackingStoreBuffered defer:NO]; | |
114 | if(!window) | |
115 | { | |
116 | fprintf(stderr, "(cocoa) can't create window\n"); | |
117 | exit(1); | |
118 | } | |
119 | ||
120 | if(qd_view) | |
121 | [qd_view release]; | |
122 | ||
123 | qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; | |
124 | ||
125 | if(!qd_view) | |
126 | { | |
127 | fprintf(stderr, "(cocoa) can't create qd_view\n"); | |
128 | exit(1); | |
129 | } | |
130 | ||
131 | [ window setAcceptsMouseMovedEvents:YES ]; | |
132 | [ window setTitle:@"Qemu" ]; | |
133 | [ window setReleasedWhenClosed:NO ]; | |
134 | ||
135 | /* Set screen to black */ | |
136 | [ window setBackgroundColor: [NSColor blackColor] ]; | |
137 | ||
138 | /* set window position */ | |
139 | [ window center ]; | |
140 | ||
141 | [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; | |
142 | [ [ window contentView ] addSubview:qd_view ]; | |
143 | [ qd_view release ]; | |
144 | [ window makeKeyAndOrderFront:nil ]; | |
145 | ||
146 | /* Careful here, the window seems to have to be onscreen to do that */ | |
147 | LockPortBits ( [ qd_view qdPort ] ); | |
148 | screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) ); | |
149 | screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) ); | |
150 | UnlockPortBits ( [ qd_view qdPort ] ); | |
151 | { | |
152 | int vOffset = [ window frame ].size.height - | |
153 | [ qd_view frame ].size.height - [ qd_view frame ].origin.y; | |
154 | ||
155 | int hOffset = [ qd_view frame ].origin.x; | |
156 | ||
157 | screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8); | |
158 | } | |
159 | ds->data = screen_pixels; | |
160 | ds->linesize = screen_pitch; | |
161 | ds->depth = device_bpp; | |
162 | ds->width = w; | |
163 | ds->height = h; | |
164 | ||
165 | current_ds = *ds; | |
166 | } | |
167 | ||
168 | /* | |
169 | ------------------------------------------------------ | |
170 | keymap conversion | |
171 | ------------------------------------------------------ | |
172 | */ | |
173 | ||
174 | static int keymap[] = | |
175 | { | |
176 | 30, //'a' 0x0 | |
177 | 31, //'s' | |
178 | 32, //'d' | |
179 | 33, //'f' | |
180 | 35, //'h' | |
181 | 34, //'g' | |
182 | 44, //'z' | |
183 | 45, //'x' | |
184 | 46, //'c' | |
185 | 47, //'v' | |
186 | 0, // 0 0x0a | |
187 | 48, //'b' | |
188 | 16, //'q' | |
189 | 17, //'w' | |
190 | 18, //'e' | |
191 | 19, //'r' | |
192 | 21, //'y' 0x10 | |
193 | 20, //'t' | |
194 | 2, //'1' | |
195 | 3, //'2' | |
196 | 4, //'3' | |
197 | 5, //'4' | |
198 | 7, //'6' | |
199 | 6, //'5' | |
200 | 0, //'=' | |
201 | 10, //'9' | |
202 | 8, //'7' 0x1A | |
203 | 0, //'-' | |
204 | 9, //'8' | |
205 | 11, //'0' | |
206 | 27, //']' | |
207 | 24, //'o' | |
208 | 22, //'u' 0x20 | |
209 | 26, //'[' | |
210 | 23, //'i' | |
211 | 25, //'p' | |
212 | 28, //'\n' | |
213 | 38, //'l' | |
214 | 36, //'j' | |
215 | 40, //'"' | |
216 | 37, //'k' | |
217 | 39, //';' | |
218 | 15, //'\t' 0x30 | |
219 | 0, //' ' | |
220 | 0, //'`' | |
221 | 14, //'<backspace>' | |
222 | 0, //'' 0x34 | |
223 | 0, //'<esc>' | |
224 | 0, //'<esc>' | |
225 | /* 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 */ | |
226 | }; | |
227 | ||
228 | static int cocoa_keycode_to_qemu(int keycode) | |
229 | { | |
230 | if(sizeof(keymap) <= keycode) | |
231 | { | |
232 | printf("(cocoa) warning unknow keycode 0x%x\n", keycode); | |
233 | return 0; | |
234 | } | |
235 | return keymap[keycode]; | |
236 | } | |
237 | ||
238 | /* | |
239 | ------------------------------------------------------ | |
240 | cocoa_refresh | |
241 | ------------------------------------------------------ | |
242 | */ | |
243 | static void cocoa_refresh(DisplayState *ds) | |
244 | { | |
245 | //printf("cocoa_refresh \n"); | |
246 | NSDate *distantPast; | |
247 | NSEvent *event; | |
248 | NSAutoreleasePool *pool; | |
249 | int grab = 1; | |
250 | ||
251 | pool = [ [ NSAutoreleasePool alloc ] init ]; | |
252 | distantPast = [ NSDate distantPast ]; | |
253 | ||
254 | if (is_active_console(vga_console)) | |
255 | vga_update_display(); | |
256 | do { | |
257 | event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast | |
258 | inMode: NSDefaultRunLoopMode dequeue:YES ]; | |
259 | if (event != nil) { | |
260 | switch ([event type]) { | |
261 | case NSKeyDown: | |
262 | if(grab) | |
263 | { | |
264 | int keycode = cocoa_keycode_to_qemu([event keyCode]); | |
265 | ||
266 | if (keycode & 0x80) | |
267 | kbd_put_keycode(0xe0); | |
268 | kbd_put_keycode(keycode & 0x7f); | |
269 | } | |
270 | break; | |
271 | case NSKeyUp: | |
272 | if(grab) | |
273 | { | |
274 | int keycode = cocoa_keycode_to_qemu([event keyCode]); | |
275 | ||
276 | if (keycode & 0x80) | |
277 | kbd_put_keycode(0xe0); | |
278 | kbd_put_keycode(keycode | 0x80); | |
279 | } | |
280 | break; | |
281 | case NSScrollWheel: | |
282 | ||
283 | case NSLeftMouseDown: | |
284 | case NSLeftMouseUp: | |
285 | ||
286 | case NSOtherMouseDown: | |
287 | case NSRightMouseDown: | |
288 | ||
289 | case NSOtherMouseUp: | |
290 | case NSRightMouseUp: | |
291 | ||
292 | case NSMouseMoved: | |
293 | case NSOtherMouseDragged: | |
294 | case NSRightMouseDragged: | |
295 | case NSLeftMouseDragged: | |
296 | ||
297 | default: [NSApp sendEvent:event]; | |
298 | } | |
299 | } | |
300 | } while(event != nil); | |
301 | } | |
302 | ||
303 | /* | |
304 | ------------------------------------------------------ | |
305 | cocoa_cleanup | |
306 | ------------------------------------------------------ | |
307 | */ | |
308 | ||
309 | static void cocoa_cleanup(void) | |
310 | { | |
311 | ||
312 | } | |
313 | ||
314 | /* | |
315 | ------------------------------------------------------ | |
316 | cocoa_display_init | |
317 | ------------------------------------------------------ | |
318 | */ | |
319 | ||
320 | void cocoa_display_init(DisplayState *ds, int full_screen) | |
321 | { | |
322 | ds->dpy_update = cocoa_update; | |
323 | ds->dpy_resize = cocoa_resize; | |
324 | ds->dpy_refresh = cocoa_refresh; | |
325 | ||
326 | cocoa_resize(ds, 640, 400); | |
327 | ||
328 | atexit(cocoa_cleanup); | |
329 | } | |
330 | ||
331 | /* | |
332 | ------------------------------------------------------ | |
333 | Interface with Cocoa | |
334 | ------------------------------------------------------ | |
335 | */ | |
336 | ||
337 | ||
338 | /* | |
339 | ------------------------------------------------------ | |
340 | QemuWindow | |
341 | Some trick from SDL to use miniwindow | |
342 | ------------------------------------------------------ | |
343 | */ | |
344 | static void QZ_SetPortAlphaOpaque () | |
345 | { | |
346 | /* Assume 32 bit if( bpp == 32 )*/ | |
347 | if ( 1 ) { | |
348 | ||
349 | uint32_t *pixels = (uint32_t*) current_ds.data; | |
350 | uint32_t rowPixels = current_ds.linesize / 4; | |
351 | uint32_t i, j; | |
352 | ||
353 | for (i = 0; i < current_ds.height; i++) | |
354 | for (j = 0; j < current_ds.width; j++) { | |
355 | ||
356 | pixels[ (i * rowPixels) + j ] |= 0xFF000000; | |
357 | } | |
358 | } | |
359 | } | |
360 | ||
361 | @implementation QemuWindow | |
362 | - (void)miniaturize:(id)sender | |
363 | { | |
364 | ||
365 | /* make the alpha channel opaque so anim won't have holes in it */ | |
366 | QZ_SetPortAlphaOpaque (); | |
367 | ||
368 | [ super miniaturize:sender ]; | |
369 | ||
370 | } | |
371 | - (void)display | |
372 | { | |
373 | /* | |
374 | This method fires just before the window deminaturizes from the Dock. | |
375 | ||
376 | We'll save the current visible surface, let the window manager redraw any | |
377 | UI elements, and restore the SDL surface. This way, no expose event | |
378 | is required, and the deminiaturize works perfectly. | |
379 | */ | |
380 | ||
381 | /* make sure pixels are fully opaque */ | |
382 | QZ_SetPortAlphaOpaque (); | |
383 | ||
384 | /* save current visible SDL surface */ | |
385 | [ self cacheImageInRect:[ qd_view frame ] ]; | |
386 | ||
387 | /* let the window manager redraw controls, border, etc */ | |
388 | [ super display ]; | |
389 | ||
390 | /* restore visible SDL surface */ | |
391 | [ self restoreCachedImage ]; | |
392 | } | |
393 | ||
394 | @end | |
395 | ||
396 | ||
397 | /* | |
398 | ------------------------------------------------------ | |
399 | QemuCocoaGUIController | |
400 | NSApp's delegate - indeed main object | |
401 | ------------------------------------------------------ | |
402 | */ | |
403 | ||
404 | @interface QemuCocoaGUIController : NSObject | |
405 | { | |
406 | } | |
407 | - (void)applicationDidFinishLaunching: (NSNotification *) note; | |
408 | - (void)applicationWillTerminate:(NSNotification *)aNotification; | |
409 | ||
410 | - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; | |
411 | ||
412 | - (void)startEmulationWithArgc:(int)argc argv:(char**)argv; | |
413 | @end | |
414 | ||
415 | @implementation QemuCocoaGUIController | |
416 | /* Called when the internal event loop has just started running */ | |
417 | - (void)applicationDidFinishLaunching: (NSNotification *) note | |
418 | { | |
5a246934 FB |
419 | |
420 | /* Display an open dialog box if no argument were passed or | |
421 | if qemu was launched from the finder ( the Finder passes "-psn" ) */ | |
422 | ||
423 | if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0) | |
5b0753e0 FB |
424 | { |
425 | NSOpenPanel *op = [[NSOpenPanel alloc] init]; | |
426 | ||
427 | cocoa_resize(¤t_ds, 640, 400); | |
428 | ||
429 | [op setPrompt:@"Boot image"]; | |
430 | ||
431 | [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; | |
432 | ||
7a674b13 | 433 | [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil] |
5b0753e0 FB |
434 | modalForWindow:window modalDelegate:self |
435 | didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; | |
436 | } | |
5a246934 FB |
437 | else |
438 | { | |
439 | /* or Launch Qemu, with the global args */ | |
440 | [self startEmulationWithArgc:gArgc argv:gArgv]; | |
441 | } | |
5b0753e0 FB |
442 | } |
443 | ||
444 | - (void)applicationWillTerminate:(NSNotification *)aNotification | |
445 | { | |
446 | printf("Application will terminate\n"); | |
447 | qemu_system_shutdown_request(); | |
448 | /* In order to avoid a crash */ | |
449 | exit(0); | |
450 | } | |
451 | ||
452 | - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo | |
453 | { | |
454 | if(returnCode == NSCancelButton) | |
455 | { | |
456 | exit(0); | |
457 | } | |
458 | ||
459 | if(returnCode == NSOKButton) | |
460 | { | |
461 | char *bin = "qemu"; | |
462 | char *img = (char*)[ [ sheet filename ] cString]; | |
463 | ||
464 | char **argv = (char**)malloc( sizeof(char*)*3 ); | |
465 | ||
466 | asprintf(&argv[0], "%s", bin); | |
467 | asprintf(&argv[1], "-hda"); | |
468 | asprintf(&argv[2], "%s", img); | |
469 | ||
470 | printf("Using argc %d argv %s -hda %s\n", 3, bin, img); | |
471 | ||
472 | [self startEmulationWithArgc:3 argv:(char**)argv]; | |
473 | } | |
474 | } | |
475 | ||
476 | - (void)startEmulationWithArgc:(int)argc argv:(char**)argv | |
477 | { | |
478 | int status; | |
479 | /* Launch Qemu */ | |
480 | printf("starting qemu...\n"); | |
481 | status = qemu_main (argc, argv); | |
482 | exit(status); | |
483 | } | |
484 | @end | |
485 | ||
486 | /* | |
487 | ------------------------------------------------------ | |
488 | Application Creation | |
489 | ------------------------------------------------------ | |
490 | */ | |
491 | ||
492 | /* Dock Connection */ | |
493 | typedef struct CPSProcessSerNum | |
494 | { | |
495 | UInt32 lo; | |
496 | UInt32 hi; | |
497 | } CPSProcessSerNum; | |
498 | ||
499 | extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); | |
500 | extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); | |
501 | extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); | |
502 | ||
503 | /* Menu Creation */ | |
504 | static void setApplicationMenu(void) | |
505 | { | |
506 | /* warning: this code is very odd */ | |
507 | NSMenu *appleMenu; | |
508 | NSMenuItem *menuItem; | |
509 | NSString *title; | |
510 | NSString *appName; | |
511 | ||
512 | appName = @"Qemu"; | |
513 | appleMenu = [[NSMenu alloc] initWithTitle:@""]; | |
514 | ||
515 | /* Add menu items */ | |
516 | title = [@"About " stringByAppendingString:appName]; | |
517 | [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; | |
518 | ||
519 | [appleMenu addItem:[NSMenuItem separatorItem]]; | |
520 | ||
521 | title = [@"Hide " stringByAppendingString:appName]; | |
522 | [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; | |
523 | ||
524 | menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; | |
525 | [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; | |
526 | ||
527 | [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; | |
528 | ||
529 | [appleMenu addItem:[NSMenuItem separatorItem]]; | |
530 | ||
531 | title = [@"Quit " stringByAppendingString:appName]; | |
532 | [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; | |
533 | ||
534 | ||
535 | /* Put menu into the menubar */ | |
536 | menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; | |
537 | [menuItem setSubmenu:appleMenu]; | |
538 | [[NSApp mainMenu] addItem:menuItem]; | |
539 | ||
540 | /* Tell the application object that this is now the application menu */ | |
541 | [NSApp setAppleMenu:appleMenu]; | |
542 | ||
543 | /* Finally give up our references to the objects */ | |
544 | [appleMenu release]; | |
545 | [menuItem release]; | |
546 | } | |
547 | ||
548 | /* Create a window menu */ | |
549 | static void setupWindowMenu(void) | |
550 | { | |
551 | NSMenu *windowMenu; | |
552 | NSMenuItem *windowMenuItem; | |
553 | NSMenuItem *menuItem; | |
554 | ||
555 | windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; | |
556 | ||
557 | /* "Minimize" item */ | |
558 | menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; | |
559 | [windowMenu addItem:menuItem]; | |
560 | [menuItem release]; | |
561 | ||
562 | /* Put menu into the menubar */ | |
563 | windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; | |
564 | [windowMenuItem setSubmenu:windowMenu]; | |
565 | [[NSApp mainMenu] addItem:windowMenuItem]; | |
566 | ||
567 | /* Tell the application object that this is now the window menu */ | |
568 | [NSApp setWindowsMenu:windowMenu]; | |
569 | ||
570 | /* Finally give up our references to the objects */ | |
571 | [windowMenu release]; | |
572 | [windowMenuItem release]; | |
573 | ||
574 | } | |
575 | ||
576 | static void CustomApplicationMain (argc, argv) | |
577 | { | |
578 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
579 | QemuCocoaGUIController *gui_controller; | |
580 | CPSProcessSerNum PSN; | |
581 | ||
582 | [NSApplication sharedApplication]; | |
583 | ||
584 | if (!CPSGetCurrentProcess(&PSN)) | |
585 | if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) | |
586 | if (!CPSSetFrontProcess(&PSN)) | |
587 | [NSApplication sharedApplication]; | |
588 | ||
589 | /* Set up the menubar */ | |
590 | [NSApp setMainMenu:[[NSMenu alloc] init]]; | |
591 | setApplicationMenu(); | |
592 | setupWindowMenu(); | |
593 | ||
594 | /* Create SDLMain and make it the app delegate */ | |
595 | gui_controller = [[QemuCocoaGUIController alloc] init]; | |
596 | [NSApp setDelegate:gui_controller]; | |
597 | ||
598 | /* Start the main event loop */ | |
599 | [NSApp run]; | |
600 | ||
601 | [gui_controller release]; | |
602 | [pool release]; | |
603 | } | |
604 | ||
605 | /* Real main of qemu-cocoa */ | |
606 | int main(int argc, char **argv) | |
607 | { | |
608 | gArgc = argc; | |
609 | gArgv = argv; | |
610 | ||
611 | CustomApplicationMain (argc, argv); | |
612 | ||
613 | return 0; | |
614 | } |