From 4fe199c6a06606b0191575b3a0127076135a952c Mon Sep 17 00:00:00 2001 From: Akemi Date: Thu, 23 Feb 2017 20:01:27 +0100 Subject: cocoa: improve calculation of new window position on a different screen forcibly moving a window from one screen to another is supposed to put it in a position that looks relative the same as on the old screen, as in bottom, top, left and right margin look the same, without changing the window size. in some situations the old code moved the window off screen or on top of the menu bar so it ended up at a somewhat random position. the new code fixes some edge cases but is probably not completely correct since the priority is to make sure that the window ends up on the right screen. --- video/out/cocoa/window.m | 57 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 13 deletions(-) (limited to 'video') diff --git a/video/out/cocoa/window.m b/video/out/cocoa/window.m index ec4d8ae530..89c9e61d6b 100644 --- a/video/out/cocoa/window.m +++ b/video/out/cocoa/window.m @@ -29,6 +29,7 @@ @property(nonatomic, retain) NSScreen *targetScreen; @property(nonatomic, retain) NSScreen *previousScreen; @property(nonatomic, retain) NSScreen *currentScreen; +@property(nonatomic, retain) NSScreen *unfScreen; - (NSRect)frameRect:(NSRect)frameRect forCenteredContentSize:(NSSize)newSize; - (void)setCenteredContentSize:(NSSize)newSize; @@ -37,7 +38,6 @@ @implementation MpvVideoWindow { NSSize _queued_video_size; NSRect _unfs_content_frame; - NSRect _unfs_screen_frame; int _is_animating; } @@ -45,6 +45,7 @@ @synthesize targetScreen = _target_screen; @synthesize previousScreen = _previous_screen; @synthesize currentScreen = _current_screen; +@synthesize unfScreen = _unf_Screen; - (id)initWithContentRect:(NSRect)content_rect styleMask:(NSUInteger)style_mask backing:(NSBackingStoreType)buffering_type @@ -62,9 +63,9 @@ self.targetScreen = screen; self.currentScreen = screen; + self.unfScreen = screen; _is_animating = 0; _unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]]; - _unfs_screen_frame = [screen frame]; } return self; } @@ -88,7 +89,7 @@ if (![self.adapter isInFullScreenMode]) { _unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]]; - _unfs_screen_frame = [[self screen] frame]; + self.unfScreen = [self screen]; } //move window to target screen when going to fullscreen @@ -284,16 +285,46 @@ { NSRect frame = [self frameRectForContentRect:_unfs_content_frame]; NSRect targetFrame = [screen frame]; - - CGFloat x_per = (_unfs_screen_frame.size.width - frame.size.width); - CGFloat y_per = (_unfs_screen_frame.size.height - frame.size.height); - if (x_per > 0) x_per = (frame.origin.x - _unfs_screen_frame.origin.x)/x_per; - if (y_per > 0) y_per = (frame.origin.y - _unfs_screen_frame.origin.y)/y_per; - - frame.origin.x = targetFrame.origin.x + - (targetFrame.size.width - frame.size.width)*x_per; - frame.origin.y = targetFrame.origin.y + - (targetFrame.size.height - frame.size.height)*y_per; + NSRect targetVisibleFrame = [screen visibleFrame]; + NSRect unfsScreenFrame = [self.unfScreen frame]; + NSRect visibleWindow = NSIntersectionRect(unfsScreenFrame, frame); + + // calculate visible area of every side + CGFloat left = frame.origin.x - unfsScreenFrame.origin.x; + CGFloat right = unfsScreenFrame.size.width - + (frame.origin.x - unfsScreenFrame.origin.x + frame.size.width); + CGFloat bottom = frame.origin.y - unfsScreenFrame.origin.y; + CGFloat top = unfsScreenFrame.size.height - + (frame.origin.y - unfsScreenFrame.origin.y + frame.size.height); + + // normalize visible areas, decide which one to take horizontal/vertical + CGFloat x_per = (unfsScreenFrame.size.width - visibleWindow.size.width); + CGFloat y_per = (unfsScreenFrame.size.height - visibleWindow.size.height); + if (x_per != 0) x_per = (left >= 0 || right < 0 ? left : right)/x_per; + if (y_per != 0) y_per = (bottom >= 0 || top < 0 ? bottom : top)/y_per; + + // calculate visible area for every side for target screen + CGFloat x_new_left = targetFrame.origin.x + + (targetFrame.size.width - visibleWindow.size.width)*x_per; + CGFloat x_new_right = targetFrame.origin.x + targetFrame.size.width - + (targetFrame.size.width - visibleWindow.size.width)*x_per - frame.size.width; + CGFloat y_new_bottom = targetFrame.origin.y + + (targetFrame.size.height - visibleWindow.size.height)*y_per; + CGFloat y_new_top = targetFrame.origin.y + targetFrame.size.height - + (targetFrame.size.height - visibleWindow.size.height)*y_per - frame.size.height; + + // calculate new coordinates, decide which one to take horizontal/vertical + frame.origin.x = left >= 0 || right < 0 ? x_new_left : x_new_right; + frame.origin.y = bottom >= 0 || top < 0 ? y_new_bottom : y_new_top; + + // don't place new window on top of a visible menubar + CGFloat top_mar = targetFrame.size.height - + (frame.origin.y - targetFrame.origin.y + frame.size.height); + CGFloat menuBarHeight = targetFrame.size.height - + (targetVisibleFrame.size.height + targetVisibleFrame.origin.y); + + if (top_mar < menuBarHeight) + frame.origin.y -= top-menuBarHeight; if (withoutBounds) return frame; -- cgit v1.2.3