mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Update HUDs to show up betterdisplay
This commit is contained in:
parent
dd726d6401
commit
cead5f9ce8
7 changed files with 66 additions and 28 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue