From 8895919a044e9e8111faebabacaa2245d8ce4e51 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 8 Dec 2013 22:59:02 +0000 Subject: [PATCH 1/9] ui/cocoa: Pass command key through to guest when VM has mousegrab The guest might want to be able to use the command key for its won purposes (as command if it is MacOS X, or for the Windows key if it is a PC guest, for instance). In line with other UI frontends, pass it through if the guest has mousegrab, and only use it for UI menu accelerators if not grabbed. Thanks to John Arbuckle for reporting this problem, helping us work through what the best solution would be and providing a patch which was the initial inspiration for this one. Reported-by: John Arbuckle Signed-off-by: Peter Maydell Message-id: 1386543546-31919-2-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 2524f185bc..34b58d5bd9 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -129,8 +129,8 @@ 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 @@ -206,8 +206,6 @@ /* 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 @@ -493,6 +491,12 @@ - (void) handleEvent:(NSEvent *)event switch ([event type]) { case NSFlagsChanged: keycode = cocoa_keycode_to_qemu([event keyCode]); + + if ((keycode == 219 || keycode == 220) && !isMouseGrabed) { + /* 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); @@ -516,15 +520,15 @@ - (void) handleEvent:(NSEvent *)event } 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 (!isMouseGrabed && ([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)) { @@ -580,6 +584,13 @@ - (void) handleEvent:(NSEvent *)event break; case NSKeyUp: keycode = cocoa_keycode_to_qemu([event keyCode]); + + // don't pass the guest a spurious key-up if we treated this + // command-key combo as a host UI action + if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) { + return; + } + if (qemu_console_is_graphic(NULL)) { if (keycode & 0x80) kbd_put_keycode(0xe0); From 49b9bd4dccac26178a4796367e4358bd67f4f59b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 8 Dec 2013 22:59:03 +0000 Subject: [PATCH 2/9] ui/cocoa: Correct typos in comments and variable names Fix various non-user-visible typos in comments and variable names. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Message-id: 1386543546-31919-3-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 34b58d5bd9..1edb944235 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -52,7 +52,7 @@ #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]; \ @@ -204,7 +204,7 @@ 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 */ /* 221 // 0xdd e0,5d APPS // E0,2A,E0,37 PRNT SCRN @@ -259,7 +259,7 @@ @interface QemuCocoaView : NSView float cx,cy,cw,ch,cdx,cdy; CGDataProviderRef dataProviderRef; int modifiers_state[256]; - BOOL isMouseGrabed; + BOOL isMouseGrabbed; BOOL isFullscreen; BOOL isAbsoluteEnabled; BOOL isTabletEnabled; @@ -270,7 +270,7 @@ - (void) ungrabMouse; - (void) toggleFullScreen:(id)sender; - (void) handleEvent:(NSEvent *)event; - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled; -- (BOOL) isMouseGrabed; +- (BOOL) isMouseGrabbed; - (BOOL) isAbsoluteEnabled; - (float) cdx; - (float) cdy; @@ -492,7 +492,7 @@ - (void) handleEvent:(NSEvent *)event case NSFlagsChanged: keycode = cocoa_keycode_to_qemu([event keyCode]); - if ((keycode == 219 || keycode == 220) && !isMouseGrabed) { + if ((keycode == 219 || keycode == 220) && !isMouseGrabbed) { /* Don't pass command key changes to guest unless mouse is grabbed */ keycode = 0; } @@ -523,7 +523,7 @@ - (void) handleEvent:(NSEvent *)event keycode = cocoa_keycode_to_qemu([event keyCode]); // forward command key combos to the host UI unless the mouse is grabbed - if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) { + if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) { [NSApp sendEvent:event]; return; } @@ -587,7 +587,7 @@ - (void) handleEvent:(NSEvent *)event // don't pass the guest a spurious key-up if we treated this // command-key combo as a host UI action - if (!isMouseGrabed && ([event modifierFlags] & NSCommandKeyMask)) { + if (!isMouseGrabbed && ([event modifierFlags] & NSCommandKeyMask)) { return; } @@ -648,7 +648,7 @@ - (void) handleEvent:(NSEvent *)event 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 { @@ -665,7 +665,7 @@ - (void) handleEvent:(NSEvent *)event COCOA_MOUSE_EVENT break; case NSScrollWheel: - if (isTabletEnabled || isMouseGrabed) { + if (isTabletEnabled || isMouseGrabbed) { kbd_mouse_event(0, 0, -[event deltaY], 0); } else { [NSApp sendEvent:event]; @@ -688,7 +688,7 @@ - (void) grabMouse } [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 @@ -703,11 +703,11 @@ - (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;} @@ -778,7 +778,7 @@ - (void)applicationDidFinishLaunching: (NSNotification *) note { 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]; @@ -1010,7 +1010,7 @@ static void cocoa_refresh(DisplayChangeListener *dcl) if (kbd_mouse_is_absolute()) { if (![cocoaView isAbsoluteEnabled]) { - if ([cocoaView isMouseGrabed]) { + if ([cocoaView isMouseGrabbed]) { [cocoaView ungrabMouse]; } } From 01cc4e6fd7d364c6c401c579d504d82c0523d67e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 8 Dec 2013 22:59:04 +0000 Subject: [PATCH 3/9] ui/cocoa: Send warning message to stderr, not stdout Bring a warning message into line with the others in this file by sending it to stderr, not stdout. Signed-off-by: Peter Maydell Message-id: 1386543546-31919-4-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 1edb944235..5249891651 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -239,7 +239,7 @@ static int cocoa_keycode_to_qemu(int keycode) { if (ARRAY_SIZE(keymap) <= keycode) { - printf("(cocoa) warning unknown keycode 0x%x\n", keycode); + fprintf(stderr, "(cocoa) warning unknown keycode 0x%x\n", keycode); return 0; } return keymap[keycode]; From 5342f990f46512487e3e5be1047a5b424f00d255 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 8 Dec 2013 22:59:05 +0000 Subject: [PATCH 4/9] ui/cocoa: Add ".qcow2" to extension list for image load dialog Add ".qcow2" to the list of file extensions which are accepted by the initial disk image load dialog which is displayed if the user runs QEMU without any command line arguments. Signed-off-by: Peter Maydell Message-id: 1386543546-31919-5-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 5249891651..fd55044547 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -785,7 +785,7 @@ - (void)applicationDidFinishLaunching: (NSNotification *) note [op setPrompt:@"Boot image"]; [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; NSArray *filetypes = [NSArray arrayWithObjects:@"img", @"iso", @"dmg", - @"qcow", @"cow", @"cloop", @"vmdk", nil]; + @"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 From 98db429d2c6d157b7e00e3f24b6b1d9036f5e358 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 8 Dec 2013 22:59:06 +0000 Subject: [PATCH 5/9] ui/cocoa: Fix code for starting QEMU via image file load dialog Fix a number of bugs in the code for starting QEMU via the image file load dialog: * use the actual argv[0] rather than "qemu": this avoids failures to find BIOS image files caused by not looking in the correct directory relative to the executable path * allocate a large enough argv array to NULL terminate it * use g_strdup(X) rather than g_strdup_printf("%s", X) or g_strdup_printf(X) * disable the printing of the simulated command line argument (which is presumably intended for debug only) Signed-off-by: Peter Maydell Message-id: 1386543546-31919-6-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index fd55044547..b90b782201 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -833,18 +833,18 @@ - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextI if(returnCode == NSCancelButton) { exit(0); } else if(returnCode == NSOKButton) { - const char *bin = "qemu"; char *img = (char*)[ [ [ sheet URL ] path ] cStringUsingEncoding:NSASCIIStringEncoding]; - char **argv = (char**)malloc( sizeof(char*)*3 ); + char **argv = g_new(char *, 4); [sheet close]; - argv[0] = g_strdup_printf("%s", bin); - argv[1] = g_strdup_printf("-hda"); - argv[2] = g_strdup_printf("%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]; } From d3345a04849374af2b21d6624dd206c4444a6ffe Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Dec 2013 02:51:46 +0000 Subject: [PATCH 6/9] ui/cocoa: Redraw at correct size when switching surface If the surface switch involved a resize, we were doing the redraw at the old size rather than the new, because the update of screen.width and screen.height was being done after the setFrame method calls which triggered a redraw. Normally this isn't very noticeable because typically after the guest triggers the window resize it also draws something to it, which will in turn cause us to redraw. However, the combination of a guest which never draws to the display and a command line setting of a screen size larger than the default can reveal odd effects. Move most of the handling of resizes to the top of the method, and guard it with a check that the surface size actually changed, to avoid unnecessary operations (including some user visible ones like "recenter the window on the screen") if the surface is the same size as the old one. Signed-off-by: Peter Maydell Message-id: 1387853507-26298-2-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index b90b782201..6a1f6b6989 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -405,6 +405,17 @@ - (void) switchSurface:(DisplaySurface *)surface 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) @@ -419,17 +430,16 @@ - (void) switchSurface:(DisplaySurface *)surface // 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 From 7d270b1c21c692478245b90bfac0aa54c6a8d98a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Dec 2013 02:51:47 +0000 Subject: [PATCH 7/9] ui/cocoa: Draw black rectangle if we have no data yet If our redraw method is called before we have any data from the guest, then draw a black rectangle rather than leaving the window empty. This mostly only matters when the guest machine has no framebuffer device, but it is more in line with the behaviour of other QEMU UIs. Signed-off-by: Peter Maydell Message-id: 1387853507-26298-3-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 6a1f6b6989..22ec29be83 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -321,7 +321,12 @@ - (void) drawRect:(NSRect) rect 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 From 49060c29c3751773265a405e6ceaed9d06fb4823 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 24 Dec 2013 11:54:12 +0000 Subject: [PATCH 8/9] ui/cocoa: Remove stray tabs The ui/cocoa.m file has just three lines with hardcoded tabs; fix them. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Message-id: 1387886052-27067-1-git-send-email-peter.maydell@linaro.org --- ui/cocoa.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 22ec29be83..866177770a 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -427,8 +427,8 @@ - (void) switchSurface:(DisplaySurface *)surface CGDataProviderRelease(dataProviderRef); //sync host window color space with guests - screen.bitsPerPixel = surface_bits_per_pixel(surface); - screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2; + screen.bitsPerPixel = surface_bits_per_pixel(surface); + screen.bitsPerComponent = surface_bytes_per_pixel(surface) * 2; dataProviderRef = CGDataProviderCreateWithData(NULL, surface_data(surface), w * 4 * h, NULL); @@ -774,7 +774,7 @@ - (id) init [normalWindow setContentView:cocoaView]; [normalWindow useOptimizedDrawing:YES]; [normalWindow makeKeyAndOrderFront:self]; - [normalWindow center]; + [normalWindow center]; } return self; From 30ef3c742526baa7910ab5023f0b85062bd85579 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 16 Dec 2013 15:17:55 +0000 Subject: [PATCH 9/9] MAINTAINERS: add myself as cocoa UI co-maintainer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add myself to the maintainers list for the cocoa UI; status remains "Odd Fixes". Signed-off-by: Peter Maydell Acked-by: Andreas Färber Message-id: 1387207075-10280-1-git-send-email-peter.maydell@linaro.org --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index a5ab8f8cea..fb5324285c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -714,6 +714,7 @@ F: ui/ Cocoa graphics M: Andreas Färber +M: Peter Maydell S: Odd Fixes F: ui/cocoa.m