brightness

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2026 License: BSD-3-Clause Imports: 1 Imported by: 0

README

go-macos/brightness

ci Go Reference License

Read and set a display's backlight on macOS, from pure Go with CGO_ENABLED=0. No cgo, no osascript, no shelling out to anything.

restore, err := brightness.Dim(display)
if err == nil {
        defer restore()      // ← the whole point
}

Why

For the case where a screen is being shown somewhere else. A pair of display glasses can mirror the Mac's own screen, and then the physical panel is worse than useless: it is a copy of private work, at reading distance, facing whoever walks past — and it is lit at full power for nobody.

Turning the backlight off beats covering the screen with a black window:

a capture of that display is unchanged the framebuffer is untouched, so a mirror keeps working
nothing to exclude no window id to keep out of the capture, no stream to rebuild
nothing can get above it a window can be covered by whatever raises itself next
the panel is off not black at full power

The restore is the API

A program that darkens a screen and then exits — or crashes, or is killed — leaves somebody with a black panel and no idea why. So Dim reads the level before changing anything and hands it straight back as the way home. Keep it and defer it.

A display that will not say what its brightness is, is not dimmed: there would be nothing to restore, and a zero read as "off" would darken a panel this package could never light again.

⚠ This is PRIVATE API

DisplayServices is a private framework. Apple may change or remove it in any release, and a program linking this cannot ship on the Mac App Store.

The documented route — IODisplaySetFloatParameter with kIODisplayBrightnessKey — is the old one: it does not drive the built-in panel on an Apple Silicon Mac. This is what does.

Every symbol is looked up at run time and a failure is reported rather than crashing, so a system that has moved on says so once (ErrUnavailable) instead of being asked again on every call.

What answers

The built-in panel answers. An external display answers only if it speaks DDC/CI and macOS is willing to use it — many do not, and Of reports ErrNoBrightness rather than pretending.

Tests

go test ./...                          # portable logic, and every failure path
BRIGHTNESS_LIVE=1 go test -run Live    # + a real panel, moved and put back

The failure paths are driven through seams — the framework that will not open, the display that will not say, the display that will not be told — so they are exercised on a machine where all of it works. The live test moves the real panel by a fifth and puts it back, because it is somebody's screen.

Requirements

macOS, Go 1.24+, CGO_ENABLED=0. Off darwin every entry point answers ErrUnsupported.

Licence

BSD-3-Clause. See LICENSE.

Documentation

Overview

Package brightness reads and sets a display's backlight on macOS, from pure Go with CGO_ENABLED=0.

It exists for the case where a screen is being shown SOMEWHERE ELSE. A pair of display glasses can mirror the Mac's own screen, and then the physical panel is worse than useless: it is a copy of private work, at reading distance, facing whoever walks past — and it is lit at full power for nobody.

restore, err := brightness.Dim(display)
if err == nil {
	defer restore()
}

Turning the backlight off is better than covering the screen with a black window: nothing changes in a capture of that display (the framebuffer is untouched), there is no window for a capture to exclude and no stream to rebuild, and no window that something else can raise itself above.

⚠ This is PRIVATE API

DisplayServices is a private framework. Apple may change or remove it in any release; a program linking this cannot ship on the Mac App Store. Every symbol is looked up at run time and a failure is reported rather than crashing, so a system that has moved on says so.

What answers

The built-in panel answers. An external display answers only if it speaks DDC/CI and macOS is willing to use it — many do not, and Of then reports ErrNoBrightness rather than pretending.

Index

Constants

View Source
const (
	Off  = 0.0
	Full = 1.0
)

Off is a dark panel, and Full is a bright one.

Variables

View Source
var (
	// ErrUnsupported is what every entry point answers away from macOS.
	ErrUnsupported = errors.New("brightness: unsupported on this platform (macOS only)")
	// ErrUnavailable means the private framework is not there, or no longer
	// exports what this package needs.
	ErrUnavailable = errors.New("brightness: the DisplayServices framework is not available")
	// ErrNoBrightness means that display will not say, or will not be told —
	// an external panel with no DDC, most often.
	ErrNoBrightness = errors.New("brightness: this display does not report a brightness")
	// ErrRange means a level outside 0..1 was asked for.
	ErrRange = errors.New("brightness: a level must be between 0 and 1")
)

Errors this package returns.

Functions

func Dim

func Dim(display uint32) (restore func() error, err error)

Dim turns the display off and returns the way back.

The restore is the point of the whole package. A program that darkens a screen and then exits — or crashes, or is killed — leaves somebody with a black panel and no idea why, so the value to go back to is read BEFORE anything is changed and handed straight back to the caller. Keep it and defer it.

A display that will not say what its brightness is, is not dimmed: there would be nothing to restore -- and the read is also the only VALIDATION there is. DisplayServicesSetBrightness answers success for a display id no machine has, so a Dim that set first would report having darkened something that does not exist.

func Of

func Of(display uint32) (float64, error)

Of returns the display's brightness, from 0 (dark) to 1 (full).

func Set

func Set(display uint32, level float64) error

Set puts the display's brightness at level, which must be between Off and Full.

It is not a fade: the panel arrives at once, which is what a person pressing a key expects and what a program restoring what it changed needs.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL