From a62de8fbe868a06d34227b9d9e04bfec7f00348b Mon Sep 17 00:00:00 2001 From: Hariharan Mudaliar Date: Sun, 30 Nov 2025 15:50:44 +0530 Subject: [PATCH 1/2] Add keyboard backlight adjustment --- .../managers/KeyboardBrightnessSensor.swift | 190 ++++++++++++++++++ .../managers/MediaKeyInterceptor.swift | 51 +++-- .../managers/SystemChangesObserver.swift | 72 ++++++- DynamicIsland/managers/SystemHUDManager.swift | 24 ++- .../SystemKeyboardBacklightController.swift | 66 ++++++ 5 files changed, 379 insertions(+), 24 deletions(-) create mode 100644 DynamicIsland/managers/KeyboardBrightnessSensor.swift create mode 100644 DynamicIsland/managers/SystemKeyboardBacklightController.swift diff --git a/DynamicIsland/managers/KeyboardBrightnessSensor.swift b/DynamicIsland/managers/KeyboardBrightnessSensor.swift new file mode 100644 index 0000000..ad40354 --- /dev/null +++ b/DynamicIsland/managers/KeyboardBrightnessSensor.swift @@ -0,0 +1,190 @@ +// +// KeyboardBrightnessSensor.swift +// DynamicIsland +// +// Copied from TheBoringWorker-HUD `KeyboardManager.swift` and adapted for Atoll. +// + +import Foundation +import IOKit +import IOKit.hid +import ObjectiveC.runtime + +final class KeyboardBrightnessSensor { + private init() {} + + private static let maxKeyboardBrightness: Float = 342 + private static let coreBrightnessClient = CoreBrightnessClient() + private static var method = SensorMethod.standard + + static func currentLevel() throws -> Float { + if let client = coreBrightnessClient, let value = client.currentBrightness() { + return clamp(value) + } + switch method { + case .standard: + do { + return normalizedValue(fromRaw: try readStandardRawLevel()) + } catch { + method = .m1 + } + case .m1: + do { + return normalizedValue(fromRaw: try readM1RawLevel()) + } catch { + method = .allFailed + } + case .allFailed: + throw SensorError.Keyboard.notFound + } + return try currentLevel() + } + + static func setLevel(_ level: Float) throws { + let clamped = max(0, min(1, level)) + if let client = coreBrightnessClient, client.setBrightness(clamped) { + return + } + let raw = rawValue(fromNormalized: clamped) + do { + try writeStandard(rawLevel: raw) + } catch { + method = .m1 + throw error + } + } + + private static func clamp(_ value: Float) -> Float { + max(0, min(1, value)) + } + + private static func normalizedValue(fromRaw rawLevel: Float) -> Float { + let clamped = max(0, min(1, rawLevel)) + if clamped <= 0.07 { + return 0 + } + let value = log10(clamped + 0.03) + 1 + return max(0, min(1, value)) + } + + private static func rawValue(fromNormalized normalized: Float) -> Float { + guard normalized > 0 else { return 0 } + let powValue = powf(10, normalized - 1) - 0.03 + return max(0, min(1, powValue)) + } + + private static func readStandardRawLevel() throws -> Float { + let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleHIDKeyboardEventDriverV2")) + guard service != 0 else { + throw SensorError.Keyboard.notStandard + } + defer { IOObjectRelease(service) } + + guard let property: CFTypeRef = IORegistryEntryCreateCFProperty( + service, + "KeyboardBacklightBrightness" as CFString, + kCFAllocatorDefault, + 0 + )?.takeUnretainedValue() else { + throw SensorError.Keyboard.notStandard + } + if CFGetTypeID(property) == CFNumberGetTypeID() { + var rawValue: Float = 0 + if CFNumberGetValue(property as! CFNumber, .floatType, &rawValue) { + return rawValue / maxKeyboardBrightness + } + } + throw SensorError.Keyboard.notStandard + } + + private static func readM1RawLevel() throws -> Float { + let task = Process() + task.launchPath = "/usr/libexec/corebrightnessdiag" + task.arguments = ["status-info"] + let pipe = Pipe() + task.standardOutput = pipe + try task.run() + let data = pipe.fileHandleForReading.readDataToEndOfFile() + task.waitUntilExit() + + if let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? NSDictionary, + let keyboards = plist["CBKeyboards"] as? [String: [String: Any]] { + for keyboard in keyboards.values { + if let backlightInfo = keyboard["CBKeyboardBacklightContainer"] as? [String: Any], + backlightInfo["KeyboardBacklightBuiltIn"] as? Bool == true, + let brightness = backlightInfo["KeyboardBacklightBrightness"] as? Float { + return brightness + } + } + } + + throw SensorError.Keyboard.notSilicon + } + + private static func writeStandard(rawLevel: Float) throws { + let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleHIDKeyboardEventDriverV2")) + guard service != 0 else { + throw SensorError.Keyboard.notStandard + } + defer { IOObjectRelease(service) } + + var scaled = rawLevel * maxKeyboardBrightness + guard let number = CFNumberCreate(kCFAllocatorDefault, .floatType, &scaled) else { + throw SensorError.Keyboard.notStandard + } + let status = IORegistryEntrySetCFProperty(service, "KeyboardBacklightBrightness" as CFString, number) + if status != KERN_SUCCESS { + throw SensorError.Keyboard.notStandard + } + } +} + +// MARK: - CoreBrightness bridge +private final class CoreBrightnessClient { + private static let keyboardID: UInt64 = 1 + private var clientInstance: NSObject? + private let getSelector = NSSelectorFromString("brightnessForKeyboard:") + private let setSelector = NSSelectorFromString("setBrightness:forKeyboard:") + + init?() { + var loaded = false + let bundlePaths = [ + "/System/Library/PrivateFrameworks/CoreBrightness.framework", + "/System/Library/PrivateFrameworks/CoreBrightness.framework/CoreBrightness" + ] + for path in bundlePaths where !loaded { + if let bundle = Bundle(path: path) { + loaded = bundle.load() + } + } + guard loaded, let cls = NSClassFromString("KeyboardBrightnessClient") as? NSObject.Type else { + return nil + } + clientInstance = cls.init() + } + + func currentBrightness() -> Float? { + guard let clientInstance, + let getter: BrightnessGetter = methodIMP(on: clientInstance, selector: getSelector, as: BrightnessGetter.self) + else { return nil } + return getter(clientInstance, getSelector, Self.keyboardID) + } + + func setBrightness(_ value: Float) -> Bool { + guard let clientInstance, + let setter: BrightnessSetter = methodIMP(on: clientInstance, selector: setSelector, as: BrightnessSetter.self) + else { return false } + return setter(clientInstance, setSelector, value, Self.keyboardID).boolValue + } + + private typealias BrightnessGetter = @convention(c) (NSObject, Selector, UInt64) -> Float + private typealias BrightnessSetter = @convention(c) (NSObject, Selector, Float, UInt64) -> ObjCBool + + private func methodIMP(on object: NSObject, selector: Selector, as type: T.Type) -> T? { + guard let cls = object_getClass(object), + let method = class_getInstanceMethod(cls, selector) + else { return nil } + let imp = method_getImplementation(method) + return unsafeBitCast(imp, to: T.self) + } +} diff --git a/DynamicIsland/managers/MediaKeyInterceptor.swift b/DynamicIsland/managers/MediaKeyInterceptor.swift index 2c118f0..d1020db 100644 --- a/DynamicIsland/managers/MediaKeyInterceptor.swift +++ b/DynamicIsland/managers/MediaKeyInterceptor.swift @@ -25,13 +25,30 @@ enum MediaKeyStep { struct MediaKeyConfiguration { var interceptVolume: Bool var interceptBrightness: Bool + var interceptCommandModifiedBrightness: Bool - static let disabled = MediaKeyConfiguration(interceptVolume: false, interceptBrightness: false) + static let disabled = MediaKeyConfiguration( + interceptVolume: false, + interceptBrightness: false, + interceptCommandModifiedBrightness: false + ) } protocol MediaKeyInterceptorDelegate: AnyObject { - func mediaKeyInterceptor(_ interceptor: MediaKeyInterceptor, didReceiveVolumeCommand direction: MediaKeyDirection, step: MediaKeyStep, isRepeat: Bool) - func mediaKeyInterceptor(_ interceptor: MediaKeyInterceptor, didReceiveBrightnessCommand direction: MediaKeyDirection, step: MediaKeyStep, isRepeat: Bool) + func mediaKeyInterceptor( + _ interceptor: MediaKeyInterceptor, + didReceiveVolumeCommand direction: MediaKeyDirection, + step: MediaKeyStep, + isRepeat: Bool, + modifiers: NSEvent.ModifierFlags + ) + func mediaKeyInterceptor( + _ interceptor: MediaKeyInterceptor, + didReceiveBrightnessCommand direction: MediaKeyDirection, + step: MediaKeyStep, + isRepeat: Bool, + modifiers: NSEvent.ModifierFlags + ) func mediaKeyInterceptorDidToggleMute(_ interceptor: MediaKeyInterceptor) } @@ -129,7 +146,7 @@ final class MediaKeyInterceptor { private func updateTapState() { guard let tap = eventTap else { return } - let shouldEnable = configuration.interceptVolume || configuration.interceptBrightness + let shouldEnable = configuration.interceptVolume || configuration.interceptBrightness || configuration.interceptCommandModifiedBrightness if shouldEnable != isTapEnabled { CGEvent.tapEnable(tap: tap, enable: shouldEnable) isTapEnabled = shouldEnable @@ -150,10 +167,11 @@ final class MediaKeyInterceptor { let keyState = ((keyFlags & 0xFF00) >> 8) == 0xA // 0xA = keyDown, 0xB = keyUp let isRepeat = (keyFlags & 0x0001) == 1 let step = step(for: nsEvent) + let modifiers = nsEvent.modifierFlags guard keyState else { // Swallow key-up events only when intercepting, otherwise let them pass through - if shouldHandle(keyCode: Int32(keyCode)) { + if shouldHandle(keyCode: Int32(keyCode), modifiers: modifiers) { return nil } return Unmanaged.passUnretained(cgEvent) @@ -162,40 +180,47 @@ final class MediaKeyInterceptor { switch Int32(keyCode) { case NX_KEYTYPE_SOUND_UP: guard configuration.interceptVolume else { return Unmanaged.passUnretained(cgEvent) } - delegate?.mediaKeyInterceptor(self, didReceiveVolumeCommand: .up, step: step, isRepeat: isRepeat) + delegate?.mediaKeyInterceptor(self, didReceiveVolumeCommand: .up, step: step, isRepeat: isRepeat, modifiers: modifiers) return nil case NX_KEYTYPE_SOUND_DOWN: guard configuration.interceptVolume else { return Unmanaged.passUnretained(cgEvent) } - delegate?.mediaKeyInterceptor(self, didReceiveVolumeCommand: .down, step: step, isRepeat: isRepeat) + delegate?.mediaKeyInterceptor(self, didReceiveVolumeCommand: .down, step: step, isRepeat: isRepeat, modifiers: modifiers) return nil case NX_KEYTYPE_MUTE: guard configuration.interceptVolume else { return Unmanaged.passUnretained(cgEvent) } delegate?.mediaKeyInterceptorDidToggleMute(self) return nil case NX_KEYTYPE_BRIGHTNESS_UP: - guard configuration.interceptBrightness else { return Unmanaged.passUnretained(cgEvent) } - delegate?.mediaKeyInterceptor(self, didReceiveBrightnessCommand: .up, step: step, isRepeat: isRepeat) + guard shouldHandleBrightness(modifiers: modifiers) else { return Unmanaged.passUnretained(cgEvent) } + delegate?.mediaKeyInterceptor(self, didReceiveBrightnessCommand: .up, step: step, isRepeat: isRepeat, modifiers: modifiers) return nil case NX_KEYTYPE_BRIGHTNESS_DOWN: - guard configuration.interceptBrightness else { return Unmanaged.passUnretained(cgEvent) } - delegate?.mediaKeyInterceptor(self, didReceiveBrightnessCommand: .down, step: step, isRepeat: isRepeat) + guard shouldHandleBrightness(modifiers: modifiers) else { return Unmanaged.passUnretained(cgEvent) } + delegate?.mediaKeyInterceptor(self, didReceiveBrightnessCommand: .down, step: step, isRepeat: isRepeat, modifiers: modifiers) return nil default: return Unmanaged.passUnretained(cgEvent) } } - private func shouldHandle(keyCode: Int32) -> Bool { + private func shouldHandle(keyCode: Int32, modifiers: NSEvent.ModifierFlags) -> Bool { switch keyCode { case NX_KEYTYPE_SOUND_UP, NX_KEYTYPE_SOUND_DOWN, NX_KEYTYPE_MUTE: return configuration.interceptVolume case NX_KEYTYPE_BRIGHTNESS_UP, NX_KEYTYPE_BRIGHTNESS_DOWN: - return configuration.interceptBrightness + return configuration.interceptBrightness || (configuration.interceptCommandModifiedBrightness && modifiers.contains(.command)) default: return false } } + private func shouldHandleBrightness(modifiers: NSEvent.ModifierFlags) -> Bool { + if configuration.interceptBrightness { + return true + } + return configuration.interceptCommandModifiedBrightness && modifiers.contains(.command) + } + private func step(for event: NSEvent) -> MediaKeyStep { let modifiers = event.modifierFlags if modifiers.contains(.option) && modifiers.contains(.shift) { diff --git a/DynamicIsland/managers/SystemChangesObserver.swift b/DynamicIsland/managers/SystemChangesObserver.swift index 644ce54..4fab402 100644 --- a/DynamicIsland/managers/SystemChangesObserver.swift +++ b/DynamicIsland/managers/SystemChangesObserver.swift @@ -1,11 +1,13 @@ import Foundation import CoreGraphics import Defaults +import AppKit final class SystemChangesObserver: MediaKeyInterceptorDelegate { private weak var coordinator: DynamicIslandViewCoordinator? private let volumeController = SystemVolumeController.shared private let brightnessController = SystemBrightnessController.shared + private let keyboardBacklightController = SystemKeyboardBacklightController.shared private let mediaKeyInterceptor = MediaKeyInterceptor.shared private let standardVolumeStep: Float = 1.0 / 16.0 @@ -14,14 +16,16 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { private var volumeEnabled = false private var brightnessEnabled = false + private var keyboardBacklightEnabled = false init(coordinator: DynamicIslandViewCoordinator) { self.coordinator = coordinator } - func startObserving(volumeEnabled: Bool, brightnessEnabled: Bool) { + func startObserving(volumeEnabled: Bool, brightnessEnabled: Bool, keyboardBacklightEnabled: Bool) { self.volumeEnabled = volumeEnabled self.brightnessEnabled = brightnessEnabled + self.keyboardBacklightEnabled = keyboardBacklightEnabled volumeController.onVolumeChange = { [weak self] volume, muted in guard let self, self.volumeEnabled else { return } @@ -40,6 +44,11 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { } brightnessController.start() + configureKeyboardBacklightCallback() + if keyboardBacklightEnabled { + keyboardBacklightController.start() + } + mediaKeyInterceptor.delegate = self let tapStarted = mediaKeyInterceptor.start() if !tapStarted { @@ -47,16 +56,35 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { } mediaKeyInterceptor.configuration = MediaKeyConfiguration( interceptVolume: volumeEnabled, - interceptBrightness: brightnessEnabled + interceptBrightness: brightnessEnabled, + interceptCommandModifiedBrightness: keyboardBacklightEnabled ) } - func update(volumeEnabled: Bool, brightnessEnabled: Bool) { + func update(volumeEnabled: Bool, brightnessEnabled: Bool, keyboardBacklightEnabled: Bool) { self.volumeEnabled = volumeEnabled self.brightnessEnabled = brightnessEnabled + let backlightStateChanged = self.keyboardBacklightEnabled != keyboardBacklightEnabled + self.keyboardBacklightEnabled = keyboardBacklightEnabled + + if keyboardBacklightEnabled { + configureKeyboardBacklightCallback() + } else { + keyboardBacklightController.onBacklightChange = nil + } + + if backlightStateChanged { + if keyboardBacklightEnabled { + keyboardBacklightController.start() + } else { + keyboardBacklightController.stop() + } + } + mediaKeyInterceptor.configuration = MediaKeyConfiguration( interceptVolume: volumeEnabled, - interceptBrightness: brightnessEnabled + interceptBrightness: brightnessEnabled, + interceptCommandModifiedBrightness: keyboardBacklightEnabled ) } @@ -70,6 +98,9 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { brightnessController.stop() brightnessController.onBrightnessChange = nil + + keyboardBacklightController.stop() + keyboardBacklightController.onBacklightChange = nil } // MARK: - MediaKeyInterceptorDelegate @@ -78,7 +109,8 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { _ interceptor: MediaKeyInterceptor, didReceiveVolumeCommand direction: MediaKeyDirection, step: MediaKeyStep, - isRepeat: Bool + isRepeat: Bool, + modifiers: NSEvent.ModifierFlags ) { guard volumeEnabled else { return } let baseStep = stepSize(for: step, base: standardVolumeStep) @@ -95,12 +127,16 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { _ interceptor: MediaKeyInterceptor, didReceiveBrightnessCommand direction: MediaKeyDirection, step: MediaKeyStep, - isRepeat: Bool + isRepeat: Bool, + modifiers: NSEvent.ModifierFlags ) { - guard brightnessEnabled else { return } let baseStep = stepSize(for: step, base: standardBrightnessStep) let delta = direction == .up ? baseStep : -baseStep - brightnessController.adjust(by: delta) + if modifiers.contains(.command) && keyboardBacklightEnabled { + keyboardBacklightController.adjust(by: delta) + } else if brightnessEnabled { + brightnessController.adjust(by: delta) + } } // MARK: - HUD Dispatch @@ -125,6 +161,26 @@ final class SystemChangesObserver: MediaKeyInterceptorDelegate { icon: "" ) } + + private func sendKeyboardBacklightNotification(value: Float) { + coordinator?.toggleSneakPeek( + status: true, + type: .backlight, + value: CGFloat(value), + icon: "" + ) + } + + private func configureKeyboardBacklightCallback() { + if keyboardBacklightEnabled { + keyboardBacklightController.onBacklightChange = { [weak self] value in + guard let self, self.keyboardBacklightEnabled else { return } + self.sendKeyboardBacklightNotification(value: value) + } + } else { + keyboardBacklightController.onBacklightChange = nil + } + } } private extension SystemChangesObserver { diff --git a/DynamicIsland/managers/SystemHUDManager.swift b/DynamicIsland/managers/SystemHUDManager.swift index dc64d38..e22626d 100644 --- a/DynamicIsland/managers/SystemHUDManager.swift +++ b/DynamicIsland/managers/SystemHUDManager.swift @@ -44,7 +44,8 @@ class SystemHUDManager { } self.changesObserver?.update( volumeEnabled: change.newValue, - brightnessEnabled: Defaults[.enableBrightnessHUD] + brightnessEnabled: Defaults[.enableBrightnessHUD], + keyboardBacklightEnabled: Defaults[.enableKeyboardBacklightHUD] ) }.store(in: &cancellables) @@ -54,7 +55,19 @@ class SystemHUDManager { } self.changesObserver?.update( volumeEnabled: Defaults[.enableVolumeHUD], - brightnessEnabled: change.newValue + brightnessEnabled: change.newValue, + keyboardBacklightEnabled: Defaults[.enableKeyboardBacklightHUD] + ) + }.store(in: &cancellables) + + Defaults.publisher(.enableKeyboardBacklightHUD, options: []).sink { [weak self] change in + guard let self = self, self.isSetupComplete, Defaults[.enableSystemHUD] else { + return + } + self.changesObserver?.update( + volumeEnabled: Defaults[.enableVolumeHUD], + brightnessEnabled: Defaults[.enableBrightnessHUD], + keyboardBacklightEnabled: change.newValue ) }.store(in: &cancellables) } @@ -89,7 +102,12 @@ class SystemHUDManager { changesObserver = SystemChangesObserver(coordinator: coordinator) let volumeEnabled = Defaults[.enableVolumeHUD] let brightnessEnabled = Defaults[.enableBrightnessHUD] - changesObserver?.startObserving(volumeEnabled: volumeEnabled, brightnessEnabled: brightnessEnabled) + let keyboardBacklightEnabled = Defaults[.enableKeyboardBacklightHUD] + changesObserver?.startObserving( + volumeEnabled: volumeEnabled, + brightnessEnabled: brightnessEnabled, + keyboardBacklightEnabled: keyboardBacklightEnabled + ) print("System HUD replacement started") isSystemOperationInProgress = false diff --git a/DynamicIsland/managers/SystemKeyboardBacklightController.swift b/DynamicIsland/managers/SystemKeyboardBacklightController.swift new file mode 100644 index 0000000..7163e01 --- /dev/null +++ b/DynamicIsland/managers/SystemKeyboardBacklightController.swift @@ -0,0 +1,66 @@ +import Foundation + +extension Notification.Name { + static let keyboardBacklightDidChange = Notification.Name("DynamicIsland.keyboardBacklightDidChange") +} + +final class SystemKeyboardBacklightController { + static let shared = SystemKeyboardBacklightController() + + var onBacklightChange: ((Float) -> Void)? + + private let workerQueue = DispatchQueue(label: "com.atoll.keyboardBacklight", qos: .userInitiated) + private let notificationCenter = NotificationCenter.default + private var isRunning = false + + private init() {} + + func start() { + guard !isRunning else { return } + isRunning = true + notifyCurrentLevel() + } + + func stop() { + guard isRunning else { return } + isRunning = false + } + + func adjust(by delta: Float) { + let target = currentLevel + delta + setLevel(target) + } + + func setLevel(_ value: Float) { + let clamped = max(0, min(1, value)) + workerQueue.async { + do { + try KeyboardBrightnessSensor.setLevel(clamped) + let level = (try? KeyboardBrightnessSensor.currentLevel()) ?? clamped + self.emitChange(level: level) + } catch { + NSLog("⚠️ Failed to set keyboard backlight: \(error)") + } + } + } + + var currentLevel: Float { + (try? KeyboardBrightnessSensor.currentLevel()) ?? 0 + } + + private func notifyCurrentLevel() { + workerQueue.async { + let level = (try? KeyboardBrightnessSensor.currentLevel()) ?? 0 + self.emitChange(level: level) + } + } + + private func emitChange(level: Float) { + guard isRunning else { return } + DispatchQueue.main.async { [weak self] in + guard let self, self.isRunning else { return } + self.onBacklightChange?(level) + self.notificationCenter.post(name: .keyboardBacklightDidChange, object: nil, userInfo: ["value": level]) + } + } +} From 5be3b9a80efb95d00d206105e2757e671e8c51a9 Mon Sep 17 00:00:00 2001 From: Hariharan Mudaliar Date: Sun, 30 Nov 2025 16:00:20 +0530 Subject: [PATCH 2/2] Replace Backlight Icons --- DynamicIsland/components/Live activities/InlineHUD.swift | 9 ++++++++- .../Live activities/SystemEventIndicatorModifier.swift | 6 +++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/DynamicIsland/components/Live activities/InlineHUD.swift b/DynamicIsland/components/Live activities/InlineHUD.swift index cbe5660..5e075c4 100644 --- a/DynamicIsland/components/Live activities/InlineHUD.swift +++ b/DynamicIsland/components/Live activities/InlineHUD.swift @@ -109,7 +109,7 @@ struct InlineHUD: View { .contentTransition(.interpolate) .frame(width: 20, height: 15, alignment: .center) case .backlight: - Image(systemName: "keyboard") + Image(systemName: BacklightSymbol(value)) .contentTransition(.interpolate) .frame(width: 20, height: 15, alignment: .center) case .mic: @@ -353,6 +353,13 @@ struct InlineHUD: View { return "sun.min" } } + + func BacklightSymbol(_ value: CGFloat) -> String { + if value >= 0.5 { + return "light.max" + } + return "light.min" + } func Type2Name(_ type: SneakContentType) -> String { switch(type) { diff --git a/DynamicIsland/components/Live activities/SystemEventIndicatorModifier.swift b/DynamicIsland/components/Live activities/SystemEventIndicatorModifier.swift index 97cceab..a7b93a5 100644 --- a/DynamicIsland/components/Live activities/SystemEventIndicatorModifier.swift +++ b/DynamicIsland/components/Live activities/SystemEventIndicatorModifier.swift @@ -46,7 +46,7 @@ struct SystemEventIndicatorModifier: View { .frame(width: 20, height: 15) .foregroundStyle(.white) case .backlight: - Image(systemName: "keyboard") + Image(systemName: BacklightSymbol(value)) .contentTransition(.symbolEffect) .frame(width: 20, height: 15) .foregroundStyle(.white) @@ -95,6 +95,10 @@ struct SystemEventIndicatorModifier: View { return "speaker.wave.2" } } + + func BacklightSymbol(_ value: CGFloat) -> String { + value >= 0.5 ? "light.max" : "light.min" + } } struct ProgressSection: View {