From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DbdPR-0001V8-Jd for qemu-devel@nongnu.org; Fri, 27 May 2005 07:53:49 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DbdLZ-0000UB-I8 for Qemu-devel@nongnu.org; Fri, 27 May 2005 07:50:10 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DbdLZ-0000TH-3e for Qemu-devel@nongnu.org; Fri, 27 May 2005 07:49:49 -0400 Received: from [195.129.94.187] (helo=srv94-187.ip-tech.ch) by monty-python.gnu.org with esmtp (TLS-1.0:DHE_RSA_3DES_EDE_CBC_SHA:24) (Exim 4.34) id 1DbdFb-0008Lk-Qs for Qemu-devel@nongnu.org; Fri, 27 May 2005 07:43:40 -0400 Message-ID: <429707A8.4040400@kberg.ch> Date: Fri, 27 May 2005 13:42:32 +0200 From: Mike Kronenberg MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------010708090501010501030501" Subject: [Qemu-devel] [PATCH] cocoa.m Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------010708090501010501030501 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hello Fabrice, hello List we are heavily working on cocoa.m. according to yesterdays post from pierre I post my patch. This patch consists of the following changes/additions: from Peter Stewart: - openGL instead of QD leaves more cpu power to qemu as windowdrawing is done by the gpu. Yes, I posted a Benchmark last week, 3.5% on a 1.5ghz. :) Maybe less on a highend... but you can get quite a overproportional speedbump on a lower end Machine! from Guillaume Outers: - fix for wrong limitation of keymap from me - full keyboard support - full mousesupport - toolbar for fda, cdrom, shutdown, reset - new commandline switches (all handled by cocoa.m) -cocoaname NAME => sets name of the running guestPC (for saving VM's and thumbnails) -cocoapath PATH => sets the path to where WM's and thumnails are saved -cocoalivethumbnail => qemu produces a 100x75 PNG thumbnail every 10 sec -cocoawindowname NAME => sets the name on the qemu window (for branding) These switches allow Apps like qemuX or Q (atm known as cocoaqemu) to take control over qemu Mike --------------010708090501010501030501 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="cocoa.m_1.4_20050527.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="cocoa.m_1.4_20050527.diff" Index: cocoa.m =================================================================== RCS file: /cvsroot/qemu/qemu/cocoa.m,v retrieving revision 1.4 diff -u -r1.4 cocoa.m --- cocoa.m 7 Apr 2005 20:36:50 -0000 1.4 +++ cocoa.m 27 May 2005 10:49:13 -0000 @@ -25,24 +25,24 @@ /* Todo : x miniaturize window x center the window - - save window position - - handle keyboard event - - handle mouse event + / save window position + / handle keyboard event + / handle mouse event - non 32 bpp support - full screen - - mouse focus + / mouse focus x simple graphical prompt to demo - - better graphical prompt + / better graphical prompt */ #import -#include "vl.h" - -NSWindow *window = NULL; -NSQuickDrawView *qd_view = NULL; +#include +#include +#include "vl.h" +/* for main */ int gArgc; char **gArgv; DisplayState current_ds; @@ -50,325 +50,828 @@ /* main defined in qemu/vl.c */ int qemu_main(int argc, char **argv); -/* To deal with miniaturization */ -@interface QemuWindow : NSWindow -{ } -@end - +/* pc Model */ +id pcModel; +NSString *pcStatus; +NSArray *fileTypes; //set allowed filetypes + +/* pc View */ +id pcWindowView; +id pcWindow; +id progressWindow; +id configWindow; + +/* openGL */ +id ogl_view = NULL; +#define SCREEN_BPP 32 +GLint screen_tex = 0; +GLuint display_list_tex = 0; + +/* NSApp controller */ +id gui_controller; +int grab = 0; +int modifiers_state[256]; /* ------------------------------------------------------ - Qemu Video Driver + Headers + ------------------------------------------------------ */ + /* ------------------------------------------------------ - cocoa_update + QemuCocoaPcWindowView ------------------------------------------------------ */ -static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) +@interface QemuCocoaPcWindowView : NSObject { - //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); - - /* Use QDFlushPortBuffer() to flush content to display */ - RgnHandle dirty = NewRgn (); - RgnHandle temp = NewRgn (); - - SetEmptyRgn (dirty); - - /* Build the region of dirty rectangles */ - MacSetRectRgn (temp, x, y, - x + w, y + h); - MacUnionRgn (dirty, temp, dirty); - - /* Flush the dirty region */ - QDFlushPortBuffer ( [ qd_view qdPort ], dirty ); - DisposeRgn (dirty); - DisposeRgn (temp); + /* pcWindow */ + NSToolbar *pcWindowToolbar; + + /* progressWindow */ + NSTextField *progressText; + NSProgressIndicator *progressIndicator; + + /* configWindow */ + NSWindow *configWindow; + NSTextField *pcname; + NSTextField *pcram; + NSTextField *pcfda; + NSTextField *pchda; + NSTextField *pccdrom; + NSTextField *pcoptions; } +/* pcWindow */ +- (void) pcWindowSetup: (int)w height:(int)h; + +/* pcWindow toolbar selectors */ +- (void) changeDevice: (id)sender; +- (void) changeDeviceSheetDidEnd: (NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo; +- (void) shutdownPC; +- (void) shutdownPCSheetDidEnd: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo; +- (void) shutdownPC2SheetDidEnd: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo; +- (void) resetPC; + +/* pcWindow toolbar delegates */ +- (NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted; +- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar; +- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar; +- (BOOL) validateToolbarItem:(NSToolbarItem *)theItem; + +/* pcWindow window delegates */ +- (void) windowDidBecomeKey:(NSNotification *)aNotification; +- (void) windowDidResignKey:(NSNotification *)aNotification; + +/* progressWindow */ +- (void) progressWindowSetup; +- (void) showProgressWindow: (NSString *)text; +- (void) hideProgressWindow; + +/* config Window */ +- (void) configWindowSetup; +- (void) closeConfigWindowQuit; +- (void) closeConfigWindowStart; +- (void) chooseFile:(id)sender; +- (void) chooseFileSheetDidEnd: (NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo; +@end + /* ------------------------------------------------------ - cocoa_resize + QemuWindow (subclass of NSWindow) ------------------------------------------------------ */ -static void cocoa_resize(DisplayState *ds, int w, int h) +@interface QemuWindow : NSWindow { - const int device_bpp = 32; - static void *screen_pixels; - static int screen_pitch; - NSRect contentRect; - - //printf("resizing to %d %d\n", w, h); - - contentRect = NSMakeRect (0, 0, w, h); - if(window) - { - [window close]; - [window release]; - } - window = [ [ QemuWindow alloc ] initWithContentRect:contentRect - styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask - backing:NSBackingStoreBuffered defer:NO]; - if(!window) - { - fprintf(stderr, "(cocoa) can't create window\n"); - exit(1); - } - - if(qd_view) - [qd_view release]; - - qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; - - if(!qd_view) - { - fprintf(stderr, "(cocoa) can't create qd_view\n"); - exit(1); - } - - [ window setAcceptsMouseMovedEvents:YES ]; - [ window setTitle:@"Qemu" ]; - [ window setReleasedWhenClosed:NO ]; - - /* Set screen to black */ - [ window setBackgroundColor: [NSColor blackColor] ]; - - /* set window position */ - [ window center ]; - - [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; - [ [ window contentView ] addSubview:qd_view ]; - [ qd_view release ]; - [ window makeKeyAndOrderFront:nil ]; - - /* Careful here, the window seems to have to be onscreen to do that */ - LockPortBits ( [ qd_view qdPort ] ); - screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) ); - screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) ); - UnlockPortBits ( [ qd_view qdPort ] ); - { - int vOffset = [ window frame ].size.height - - [ qd_view frame ].size.height - [ qd_view frame ].origin.y; - - int hOffset = [ qd_view frame ].origin.x; - - screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8); - } - ds->data = screen_pixels; - ds->linesize = screen_pitch; - ds->depth = device_bpp; - ds->width = w; - ds->height = h; - - current_ds = *ds; } +- (void) miniaturize:(id)sender; +- (void) display; +- (BOOL) windowShouldClose:(id)sender; +@end + /* ------------------------------------------------------ - keymap conversion + QemuCocoaQuickDrawView (subclass of NSQuickDrawView) ------------------------------------------------------ */ - -static int keymap[] = -{ - 30, //'a' 0x0 - 31, //'s' - 32, //'d' - 33, //'f' - 35, //'h' - 34, //'g' - 44, //'z' - 45, //'x' - 46, //'c' - 47, //'v' - 0, // 0 0x0a - 48, //'b' - 16, //'q' - 17, //'w' - 18, //'e' - 19, //'r' - 21, //'y' 0x10 - 20, //'t' - 2, //'1' - 3, //'2' - 4, //'3' - 5, //'4' - 7, //'6' - 6, //'5' - 0, //'=' - 10, //'9' - 8, //'7' 0x1A - 0, //'-' - 9, //'8' - 11, //'0' - 27, //']' - 24, //'o' - 22, //'u' 0x20 - 26, //'[' - 23, //'i' - 25, //'p' - 28, //'\n' - 38, //'l' - 36, //'j' - 40, //'"' - 37, //'k' - 39, //';' - 15, //'\t' 0x30 - 0, //' ' - 0, //'`' - 14, //'' - 0, //'' 0x34 - 0, //'' - 0, //'' - /* 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 */ -}; - -static int cocoa_keycode_to_qemu(int keycode) +@interface QemuCocoaOpenGLView : NSOpenGLView { - if(sizeof(keymap) <= keycode) - { - printf("(cocoa) warning unknow keycode 0x%x\n", keycode); - return 0; - } - return keymap[keycode]; } +- (void)mouseDown:(NSEvent *)theEvent; +@end + /* ------------------------------------------------------ - cocoa_refresh + QemuCocoaPcModel ------------------------------------------------------ */ -static void cocoa_refresh(DisplayState *ds) +@interface QemuCocoaPcModel : NSObject { - //printf("cocoa_refresh \n"); - NSDate *distantPast; - NSEvent *event; - NSAutoreleasePool *pool; - int grab = 1; - - pool = [ [ NSAutoreleasePool alloc ] init ]; - distantPast = [ NSDate distantPast ]; - - if (is_active_console(vga_console)) - vga_update_display(); - do { - event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast - inMode: NSDefaultRunLoopMode dequeue:YES ]; - if (event != nil) { - switch ([event type]) { - case NSKeyDown: - if(grab) - { - int keycode = cocoa_keycode_to_qemu([event keyCode]); - - if (keycode & 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode & 0x7f); - } - break; - case NSKeyUp: - if(grab) - { - int keycode = cocoa_keycode_to_qemu([event keyCode]); - - if (keycode & 0x80) - kbd_put_keycode(0xe0); - kbd_put_keycode(keycode | 0x80); - } - break; - case NSScrollWheel: - - case NSLeftMouseDown: - case NSLeftMouseUp: - - case NSOtherMouseDown: - case NSRightMouseDown: - - case NSOtherMouseUp: - case NSRightMouseUp: - - case NSMouseMoved: - case NSOtherMouseDragged: - case NSRightMouseDragged: - case NSLeftMouseDragged: - - default: [NSApp sendEvent:event]; - } - } - } while(event != nil); + NSString *pcWindowName; + NSString *pcName; + NSString *pcPath; + int pcLiveThumbnail; + NSTimer *timer; } +- (NSString *) pcName; +- (NSString *) pcWindowName; +- (NSImage *) thumbnailFast; +- (NSImage *) thumbnailQuality; + +- (void) liveThumbnail; +- (void) saveVM; +- (int) ejectDevice: (BlockDriverState *) bs withForce: (int) force; +- (void) ejectImage:(const char *) filename withForce: (int) force; +- (void) changeDeviceImage: (const char *) device filename: (const char *) filename withForce: (int) force; +- (void) startPC:(int)argc withArgs:(char**)argv; +- (void) resetPC; +- (void) shutdownPC; +@end + /* ------------------------------------------------------ - cocoa_cleanup + NSApp ------------------------------------------------------ */ - -static void cocoa_cleanup(void) +@interface QemuCocoaGUIController : NSObject { - } +/* NSApp methods */ +- (void) applicationMenuSetup; +- (void) windowMenuSetup; + +/* NSApp delegates*/ +- (void) applicationWillFinishLaunching: (NSNotification *) note; +- (void) applicationDidFinishLaunching: (NSNotification *) note; +- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender; +@end + /* ------------------------------------------------------ - cocoa_display_init + QemuCocoa Video Driver ------------------------------------------------------ */ +static void cocoa_update(DisplayState *ds, int x, int y, int w, int h); +static void cocoa_resize(DisplayState *ds, int w, int h); +static int cocoa_keycode_to_qemu(int keycode); +static void cocoa_refresh(DisplayState *ds); +static void cocoa_cleanup(void) ; +void cocoa_display_init(DisplayState *ds, int full_screen); + -void cocoa_display_init(DisplayState *ds, int full_screen) -{ - ds->dpy_update = cocoa_update; - ds->dpy_resize = cocoa_resize; - ds->dpy_refresh = cocoa_refresh; - - cocoa_resize(ds, 640, 400); - - atexit(cocoa_cleanup); -} /* ------------------------------------------------------ - Interface with Cocoa + Implementations + ------------------------------------------------------ */ - - /* ------------------------------------------------------ - QemuWindow - Some trick from SDL to use miniwindow + QemuCocoaPcWindowView ------------------------------------------------------ */ -static void QZ_SetPortAlphaOpaque () -{ - /* Assume 32 bit if( bpp == 32 )*/ - if ( 1 ) { - - uint32_t *pixels = (uint32_t*) current_ds.data; - uint32_t rowPixels = current_ds.linesize / 4; - uint32_t i, j; - - for (i = 0; i < current_ds.height; i++) - for (j = 0; j < current_ds.width; j++) { +@implementation QemuCocoaPcWindowView +/* creating pcWindow */ +- (void) pcWindowSetup: (int)w height:(int)h +{ + /* Init pixel format attribs */ + NSOpenGLPixelFormatAttribute attrs[] = + { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + 0 + }; + + NSRect contentRect = NSMakeRect (0, 0, w, h); + + /* Get pixel format from OpenGL */ + NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + if (!pixFmt) + { + fprintf(stderr, "No pixel format -- exiting"); + exit(1); + } + + pcWindow = [ [ QemuWindow alloc ] initWithContentRect:NSMakeRect (0, 0, w, h) + styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered defer:NO]; + + if(!pcWindow) + { + fprintf(stderr, "(cocoa) can't create pcWindow\n"); + exit(1); + } + + ogl_view = [ [ QemuCocoaOpenGLView alloc ] initWithFrame:contentRect pixelFormat:pixFmt ]; + + if(!ogl_view) + { + fprintf(stderr, "(cocoa) can't create ogl_view\n"); + exit(1); + } + + [ pcWindow center ]; + [ pcWindow setFrameAutosaveName: [ NSString stringWithFormat:@"%@ - %@", [ pcModel pcWindowName ], [ pcModel pcName ] ] ]; + [ pcWindow setAcceptsMouseMovedEvents:YES ]; + [ pcWindow setTitle: [ NSString stringWithFormat:@"%@ - %@", [ pcModel pcWindowName ], [ pcModel pcName ] ] ]; + [ pcWindow setReleasedWhenClosed:NO ]; + [ pcWindow setDelegate: self ]; + + //Toolbar + pcWindowToolbar = [ [ [ NSToolbar alloc ] initWithIdentifier: @"pcWindowToolbarIdentifier" ] autorelease ]; + [ pcWindowToolbar setAllowsUserCustomization: YES ]; //allow customisation + [ pcWindowToolbar setAutosavesConfiguration: YES ]; //autosave changes +// [ pcWindowToolbar setDisplayMode: NSToolbarDisplayModeLabelOnly ]; //what is shown + [ pcWindowToolbar setDisplayMode: NSToolbarDisplayModeIconOnly ]; //what is shown + [ pcWindowToolbar setSizeMode:NSToolbarSizeModeSmall ]; //default Toolbar Size + [ pcWindowToolbar setDelegate: self ]; // We are the delegate + [ pcWindow setToolbar: pcWindowToolbar ]; // Attach the toolbar to the document window + + [ ogl_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ [ pcWindow contentView ] addSubview:ogl_view ]; + [ ogl_view release ]; + + [ pcWindow makeKeyAndOrderFront:nil ]; +} + +/* Toolbar Delegates*/ +- (NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted +{ + NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdent] autorelease ]; + if ([itemIdent isEqual: @"fdaChangeIdentifier"]) { + [toolbarItem setLabel: @"Floppy A"]; + [toolbarItem setPaletteLabel: @"Floppy A"]; + [toolbarItem setToolTip: @"Change Floppy Drive A Image"]; + [toolbarItem setImage: [NSImage imageNamed: @"cocoa_tb_dmg_32_a.png"]]; + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector( changeDevice: )]; + } else if([itemIdent isEqual: @"fdbChangeIdentifier"]) { + [toolbarItem setLabel: @"Floppy B"]; + [toolbarItem setPaletteLabel: @"Floppy B"]; + [toolbarItem setToolTip: @"Change Floppy Drive B Image"]; + [toolbarItem setImage: [NSImage imageNamed: @"cocoa_tb_dmg_32_b.png"]]; + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector( changeDevice: )]; + } else if([itemIdent isEqual: @"cdromChangeIdentifier"]) { + [toolbarItem setLabel: @"CD-ROM"]; + [toolbarItem setPaletteLabel: @"CD-ROM"]; + [toolbarItem setToolTip: @"Change CD-ROM Image"]; + [toolbarItem setImage: [NSImage imageNamed: @"cocoa_tb_cdrom_32.png"]]; + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector( changeDevice: )]; + } else if([itemIdent isEqual: @"systemResetIdentifier"]) { + [toolbarItem setLabel: @"Reset PC"]; + [toolbarItem setPaletteLabel: @"Reset PC"]; + [toolbarItem setToolTip: @"Reset PC"]; + [toolbarItem setImage: [NSImage imageNamed: @"cocoa_tb_reset_32.png"]]; + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector( resetPC )]; + } else if ([itemIdent isEqual: @"shutdownPCIdentifier"]) { + [toolbarItem setLabel: @"Shutdown PC"]; + [toolbarItem setPaletteLabel: @"Shutdown PC"]; + [toolbarItem setToolTip: @"Shutdown PC"]; + [toolbarItem setImage: [NSImage imageNamed: @"cocoa_tb_shutdown_32.png"]]; + [toolbarItem setTarget: self]; + [toolbarItem setAction: @selector( shutdownPC )]; + } else { + toolbarItem = nil; + } + + return toolbarItem; +} + +- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar +{ + return [NSArray arrayWithObjects: + @"fdaChangeIdentifier", + @"fdbChangeIdentifier", + @"cdromChangeIdentifier", + @"systemResetIdentifier", + @"shutdownPCIdentifier", + NSToolbarCustomizeToolbarItemIdentifier, + NSToolbarFlexibleSpaceItemIdentifier, + NSToolbarSpaceItemIdentifier, + NSToolbarSeparatorItemIdentifier, + nil]; +} + +- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar +{ + return [NSArray arrayWithObjects: + @"fdaChangeIdentifier", + @"cdromChangeIdentifier", + NSToolbarSeparatorItemIdentifier, + @"shutdownPCIdentifier", + NSToolbarFlexibleSpaceItemIdentifier, + @"systemResetIdentifier", + nil]; +} + +- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem +{ + return YES; +} + +/* creating progressWindow */ +- (void)progressWindowSetup +{ + progressWindow = [ [ NSWindow alloc ] initWithContentRect:NSMakeRect (0, 0, 250, 50) + styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered defer:NO ]; + if(!progressWindow) + { + fprintf(stderr, "(cocoa) can't create progressWindow\n"); + exit(1); + } + [ progressWindow setDelegate: self ]; + [ progressWindow setMinSize:NSMakeRect (0, 0, 250, 50).size ]; + + /* creating NSprogressbarIndicator */ + progressIndicator = [ [ NSProgressIndicator alloc ] + initWithFrame:NSMakeRect(100, 20, 128, NSProgressIndicatorPreferredThickness) ]; + [ progressIndicator setIndeterminate:YES ]; + [ progressIndicator setUsesThreadedAnimation: YES ]; + [ [ progressWindow contentView ] addSubview:progressIndicator ]; + + /* creating NSTextField */ + progressText = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(20, 20, 80, 17) ]; + [ progressText setDrawsBackground: NO ]; + [ progressText setBordered: NO ]; + [ progressText setStringValue: [ [ [ NSAttributedString alloc] initWithString:@"Saving PC" attributes:[ NSDictionary dictionaryWithObject: [ NSFont boldSystemFontOfSize:[ NSFont systemFontSize] ] forKey:NSFontAttributeName ] ] autorelease ] ]; + [ progressText setSelectable:NO ]; + [ progressText setEditable:NO ]; + [ [ progressWindow contentView ] addSubview: progressText ]; + [ progressText release ]; +} + +- (void) showProgressWindow: (NSString *)text +{ + [ progressText setStringValue: [ [ [ NSAttributedString alloc] initWithString:text attributes:[ NSDictionary dictionaryWithObject: [ NSFont boldSystemFontOfSize:[ NSFont systemFontSize] ] forKey:NSFontAttributeName ] ] autorelease ] ]; + [ progressIndicator startAnimation:nil ]; + [ NSApp beginSheet:progressWindow + modalForWindow:pcWindow + modalDelegate:nil + didEndSelector:nil + contextInfo:nil ]; +} + +- (void) hideProgressWindow +{ + [ NSApp endSheet:progressWindow ]; + [ progressWindow orderOut: [ progressWindow self ] ]; + [ progressIndicator stopAnimation:nil ]; +} + +- (void) changeDevice:(id)sender +{ + NSString *description; + NSString *context; + + if ([ [ sender itemIdentifier ] isEqualTo: @"fdaChangeIdentifier" ]) { + description = @"Floppy A"; + context = @"fda"; + } else if ([ [ sender itemIdentifier ] isEqualTo: @"fdbChangeIdentifier" ]) { + description = @"Floppy B"; + context = @"fdb"; + } else if ([ [ sender itemIdentifier ] isEqualTo: @"cdromChangeIdentifier" ]) { + description = @"CD-Rom"; + context = @"cdrom"; + } else { + description = @""; + context = @""; + } + + NSOpenPanel *op = [[NSOpenPanel alloc] init]; + [op setPrompt: [ NSString stringWithFormat:@"choose Image for %@", description ] ]; + [op setMessage: [ NSString stringWithFormat:@"Select the diskimage you want to use as %@.\n\nHit the \"Cancel\" button to quit", description ] ]; + [op beginSheetForDirectory:nil + file:nil + types:fileTypes + modalForWindow:pcWindow + modalDelegate:self + didEndSelector:@selector(changeDeviceSheetDidEnd:returnCode:contextInfo:) + contextInfo:context ]; +} + +- (void)changeDeviceSheetDidEnd: (NSOpenPanel *)sheet + returnCode:(int)returnCode + contextInfo:(NSString *)contextInfo +{ + if(returnCode == NSOKButton) + [ pcModel changeDeviceImage:[ contextInfo cString] filename:[ [ sheet filename ] cString ] withForce:1 ]; +} + +- (void) shutdownPC +{ + if ( [ [ pcModel pcName ] isEqual:@"" ]) { + NSAlert *alert = [ NSAlert alertWithMessageText:@"Shutting down Guest PC" + defaultButton:@"Cancel" + alternateButton:@"Shutdown" + otherButton:@"" + informativeTextWithFormat:@"The Guest OS is still running. If you shutdown the Guest PC, you may loose Data." ]; + [ alert beginSheetModalForWindow:pcWindow + modalDelegate:self + didEndSelector:@selector(shutdownPC2SheetDidEnd:returnCode:contextInfo:) + contextInfo:nil]; + } else { + NSAlert *alert = [ NSAlert alertWithMessageText:@"Shutting down Guest PC" + defaultButton:@"Save PC" + alternateButton:@"Cancel" + otherButton:@"Don't save PC" + informativeTextWithFormat:@"The Guest OS is still running. If you don't save the PC, you may loose Data." ]; + [ alert beginSheetModalForWindow:pcWindow + modalDelegate:self + didEndSelector:@selector(shutdownPCSheetDidEnd:returnCode:contextInfo:) + contextInfo:nil]; + } +} + +- (void) shutdownPCSheetDidEnd: (NSWindow *)sheet + returnCode: (int)returnCode + contextInfo: (void *)contextInfo +{ + [ [ sheet window ] orderOut:self ]; + if (returnCode == NSAlertDefaultReturn) + { + [ pcModel saveVM ]; + [ pcModel shutdownPC ]; + exit(2); //return 2 => saved + } + else if (returnCode == NSAlertOtherReturn) + { + [ pcModel shutdownPC ]; + exit(0); //return 0 => shutdown + } +} + +- (void) shutdownPC2SheetDidEnd: (NSWindow *)sheet + returnCode: (int)returnCode + contextInfo: (void *)contextInfo +{ + [ [ sheet window ] orderOut:self ]; + if (returnCode == NSAlertDefaultReturn) + { + } + else + { + [ pcModel shutdownPC ]; + exit(0); //return 0 => shutdown + } +} +- (void) resetPC +{ + qemu_system_reset_request(); +} + +/* Window delegates */ +- (void) windowDidBecomeKey:(NSNotification *)aNotification +{ +} + +- (void) windowDidResignKey:(NSNotification *)aNotification +{ + /* ungrab Mouse */ + grab = 0; + [ pcWindow setTitle: [ NSString stringWithFormat: @"%@ - %@",[ pcModel pcWindowName ], [ pcModel pcName ] ] ]; + [ NSCursor unhide ]; + CGAssociateMouseAndMouseCursorPosition ( TRUE ); + + /* reset Key Modifiers */ + int i; + for(i = 0; i < 256; i++) { + if (modifiers_state[i]) { + if (i & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(i | 0x80); + modifiers_state[i] = 0; + } + } +} + +/* create configWindow */ +- (void)configWindowSetup +{ + configWindow = [ [ NSWindow alloc ] initWithContentRect:NSMakeRect (0, 0, 400, 358) + styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered defer:NO]; + if(!configWindow) + { + fprintf(stderr, "(cocoa) can't create configWindow\n"); + exit(1); + } + [ configWindow setMinSize:NSMakeRect (0, 0, 400, 358).size ]; + [ configWindow setTitle:@"cocoaqemu - PC Setup" ]; + [ configWindow setReleasedWhenClosed:YES ]; + [ configWindow setDelegate: self ]; + + //Title + NSTextField *pctitle = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(20, 326, 360, 17) ]; + [ pctitle setDrawsBackground: NO ]; + [ pctitle setBordered: NO ]; + [ pctitle setStringValue: [ [ [ NSAttributedString alloc] initWithString:@"Configure your qemu PC" attributes:[ NSDictionary dictionaryWithObject: [ NSFont boldSystemFontOfSize:[ NSFont systemFontSize] ] forKey:NSFontAttributeName ] ] autorelease ] ]; + [ pctitle setSelectable:NO ]; + [ pctitle setEditable:NO ]; + [ [ configWindow contentView ] addSubview: pctitle ]; + [ pctitle release ]; + + NSTextField *pcramlabel = [[NSTextField alloc] initWithFrame: NSMakeRect(20, 223, 100, 17) ]; + [ pcramlabel setDrawsBackground: NO ]; + [ pcramlabel setBordered: NO ]; + [ pcramlabel setAlignment: NSRightTextAlignment ]; + [ pcramlabel setStringValue: @"Ram" ]; + [ pcramlabel setEditable:NO ]; + [ pcramlabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcramlabel ]; + [ pcramlabel release ]; + + NSTextField *pcdriveslabel = [[NSTextField alloc] initWithFrame: NSMakeRect(20, 176, 100, 17) ]; + [ pcdriveslabel setDrawsBackground: NO ]; + [ pcdriveslabel setBordered: NO ]; + [ pcdriveslabel setAlignment: NSRightTextAlignment ]; + [ pcdriveslabel setStringValue: @"Drives" ]; + [ pcdriveslabel setEditable:NO ]; + [ pcdriveslabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcdriveslabel ]; + [ pcdriveslabel release ]; + + NSTextField *pcdrivesAlabel = [[NSTextField alloc] initWithFrame: NSMakeRect(108, 176, 100, 17) ]; + [ pcdrivesAlabel setDrawsBackground: NO ]; + [ pcdrivesAlabel setBordered: NO ]; + [ pcdrivesAlabel setAlignment: NSRightTextAlignment ]; + [ pcdrivesAlabel setStringValue: @"Floppy A" ]; + [ pcdrivesAlabel setEditable:NO ]; + [ pcdrivesAlabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcdrivesAlabel ]; + [ pcdrivesAlabel release ]; + + NSTextField *pcdrivesClabel = [[NSTextField alloc] initWithFrame: NSMakeRect(108, 142, 100, 17) ]; + [ pcdrivesClabel setDrawsBackground: NO ]; + [ pcdrivesClabel setBordered: NO ]; + [ pcdrivesClabel setAlignment: NSRightTextAlignment ]; + [ pcdrivesClabel setStringValue: @"Harddisk" ]; + [ pcdrivesClabel setEditable:NO ]; + [ pcdrivesClabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcdrivesClabel ]; + [ pcdrivesClabel release ]; + + NSTextField *pcdrivesDlabel = [[NSTextField alloc] initWithFrame: NSMakeRect(108, 108, 100, 17) ]; + [ pcdrivesDlabel setDrawsBackground: NO ]; + [ pcdrivesDlabel setBordered: NO ]; + [ pcdrivesDlabel setAlignment: NSRightTextAlignment ]; + [ pcdrivesDlabel setStringValue: @"CD-ROM" ]; + [ pcdrivesDlabel setEditable:NO ]; + [ pcdrivesDlabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcdrivesDlabel ]; + [ pcdrivesDlabel release ]; + + NSTextField *pcoptionslabel = [[NSTextField alloc] initWithFrame: NSMakeRect(20, 63, 100, 17) ]; + [ pcoptionslabel setDrawsBackground: NO ]; + [ pcoptionslabel setBordered: NO ]; + [ pcoptionslabel setAlignment: NSRightTextAlignment ]; + [ pcoptionslabel setStringValue: @"Options" ]; + [ pcoptionslabel setEditable:NO ]; + [ pcoptionslabel setSelectable:NO ]; + [ [ configWindow contentView ] addSubview: pcoptionslabel ]; + [ pcoptionslabel release ]; + + pcram = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(128, 220, 50, 22) ]; + [ pcram setBezelStyle: 1 ]; + [ pcram setBezeled: YES ]; + [ pcram setEditable: YES ]; + [ pcram setSelectable:YES ]; + [ [ pcram cell ] setScrollable: YES ]; + [ [ pcram cell ] setWraps: NO ]; + [ pcram setStringValue: @"" ]; + [ [ configWindow contentView ] addSubview: pcram ]; + [ pcram release ]; + + pcfda = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(211, 175, 136, 22) ]; + [ pcfda setBezelStyle: 1 ]; + [ pcfda setBezeled: YES ]; + [ pcfda setEditable: YES ]; + [ pcfda setSelectable:YES ]; + [ [ pcfda cell ] setScrollable: YES ]; + [ [ pcfda cell ] setWraps: NO ]; + [ pcfda setStringValue: @"" ]; + [ [ configWindow contentView ] addSubview: pcfda ]; + [ pcfda release ]; + + pchda = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(211, 141, 136, 22) ]; + [ pchda setBezelStyle: 1 ]; + [ pchda setBezeled: YES ]; + [ pchda setEditable: YES ]; + [ pchda setSelectable:YES ]; + [ [ pchda cell ] setScrollable: YES ]; + [ [ pchda cell ] setWraps: NO ]; + [ pchda setStringValue: @"" ]; + [ [ configWindow contentView ] addSubview: pchda ]; + [ pchda release ]; + + pccdrom = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(211, 107, 136, 22) ]; + [ pccdrom setBezelStyle: 1 ]; + [ pccdrom setBezeled: YES ]; + [ pccdrom setEditable: YES ]; + [ pccdrom setSelectable:YES ]; + [ [ pccdrom cell ] setScrollable: YES ]; + [ [ pccdrom cell ] setWraps: NO ]; + [ pccdrom setStringValue: @"" ]; + [ [ configWindow contentView ] addSubview: pccdrom ]; + [ pccdrom release ]; + + pcoptions = [ [ NSTextField alloc ] initWithFrame: NSMakeRect(128, 62, 250, 22) ]; + [ pcoptions setBezelStyle: 1 ]; + [ pcoptions setBezeled: YES ]; + [ pcoptions setEditable: YES ]; + [ pcoptions setSelectable:YES ]; + [ pcoptions setStringValue: @"" ]; + [ [ pcoptions cell ] setScrollable: YES ]; + [ [ pcoptions cell ] setWraps: NO ]; + [ [ configWindow contentView ] addSubview: pcoptions ]; + [ pcoptions release ]; + + NSButton *fdabutton = [ [ [ NSButton alloc ] initWithFrame: NSMakeRect(355,167,30,30) ] autorelease ]; + [ fdabutton setButtonType: NSMomentaryPushButton ]; + [ fdabutton setBezelStyle: NSCircularBezelStyle ]; + [ fdabutton setTitle: @"..." ]; + [ fdabutton setTarget: self ]; + [ fdabutton setTag:1 ]; + [ fdabutton setAction: @selector( chooseFile: ) ]; + [ [ configWindow contentView ] addSubview: fdabutton ]; + + NSButton *hdabutton = [ [ [ NSButton alloc ] initWithFrame: NSMakeRect(355,132,30,30) ] autorelease ]; + [ hdabutton setButtonType: NSMomentaryPushButton ]; + [ hdabutton setBezelStyle: NSCircularBezelStyle ]; + [ hdabutton setTitle: @"..." ]; + [ hdabutton setTarget: self ]; + [ hdabutton setTag:2 ]; + [ hdabutton setAction: @selector( chooseFile: ) ]; + [ [ configWindow contentView ] addSubview: hdabutton ]; + + NSButton *cdrombutton = [ [ [ NSButton alloc ] initWithFrame: NSMakeRect(355,98,30,30) ] autorelease ]; + [ cdrombutton setButtonType: NSMomentaryPushButton ]; + [ cdrombutton setBezelStyle: NSCircularBezelStyle ]; + [ cdrombutton setTitle: @"..." ]; + [ cdrombutton setTarget: self ]; + [ cdrombutton setTag:3 ]; + [ cdrombutton setAction: @selector( chooseFile: ) ]; + [ [ configWindow contentView ] addSubview: cdrombutton ]; + + NSButton *cancelbutton = [ [ [ NSButton alloc ] initWithFrame: NSMakeRect(188,22,100,30) ] autorelease ]; + [ cancelbutton setButtonType: NSMomentaryPushButton ]; + [ cancelbutton setBezelStyle: NSRoundedBezelStyle ]; + [ cancelbutton setKeyEquivalent: @"\E" ]; + [ cancelbutton setTitle: @"Quit qemu" ]; + [ cancelbutton setTarget: self ]; + [ cancelbutton setAction: @selector( closeConfigWindowQuit ) ]; + [ [ configWindow contentView ] addSubview: cancelbutton ]; + + NSButton *okbutton = [ [ [ NSButton alloc ] initWithFrame: NSMakeRect(288,22,100,30) ] autorelease ]; + [ okbutton setButtonType: NSMomentaryPushButton ]; + [ okbutton setBezelStyle: NSRoundedBezelStyle ]; + [ okbutton setKeyEquivalent: @"\r" ]; + [ okbutton setTitle: @"Start PC" ]; + [ okbutton setTarget: self ]; + [ okbutton setAction: @selector( closeConfigWindowStart ) ]; + [ [ configWindow contentView ] addSubview: okbutton ]; + + /* default values */ + [ pcram setStringValue: @"64" ]; + [ pcfda setStringValue: @"" ]; + [ pchda setStringValue: @"" ]; + [ pccdrom setStringValue: @"" ]; + [ pcoptions setStringValue: @"" ]; + + /* show configWindow */ + [ configWindow center ]; + [ configWindow makeKeyAndOrderFront:nil ]; +} + +/* Methods of configWindow */ +- (void) chooseFile:(id)sender +{ + NSString *description; + NSString *contextInfo; + + if ( [ sender tag ] == 1 ) { + contextInfo = @"fda"; + description = @"Floppy A"; + } else if ( [ sender tag ] == 2 ) { + contextInfo = @"hda"; + description = @"Harddisk"; + } else if ( [ sender tag ] == 3 ) { + contextInfo = @"cdrom"; + description = @"CD-Rom"; + } else { + contextInfo = @""; + description = @""; + } + + NSOpenPanel *op = [[NSOpenPanel alloc] init]; + [op setPrompt: [ NSString stringWithFormat:@"choose Image for %@", description ] ]; + [op setMessage: [ NSString stringWithFormat:@"Select the diskimage you want to use as %@.\n\nHit the \"Cancel\" button to quit", description ] ]; + [op beginSheetForDirectory:nil + file:nil + types:fileTypes + modalForWindow:configWindow + modalDelegate:self + didEndSelector:@selector(chooseFileSheetDidEnd:returnCode:contextInfo:) + contextInfo:contextInfo ]; +} + +- (void)chooseFileSheetDidEnd: (NSOpenPanel *)sheet + returnCode:(int)returnCode + contextInfo:(NSString *)contextInfo +{ + if(returnCode == NSOKButton) { + if ( [ contextInfo isEqual: @"fda" ] ) + [ pchda setStringValue:[ sheet filename ] ]; + if ( [ contextInfo isEqual: @"hda" ] ) + [ pchda setStringValue:[ sheet filename ] ]; + if ( [ contextInfo isEqual: @"cdrom" ] ) + [ pchda setStringValue:[ sheet filename ] ]; + } +} + +- (void)closeConfigWindowQuit +{ + [ configWindow close ]; + [ configWindow release ]; + exit(0); //return 0 => pc shutdown +} + +- (void)closeConfigWindowStart +{ + /* get Values from configWindow */ + NSArray *options; + int i = 3; + int j; + char **argv = (char**)malloc( sizeof(char*)*3 ); - pixels[ (i * rowPixels) + j ] |= 0xFF000000; - } - } + asprintf(&argv[0], "qemu"); + asprintf(&argv[1], "-m"); + asprintf(&argv[2], "%s",[ [ pcram stringValue ] cString ]); + + if (![ [ pcfda stringValue ] isEqual:@"" ]) { + asprintf(&argv[i], "-fda"); + i++; + asprintf(&argv[i], [ [ pcfda stringValue ] cString ]); + i++; + } + + if (![ [ pchda stringValue ] isEqual:@"" ]) { + asprintf(&argv[i], "-hda"); + i++; + asprintf(&argv[i], [ [ pchda stringValue ] cString ]); + i++; + } + + if (![ [ pccdrom stringValue ] isEqual:@"" ]) { + asprintf(&argv[i], "-cdrom"); + i++; + asprintf(&argv[i], [ [ pccdrom stringValue ] cString ]); + i++; + } + + options = [ [ pcoptions stringValue ] componentsSeparatedByString:@" " ]; + for (j = 0; j < [ options count ]; j++) { + asprintf(&argv[i], [ [ options objectAtIndex:j ] cString ]); + i++; + } + + /* cleanup */ + [ configWindow close ]; + [ configWindow release ]; + + /* start PC */ + [ pcModel startPC:(i-1) withArgs:argv ]; } +@end + +/* + ------------------------------------------------------ + QemuWindow + ------------------------------------------------------ +*/ @implementation QemuWindow -- (void)miniaturize:(id)sender +- (void) miniaturize:(id)sender { /* make the alpha channel opaque so anim won't have holes in it */ - QZ_SetPortAlphaOpaque (); - [ super miniaturize:sender ]; + /* there is no mini image of the openGL View */ } -- (void)display + +- (void) display { /* This method fires just before the window deminaturizes from the Dock. @@ -378,237 +881,1024 @@ is required, and the deminiaturize works perfectly. */ - /* make sure pixels are fully opaque */ - QZ_SetPortAlphaOpaque (); - /* save current visible SDL surface */ - [ self cacheImageInRect:[ qd_view frame ] ]; - + [ self cacheImageInRect:[ ogl_view frame ] ]; + /* let the window manager redraw controls, border, etc */ [ super display ]; - + /* restore visible SDL surface */ [ self restoreCachedImage ]; } +- (BOOL) windowShouldClose:(id)sender +{ + [ pcWindowView shutdownPC ]; + return NO; +} @end /* ------------------------------------------------------ - QemuCocoaGUIController - NSApp's delegate - indeed main object + QemuCocoaQuickDrawView ------------------------------------------------------ */ +@implementation QemuCocoaOpenGLView +- (void)mouseDown:(NSEvent *)theEvent +{ + /* Mouse-grab is activatet by clicks in View only, + so we can handle clicks on other GUI Items */ + grab = 1; + [ pcWindow setTitle: [ NSString stringWithFormat:@"%@ - %@ (Press ctrl + alt to release Mouse)",[ pcModel pcWindowName ], [ pcModel pcName ] ] ]; + [ NSCursor hide ]; + CGAssociateMouseAndMouseCursorPosition ( FALSE ); + return; +} +@end -@interface QemuCocoaGUIController : NSObject + + +/* + ------------------------------------------------------ + QemuCocoaPcModel + ------------------------------------------------------ +*/ +@implementation QemuCocoaPcModel +- (NSString *) pcName { + return pcName; } -- (void)applicationDidFinishLaunching: (NSNotification *) note; -- (void)applicationWillTerminate:(NSNotification *)aNotification; -- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo; +- (NSString *) pcWindowName +{ + return pcWindowName; +} -- (void)startEmulationWithArgc:(int)argc argv:(char**)argv; -@end +- (NSImage *) thumbnailFast +{ + /* thumnailFast is broken atm => second half of image is garbled */ + uint8_t buffer[22500]; + uint8_t *d, *d1, *b; + int x,y; + float dx = current_ds.width / 100.0; + float dy = current_ds.height / 75.0; + b = buffer; + + for (y = 0; y < 75 ; y++) { + d1 = ¤t_ds.data[ 1 + (int)( y * dy ) * current_ds.linesize ]; // offset 1 to save 100 Additions per Line + d = d1; + for (x = 0; x < 100; x ++) { + d = d1 + (int)( x * dx ) * 4; + *b = *d; //red + b++; + d++; + *b = *d; //green + b++; + d++; + *b = *d; //blue + b++; + } + } + + b = buffer; + NSBitmapImageRep *rawBitmapRep; + rawBitmapRep = [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes:&b + pixelsWide:100 + pixelsHigh:75 + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:NO + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bytesPerRow:300 + bitsPerPixel:24 ]; + NSImage *image = [ [ [ NSImage alloc ] init ] autorelease ]; + [ image addRepresentation:rawBitmapRep ]; + [ rawBitmapRep release ]; + + return image; +} -@implementation QemuCocoaGUIController -/* Called when the internal event loop has just started running */ -- (void)applicationDidFinishLaunching: (NSNotification *) note +- (NSImage *) thumbnailQuality { + uint8_t buffer[current_ds.width * current_ds.height * 3]; + uint8_t *d, *b; + int p; + d = current_ds.data; + b = buffer; + for (p = 0; p < current_ds.width * current_ds.height ; p++) { + d++; //jump empty byte + *b = *d; //red + d++; + b++; + *b = *d; //green + d++; + b++; + *b = *d; //blue + d++; + b++; + } + b = buffer; + NSBitmapImageRep *rawBitmapRep = [ [ NSBitmapImageRep alloc ] initWithBitmapDataPlanes:&b + pixelsWide:current_ds.width + pixelsHigh:current_ds.height + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:NO + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bytesPerRow:current_ds.width * 3 + bitsPerPixel:24 ]; + NSImage *sourceImage = [ [ NSImage alloc ] init ]; + [ sourceImage addRepresentation:rawBitmapRep ]; + [ sourceImage setScalesWhenResized:YES ]; + [ rawBitmapRep release ]; + NSImage *smallImage = [ [ [ NSImage alloc ] initWithSize:NSMakeSize(100, 75) ] autorelease ]; + [ smallImage lockFocus ]; + [ [ NSGraphicsContext currentContext ] setImageInterpolation:NSImageInterpolationHigh ]; + [ sourceImage setSize:NSMakeSize(100, 75) ]; + [ sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy ]; + [ smallImage unlockFocus ]; + + return smallImage; +} - /* Display an open dialog box if no argument were passed or - if qemu was launched from the finder ( the Finder passes "-psn" ) */ +- (void) liveThumbnail +{ + /* create liveThumbnail */ + NSBitmapImageRep *bitmapImageRep = [ NSBitmapImageRep imageRepWithData: [ [ self thumbnailQuality ] TIFFRepresentation ] ]; + NSData *data = [ bitmapImageRep representationUsingType: NSPNGFileType properties: nil ]; + [ data writeToFile: [ NSString stringWithFormat: @"%@/%@.png", pcPath, pcName ] atomically: YES ]; +} - if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0) - { - NSOpenPanel *op = [[NSOpenPanel alloc] init]; - - cocoa_resize(¤t_ds, 640, 400); - - [op setPrompt:@"Boot image"]; - - [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; - - [op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil] - modalForWindow:window modalDelegate:self - didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; - } - else - { - /* or Launch Qemu, with the global args */ - [self startEmulationWithArgc:gArgc argv:gArgv]; +/* copied and adapted from monitor.c */ +- (int) ejectDevice: (BlockDriverState *) bs + withForce: (int) force +{ + if (bdrv_is_inserted(bs)) { + if (!force) { + if (!bdrv_is_removable(bs)) { + printf("device is not removable\n"); + return -1; + } + if (bdrv_is_locked(bs)) { + printf("device is locked\n"); + return -1; + } + } + bdrv_close(bs); } + return 0; } -- (void)applicationWillTerminate:(NSNotification *)aNotification +- (void) ejectImage:(const char *) filename + withForce: (int) force { - printf("Application will terminate\n"); - qemu_system_shutdown_request(); - /* In order to avoid a crash */ - exit(0); + BlockDriverState *bs; + + bs = bdrv_find(filename); + if (!bs) { + printf("device not found\n"); + return; + } + [ self ejectDevice:bs withForce:force ]; } -- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +- (void) changeDeviceImage: (const char *) device + filename: (const char *) filename + withForce: (int) force { - if(returnCode == NSCancelButton) - { - exit(0); + BlockDriverState *bs; + int i; + char password[256]; + + bs = bdrv_find(device); + if (!bs) { + printf("device not found\n"); + return; } - - if(returnCode == NSOKButton) - { - char *bin = "qemu"; - char *img = (char*)[ [ sheet filename ] cString]; - - char **argv = (char**)malloc( sizeof(char*)*3 ); - - asprintf(&argv[0], "%s", bin); - asprintf(&argv[1], "-hda"); - asprintf(&argv[2], "%s", img); - - printf("Using argc %d argv %s -hda %s\n", 3, bin, img); - - [self startEmulationWithArgc:3 argv:(char**)argv]; + if ([ self ejectDevice:bs withForce:force ] < 0) + return; + bdrv_open(bs, filename, 0); + if (bdrv_is_encrypted(bs)) { + printf("%s is encrypted.\n", device); + for(i = 0; i < 3; i++) { + monitor_readline("Password: ", 1, password, sizeof(password)); + if (bdrv_set_key(bs, password) == 0) + break; + printf("invalid password\n"); + } } } -- (void)startEmulationWithArgc:(int)argc argv:(char**)argv +- (void) saveVM +{ + /* show progressWindow */ + [ pcWindowView showProgressWindow:@"Saving PC" ]; + + /* generate Preview */ + NSBitmapImageRep *bitmapImageRep = [ NSBitmapImageRep imageRepWithData: [ [ self thumbnailQuality ] TIFFRepresentation ] ]; + NSData *data = [ bitmapImageRep representationUsingType: NSPNGFileType properties: nil ]; + [ data writeToFile: [ NSString stringWithFormat: @"%@/%@.png", pcPath, pcName ] atomically: YES ]; + vm_stop(0); //stop PC + qemu_savevm( [ [ NSString stringWithFormat: @"%@/%@.vm", pcPath, pcName ] cString ]); + + /* hide progressWindow */ + [ pcWindowView hideProgressWindow ]; + + /* set status */ + pcStatus = @"saved"; +} + +- (void) startPC:(int)argc withArgs:(char**)argv +{ + /* filter cocoa arguments */ + pcWindowName = @"qemu"; + pcName = @""; + pcPath = [ @"~/Library/Application Support/cocoaqemu" stringByExpandingTildeInPath]; + pcLiveThumbnail = 0; + + int i; + for (i = 0; i < argc; i++) { + if ( strcmp(argv[i], "-cocoawindowname" ) == 0 ) { + pcWindowName = [ NSString stringWithFormat:@"%s", argv[i+1] ]; + argv[i] = ""; + argv[i+1] = ""; + } + if ( strcmp(argv[i], "-cocoaname" ) == 0 ) { + pcName = [ NSString stringWithFormat:@"%s", argv[i+1] ]; + argv[i] = ""; + argv[i+1] = ""; + } + if ( strcmp(argv[i], "-cocoapath" ) == 0 ) { + pcPath = [ NSString stringWithFormat:@"%s", argv[i+1] ]; + argv[i] = ""; + argv[i+1] = ""; + } + if ( strcmp(argv[i], "-cocoalivethumbnail" ) == 0 ) { + pcLiveThumbnail = 1; + argv[i] = ""; + timer = [ NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector( liveThumbnail ) userInfo:nil repeats:YES ]; + } + } + + /* show pcWindow */ + [ pcWindowView pcWindowSetup: 640 height:400 ]; //create inital Window for qemu + + /* show progressWindow */ + [ pcWindowView progressWindowSetup ]; //create Window for Progressbar + [ pcWindowView showProgressWindow:@"Loading PC" ]; + + /* set status */ + pcStatus = @"running"; + + /* hide progressWindow */ + [ pcWindowView hideProgressWindow ]; + + /* Launch Qemu */ + qemu_main (argc, argv); +} + +- (void) resetPC +{ + qemu_system_reset_request(); +} + +- (void) shutdownPC { - int status; - /* Launch Qemu */ - printf("starting qemu...\n"); - status = qemu_main (argc, argv); - exit(status); + qemu_system_shutdown_request(); + + if ( [ pcStatus isEqual: @"running" ] ) + pcStatus = @"shutdown"; } @end + + /* ------------------------------------------------------ - Application Creation + NSApp ------------------------------------------------------ */ +@implementation QemuCocoaGUIController +- (void) applicationMenuSetup +{ + + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *appName; + + appName = [ pcModel pcWindowName ]; //@"qemu"; + appleMenu = [ [ NSMenu alloc ] initWithTitle:@"" ]; + + /* Add menu items */ + [ appleMenu addItemWithTitle:[ @"About " stringByAppendingString:appName ] action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@"" ]; + [ appleMenu addItem:[NSMenuItem separatorItem ] ]; + [ appleMenu addItemWithTitle:[ @"Hide " stringByAppendingString:appName ] action:@selector(hide:) keyEquivalent:@"h" ]; + + menuItem = (NSMenuItem *)[ appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h" ]; + [ menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask) ]; + + [ appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@"" ]; + [ appleMenu addItem:[NSMenuItem separatorItem ] ]; + [ appleMenu addItemWithTitle:[@"Quit " stringByAppendingString:appName ] action:@selector(terminate:) keyEquivalent:@"q" ]; + + /* Put menu into the menubar */ + menuItem = [ [ NSMenuItem alloc ] initWithTitle:@"" action:nil keyEquivalent:@"" ]; + [ menuItem setSubmenu:appleMenu ]; + [ [ NSApp mainMenu] addItem:menuItem ]; + + /* Tell the application object that this is now the application menu */ + [ NSApp setAppleMenu:appleMenu ]; + + /* Finally give up our references to the objects */ + [ appleMenu release ]; + [ menuItem release ]; + +} -/* Dock Connection */ -typedef struct CPSProcessSerNum +- (void) windowMenuSetup { - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [ [ NSMenu alloc ] initWithTitle:@"Window" ]; + + /* "Minimize" item */ + menuItem = [ [ NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m" ]; + [ windowMenu addItem:menuItem ]; + [ menuItem release ]; + + /* Put menu into the menubar */ + windowMenuItem = [ [ NSMenuItem alloc ] initWithTitle:@"Window" action:nil keyEquivalent:@"" ]; + [ windowMenuItem setSubmenu:windowMenu ]; + [ [ NSApp mainMenu] addItem:windowMenuItem ]; + + /* Tell the application object that this is now the window menu */ + [ NSApp setWindowsMenu:windowMenu ]; + + /* Finally give up our references to the objects */ + [ windowMenu release ]; + [ windowMenuItem release ]; +} -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); +/* Delegates of NSApp */ +- (void)applicationWillFinishLaunching: (NSNotification *) note +{ + [ NSApp setMainMenu:[ [ NSMenu alloc ] init ] ]; + [ self applicationMenuSetup ]; + [ self windowMenuSetup ]; +} -/* Menu Creation */ -static void setApplicationMenu(void) +- (void)applicationDidFinishLaunching: (NSNotification *) note { - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = @"Qemu"; - appleMenu = [[NSMenu alloc] initWithTitle:@""]; + /* Display config Window if no argument were passed or + if qemu was launched from the finder ( the Finder passes "-psn" ) */ + if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0) + { + /* show configWindow */ + [ pcWindowView configWindowSetup ]; + } + else + { + /* start PC with cmd-line Args */ + [ pcModel startPC:gArgc withArgs:gArgv ]; + } +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +{ + [ pcWindowView shutdownPC ]; + return NO; +} +@end + + +/* + ------------------------------------------------------ + Qemu Video Driver - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + ------------------------------------------------------ +*/ +/* + ------------------------------------------------------ + cocoa_update + ------------------------------------------------------ +*/ +static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) +{ + /* Make this context current */ + [[ogl_view openGLContext] makeCurrentContext]; + + /* Bind, update and draw new image */ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, screen_tex); + + /* glTexSubImage2D is faster when not using a texture range */ + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, (GLint)ds->width, (GLint)ds->height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ds->data); + + /* Use the compiled display list */ + glCallList(display_list_tex); + + /* Swap buffer to screen */ + [[ogl_view openGLContext] flushBuffer]; +} - [appleMenu addItem:[NSMenuItem separatorItem]]; +/* + ------------------------------------------------------ + cocoa_resize + ------------------------------------------------------ +*/ +static void cocoa_resize(DisplayState *ds, int w, int h) +{ + NSRect contentRect; - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + // printf("resizing to %d %d\n", w, h); - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + contentRect = NSMakeRect (0, 0, w, h); - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + [pcWindow setContentSize:contentRect.size]; + [pcWindow update]; + + [[ogl_view openGLContext] makeCurrentContext]; + [[ogl_view openGLContext] update]; - [appleMenu addItem:[NSMenuItem separatorItem]]; + glViewport(0, 0, (int) contentRect.size.width, (int) contentRect.size.height); - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + /* This is used as a init'd flag as well... */ + if(screen_tex != 0) { + glDeleteTextures(1, &screen_tex); + glDeleteLists(display_list_tex, 1); + } + + screen_tex = 1; + + if(ds->data != NULL) free(ds->data); + ds->data = (GLubyte *) malloc(w * h * (SCREEN_BPP >> 3)); + assert(ds->data != NULL); + ds->linesize = w * (SCREEN_BPP >> 3); + ds->depth = SCREEN_BPP; + ds->width = w; + ds->height = h; + + /* Setup some basic OpenGL stuff as from Apple */ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glEnable(GL_TEXTURE_RECTANGLE_EXT); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, screen_tex); + + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, w * h * (SCREEN_BPP >> 3), ds->data); + + /* Use CACHED for VRAM+reused tex Use SHARED for AGP+used once tex + Note the texture is always changing so use SHARED */ + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ds->data); + + glFlush(); + + /* Setup a display list to save all the operations below */ + display_list_tex = glGenLists(1); + glNewList(display_list_tex, GL_COMPILE); + + glBegin(GL_QUADS); + + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, 1.0f); + + glTexCoord2f(0.0f, (GLfloat)h); + glVertex2f(-1.0f, -1.0f); - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; + glTexCoord2f((GLfloat)w, (GLfloat)h); + glVertex2f(1.0f, -1.0f); - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; + glTexCoord2f((GLfloat)w, 0.0f); + glVertex2f(1.0f, 1.0f); + + glEnd(); + + glEndList(); + + /* Swap buffer to screen */ + [[ogl_view openGLContext] flushBuffer]; + + memcpy(¤t_ds, ds, sizeof(DisplayState)); } -/* Create a window menu */ -static void setupWindowMenu(void) +/* + ------------------------------------------------------ + keymap conversion + ------------------------------------------------------ +*/ + +static int keymap[] = { - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; +// SdlI macI macH SdlH 104xtH 104xtC sdl + 30, // 0 0x00 0x1e A QZ_a + 31, // 1 0x01 0x1f S QZ_s + 32, // 2 0x02 0x20 D QZ_d + 33, // 3 0x03 0x21 F QZ_f + 35, // 4 0x04 0x23 H QZ_h + 34, // 5 0x05 0x22 G QZ_g + 44, // 6 0x06 0x2c Z QZ_z + 45, // 7 0x07 0x2d X QZ_x + 46, // 8 0x08 0x2e C QZ_c + 47, // 9 0x09 0x2f V QZ_v + 0, // 10 0x0A Undefined + 48, // 11 0x0B 0x30 B QZ_b + 16, // 12 0x0C 0x10 Q QZ_q + 17, // 13 0x0D 0x11 W QZ_w + 18, // 14 0x0E 0x12 E QZ_e + 19, // 15 0x0F 0x13 R QZ_r + 21, // 16 0x10 0x15 Y QZ_y + 20, // 17 0x11 0x14 T QZ_t + 2, // 18 0x12 0x2 1 QZ_1 + 3, // 19 0x13 0x3 2 QZ_2 + 4, // 20 0x14 0x4 3 QZ_3 + 5, // 21 0x15 0x5 4 QZ_4 + 7, // 22 0x16 0x7 6 QZ_6 + 6, // 23 0x17 0x6 5 QZ_5 + 13, // 24 0x18 0xd = QZ_EQUALS + 10, // 25 0x19 0xa 9 QZ_9 + 8, // 26 0x1A 0x8 7 QZ_7 + 12, // 27 0x1B 0xc - QZ_MINUS + 9, // 28 0x1C 0x9 8 QZ_8 + 11, // 29 0x1D 0xb 0 QZ_0 + 27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET + 24, // 31 0x1F 0x18 O QZ_o + 22, // 32 0x20 0x16 U QZ_u + 26, // 33 0x21 0x1a [ QZ_LEFTBRACKET + 23, // 34 0x22 0x17 I QZ_i + 25, // 35 0x23 0x19 P QZ_p + 28, // 36 0x24 0x1c ENTER QZ_RETURN + 38, // 37 0x25 0x26 L QZ_l + 36, // 38 0x26 0x24 J QZ_j + 40, // 39 0x27 0x28 ' QZ_QUOTE + 37, // 40 0x28 0x25 K QZ_k + 39, // 41 0x29 0x27 ; QZ_SEMICOLON + 43, // 42 0x2A 0x2b \ QZ_BACKSLASH + 51, // 43 0x2B 0x33 , QZ_COMMA + 53, // 44 0x2C 0x35 / QZ_SLASH + 49, // 45 0x2D 0x31 N QZ_n + 50, // 46 0x2E 0x32 M QZ_m + 52, // 47 0x2F 0x34 . QZ_PERIOD + 15, // 48 0x30 0xf TAB QZ_TAB + 57, // 49 0x31 0x39 SPACE QZ_SPACE + 41, // 50 0x32 0x29 ` QZ_BACKQUOTE + 14, // 51 0x33 0xe BKSP QZ_BACKSPACE + 0, // 52 0x34 Undefined + 1, // 53 0x35 0x1 ESC QZ_ESCAPE + 0, // 54 0x36 QZ_RMETA + 0, // 55 0x37 QZ_LMETA + 42, // 56 0x38 0x2a L SHFT QZ_LSHIFT + 58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK + 56, // 58 0x3A 0x38 L ALT QZ_LALT + 29, // 59 0x3B 0x1d L CTRL QZ_LCTRL + 54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT + 184, // 61 0x3D 0xb8 E0,38 R ALT QZ_RALT + 157, // 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL + 0, // 63 0x3F Undefined + 0, // 64 0x40 Undefined + 0, // 65 0x41 Undefined + 0, // 66 0x42 Undefined + 55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY + 0, // 68 0x44 Undefined + 78, // 69 0x45 0x4e KP + QZ_KP_PLUS + 0, // 70 0x46 Undefined + 69, // 71 0x47 0x45 NUM QZ_NUMLOCK + 0, // 72 0x48 Undefined + 0, // 73 0x49 Undefined + 0, // 74 0x4A Undefined + 181, // 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE + 152, // 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER + 0, // 77 0x4D undefined + 74, // 78 0x4E 0x4a KP - QZ_KP_MINUS + 0, // 79 0x4F Undefined + 0, // 80 0x50 Undefined + 0, // 81 0x51 QZ_KP_EQUALS + 82, // 82 0x52 0x52 KP 0 QZ_KP0 + 79, // 83 0x53 0x4f KP 1 QZ_KP1 + 80, // 84 0x54 0x50 KP 2 QZ_KP2 + 81, // 85 0x55 0x51 KP 3 QZ_KP3 + 75, // 86 0x56 0x4b KP 4 QZ_KP4 + 76, // 87 0x57 0x4c KP 5 QZ_KP5 + 77, // 88 0x58 0x4d KP 6 QZ_KP6 + 71, // 89 0x59 0x47 KP 7 QZ_KP7 + 0, // 90 0x5A Undefined + 72, // 91 0x5B 0x48 KP 8 QZ_KP8 + 73, // 92 0x5C 0x49 KP 9 QZ_KP9 + 0, // 93 0x5D Undefined + 0, // 94 0x5E Undefined + 0, // 95 0x5F Undefined + 63, // 96 0x60 0x3f F5 QZ_F5 + 64, // 97 0x61 0x40 F6 QZ_F6 + 65, // 98 0x62 0x41 F7 QZ_F7 + 61, // 99 0x63 0x3d F3 QZ_F3 + 66, // 100 0x64 0x42 F8 QZ_F8 + 67, // 101 0x65 0x43 F9 QZ_F9 + 0, // 102 0x66 Undefined + 87, // 103 0x67 0x57 F11 QZ_F11 + 0, // 104 0x68 Undefined + 183, // 105 0x69 0xb7 QZ_PRINT + 0, // 106 0x6A Undefined + 70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK + 0, // 108 0x6C Undefined + 68, // 109 0x6D 0x44 F10 QZ_F10 + 0, // 110 0x6E Undefined + 88, // 111 0x6F 0x58 F12 QZ_F12 + 0, // 112 0x70 Undefined + 110, // 113 0x71 0x0 QZ_PAUSE + 210, // 114 0x72 0xd2 E0,52 INSERT QZ_INSERT + 199, // 115 0x73 0xc7 E0,47 HOME QZ_HOME + 201, // 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP + 211, // 117 0x75 0xd3 E0,53 DELETE QZ_DELETE + 62, // 118 0x76 0x3e F4 QZ_F4 + 207, // 119 0x77 0xcf E0,4f END QZ_END + 60, // 120 0x78 0x3c F2 QZ_F2 + 209, // 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN + 59, // 122 0x7A 0x3b F1 QZ_F1 + 203, // 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT + 205, // 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT + 208, // 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN + 200, // 126 0x7E 0xc8 E0,48 U ARROW QZ_UP +/* 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 */ + +/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */ +/* + 219 // 0xdb e0,5b L GUI + 220 // 0xdc e0,5c R GUI + 221 // 0xdd e0,5d APPS + // E0,2A,E0,37 PRNT SCRN + // E1,1D,45,E1,9D,C5 PAUSE + 83 // 0x53 0x53 KP . +// ACPI Scan Codes + 222 // 0xde E0, 5E Power + 223 // 0xdf E0, 5F Sleep + 227 // 0xe3 E0, 63 Wake +// Windows Multimedia Scan Codes + 153 // 0x99 E0, 19 Next Track + 144 // 0x90 E0, 10 Previous Track + 164 // 0xa4 E0, 24 Stop + 162 // 0xa2 E0, 22 Play/Pause + 160 // 0xa0 E0, 20 Mute + 176 // 0xb0 E0, 30 Volume Up + 174 // 0xae E0, 2E Volume Down + 237 // 0xed E0, 6D Media Select + 236 // 0xec E0, 6C E-Mail + 161 // 0xa1 E0, 21 Calculator + 235 // 0xeb E0, 6B My Computer + 229 // 0xe5 E0, 65 WWW Search + 178 // 0xb2 E0, 32 WWW Home + 234 // 0xea E0, 6A WWW Back + 233 // 0xe9 E0, 69 WWW Forward + 232 // 0xe8 E0, 68 WWW Stop + 231 // 0xe7 E0, 67 WWW Refresh + 230 // 0xe6 E0, 66 WWW Favorites +*/ +}; - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; +static int cocoa_keycode_to_qemu(int keycode) +{ + if((sizeof(keymap)/sizeof(int)) <= keycode) + { + printf("(cocoa) warning unknow keycode 0x%x\n", keycode); + return 0; + } + return keymap[keycode]; +} - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; - +/* + ------------------------------------------------------ + cocoa_refresh + ------------------------------------------------------ +*/ +static void cocoa_refresh(DisplayState *ds) +{ + //printf("cocoa_refresh \n"); + NSDate *distantPast; + NSEvent *event; + NSAutoreleasePool *pool; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + distantPast = [ NSDate distantPast ]; + + if (is_active_console(vga_console)) + vga_update_display(); + do { + event = [ NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:distantPast + inMode: NSDefaultRunLoopMode + dequeue:YES ]; + if (event != nil) { + + /* release Mouse grab when pressing ctrl+alt */ + if (([ event modifierFlags ] & NSControlKeyMask) && ([ event modifierFlags ] & NSAlternateKeyMask)) + { + grab = 0; + [ pcWindow setTitle: [ NSString stringWithFormat: @"%@ - %@",[ pcModel pcWindowName ], [ pcModel pcName ] ] ]; //[ pcWindow setTitle:@"Qemu" ]; + [ NSCursor unhide ]; + CGAssociateMouseAndMouseCursorPosition ( TRUE ); + } + + /* handle Events */ + switch ([event type]) + { + + case NSFlagsChanged: + if ([ pcWindow isKeyWindow ]) { + int keycode = cocoa_keycode_to_qemu([event keyCode]); + modifiers_state[keycode] = (modifiers_state[keycode] == 0) ? 1 : 0; + + if (modifiers_state[keycode]) { /* Keydown */ + if (keycode & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode & 0x7f); + } else { /* Keyup */ + if (keycode & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode | 0x80); + } + + /* emulate caps lock and num lock keyup */ + if ((keycode == 58) || (keycode == 69)) + { + modifiers_state[keycode] = 0; + if (keycode & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode | 0x80); + } + } else { + [NSApp sendEvent:event]; + } + break; + + case NSKeyDown: + if ([ pcWindow isKeyWindow ]) { + int keycode = cocoa_keycode_to_qemu([event keyCode]); + if (keycode & 0x80) //check bit for e0 in front + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front + } else { + [NSApp sendEvent:event]; + } + break; + + case NSKeyUp: + if ([ pcWindow isKeyWindow ]) { + int keycode = cocoa_keycode_to_qemu([event keyCode]); + if (keycode & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key + } else { + [NSApp sendEvent:event]; + } + break; + + case NSScrollWheel: + if (grab) { + int dz = [event deltaY]; + kbd_mouse_event(0, 0, -dz, 0); + } + break; + + case NSLeftMouseDown: + if (grab) { + int buttons = 0; + + /* leftclick+command simulates rightclick */ + if ([ event modifierFlags ] & NSCommandKeyMask) { + buttons |= MOUSE_EVENT_RBUTTON; + } else { + buttons |= MOUSE_EVENT_LBUTTON; + } + kbd_mouse_event(0, 0, 0, buttons); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSLeftMouseUp: + if (grab) { + kbd_mouse_event(0, 0, 0, 0); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSOtherMouseDown: + if (grab) { + int buttons = 0; + buttons |= MOUSE_EVENT_MBUTTON; + kbd_mouse_event(0, 0, 0, buttons); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSRightMouseDown: + if (grab) { + int buttons = 0; + buttons |= MOUSE_EVENT_RBUTTON; + kbd_mouse_event(0, 0, 0, buttons); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSOtherMouseUp: + if (grab) { + kbd_mouse_event(0, 0, 0, 0); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSRightMouseUp: + if (grab) { + kbd_mouse_event(0, 0, 0, 0); + } else { + [NSApp sendEvent:event]; + } + break; + + case NSMouseMoved: + if (grab) { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + int buttons = 0; + kbd_mouse_event(dx, dy, dz, buttons); + } + break; + + case NSOtherMouseDragged: + if (grab) { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + int buttons = 0; + buttons |= MOUSE_EVENT_MBUTTON; + kbd_mouse_event(dx, dy, dz, buttons); + } + break; + + case NSRightMouseDragged: + if (grab) { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + int buttons = 0; + buttons |= MOUSE_EVENT_RBUTTON; + kbd_mouse_event(dx, dy, dz, buttons); + } + break; + + case NSLeftMouseDragged: + if (grab) { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + int buttons = 0; + if ([ [ NSApp currentEvent ] modifierFlags ] & NSCommandKeyMask) { //leftclick+command simulates rightclick + buttons |= MOUSE_EVENT_RBUTTON; + } else { + buttons |= MOUSE_EVENT_LBUTTON; + } + kbd_mouse_event(dx, dy, dz, buttons); + } + break; + + default: [NSApp sendEvent:event]; + } + } + } while(event != nil); } -static void CustomApplicationMain (argc, argv) + +/* + ------------------------------------------------------ + cocoa_cleanup + ------------------------------------------------------ +*/ +static void cocoa_cleanup(void) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - QemuCocoaGUIController *gui_controller; - CPSProcessSerNum PSN; - - [NSApplication sharedApplication]; + +} + + +/* + ------------------------------------------------------ + cocoa_display_init + ------------------------------------------------------ +*/ +void cocoa_display_init(DisplayState *ds, int full_screen) +{ + //printf("resizing to %d %d\n", w, h); + + const int w = 640; + const int h = 400; + + if(pcWindow == nil) + { + [ pcWindowView pcWindowSetup:w height:h ]; + } + + ds->dpy_update = cocoa_update; + ds->dpy_resize = cocoa_resize; + ds->dpy_refresh = cocoa_refresh; + + cocoa_resize(ds, 640, 400); + + [ pcWindow display ]; + [ pcWindow makeMainWindow ]; + [ pcWindow makeKeyWindow ]; + + atexit(cocoa_cleanup); +} + + + +/* + ------------------------------------------------------ + Application Creation - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [NSApplication sharedApplication]; - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - gui_controller = [[QemuCocoaGUIController alloc] init]; - [NSApp setDelegate:gui_controller]; + ------------------------------------------------------ +*/ + +/* Dock Connection */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +static void CustomApplicationMain (argc, argv) +{ + NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ]; + CPSProcessSerNum PSN; - /* Start the main event loop */ - [NSApp run]; + [ NSApplication sharedApplication ]; - [gui_controller release]; - [pool release]; + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [ NSApplication sharedApplication ]; + + /* overrun defaults for bios_dir, so we can run qemu everywhere */ + bios_dir = [ [ NSString stringWithFormat:@"%@/share/qemu", [ [ [ NSBundle mainBundle ] resourcePath ] stringByDeletingLastPathComponent ] ] cString ]; + + /* set allowed filetypes */ + fileTypes = [ [ NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil ] retain ]; + + gui_controller = [ [ QemuCocoaGUIController alloc ] init ]; + [NSApp setDelegate:gui_controller]; + + pcWindowView = [ [ QemuCocoaPcWindowView alloc ] init ]; //start the PC View + pcModel = [ [ QemuCocoaPcModel alloc ] init ]; //create the PC model + + [ NSApp run ]; //Start the main event loop + + /* cleanup */ + [ pcModel release ]; + [ progressWindow release ]; + [ pcWindow close ]; + [ pcWindow release ]; + [ pcWindowView release ]; + [ gui_controller release ]; + [ pool release ]; } /* Real main of qemu-cocoa */ int main(int argc, char **argv) { - gArgc = argc; - gArgv = argv; - - CustomApplicationMain (argc, argv); - - return 0; + gArgc = argc; + gArgv = argv; + + CustomApplicationMain (argc, argv); + + if ( [ pcStatus isEqual: @"shutdown" ] ) { + return 0; // return 0 => pc shutdown + } else { + return 2; // return 2 => pc saved + } } --------------010708090501010501030501 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="Makefile.target_1.69_20050527.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="Makefile.target_1.69_20050527.diff" Index: Makefile.target =================================================================== RCS file: /cvsroot/qemu/qemu/Makefile.target,v retrieving revision 1.69 diff -u -r1.69 Makefile.target --- Makefile.target 28 Apr 2005 21:15:08 -0000 1.69 +++ Makefile.target 27 May 2005 10:51:17 -0000 @@ -469,3 +469,8 @@ ifneq ($(wildcard .depend),) include .depend endif + +ifdef CONFIG_COCOA +VL_OBJS+=cocoa.o +COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework OpenGL +endif --------------010708090501010501030501--