From d2ee0420a394bb0affb06659bdb5d706af24157b Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 23 Mar 2024 15:20:01 +0900 Subject: ui/cocoa: Fix aspect ratio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [NSWindow setContentAspectRatio:] does not trigger window resize itself, so the wrong aspect ratio will persist if nothing resizes the window. Call [NSWindow setContentSize:] in such a case. Fixes: 91aa508d0274 ("ui/cocoa: Let the platform toggle fullscreen") Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Message-ID: <20240323-fixes-v2-1-18651a2b0394@daynix.com> Signed-off-by: Philippe Mathieu-Daudé --- ui/cocoa.m | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/cocoa.m b/ui/cocoa.m index 810751c..17e125d 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -519,6 +519,43 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven } } +- (NSSize)fixAspectRatio:(NSSize)max +{ + NSSize scaled; + NSSize fixed; + + scaled.width = screen.width * max.height; + scaled.height = screen.height * max.width; + + /* + * Here screen is our guest's output size, and max is the size of the + * largest possible area of the screen we can display on. + * We want to scale up (screen.width x screen.height) by either: + * 1) max.height / screen.height + * 2) max.width / screen.width + * With the first scale factor the scale will result in an output height of + * max.height (i.e. we will fill the whole height of the available screen + * space and have black bars left and right) and with the second scale + * factor the scaling will result in an output width of max.width (i.e. we + * fill the whole width of the available screen space and have black bars + * top and bottom). We need to pick whichever keeps the whole of the guest + * output on the screen, which is to say the smaller of the two scale + * factors. + * To avoid doing more division than strictly necessary, instead of directly + * comparing scale factors 1 and 2 we instead calculate and compare those + * two scale factors multiplied by (screen.height * screen.width). + */ + if (scaled.width < scaled.height) { + fixed.width = scaled.width / screen.height; + fixed.height = max.height; + } else { + fixed.width = max.width; + fixed.height = scaled.height / screen.width; + } + + return fixed; +} + - (NSSize) screenSafeAreaSize { NSSize size = [[[self window] screen] frame].size; @@ -536,8 +573,10 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [[self window] setContentSize:NSMakeSize(screen.width, screen.height)]; [[self window] center]; } else if ([[self window] styleMask] & NSWindowStyleMaskFullScreen) { - [[self window] setContentSize:[self screenSafeAreaSize]]; + [[self window] setContentSize:[self fixAspectRatio:[self screenSafeAreaSize]]]; [[self window] center]; + } else { + [[self window] setContentSize:[self fixAspectRatio:[self frame].size]]; } } -- cgit v1.1 From f69a6f04133df61e2ab23553496a070f27f5b732 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 23 Mar 2024 15:20:02 +0900 Subject: ui/cocoa: Resize window after toggling zoom-to-fit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resize the window so that the content will fit without zooming. Fixes: 91aa508d0274 ("ui/cocoa: Let the platform toggle fullscreen") Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Message-ID: <20240323-fixes-v2-2-18651a2b0394@daynix.com> Signed-off-by: Philippe Mathieu-Daudé --- ui/cocoa.m | 1 + 1 file changed, 1 insertion(+) (limited to 'ui') diff --git a/ui/cocoa.m b/ui/cocoa.m index 17e125d..3efa8ac 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1408,6 +1408,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven [[cocoaView window] setStyleMask:styleMask]; [sender setState:styleMask & NSWindowStyleMaskResizable ? NSControlStateValueOn : NSControlStateValueOff]; + [cocoaView resizeWindow]; } - (void)toggleZoomInterpolation:(id) sender -- cgit v1.1 From ccebb9ae352eea63cb1491cb829e4cd0f7576f1c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sat, 23 Mar 2024 15:20:03 +0900 Subject: ui/cocoa: Use NSTrackingInVisibleRect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I observed [NSTrackingArea rect] becomes de-synchronized with the view frame with some unknown condition, and fails to track mouse movement on some area of the view. Specify NSTrackingInVisibleRect option to let Cocoa automatically update NSTrackingArea, which also saves code for synchronization. Fixes: 91aa508d0274 ("ui/cocoa: Let the platform toggle fullscreen") Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Message-ID: <20240323-fixes-v2-3-18651a2b0394@daynix.com> Signed-off-by: Philippe Mathieu-Daudé --- ui/cocoa.m | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) (limited to 'ui') diff --git a/ui/cocoa.m b/ui/cocoa.m index 3efa8ac..25e0db9 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -307,7 +307,6 @@ static void handleAnyDeviceErrors(Error * err) */ @interface QemuCocoaView : NSView { - NSTrackingArea *trackingArea; QEMUScreen screen; pixman_image_t *pixman_image; BOOL isMouseGrabbed; @@ -359,6 +358,19 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven self = [super initWithFrame:frameRect]; if (self) { + NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow | + NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | + NSTrackingInVisibleRect; + + NSTrackingArea *trackingArea = + [[NSTrackingArea alloc] initWithRect:CGRectZero + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; + [trackingArea release]; screen.width = frameRect.size.width; screen.height = frameRect.size.height; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0 @@ -389,41 +401,9 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven return YES; } -- (void) removeTrackingRect -{ - if (trackingArea) { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; - trackingArea = nil; - } -} - -- (void) frameUpdated -{ - [self removeTrackingRect]; - - if ([self window]) { - NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow | - NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved; - trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame] - options:options - owner:self - userInfo:nil]; - [self addTrackingArea:trackingArea]; - [self updateUIInfo]; - } -} - - (void) viewDidMoveToWindow { [self resizeWindow]; - [self frameUpdated]; -} - -- (void) viewWillMoveToWindow:(NSWindow *)newWindow -{ - [self removeTrackingRect]; } - (void) selectConsoleLocked:(unsigned int)index @@ -1314,7 +1294,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven - (void)windowDidResize:(NSNotification *)notification { [cocoaView updateBounds]; - [cocoaView frameUpdated]; + [cocoaView updateUIInfo]; } /* Called when the user clicks on a window's close button */ -- cgit v1.1