#include <crt_externs.h>
#include "qemu-common.h"
-#include "console.h"
-#include "sysemu.h"
+#include "ui/console.h"
+#include "sysemu/sysemu.h"
#ifndef MAC_OS_X_VERSION_10_4
#define MAC_OS_X_VERSION_10_4 1040
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
//#define DEBUG
#define COCOA_MOUSE_EVENT \
if (isTabletEnabled) { \
kbd_mouse_event((int)(p.x * 0x7FFF / (screen.width - 1)), (int)((screen.height - p.y) * 0x7FFF / (screen.height - 1)), 0, buttons); \
- } else if (isMouseGrabed) { \
+ } else if (isMouseGrabbed) { \
kbd_mouse_event((int)[event deltaX], (int)[event deltaY], 0, buttons); \
} else { \
[NSApp sendEvent:event]; \
14, // 51 0x33 0x0e BKSP QZ_BACKSPACE
0, // 52 0x34 Undefined
1, // 53 0x35 0x01 ESC QZ_ESCAPE
- 0, // 54 0x36 QZ_RMETA
- 0, // 55 0x37 QZ_LMETA
+ 220, // 54 0x36 0xdc E0,5C R GUI QZ_RMETA
+ 219, // 55 0x37 0xdb E0,5B L GUI 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
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 */
+/* Additional 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
static int cocoa_keycode_to_qemu(int keycode)
{
- if((sizeof(keymap)/sizeof(int)) <= keycode)
- {
- printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
+ if (ARRAY_SIZE(keymap) <= keycode) {
+ fprintf(stderr, "(cocoa) warning unknown keycode 0x%x\n", keycode);
return 0;
}
return keymap[keycode];
float cx,cy,cw,ch,cdx,cdy;
CGDataProviderRef dataProviderRef;
int modifiers_state[256];
- BOOL isMouseGrabed;
+ BOOL isMouseGrabbed;
BOOL isFullscreen;
BOOL isAbsoluteEnabled;
BOOL isTabletEnabled;
}
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds;
+- (void) switchSurface:(DisplaySurface *)surface;
- (void) grabMouse;
- (void) ungrabMouse;
- (void) toggleFullScreen:(id)sender;
- (void) handleEvent:(NSEvent *)event;
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
-- (BOOL) isMouseGrabed;
+- (BOOL) isMouseGrabbed;
- (BOOL) isAbsoluteEnabled;
- (float) cdx;
- (float) cdy;
CGContextSetShouldAntialias (viewContextRef, NO);
// draw screen bitmap directly to Core Graphics context
- if (dataProviderRef) {
+ if (!dataProviderRef) {
+ // Draw request before any guest device has set up a framebuffer:
+ // just draw an opaque black rectangle
+ CGContextSetRGBFillColor(viewContextRef, 0, 0, 0, 1.0);
+ CGContextFillRect(viewContextRef, NSRectToCGRect(rect));
+ } else {
CGImageRef imageRef = CGImageCreate(
screen.width, //width
screen.height, //height
}
}
-- (void) resizeContentToWidth:(int)w height:(int)h displayState:(DisplayState *)ds
+- (void) switchSurface:(DisplaySurface *)surface
{
- COCOA_DEBUG("QemuCocoaView: resizeContent\n");
+ COCOA_DEBUG("QemuCocoaView: switchSurface\n");
+
+ int w = surface_width(surface);
+ int h = surface_height(surface);
+ bool isResize = (w != screen.width || h != screen.height);
+
+ int oldh = screen.height;
+ if (isResize) {
+ // Resize before we trigger the redraw, or we'll redraw at the wrong size
+ COCOA_DEBUG("switchSurface: new size %d x %d\n", w, h);
+ screen.width = w;
+ screen.height = h;
+ [self setContentDimensions];
+ [self setFrame:NSMakeRect(cx, cy, cw, ch)];
+ }
// update screenBuffer
if (dataProviderRef)
CGDataProviderRelease(dataProviderRef);
//sync host window color space with guests
- screen.bitsPerPixel = ds_get_bits_per_pixel(ds);
- screen.bitsPerComponent = ds_get_bytes_per_pixel(ds) * 2;
+ screen.bitsPerPixel = surface_bits_per_pixel(surface);
+ screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2;
- dataProviderRef = CGDataProviderCreateWithData(NULL, ds_get_data(ds), w * 4 * h, NULL);
+ dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL);
// update windows
if (isFullscreen) {
[[fullScreenWindow contentView] setFrame:[[NSScreen mainScreen] frame]];
- [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:NO animate:NO];
+ [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:NO animate:NO];
} else {
if (qemu_name)
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
- [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w, h + [normalWindow frame].size.height - screen.height) display:YES animate:NO];
+ [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:YES animate:NO];
+ }
+
+ if (isResize) {
+ [normalWindow center];
}
- screen.width = w;
- screen.height = h;
- [normalWindow center];
- [self setContentDimensions];
- [self setFrame:NSMakeRect(cx, cy, cw, ch)];
}
- (void) toggleFullScreen:(id)sender
switch ([event type]) {
case NSFlagsChanged:
keycode = cocoa_keycode_to_qemu([event keyCode]);
+
+ if ((keycode == 219 || keycode == 220) && !isMouseGrabbed) {
+ /* Don't pass command key changes to guest unless mouse is grabbed */
+ keycode = 0;
+ }
+
if (keycode) {
if (keycode == 58 || keycode == 69) { // emulate caps lock and num lock keydown and keyup
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | 0x80);
- } else if (is_graphic_console()) {
+ } else if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (modifiers_state[keycode] == 0) { // keydown
}
break;
case NSKeyDown:
+ keycode = cocoa_keycode_to_qemu([event keyCode]);
- // forward command Key Combos
- if ([event modifierFlags] & NSCommandKeyMask) {
+ // forward command key combos to the host UI unless the mouse is grabbed
+ if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) {
[NSApp sendEvent:event];
return;
}
// default
- keycode = cocoa_keycode_to_qemu([event keyCode]);
// handle control + alt Key Combos (ctrl+alt is reserved for QEMU)
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
}
// handle keys for graphic console
- } else if (is_graphic_console()) {
+ } else if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80) //check bit for e0 in front
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
break;
case NSKeyUp:
keycode = cocoa_keycode_to_qemu([event keyCode]);
- if (is_graphic_console()) {
+
+ // don't pass the guest a spurious key-up if we treated this
+ // command-key combo as a host UI action
+ if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) {
+ return;
+ }
+
+ if (qemu_console_is_graphic(NULL)) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
case NSLeftMouseUp:
if (isTabletEnabled) {
COCOA_MOUSE_EVENT
- } else if (!isMouseGrabed) {
+ } else if (!isMouseGrabbed) {
if (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height) {
[self grabMouse];
} else {
COCOA_MOUSE_EVENT
break;
case NSScrollWheel:
- if (isTabletEnabled || isMouseGrabed) {
+ if (isTabletEnabled || isMouseGrabbed) {
kbd_mouse_event(0, 0, -[event deltaY], 0);
} else {
[NSApp sendEvent:event];
}
[NSCursor hide];
CGAssociateMouseAndMouseCursorPosition(FALSE);
- isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
+ isMouseGrabbed = TRUE; // while isMouseGrabbed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
}
- (void) ungrabMouse
}
[NSCursor unhide];
CGAssociateMouseAndMouseCursorPosition(TRUE);
- isMouseGrabed = FALSE;
+ isMouseGrabbed = FALSE;
}
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {isAbsoluteEnabled = tIsAbsoluteEnabled;}
-- (BOOL) isMouseGrabed {return isMouseGrabed;}
+- (BOOL) isMouseGrabbed {return isMouseGrabbed;}
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
- (float) cdx {return cdx;}
- (float) cdy {return cdy;}
[normalWindow setContentView:cocoaView];
[normalWindow useOptimizedDrawing:YES];
[normalWindow makeKeyAndOrderFront:self];
- [normalWindow center];
+ [normalWindow center];
}
return self;
{
COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n");
- // Display an open dialog box if no argument were passed or
+ // Display an open dialog box if no arguments were passed or
// if qemu was launched from the finder ( the Finder passes "-psn" )
if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) {
NSOpenPanel *op = [[NSOpenPanel alloc] init];
[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]
+ NSArray *filetypes = [NSArray arrayWithObjects:@"img", @"iso", @"dmg",
+ @"qcow", @"qcow2", @"cow", @"cloop", @"vmdk", nil];
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
+ [op setAllowedFileTypes:filetypes];
+ [op beginSheetModalForWindow:normalWindow
+ completionHandler:^(NSInteger returnCode)
+ { [self openPanelDidEnd:op
+ returnCode:returnCode contextInfo:NULL ]; } ];
+#else
+ // Compatibility code for pre-10.6, using deprecated method
+ [op beginSheetForDirectory:nil file:nil types:filetypes
modalForWindow:normalWindow modalDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
+#endif
} else {
- // or Launch Qemu, with the global args
+ // or launch QEMU, with the global args
[self startEmulationWithArgc:gArgc argv:(char **)gArgv];
}
}
if(returnCode == NSCancelButton) {
exit(0);
} else if(returnCode == NSOKButton) {
- const char *bin = "qemu";
- char *img = (char*)[ [ sheet filename ] cStringUsingEncoding:NSASCIIStringEncoding];
+ char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding];
- char **argv = (char**)malloc( sizeof(char*)*3 );
+ char **argv = g_new(char *, 4);
[sheet close];
- asprintf(&argv[0], "%s", bin);
- asprintf(&argv[1], "-hda");
- asprintf(&argv[2], "%s", img);
+ argv[0] = g_strdup(gArgv[0]);
+ argv[1] = g_strdup("-hda");
+ argv[2] = g_strdup(img);
+ argv[3] = NULL;
- printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
+ // printf("Using argc %d argv %s -hda %s\n", 3, gArgv[0], img);
[self startEmulationWithArgc:3 argv:(char**)argv];
}
-// Dock Connection
-typedef struct CPSProcessSerNum
-{
- UInt32 lo;
- UInt32 hi;
-} CPSProcessSerNum;
-
-OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
-OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
-OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
-
int main (int argc, const char * argv[]) {
gArgc = argc;
gArgv = (char **)argv;
- CPSProcessSerNum PSN;
int i;
/* In case we don't need to display a window, let's not do that */
!strcmp(opt, "-vnc") ||
!strcmp(opt, "-nographic") ||
!strcmp(opt, "-version") ||
- !strcmp(opt, "-curses")) {
+ !strcmp(opt, "-curses") ||
+ !strcmp(opt, "-qtest")) {
return qemu_main(gArgc, gArgv, *_NSGetEnviron());
}
}
}
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [NSApplication sharedApplication];
- if (!CPSGetCurrentProcess(&PSN))
- if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
- if (!CPSSetFrontProcess(&PSN))
- [NSApplication sharedApplication];
+ // Pull this console process up to being a fully-fledged graphical
+ // app with a menubar and Dock icon
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+
+ [NSApplication sharedApplication];
// Add menus
NSMenu *menu;
#pragma mark qemu
-static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
+static void cocoa_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
NSRect rect;
h * [cocoaView cdy]);
}
[cocoaView setNeedsDisplayInRect:rect];
+
+ [pool release];
}
-static void cocoa_resize(DisplayState *ds)
+static void cocoa_switch(DisplayChangeListener *dcl,
+ DisplaySurface *surface)
{
- COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- [cocoaView resizeContentToWidth:(int)(ds_get_width(ds)) height:(int)(ds_get_height(ds)) displayState:ds];
+ COCOA_DEBUG("qemu_cocoa: cocoa_switch\n");
+ [cocoaView switchSurface:surface];
+ [pool release];
}
-static void cocoa_refresh(DisplayState *ds)
+static void cocoa_refresh(DisplayChangeListener *dcl)
{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
if (kbd_mouse_is_absolute()) {
if (![cocoaView isAbsoluteEnabled]) {
- if ([cocoaView isMouseGrabed]) {
+ if ([cocoaView isMouseGrabbed]) {
[cocoaView ungrabMouse];
}
}
[cocoaView handleEvent:event];
}
} while(event != nil);
- vga_hw_update();
+ graphic_hw_update(NULL);
+ [pool release];
}
static void cocoa_cleanup(void)
g_free(dcl);
}
+static const DisplayChangeListenerOps dcl_ops = {
+ .dpy_name = "cocoa",
+ .dpy_gfx_update = cocoa_update,
+ .dpy_gfx_switch = cocoa_switch,
+ .dpy_refresh = cocoa_refresh,
+};
+
void cocoa_display_init(DisplayState *ds, int full_screen)
{
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
dcl = g_malloc0(sizeof(DisplayChangeListener));
// register vga output callbacks
- dcl->dpy_update = cocoa_update;
- dcl->dpy_resize = cocoa_resize;
- dcl->dpy_refresh = cocoa_refresh;
-
- register_displaychangelistener(ds, dcl);
+ dcl->ops = &dcl_ops;
+ register_displaychangelistener(dcl);
// register cleanup function
atexit(cocoa_cleanup);