diff --git a/SlimHUD.xcodeproj/xcshareddata/xcschemes/SlimHUD.xcscheme b/SlimHUD.xcodeproj/xcshareddata/xcschemes/SlimHUD.xcscheme index 330fb6e9..55822202 100644 --- a/SlimHUD.xcodeproj/xcshareddata/xcschemes/SlimHUD.xcscheme +++ b/SlimHUD.xcodeproj/xcshareddata/xcschemes/SlimHUD.xcscheme @@ -99,7 +99,7 @@ + isEnabled = "NO"> diff --git a/SlimHUD/Services/DisplayManager.swift b/SlimHUD/Services/DisplayManager.swift index 488a02be..bdddeace 100644 --- a/SlimHUD/Services/DisplayManager.swift +++ b/SlimHUD/Services/DisplayManager.swift @@ -7,6 +7,7 @@ import Foundation import Cocoa +import CoreGraphics class DisplayManager { private init() {} @@ -71,6 +72,41 @@ class DisplayManager { throw SensorError.Display.notSilicon } + static func isInternalDisplay(_ screen: NSScreen) -> Bool { + // Retrieve the screen's display ID + guard let screenNumber = screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID else { + return false + } + + // Use CoreGraphics API to check if the display is built-in + let isBuiltIn = CGDisplayIsBuiltin(screenNumber) != 0 + return isBuiltIn + } + + /* https://github.com/AlexPerathoner/SlimHUD/issues/145 + Used to check if the internal screen + */ + static func hasNotch() -> Bool { + guard let mainScreen = NSScreen.main else { + return false + } + // todo multiple monitors: will have to deal with following situation + // slimhud should appear on internal screen with notch, but main screen is external one + if !isInternalDisplay(mainScreen) { + // for now, if not the focus is not on the internal display, + + } + + // Get the safe area insets of the main screen + if #available(macOS 12.0, *) { + let safeAreaInsets = mainScreen.safeAreaInsets + // A device with a notch will have non-zero safe area insets at the top + return safeAreaInsets.top > 0 + } else { + return false + } + } + /* Note the difference between NSScreen.main and NSScreen.screens[0]: * NSScreen.main is the "key" screen, where the currently frontmost window resides. * NSScreen.screens[0] is the screen which has a menu bar, and is chosen in the Preferences > monitor settings @@ -87,7 +123,7 @@ class DisplayManager { return getZeroScreen().visibleFrame } - static func getMenuBarThickness() -> CGFloat { + static func getMenuBarVisibleThickness() -> CGFloat { let screenFrame = getScreenFrame() let visibleFrame = getVisibleScreenFrame() var menuBarThickness: CGFloat = 0 @@ -97,6 +133,29 @@ class DisplayManager { return menuBarThickness } + static func getNotchThickness() -> CGFloat { + // todo duplicated code from hasNotch() - refactor when solving multiple monitors + guard let mainScreen = NSScreen.main else { + return 0 + } + // todo multiple monitors: will have to deal with following situation + // slimhud should appear on internal screen with notch, but main screen is external one + if !isInternalDisplay(mainScreen) { + // for now, if not the focus is not on the internal display, + + } + + // Get the safe area insets of the main screen + if #available(macOS 12.0, *) { + let safeAreaInsets = mainScreen.safeAreaInsets + if safeAreaInsets.top == 0 { + return 0 + } + return safeAreaInsets.top + } + return 0 + } + static func getDockHeight() -> (xDockHeight: CGFloat, yDockHeight: CGFloat) { let screenFrame = getScreenFrame() let visibleFrame = getVisibleScreenFrame() diff --git a/SlimHUD/Services/PositionManager.swift b/SlimHUD/Services/PositionManager.swift index b6671946..1e861c39 100644 --- a/SlimHUD/Services/PositionManager.swift +++ b/SlimHUD/Services/PositionManager.swift @@ -48,7 +48,7 @@ class PositionManager { setBarsOrientation(isHorizontal: isHudHorizontal) setHudsPosition(originPosition: originPosition, screenEdge: screenEdge) - NSLog("screenFrame is \(screenFrame) \(originPosition)") + NSLog("screenFrame is \(screenFrame).\n Origin of hud: \(originPosition).\n Notch present: \(DisplayManager.hasNotch())") } static func calculateHUDsOriginPosition(hudPosition: Position, dockPosition: Position, @@ -67,8 +67,22 @@ class PositionManager { position = CGPoint(x: (screenFrame.width/2) - (barViewFrame.height/2), y: yDockHeight + barViewFrame.width) case .top: + var paddingFromTop: CGFloat = 0 + if DisplayManager.hasNotch() { + paddingFromTop = DisplayManager.getNotchThickness() + } else { + if !isInFullscreen { + paddingFromTop = DisplayManager.getMenuBarVisibleThickness() + } + } + #if DEBUG + print("is full scren \(isInFullscreen)") + print("Has notch: \(DisplayManager.hasNotch())") + print("Padding from top: \(paddingFromTop)") + print("Position calculation: screenFrame.height \(screenFrame.height) - pad \(paddingFromTop)") + #endif position = CGPoint(x: (screenFrame.width/2) - (barViewFrame.height/2), - y: screenFrame.height - (isInFullscreen ? 0 : DisplayManager.getMenuBarThickness())) + y: screenFrame.height - paddingFromTop) } return position }