import AppKit import IOKit // Gibt es einen benutzbaren Weg, die Bildschirmhelligkeit zu *lesen* — und // besser noch: auf ihre Änderung zu *hören*? // // Öffentlich gibt es keinen. Geprüft werden deshalb drei private bzw. // halböffentliche Wege, jeder einzeln, damit hinterher klar ist, welcher trägt // und welcher nur auf manchen Geräten funktioniert. let displays: [CGDirectDisplayID] = NSScreen.screens.compactMap { $0.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID } print("Bildschirme: \(displays)\n") // MARK: - Weg 1: DisplayServices typealias GetBrightness = @convention(c) (CGDirectDisplayID, UnsafeMutablePointer) -> Int32 typealias RegisterNotify = @convention(c) (CGDirectDisplayID, UnsafeRawPointer?, UnsafeRawPointer?) -> Int32 let dsPath = "/System/Library/PrivateFrameworks/DisplayServices.framework/DisplayServices" if let handle = dlopen(dsPath, RTLD_LAZY) { print("DisplayServices: geladen") if let sym = dlsym(handle, "DisplayServicesGetBrightness") { let fn = unsafeBitCast(sym, to: GetBrightness.self) for id in displays { var value: Float = -1 let status = fn(id, &value) print(" GetBrightness(\(id)) → status \(status), Wert \(value)") } } else { print(" DisplayServicesGetBrightness: nicht vorhanden") } print(" RegisterForBrightnessChangeNotifications: " + (dlsym(handle, "DisplayServicesRegisterForBrightnessChangeNotifications") != nil ? "vorhanden" : "FEHLT")) } else { print("DisplayServices: nicht ladbar — \(String(cString: dlerror()))") } // MARK: - Weg 2: CoreDisplay typealias UserBrightness = @convention(c) (CGDirectDisplayID) -> Double let cdPath = "/System/Library/Frameworks/CoreDisplay.framework/CoreDisplay" if let handle = dlopen(cdPath, RTLD_LAZY) { print("\nCoreDisplay: geladen") if let sym = dlsym(handle, "CoreDisplay_Display_GetUserBrightness") { let fn = unsafeBitCast(sym, to: UserBrightness.self) for id in displays { print(" GetUserBrightness(\(id)) → \(fn(id))") } } else { print(" CoreDisplay_Display_GetUserBrightness: nicht vorhanden") } } else { print("\nCoreDisplay: nicht ladbar") } // MARK: - Weg 3: IOKit print("\nIOKit IODisplayGetFloatParameter:") var iterator = io_iterator_t() let matching = IOServiceMatching("IODisplayConnect") if IOServiceGetMatchingServices(kIOMainPortDefault, matching, &iterator) == KERN_SUCCESS { var found = false var service = IOIteratorNext(iterator) while service != 0 { found = true var brightness: Float = -1 let status = IODisplayGetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString, &brightness) print(" Dienst \(service) → status \(status), Wert \(brightness)") IOObjectRelease(service) service = IOIteratorNext(iterator) } if !found { print(" kein IODisplayConnect gefunden (auf Apple Silicon üblich)") } IOObjectRelease(iterator) } else { print(" IOServiceGetMatchingServices fehlgeschlagen") }