8

I want to control the brightness of the main-screen within my Mac OS X app (like the F1/F2 buttons). In iOS, there's something like this:

UIScreen.mainScreen().brightness = CGFloat(0.5)

In OSX we have NSScreen, which is nice to find out what the main-screen is, but it misses the .brightness method.

So how can I adjust the monitor brightness using Swift on OSX?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
ixany
  • 5,433
  • 9
  • 41
  • 65

1 Answers1

17

There's no such nice API for doing this on OS X.

We have to use IOServiceGetMatchingServices to find "IODisplayConnect" (the display device) then use the kIODisplayBrightnessKey to set the brightness:

func setBrightnessLevel(level: Float) {

    var iterator: io_iterator_t = 0

    if IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"), &iterator) == kIOReturnSuccess {

        var service: io_object_t = 1

        while service != 0 {

            service = IOIteratorNext(iterator)
            IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey, level)
            IOObjectRelease(service)

        }

    }
}

setBrightnessLevel(0.5)
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • great solution, thank you! works perfectly fine on my MacBook with the build-in display. Could you please also give me a hint how to control the brightness of an external display, like a CinemaDisplay? Is it another IOService I have to match? I couldn't find any help in the Apple Docs. – ixany Sep 21 '15 at 11:04
  • Since we're interating the services matching "IODisplayConnect" I think it will work for internal and external displays (it should apply on all displays it finds, actually). If it doesn't work for you then I'll inspect further. *Note that some external displays can not be setup programmatically from OS X anyway.* – Eric Aya Sep 21 '15 at 11:50
  • I tested it with an actual MacBookPro (with the latest OSX 10.11 Beta) and an Apple Thunderbold Display connected via DisplayPort/Thunderbold. The build-in display reacts, but the Thunderbold-Display didn't. `NSScreen.screens()` returns two displays correctly. I appreciate your support :) – ixany Sep 21 '15 at 12:38
  • Do you have any idea yet why it's not working with multiple displays? – ixany Sep 24 '15 at 12:34
  • No, I've tested lots of stuff but haven't found why we don't get external displays with this method, and haven't found relevant documentation about it either. All other methods I've found are now deprecated and don't work at all. I only see this incomplete one for now in 10.10+. – Eric Aya Sep 24 '15 at 12:36
  • following command lists the display as AppleDisplay. Not sure if that in internal or external. ioreg -l | grep -5 IODisplayEDID – Gamma-Point Nov 06 '15 at 00:03
  • You sir are a gentleman and a scholar. Thank you! As an addition to this answer, if you need to control external displays, you can do this through IOKit as well, using DDC. Another fine gentleman wrote an application for this called `ddcctl` which you can find on github. I am currently working on adding an option to this app that would allow it to track the main display and set the external to match brightness. – CatalinM Apr 06 '18 at 12:35
  • 1
    works perfectly but I think that due to macOS restrictions or a bug, the brightness slider in the setting does not change when you set a new brightness. – Duck Jan 13 '20 at 21:45