Commit 5b0753e0d8dfca5a33edcd3cc1306bb5d0594005

Authored by bellard
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
Makefile.target
... ... @@ -346,6 +346,10 @@ endif
346 346 ifdef CONFIG_SDL
347 347 VL_OBJS+=sdl.o
348 348 endif
  349 +ifdef CONFIG_COCOA
  350 +VL_OBJS+=cocoa.o
  351 +COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
  352 +endif
349 353 ifdef CONFIG_SLIRP
350 354 DEFINES+=-I$(SRC_PATH)/slirp
351 355 SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
... ... @@ -373,7 +377,10 @@ VL_LDFLAGS+=-p
373 377 endif
374 378  
375 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 385 sdl.o: sdl.c keymaps.c sdl_keysym.h
379 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(&current_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=&quot;&quot;
83 83 linux="no"
84 84 kqemu="no"
85 85 kernel_path=""
  86 +cocoa="no"
86 87  
87 88 # OS specific
88 89 targetos=`uname -s`
... ... @@ -178,6 +179,8 @@ for opt do
178 179 ;;
179 180 --kernel-path=*) kernel_path=${opt#--kernel-path=}
180 181 ;;
  182 + --enable-cocoa) cocoa="yes" ; sdl="no"
  183 + ;;
181 184 esac
182 185 done
183 186  
... ... @@ -403,6 +406,9 @@ echo &quot;host big endian $bigendian&quot;
403 406 echo "target list $target_list"
404 407 echo "gprof enabled $gprof"
405 408 echo "static build $static"
  409 +if test "$darwin" = "yes" ; then
  410 + echo "Cocoa support $cocoa"
  411 +fi
406 412 echo "SDL support $sdl"
407 413 echo "SDL static link $sdl_static"
408 414 echo "mingw32 support $mingw32"
... ... @@ -676,6 +682,11 @@ if test &quot;$target_user_only&quot; = &quot;no&quot;; then
676 682 fi
677 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 690 done # for target in $targets
680 691  
681 692 # build tree in object directory if source path is different from current one
... ...
... ... @@ -72,6 +72,11 @@
72 72 #endif
73 73 #endif /* CONFIG_SDL */
74 74  
  75 +#ifdef CONFIG_COCOA
  76 +#undef main
  77 +#define main qemu_main
  78 +#endif /* CONFIG_COCOA */
  79 +
75 80 #include "disas.h"
76 81  
77 82 #include "exec-all.h"
... ... @@ -3554,8 +3559,10 @@ int main(int argc, char **argv)
3554 3559 if (nographic) {
3555 3560 dumb_display_init(ds);
3556 3561 } else {
3557   -#ifdef CONFIG_SDL
  3562 +#if defined(CONFIG_SDL)
3558 3563 sdl_display_init(ds, full_screen);
  3564 +#elif defined(CONFIG_COCOA)
  3565 + cocoa_display_init(ds, full_screen);
3559 3566 #else
3560 3567 dumb_display_init(ds);
3561 3568 #endif
... ...