Update HUDs to show up betterdisplay

This commit is contained in:
Hariharan Mudaliar 2026-03-03 00:19:51 +05:30
commit cead5f9ce8
No known key found for this signature in database
GPG key ID: 025583EB0BE5640E
7 changed files with 66 additions and 28 deletions

View file

@ -249,8 +249,9 @@ struct ContentView: View {
}
/// Whether the notch/island should hide off-screen when closed on a non-notch display.
/// Temporarily reveals the notch when a sneakPeek HUD (volume, brightness, music, etc.) is active.
private var shouldHideUntilHover: Bool {
hideNonNotchUntilHover && isNonNotchScreen && vm.notchState == .closed
hideNonNotchUntilHover && isNonNotchScreen && vm.notchState == .closed && !coordinator.sneakPeek.show
}
/// Pill shape for Dynamic Island mode with animated corner radius transitions.

View file

@ -212,7 +212,7 @@ struct InlineHUD: View {
.frame(width: 20, height: 15, alignment: .leading)
}
case .brightness:
Image(systemName: BrightnessSymbol(value))
Image(systemName: !icon.isEmpty ? icon : BrightnessSymbol(value))
.contentTransition(.interpolate)
.frame(width: 20, height: 15, alignment: .center)
case .backlight:

View file

@ -205,40 +205,44 @@ final class BetterDisplayManager: ObservableObject {
private func routeOSDToHUD(_ osd: BetterDisplayOSDNotification) {
let category = classifyControlTarget(osd.controlTarget, systemIconID: osd.systemIconID)
let normalizedValue = normalizeValue(osd.value, maxValue: osd.maxValue)
let targetScreen = resolveScreen(for: osd.displayID)
let isExternalDisplay = isExternal(displayID: osd.displayID)
switch category {
case .brightness:
guard Defaults[.enableBrightnessHUD] else { return }
dispatchBrightnessHUD(value: normalizedValue)
let icon = isExternalDisplay ? "display" : nil
dispatchBrightnessHUD(value: normalizedValue, customSymbol: icon, onScreen: targetScreen)
case .volume:
guard Defaults[.enableVolumeHUD] else { return }
let isMuted = osd.controlTarget == "mute" || osd.systemIconID == 4
dispatchVolumeHUD(value: normalizedValue, isMuted: isMuted)
dispatchVolumeHUD(value: normalizedValue, isMuted: isMuted, onScreen: targetScreen)
case .other:
// For unsupported control targets (contrast, gamma, temperature, etc.),
// show a generic brightness-style HUD if the user has brightness HUD enabled
guard Defaults[.enableBrightnessHUD] else { return }
dispatchBrightnessHUD(value: normalizedValue, customSymbol: osd.customSymbol)
let icon = isExternalDisplay ? "display" : osd.customSymbol
dispatchBrightnessHUD(value: normalizedValue, customSymbol: icon, onScreen: targetScreen)
}
}
// MARK: - HUD Dispatch (mirrors SystemChangesObserver logic)
private func dispatchVolumeHUD(value: CGFloat, isMuted: Bool) {
private func dispatchVolumeHUD(value: CGFloat, isMuted: Bool, onScreen targetScreen: NSScreen? = nil) {
if HUDSuppressionCoordinator.shared.shouldSuppressVolumeHUD { return }
if Defaults[.enableCircularHUD] {
CircularHUDWindowManager.shared.show(type: .volume, value: value)
CircularHUDWindowManager.shared.show(type: .volume, value: value, onScreen: targetScreen)
return
}
if Defaults[.enableVerticalHUD] {
VerticalHUDWindowManager.shared.show(type: .volume, value: value, icon: "")
VerticalHUDWindowManager.shared.show(type: .volume, value: value, icon: "", onScreen: targetScreen)
return
}
if Defaults[.enableCustomOSD] && Defaults[.enableOSDVolume] {
CustomOSDWindowManager.shared.showVolume(value: value)
CustomOSDWindowManager.shared.showVolume(value: value, onScreen: targetScreen)
}
if Defaults[.enableSystemHUD] && !Defaults[.enableCustomOSD] && !Defaults[.enableVerticalHUD] && !Defaults[.enableCircularHUD] {
coordinator?.toggleSneakPeek(
@ -250,30 +254,49 @@ final class BetterDisplayManager: ObservableObject {
}
}
private func dispatchBrightnessHUD(value: CGFloat, customSymbol: String? = nil) {
private func dispatchBrightnessHUD(value: CGFloat, customSymbol: String? = nil, onScreen targetScreen: NSScreen? = nil) {
let icon = customSymbol ?? ""
if Defaults[.enableCircularHUD] {
CircularHUDWindowManager.shared.show(type: .brightness, value: value)
CircularHUDWindowManager.shared.show(type: .brightness, value: value, icon: icon, onScreen: targetScreen)
return
}
if Defaults[.enableVerticalHUD] {
VerticalHUDWindowManager.shared.show(type: .brightness, value: value)
VerticalHUDWindowManager.shared.show(type: .brightness, value: value, icon: icon, onScreen: targetScreen)
return
}
if Defaults[.enableCustomOSD] && Defaults[.enableOSDBrightness] {
CustomOSDWindowManager.shared.showBrightness(value: value)
CustomOSDWindowManager.shared.showBrightness(value: value, icon: icon, onScreen: targetScreen)
}
if Defaults[.enableSystemHUD] && !Defaults[.enableCustomOSD] && !Defaults[.enableVerticalHUD] && !Defaults[.enableCircularHUD] {
coordinator?.toggleSneakPeek(
status: true,
type: .brightness,
value: value,
icon: ""
icon: icon
)
}
}
// MARK: - Helpers
/// Resolve a BetterDisplay `displayID` (CGDirectDisplayID) to the matching NSScreen, if any.
private func resolveScreen(for displayID: Int?) -> NSScreen? {
guard let displayID else { return nil }
let target = UInt32(displayID)
return NSScreen.screens.first { screen in
guard let screenNumber = screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber else {
return false
}
return screenNumber.uint32Value == target
}
}
/// Whether the given displayID refers to an external (non-built-in) display.
private func isExternal(displayID: Int?) -> Bool {
guard let displayID else { return false }
return CGDisplayIsBuiltin(UInt32(displayID)) == 0
}
private func classifyControlTarget(_ target: String?, systemIconID: Int?) -> BetterDisplayControlCategory {
if let target {
if brightnessControlTargets.contains(target) { return .brightness }

View file

@ -66,13 +66,13 @@ final class CircularHUDWindowManager {
}
}
func show(type: SneakContentType, value: CGFloat, icon: String = "") {
func show(type: SneakContentType, value: CGFloat, icon: String = "", onScreen targetScreen: NSScreen? = nil) {
guard Defaults[.enableCircularHUD] else { return }
let screens = NSScreen.screens
let screens = targetScreen.map { [$0] } ?? NSScreen.screens
guard !screens.isEmpty else { return }
// Show on all screens
// Show on target screen(s)
for screen in screens {
let windowContext = ensureWindow(for: type, screen: screen)
updateContent(window: windowContext, type: type, value: value, icon: icon)

View file

@ -46,14 +46,14 @@ final class CustomOSDWindowManager {
// MARK: - Public API
func showVolume(value: CGFloat, isMuted: Bool = false, icon: String = "") {
func showVolume(value: CGFloat, isMuted: Bool = false, icon: String = "", onScreen targetScreen: NSScreen? = nil) {
guard Defaults[.enableCustomOSD], isInitialized else { return }
show(type: .volume, value: value, icon: icon)
show(type: .volume, value: value, icon: icon, onScreen: targetScreen)
}
func showBrightness(value: CGFloat) {
func showBrightness(value: CGFloat, icon: String = "", onScreen targetScreen: NSScreen? = nil) {
guard Defaults[.enableCustomOSD], isInitialized else { return }
show(type: .brightness, value: value, icon: "")
show(type: .brightness, value: value, icon: icon, onScreen: targetScreen)
}
func showBacklight(value: CGFloat) {
@ -67,14 +67,14 @@ final class CustomOSDWindowManager {
// MARK: - Private Implementation
private func show(type: SneakContentType, value: CGFloat, icon: String) {
let screens = NSScreen.screens
private func show(type: SneakContentType, value: CGFloat, icon: String, onScreen targetScreen: NSScreen? = nil) {
let screens = targetScreen.map { [$0] } ?? NSScreen.screens
guard !screens.isEmpty else { return }
// Close other windows first
hideAllWindowsExcept(type: type)
// Show on all screens
// Show on target screen(s)
for screen in screens {
let window = ensureWindow(for: type, screen: screen)
updateContent(window: window, type: type, value: value, icon: icon)

View file

@ -174,6 +174,14 @@ class SystemHUDManager {
keyboardBacklightEnabled: change.newValue
)
}.store(in: &cancellables)
// When BetterDisplay integration toggled, restart observer to update Cmd+Brightness key interception
Defaults.publisher(.enableBetterDisplayIntegration, options: []).sink { [weak self] _ in
guard let self = self, self.isSetupComplete else { return }
Task { @MainActor in
await self.startSystemObserver()
}
}.store(in: &cancellables)
}
private var cancellables = Set<AnyCancellable>()
@ -218,7 +226,7 @@ class SystemHUDManager {
// Determine which controls to enable based on HUD or OSD mode
let volumeEnabled: Bool
let brightnessEnabled: Bool
let keyboardBacklightEnabled: Bool
var keyboardBacklightEnabled: Bool
if Defaults[.enableCircularHUD] || Defaults[.enableVerticalHUD] {
// Respect per-control toggles so the system HUD can handle disabled events
@ -234,6 +242,12 @@ class SystemHUDManager {
brightnessEnabled = Defaults[.enableBrightnessHUD]
keyboardBacklightEnabled = Defaults[.enableKeyboardBacklightHUD]
}
// When BetterDisplay integration is on, disable Cmd+Brightness key interception
// because BetterDisplay uses Cmd+F1/F2 for its own display controls.
if Defaults[.enableBetterDisplayIntegration] {
keyboardBacklightEnabled = false
}
changesObserver?.startObserving(
volumeEnabled: volumeEnabled,

View file

@ -136,13 +136,13 @@ final class VerticalHUDWindowManager {
windows.removeAll()
}
func show(type: SneakContentType, value: CGFloat, icon: String = "") {
func show(type: SneakContentType, value: CGFloat, icon: String = "", onScreen targetScreen: NSScreen? = nil) {
guard Defaults[.enableVerticalHUD] else { return }
let screens = NSScreen.screens
let screens = targetScreen.map { [$0] } ?? NSScreen.screens
guard !screens.isEmpty else { return }
// Show on all screens
// Show on target screen(s)
for screen in screens {
let windowContext = ensureWindow(for: type, screen: screen)
updateContent(window: windowContext, type: type, value: value, icon: icon)