This patch makes several changes: - Fixes issue of returning to window mode and QEMU not setting the right graphic settings if there was a change during full screen mode. - Eliminated distorted full screen display. - Makes full screen mode available on Mac OS 10.7 and higher. - Removes unneeded global variables cdx, and cdy. - Changes a few comments to make them clearer.
Signed-off-by: John Arbuckle <programmingk...@gmail.com> --- ui/cocoa.m | 106 ++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 65 insertions(+), 41 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index d37c29b..704d199 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -40,7 +40,6 @@ #define MAC_OS_X_VERSION_10_6 1060 #endif - //#define DEBUG #ifdef DEBUG @@ -250,13 +249,14 @@ static int cocoa_keycode_to_qemu(int keycode) { QEMUScreen screen; NSWindow *fullScreenWindow; - float cx,cy,cw,ch,cdx,cdy; + float cx,cy,cw,ch; CGDataProviderRef dataProviderRef; int modifiers_state[256]; BOOL isMouseGrabbed; BOOL isFullscreen; BOOL isAbsoluteEnabled; BOOL isMouseDeassociated; + NSDictionary * window_mode_dict; /* keeps track of the guest' graphic settings */ } - (void) switchSurface:(DisplaySurface *)surface; - (void) grabMouse; @@ -279,9 +279,10 @@ static int cocoa_keycode_to_qemu(int keycode) - (BOOL) isMouseGrabbed; - (BOOL) isAbsoluteEnabled; - (BOOL) isMouseDeassociated; -- (float) cdx; -- (float) cdy; - (QEMUScreen) gscreen; +- (void) updateWindowModeSettings; +- (void) switchDisplayToWindowMode; +- (void) switchDisplayToFullScreenMode; @end QemuCocoaView *cocoaView; @@ -293,12 +294,11 @@ QemuCocoaView *cocoaView; self = [super initWithFrame:frameRect]; if (self) { - screen.bitsPerComponent = 8; screen.bitsPerPixel = 32; screen.width = frameRect.size.width; screen.height = frameRect.size.height; - + [self updateWindowModeSettings]; } return self; } @@ -394,10 +394,10 @@ QemuCocoaView *cocoaView; [self getRectsBeingDrawn:&rectList count:&rectCount]; for (i = 0; i < rectCount; i++) { - clipRect.origin.x = rectList[i].origin.x / cdx; - clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy; - clipRect.size.width = rectList[i].size.width / cdx; - clipRect.size.height = rectList[i].size.height / cdy; + clipRect.origin.x = rectList[i].origin.x; + clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height); + clipRect.size.width = rectList[i].size.width; + clipRect.size.height = rectList[i].size.height; clipImageRef = CGImageCreateWithImageInRect( imageRef, clipRect @@ -416,10 +416,8 @@ QemuCocoaView *cocoaView; COCOA_DEBUG("QemuCocoaView: setContentDimensions\n"); if (isFullscreen) { - cdx = [[NSScreen mainScreen] frame].size.width / (float)screen.width; - cdy = [[NSScreen mainScreen] frame].size.height / (float)screen.height; - cw = screen.width * cdx; - ch = screen.height * cdy; + cw = screen.width; + ch = screen.height; cx = ([[NSScreen mainScreen] frame].size.width - cw) / 2.0; cy = ([[NSScreen mainScreen] frame].size.height - ch) / 2.0; } else { @@ -427,23 +425,15 @@ QemuCocoaView *cocoaView; cy = 0; cw = screen.width; ch = screen.height; - cdx = 1.0; - cdy = 1.0; } } - (void) switchSurface:(DisplaySurface *)surface { COCOA_DEBUG("QemuCocoaView: switchSurface\n"); - int w = surface_width(surface); int h = surface_height(surface); - /* cdx == 0 means this is our very first surface, in which case we need - * to recalculate the content dimensions even if it happens to be the size - * of the initial empty window. - */ - bool isResize = (w != screen.width || h != screen.height || cdx == 0.0); - + 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 @@ -452,6 +442,16 @@ QemuCocoaView *cocoaView; screen.height = h; [self setContentDimensions]; [self setFrame:NSMakeRect(cx, cy, cw, ch)]; + + if (isFullscreen) { + /* I know, calling toggleFullScreen: looks like a mistake, but + it is the solution that works. I spent a long time looking + for another way. This way is simple and works very well. */ + [self toggleFullScreen: nil]; + [self toggleFullScreen: nil]; + } + else /* !isFullscreen */ + [self updateWindowModeSettings]; } // update screenBuffer @@ -482,8 +482,8 @@ QemuCocoaView *cocoaView; - (void) toggleFullScreen:(id)sender { COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n"); - - if (isFullscreen) { // switch from fullscreen to desktop + if (isFullscreen) { // switch from fullscreen to window mode + [self switchDisplayToWindowMode]; isFullscreen = FALSE; [self ungrabMouse]; [self setContentDimensions]; @@ -500,7 +500,8 @@ QemuCocoaView *cocoaView; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) } #endif - } else { // switch from desktop to fullscreen + } else { // switch from window to fullscreen mode + [self switchDisplayToFullScreenMode]; isFullscreen = TRUE; [self grabMouse]; [self setContentDimensions]; @@ -561,7 +562,7 @@ QemuCocoaView *cocoaView; } // release Mouse grab when pressing ctrl+alt - if (!isFullscreen && ([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) { + if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) { [self ungrabMouse]; } break; @@ -781,9 +782,33 @@ QemuCocoaView *cocoaView; - (BOOL) isMouseGrabbed {return isMouseGrabbed;} - (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;} - (BOOL) isMouseDeassociated {return isMouseDeassociated;} -- (float) cdx {return cdx;} -- (float) cdy {return cdy;} - (QEMUScreen) gscreen {return screen;} + +/* Learn the guest' graphic settings when in window mode */ +- (void) updateWindowModeSettings +{ + window_mode_dict = CGDisplayCurrentMode(kCGDirectMainDisplay); +} + +/* Switches the monitor's display settings for using QEMU in a window mode */ +- (void) switchDisplayToWindowMode +{ + CGDisplaySwitchToMode(kCGDirectMainDisplay, window_mode_dict); +} + +/* Switches the monitor's display settings for using QEMU in full screen mode */ +- (void) switchDisplayToFullScreenMode +{ + size_t desired_bit_depth = 32; + boolean_t exact_match; + NSDictionary * mode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, desired_bit_depth, (size_t)cw, (size_t)ch, &exact_match); + COCOA_DEBUG("switching to full screen: %d x %d\n", [[mode valueForKey: @"Width"] intValue], [[mode valueForKey: @"Height"] intValue]); + if (mode != nil) + CGDisplaySwitchToMode(kCGDirectMainDisplay, mode); + else + printf("ERROR: failed to determine best mode for display!\n"); +} + @end @@ -832,7 +857,6 @@ QemuCocoaView *cocoaView; [normalWindow useOptimizedDrawing:YES]; [normalWindow makeKeyAndOrderFront:self]; [normalWindow center]; - } return self; } @@ -921,6 +945,15 @@ QemuCocoaView *cocoaView; [self startEmulationWithArgc:3 argv:(char**)argv]; } } + +/* We abstract the method called by the Enter Fullscreen menu item +because Mac OS 10.7 and higher disables it. This is because of the +menu item's old selector's name toggleFullScreen: */ +- (void) doToggleFullScreen:(id)sender +{ + [self toggleFullScreen:(id)sender]; +} + - (void)toggleFullScreen:(id)sender { COCOA_DEBUG("QemuCocoaAppController: toggleFullScreen\n"); @@ -1005,7 +1038,7 @@ int main (int argc, const char * argv[]) { // View menu menu = [[NSMenu alloc] initWithTitle:@"View"]; - [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen + [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(doToggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""] autorelease]; [menuItem setSubmenu:menu]; [[NSApp mainMenu] addItem:menuItem]; @@ -1050,17 +1083,8 @@ static void cocoa_update(DisplayChangeListener *dcl, COCOA_DEBUG("qemu_cocoa: cocoa_update\n"); NSRect rect; - if ([cocoaView cdx] == 1.0) { - rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h); - } else { - rect = NSMakeRect( - x * [cocoaView cdx], - ([cocoaView gscreen].height - y - h) * [cocoaView cdy], - w * [cocoaView cdx], - h * [cocoaView cdy]); - } + rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h); [cocoaView setNeedsDisplayInRect:rect]; - [pool release]; } -- 1.7.5.4