From 6d044f934428754b5fa6f8f9f4208da4fa110030 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Thu, 4 Feb 2021 06:02:38 -0800 Subject: [PATCH] Fix non-native full screen sizing, fix 'fuoptions', allow menus Fix misc non-native full screen sizing issues. Previously, in certain cases such as using non-native full screen in a secondary monitor, the non-native full screen window would be offsetted and half the window shown offscreen, making it hard to use. The bug is that we call `resizeVimView` and `centerView` immediately after resizing Vim's frame, but the frame resize only asynchronously calls processInputQueueDidFinish in MMWindowController, which now actually handles all the frame resizing logic. `centerView` was therefore calculating using the wrong info, and tried to center the view on wrong coordinates. Just fix this by removing those two functions as they are no longer needed as processInputQueueDidFinish already does everything. Also, fix `fuopts` to support unsetting maxvert/maxhorz again (this was what `centerView` was trying to do). Simply add hooks to processInputQueueDidFinish to query the non-native full screen window for what the desired size is, instead of just assuming we wan to fill the whole frame. * Fix #509 Also, add a new option `MMNonNativeFullScreenShowMenu` to allow showing the menu bar instead of auto-hiding it while using non-native full screen as it could be useful to show it, and less jarring to switch among different apps. Move preferences around so non-native full screen is now a "regular" option under Apperance instead of Advanced. Also expose the non-native show menu option so it's exposed to users. This is a follow-up to #1155. --- runtime/doc/gui_mac.txt | 1 + runtime/doc/options.txt | 29 ++---- runtime/doc/tags | 1 + src/MacVim/Base.lproj/Preferences.xib | 105 +++++++++++++-------- src/MacVim/MMAppController.m | 1 + src/MacVim/MMFullScreenWindow.h | 6 +- src/MacVim/MMFullScreenWindow.m | 127 ++++++++------------------ src/MacVim/MMWindowController.m | 13 ++- src/MacVim/Miscellaneous.h | 1 + src/MacVim/Miscellaneous.m | 1 + 10 files changed, 130 insertions(+), 155 deletions(-) diff --git a/runtime/doc/gui_mac.txt b/runtime/doc/gui_mac.txt index 35a1946c41..146cc9641d 100644 --- a/runtime/doc/gui_mac.txt +++ b/runtime/doc/gui_mac.txt @@ -263,6 +263,7 @@ KEY VALUE ~ *MMLoginShellArgument* login shell parameter [string] *MMLoginShellCommand* which shell to use to launch Vim [string] *MMNativeFullScreen* use native full screen mode [bool] +*MMNonNativeFullScreenShowMenu* show menus when in non-native full screen [bool] *MMNoFontSubstitution* disable automatic font substitution [bool] (Deprecated: Non-CoreText renderer only) *MMFontPreserveLineSpacing* use the line-spacing as specified by font [bool] diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f577d87ad8..064f966bca 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3607,23 +3607,19 @@ A jump table for the options with a short description can be found at |Q_op|. global {not in Vi} {only in MacVim GUI} - In fullscreen mode, most of the screen is black, only a part of the - screen is covered by the actual Vim control. The control is centered. - This option controls the size of the Vim control as well as the color - of the unused screen area. + {not supported in native full screen mode} + In non-native fullscreen mode, MacVim can be configured to either show + all the content filling up the whole screen, or only use part of the + screen to show the content, centered. This option controls the size + of the Vim control as well as the color of the unused screen area. value effect ~ maxvert When entering fullscreen, 'lines' is set to the maximum number - of lines fitting on the screen in fullscreen mode. When - leaving fullscreen, if 'lines' is still equal to the maximized - number of lines, it is restored to the value it had before - entering fullscreen. + of lines fitting on the screen in fullscreen mode. If unset, + 'lines' will be unchanged when entering fullscreen mode. maxhorz When entering fullscreen, 'columns' is set to the maximum number - of columns fitting on the screen in fullscreen mode. When - leaving fullscreen, if 'columns' is still equal to the maximized - number of columns, it is restored to the value it had before - entering fullscreen. + of columns fitting on the screen in fullscreen mode. If unset, + 'columns' will be unchanged when entering fullscreen mode. background:color - {not supported in Mac OS X native full screen} When entering fullscreen, 'color' defines the color of the part of the screen that is not occupied by the Vim control. If 'color' is an 8-digit hexadecimal number preceded by '#', @@ -3645,13 +3641,6 @@ A jump table for the options with a short description can be found at |Q_op|. < Don't change size when entering fullscreen, and color the background like the current text background: > :set fuoptions=background:Normal -< - XXX: what if the font size is changed? you probably never want to - restore the old 'lines' or 'columns' in that case. - XXX: Each time the Vim window resizes (for example due to font size - changes, re-maximize Vim to fullscreen?) - XXX: The approach doesn't restore vertical Vim size if fu is entered - without tabs and leaves with tabs (or the other way round). diff --git a/runtime/doc/tags b/runtime/doc/tags index f8cac19f19..10e2775ab5 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -5030,6 +5030,7 @@ MMLoginShellCommand gui_mac.txt /*MMLoginShellCommand* MMNativeFullScreen gui_mac.txt /*MMNativeFullScreen* MMNoFontSubstitution gui_mac.txt /*MMNoFontSubstitution* MMNoTitleBarWindow gui_mac.txt /*MMNoTitleBarWindow* +MMNonNativeFullScreenShowMenu gui_mac.txt /*MMNonNativeFullScreenShowMenu* MMShareFindPboard gui_mac.txt /*MMShareFindPboard* MMShowAddTabButton gui_mac.txt /*MMShowAddTabButton* MMTabMaxWidth gui_mac.txt /*MMTabMaxWidth* diff --git a/src/MacVim/Base.lproj/Preferences.xib b/src/MacVim/Base.lproj/Preferences.xib index c402c241c1..9446be602a 100644 --- a/src/MacVim/Base.lproj/Preferences.xib +++ b/src/MacVim/Base.lproj/Preferences.xib @@ -227,11 +227,11 @@ - + - + @@ -292,7 +292,7 @@ - + - + + + + + + + + + + + + + + + + + + - - + - + @@ -359,14 +405,14 @@ - + - + - + @@ -376,7 +422,7 @@ - + @@ -397,7 +443,7 @@ - + @@ -419,7 +465,7 @@ - - - - - - You may want to disable this option when using multiple monitors since the native full-screen support renders secondary monitors useless. - - - - - - + diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 4ace0b1fb8..83dccbd6c4 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -249,6 +249,7 @@ + (void)initialize [NSNumber numberWithBool:NO], MMSuppressTerminationAlertKey, [NSNumber numberWithBool:YES], MMNativeFullScreenKey, [NSNumber numberWithDouble:0.25], MMFullScreenFadeTimeKey, + [NSNumber numberWithBool:NO], MMNonNativeFullScreenShowMenuKey, [NSNumber numberWithBool:YES], MMShareFindPboardKey, nil]; diff --git a/src/MacVim/MMFullScreenWindow.h b/src/MacVim/MMFullScreenWindow.h index 629570c40c..4dd870fd58 100644 --- a/src/MacVim/MMFullScreenWindow.h +++ b/src/MacVim/MMFullScreenWindow.h @@ -25,8 +25,8 @@ // These are only valid in full-screen mode and store pre-fu vim size int nonFuRows, nonFuColumns; - // These store the size vim had right after entering fu mode - int startFuRows, startFuColumns; + /// The non-full-screen size of the Vim view. Used for non-maxvert/maxhorz options. + NSSize nonFuVimViewSize; // This stores the contents of fuoptions_flags at fu start time int startFuFlags; @@ -41,7 +41,7 @@ - (void)setOptions:(int)opt; - (void)enterFullScreen; - (void)leaveFullScreen; -- (void)centerView; +- (NSRect)getDesiredFrame; - (BOOL)canBecomeKeyWindow; - (BOOL)canBecomeMainWindow; diff --git a/src/MacVim/MMFullScreenWindow.m b/src/MacVim/MMFullScreenWindow.m index c18f4ab983..2549c8cb8f 100644 --- a/src/MacVim/MMFullScreenWindow.m +++ b/src/MacVim/MMFullScreenWindow.m @@ -50,7 +50,6 @@ - (BOOL)screenHasDockAndMenu; - (void)windowDidBecomeMain:(NSNotification *)notification; - (void)windowDidResignMain:(NSNotification *)notification; - (void)windowDidMove:(NSNotification *)notification; -- (void)resizeVimView; @end @implementation MMFullScreenWindow @@ -140,7 +139,11 @@ - (void)enterFullScreen // Hide Dock and menu bar when going to full screen. Only do so if the current screen // has a menu bar and dock. if ([self screenHasDockAndMenu]) { - [NSApplication sharedApplication].presentationOptions = + const bool showMenu = [[NSUserDefaults standardUserDefaults] + boolForKey:MMNonNativeFullScreenShowMenuKey]; + + [NSApplication sharedApplication].presentationOptions = showMenu ? + NSApplicationPresentationAutoHideDock : NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar; } @@ -198,7 +201,7 @@ - (void)enterFullScreen // Store view dimension used before entering full-screen, then resize the // view to match 'fuopt'. [[view textView] getMaxRows:&nonFuRows columns:&nonFuColumns]; - [self resizeVimView]; + nonFuVimViewSize = view.frame.size; // Store options used when entering full-screen so that we can restore // dimensions when exiting full-screen. @@ -244,19 +247,7 @@ - (void)leaveFullScreen // restore old vim view size int currRows, currColumns; [[view textView] getMaxRows:&currRows columns:&currColumns]; - int newRows = currRows, newColumns = currColumns; - - // Compute desired non-fu size. - // - // If current fu size is almost equal to fu size at fu enter time, - // restore the old size. Don't check for sizes to match exactly since then - // the non-fu size will not be restored if e.g. the tabline or scrollbars - // were toggled while in fu-mode. - if (startFuFlags & FUOPT_MAXVERT && abs(startFuRows-currRows)<5) - newRows = nonFuRows; - - if (startFuFlags & FUOPT_MAXHORZ && abs(startFuColumns-currColumns)<5) - newColumns = nonFuColumns; + int newRows = nonFuRows, newColumns = nonFuColumns; // resize vim if necessary if (currRows != newRows || currColumns != newColumns) { @@ -379,29 +370,39 @@ - (void)applicationDidChangeScreenParameters:(NSNotification *)notification // Ensure the full-screen window is still covering the entire screen and // then resize view according to 'fuopt'. [self setFrame:[screen frame] display:NO]; - [self resizeVimView]; } +/// Get the view vertical offset to allow us space to show the menu bar and what not. - (CGFloat) viewOffset { - CGFloat menuBarHeight = 0; - if([self screen] != [[NSScreen screens] objectAtIndex:0]) { - // Screens other than the primary screen will not hide their menu bar, adjust the visible view down by the menu height - menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]-1; + if ([[NSUserDefaults standardUserDefaults] + boolForKey:MMNonNativeFullScreenShowMenuKey]) { + return [[[NSApplication sharedApplication] mainMenu] menuBarHeight]-1; + } else { + return 0; } - return menuBarHeight; } -- (void)centerView +/// Returns the desired frame of the Vim view, which takes fuopts into account +/// by centering the view in the middle of the full-screen frame. If using the +/// default of having both maxvert/maxhorz set, this will simply return +/// desiredFrameSize back. +/// +/// @return Desired frame, including size and offset. +- (NSRect)getDesiredFrame; { - NSRect outer = [self frame], inner = [view frame]; + NSRect windowFrame = [self frame]; + NSSize desiredFrameSize = windowFrame.size; + desiredFrameSize.height -= [self viewOffset]; + + if (!(options & FUOPT_MAXVERT)) + desiredFrameSize.height = MIN(desiredFrameSize.height, nonFuVimViewSize.height); + if (!(options & FUOPT_MAXHORZ)) + desiredFrameSize.width = MIN(desiredFrameSize.width, nonFuVimViewSize.width); - // NOTE! Make sure the origin coordinates are integral or very strange - // rendering issues may arise (screen looks blurry, each redraw clears the - // entire window, etc.). - NSPoint origin = { floor((outer.size.width - inner.size.width)/2), - floor((outer.size.height - inner.size.height)/2 - [self viewOffset]/2) }; + NSPoint origin = { floor((windowFrame.size.width - desiredFrameSize.width)/2), + floor((windowFrame.size.height - desiredFrameSize.height)/2 - [self viewOffset] / 2) }; - [view setFrameOrigin:origin]; + return NSMakeRect(origin.x, origin.y, desiredFrameSize.width, desiredFrameSize.height); } - (void)scrollWheel:(NSEvent *)theEvent @@ -462,7 +463,11 @@ - (void)windowDidBecomeMain:(NSNotification *)notification { // Hide menu and dock when this window gets focus. if ([self screenHasDockAndMenu]) { - [NSApplication sharedApplication].presentationOptions = + const bool showMenu = [[NSUserDefaults standardUserDefaults] + boolForKey:MMNonNativeFullScreenShowMenuKey]; + + [NSApplication sharedApplication].presentationOptions = showMenu ? + NSApplicationPresentationAutoHideDock : NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar; } } @@ -489,66 +494,6 @@ - (void)windowDidMove:(NSNotification *)notification // Ensure the full-screen window is still covering the entire screen and // then resize view according to 'fuopt'. [self setFrame:[[self screen] frame] display:NO]; - [self resizeVimView]; -} - -- (void)resizeVimView -{ - // Resize vim view according to options - int currRows, currColumns; - [[view textView] getMaxRows:&currRows columns:&currColumns]; - - int fuRows = currRows, fuColumns = currColumns; - - // NOTE: Do not use [NSScreen visibleFrame] when determining the screen - // size since it compensates for menu and dock. - int maxRows, maxColumns; - NSSize size = [[self screen] frame].size; - size.height -= [self viewOffset]; - - [view constrainRows:&maxRows columns:&maxColumns toSize:size]; - - // Compute current fu size - if (options & FUOPT_MAXVERT) - fuRows = maxRows; - if (options & FUOPT_MAXHORZ) - fuColumns = maxColumns; - - // if necessary, resize vim to target fu size - if (currRows != fuRows || currColumns != fuColumns) { - // The size sent here is queued and sent to vim when it's in - // event processing mode again. Make sure to only send the values we - // care about, as they override any changes that were made to 'lines' - // and 'columns' after 'fu' was set but before the event loop is run. - NSData *data = nil; - int msgid = 0; - if (currRows != fuRows && currColumns != fuColumns) { - int newSize[2] = { fuRows, fuColumns }; - data = [NSData dataWithBytes:newSize length:2*sizeof(int)]; - msgid = SetTextDimensionsMsgID; - } else if (currRows != fuRows) { - data = [NSData dataWithBytes:&fuRows length:sizeof(int)]; - msgid = SetTextRowsMsgID; - } else if (currColumns != fuColumns) { - data = [NSData dataWithBytes:&fuColumns length:sizeof(int)]; - msgid = SetTextColumnsMsgID; - } - NSParameterAssert(data != nil && msgid != 0); - - MMVimController *vc = [[self windowController] vimController]; - [vc sendMessage:msgid data:data]; - [[view textView] setMaxRows:fuRows columns:fuColumns]; - } - - // The new view dimensions are stored and then consulted when attempting to - // restore the windowed view dimensions when leaving full-screen. - // NOTE: Store them here and not only in enterFullScreen, otherwise the - // windowed view dimensions will not be restored if the full-screen was on - // a screen that later was unplugged. - startFuRows = fuRows; - startFuColumns = fuColumns; - - [self centerView]; } @end // MMFullScreenWindow (Private) diff --git a/src/MacVim/MMWindowController.m b/src/MacVim/MMWindowController.m index 2a245c60f2..02766c9fdf 100644 --- a/src/MacVim/MMWindowController.m +++ b/src/MacVim/MMWindowController.m @@ -785,7 +785,18 @@ - (void)processInputQueueDidFinish keepOnScreen:keepOnScreen]; } else { - NSSize frameSize = fullScreenWindow ? [fullScreenWindow frame].size : (fullScreenEnabled ? desiredWindowSize : originalSize); + NSSize frameSize; + if (fullScreenWindow) { + // Non-native full screen mode. + NSRect desiredFrame = [fullScreenWindow getDesiredFrame]; + frameSize = desiredFrame.size; + [vimView setFrameOrigin:desiredFrame.origin]; // This will get set back to normal in MMFullScreenWindow::leaveFullScreen. + } else if (fullScreenEnabled) { + // Native full screen mode. + frameSize = desiredWindowSize; + } else { + frameSize = originalSize; + } [vimView setFrameSizeKeepGUISize:frameSize]; } } diff --git a/src/MacVim/Miscellaneous.h b/src/MacVim/Miscellaneous.h index 45481b0079..f65094b8be 100644 --- a/src/MacVim/Miscellaneous.h +++ b/src/MacVim/Miscellaneous.h @@ -56,6 +56,7 @@ extern NSString *MMSuppressTerminationAlertKey; extern NSString *MMNativeFullScreenKey; extern NSString *MMUseMouseTimeKey; extern NSString *MMFullScreenFadeTimeKey; +extern NSString *MMNonNativeFullScreenShowMenuKey; // Enum for MMUntitledWindowKey diff --git a/src/MacVim/Miscellaneous.m b/src/MacVim/Miscellaneous.m index 93cdd9131d..9ee98ee10c 100644 --- a/src/MacVim/Miscellaneous.m +++ b/src/MacVim/Miscellaneous.m @@ -52,6 +52,7 @@ NSString *MMNativeFullScreenKey = @"MMNativeFullScreen"; NSString *MMUseMouseTimeKey = @"MMUseMouseTime"; NSString *MMFullScreenFadeTimeKey = @"MMFullScreenFadeTime"; +NSString *MMNonNativeFullScreenShowMenuKey = @"MMNonNativeFullScreenShowMenu";