@@ -376,29 +376,48 @@ - (void)applicationDidChangeScreenParameters:(NSNotification *)notification
376376 [self setFrame: [screen frame ] display: NO ];
377377}
378378
379- // / 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.
379+ // / Get the view offset to allow us space to show the menu bar, or account for "safe area" (a.k.a.
380+ // / notch) in certain MacBook Pro's.
380381- (NSEdgeInsets ) viewOffset {
381382 NSEdgeInsets offset = NSEdgeInsetsMake (0 , 0 , 0 , 0 );
382383
384+ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults ];
385+ const BOOL showMenu = [ud boolForKey: MMNonNativeFullScreenShowMenuKey];
386+
383387#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_12_0)
384388 // Account for newer MacBook Pro's which have a notch, which can be queried using the safe area API.
385389 if (@available (macos 12.0 , *)) {
386- const int safeAreaBehavior = [[NSUserDefaults standardUserDefaults ]
387- integerForKey: MMNonNativeFullScreenSafeAreaBehaviorKey];
388-
389- // The safe area utilization is configuration. Right now, we only have two choices.
390- // In the future there may be more, e.g. showing tabs in the safe area.
391- if (safeAreaBehavior == 0 ) {
392- offset = [[self screen ] safeAreaInsets ];
390+ const int safeAreaBehavior = [ud integerForKey: MMNonNativeFullScreenSafeAreaBehaviorKey];
391+
392+ // The safe area utilization is configuration. Right now, we only have two choices:
393+ // - 0: avoid the safe area (default)
394+ // - 1: draw into the safe area, which would cause some contents to be obscured.
395+ // In the future there may be more. E.g. we can draw tabs in the safe area.
396+ // If menu is shown, we ignore this because this doesn't make sense.
397+ if (safeAreaBehavior == 0 || showMenu) {
398+ offset = [self screen ].safeAreaInsets ;
393399 }
394400 }
395401#endif
396402
397- if ([[NSUserDefaults standardUserDefaults ]
398- boolForKey: MMNonNativeFullScreenShowMenuKey]) {
399- const CGFloat menuBarHeight = [[[NSApplication sharedApplication ] mainMenu ] menuBarHeight ];
400- if (menuBarHeight > offset.top ) {
401- offset.top = menuBarHeight;
403+ if (showMenu) {
404+ // Offset by menu height
405+ if (offset.top == 0 ) {
406+ const CGFloat menuBarHeight = [[[NSApplication sharedApplication ] mainMenu ] menuBarHeight ];
407+ if (menuBarHeight > offset.top ) {
408+ offset.top = menuBarHeight;
409+ }
410+ } else {
411+ // Unfortunately, if there is a notch (safe area != 0), menuBarHeight does *not* return
412+ // the menu height shown in the main screen, so we need to calculate it otherwise.
413+ // visibleArea is supposed to give us this information but it's oddly off by one, leading
414+ // to a one-pixel black line, so we need to manually increment it by one. Yes, it sucks.
415+ NSRect visibleFrame = [self screen ].visibleFrame ;
416+ visibleFrame.size .height += 1 ;
417+ const CGFloat menuBarHeight = [self screen ].frame .size .height - NSMaxY (visibleFrame);
418+ if (menuBarHeight > offset.top ) {
419+ offset.top = menuBarHeight;
420+ }
402421 }
403422 }
404423
@@ -482,6 +501,16 @@ - (BOOL)isOnPrimaryScreen
482501 return selfScreenNum == primaryScreenNum;
483502}
484503
504+ // / Returns true when this screen has a dock and menu shown.
505+ // /
506+ // / @note
507+ // / This does not reliably detect whether the dock is on the current screen or
508+ // / not as there is no API to reliably detect this. We are mostly guessing here
509+ // / but if the user sets the dock to display on left/right on a horizontal
510+ // / layout, it may be on the other screen.
511+ // / Also, technically when not using separate spaces, it's possible for the
512+ // / menu to be on one screen and dock on the other.
513+ // / This should be revisited in the future.
485514- (BOOL )screenHasDockAndMenu
486515{
487516 return NSScreen .screensHaveSeparateSpaces || [self isOnPrimaryScreen ];
0 commit comments