Skip to content

Commit

Permalink
Merge pull request #1450 from ychin/fix-fullscreen-notch-menu
Browse files Browse the repository at this point in the history
Fix non-native full screen show menu with notch, and changing resolution
  • Loading branch information
ychin committed Oct 21, 2023
2 parents af215e4 + b200f56 commit 4c5bd96
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 19 deletions.
13 changes: 8 additions & 5 deletions runtime/doc/gui_mac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -370,11 +370,14 @@ MacVim can be used in full screen mode, see 'fullscreen'.

There are two types of full screen modes. By default, MacVim uses macOS'
native full screen functionality, which creates a separate space in Mission
Control. MacVim also provides a non-native full screen mode, which can be set
by disabling native full screen in the settings panel, or by setting
|MMNativeFullScreen| to `NO` manually. If you have a MacBook with a "notch"
at the top of the screen, you can set |MMNonNativeFullScreenShowMenu| to `NO`
and |MMNonNativeFullScreenSafeAreaBehavior| to 1 to utilitize the whole screen
Control.

MacVim also provides a non-native full screen mode, which can be set by
disabling native full screen in the settings panel (see |MMNativeFullScreen|).
Use 'fuoptions' to configure the background color and whether to maximize the
rows/columns. If you have a MacBook with a camera housing ("notch") at the
top of the screen, you can set |MMNonNativeFullScreenShowMenu| to `NO` and
|MMNonNativeFullScreenSafeAreaBehavior| to 1 to utilitize the whole screen
(this will cause some of the content to be obscured by the notch).

==============================================================================
Expand Down
55 changes: 42 additions & 13 deletions src/MacVim/MMFullScreenWindow.m
Original file line number Diff line number Diff line change
Expand Up @@ -376,29 +376,48 @@ - (void)applicationDidChangeScreenParameters:(NSNotification *)notification
[self setFrame:[screen frame] display:NO];
}

/// Get the view offset to allow us space to show the menu bar, or account for "safe area" (a.k.a. notch) in certain MacBook Pro's.
/// Get the view offset to allow us space to show the menu bar, or account for "safe area" (a.k.a.
/// notch) in certain MacBook Pro's.
- (NSEdgeInsets) viewOffset {
NSEdgeInsets offset = NSEdgeInsetsMake(0, 0, 0, 0);

NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
const BOOL showMenu = [ud boolForKey:MMNonNativeFullScreenShowMenuKey];

#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_12_0)
// Account for newer MacBook Pro's which have a notch, which can be queried using the safe area API.
if (@available(macos 12.0, *)) {
const int safeAreaBehavior = [[NSUserDefaults standardUserDefaults]
integerForKey:MMNonNativeFullScreenSafeAreaBehaviorKey];

// The safe area utilization is configuration. Right now, we only have two choices.
// In the future there may be more, e.g. showing tabs in the safe area.
if (safeAreaBehavior == 0) {
offset = [[self screen] safeAreaInsets];
const int safeAreaBehavior = [ud integerForKey:MMNonNativeFullScreenSafeAreaBehaviorKey];

// The safe area utilization is configuration. Right now, we only have two choices:
// - 0: avoid the safe area (default)
// - 1: draw into the safe area, which would cause some contents to be obscured.
// In the future there may be more. E.g. we can draw tabs in the safe area.
// If menu is shown, we ignore this because this doesn't make sense.
if (safeAreaBehavior == 0 || showMenu) {
offset = [self screen].safeAreaInsets;
}
}
#endif

if ([[NSUserDefaults standardUserDefaults]
boolForKey:MMNonNativeFullScreenShowMenuKey]) {
const CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
if (menuBarHeight > offset.top) {
offset.top = menuBarHeight;
if (showMenu) {
// Offset by menu height
if (offset.top == 0) {
const CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
if (menuBarHeight > offset.top) {
offset.top = menuBarHeight;
}
} else {
// Unfortunately, if there is a notch (safe area != 0), menuBarHeight does *not* return
// the menu height shown in the main screen, so we need to calculate it otherwise.
// visibleArea is supposed to give us this information but it's oddly off by one, leading
// to a one-pixel black line, so we need to manually increment it by one. Yes, it sucks.
NSRect visibleFrame = [self screen].visibleFrame;
visibleFrame.size.height += 1;
const CGFloat menuBarHeight = [self screen].frame.size.height - NSMaxY(visibleFrame);
if (menuBarHeight > offset.top) {
offset.top = menuBarHeight;
}
}
}

Expand Down Expand Up @@ -482,6 +501,16 @@ - (BOOL)isOnPrimaryScreen
return selfScreenNum == primaryScreenNum;
}

/// Returns true when this screen has a dock and menu shown.
///
/// @note
/// This does not reliably detect whether the dock is on the current screen or
/// not as there is no API to reliably detect this. We are mostly guessing here
/// but if the user sets the dock to display on left/right on a horizontal
/// layout, it may be on the other screen.
/// Also, technically when not using separate spaces, it's possible for the
/// menu to be on one screen and dock on the other.
/// This should be revisited in the future.
- (BOOL)screenHasDockAndMenu
{
return NSScreen.screensHaveSeparateSpaces || [self isOnPrimaryScreen];
Expand Down
12 changes: 11 additions & 1 deletion src/MacVim/MMWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,17 @@ - (void)windowDidResize:(id)sender
// Calling setFrameSizeKeepGUISize: instead of setFrameSize: prevents a
// degenerate case where frameSizeMayHaveChanged: ends up resizing the window
// *again* causing windowDidResize: to be called.
[vimView setFrameSizeKeepGUISize:[self contentSize]];
if (fullScreenWindow == nil) {
[vimView setFrameSizeKeepGUISize:[self contentSize]];
} else {
// Non-native full screen mode is more complicated and needs to
// re-layout the Vim view to properly account for the menu bar / notch,
// and misc fuopt configuration.
// This code is similar to what's done in processInputQueueDidFinish.
NSRect desiredFrame = [fullScreenWindow getDesiredFrame];
[vimView setFrameOrigin:desiredFrame.origin];
[vimView setFrameSizeKeepGUISize:desiredFrame.size];
}
}

- (void)windowDidChangeBackingProperties:(NSNotification *)notification
Expand Down

0 comments on commit 4c5bd96

Please sign in to comment.