Fedora Brightness Automation Buttons OSD
Small Fedora/GNOME brightness setup for laptops with an internal Linux backlight and an external DDC/CI monitor.
The internal display is the master. Brightness keys change the internal panel, show a compact OSD, and a user service mirrors the same percentage to the external monitor with ddcutil.
This avoids drift from letting two outputs auto-adjust independently.
Features
- Internal display controlled with
brightnessctl - External monitor mirrored with
ddcutilVCP code10 - Compact GTK4/libadwaita OSD for custom brightness shortcuts
- Debounced brightness changes: fast repeated key presses become one final jump
- Optional Wayland top-edge positioning with
gtk4-layer-shell - systemd user service for continuous external sync
- Configurable backlight device, DDC bus, monitor model, step size, and sync interval
- Optional wluma config where only the internal display is managed
Tested Setup
- Fedora 43
- GNOME Shell 49
- Internal panel:
intel_backlight - External monitor: DDC/CI via
ddcutil
Other Fedora/GNOME setups should work if brightnessctl and ddcutil can control the displays.
Dependencies
sudo dnf install -y brightnessctl ddcutil python3-gobject gtk4 libadwaita gtk4-layer-shell
gtk4-layer-shell is recommended on GNOME Wayland. Without it, GNOME may place the OSD like a normal GTK window instead of pinning it at the top edge.
If your ddcutil command needs sudo, configure passwordless sudo for the specific command you use. Example:
jan ALL=(root) NOPASSWD: /usr/bin/ddcutil
Use a stricter sudoers rule if you prefer limiting arguments.
Quick Install
git clone https://gitea.diehanis.de/Jan/Fedora_Brightness_Automation_Buttons_OSD.git
cd Fedora_Brightness_Automation_Buttons_OSD
./install.sh
The installer writes:
~/.local/bin/brightness-osd
~/.local/bin/brightness-step
~/.local/bin/brightness-up-all
~/.local/bin/brightness-down-all
~/.local/bin/brightness-sync-hg342pcb
~/.config/systemd/user/external-brightness-sync.service
~/.config/brightness-automation/env
Then set your GNOME custom keyboard shortcuts to:
/home/YOUR_USER/.local/bin/brightness-down-all
/home/YOUR_USER/.local/bin/brightness-up-all
Use the full path in GNOME Settings.
Configuration
Edit:
~/.config/brightness-automation/env
Default config:
BRIGHTNESS_BACKLIGHT_DEVICE="intel_backlight"
BRIGHTNESS_SYNC_BACKLIGHT="/sys/class/backlight/intel_backlight"
BRIGHTNESS_STEP="10"
BRIGHTNESS_DDCUTIL_MODEL="HG342PCB"
BRIGHTNESS_DDCUTIL_DISPLAY="1"
BRIGHTNESS_DDCUTIL_BUS="16"
BRIGHTNESS_SYNC_INTERVAL="1"
BRIGHTNESS_SYNC_MIN_PERCENT="1"
BRIGHTNESS_OSD_VISIBLE_MS="1400"
BRIGHTNESS_APPLY_DEBOUNCE_MS="180"
BRIGHTNESS_APPLY_DEBOUNCE_MS controls how long the scripts wait for another key press before applying the final brightness. The OSD updates immediately to the target value, but brightnessctl runs only once at the end of a quick key-press burst.
After changing DDC or sync values:
systemctl --user restart external-brightness-sync.service
Finding Your Values
Backlight device:
brightnessctl -l
ls /sys/class/backlight
External monitor:
sudo ddcutil detect
sudo ddcutil getvcp 10
If ddcutil detect reports a bus like /dev/i2c-16, set:
BRIGHTNESS_DDCUTIL_BUS="16"
wluma
If you use wluma, let it manage only the internal display. The external monitor should follow through the sync service.
Optional install of the example wluma config:
INSTALL_WLUMA_CONFIG=1 ./install.sh
systemctl --user restart wluma.service
Example config is in:
wluma/config.toml
Status
systemctl --user status external-brightness-sync.service
journalctl --user -u external-brightness-sync.service -n 50 --no-pager
Uninstall
./uninstall.sh
The uninstall script keeps ~/.config/brightness-automation/env so local settings are not destroyed.