danmc.net

Display Backlight Control in the Sway

This is just a quick reference for anyone setting up Sway on a laptop. By default the brightness control function keys do not work. To get them functioning, there are a couple of not-so-obvious steps required.

Changing the Backlight Brightness from the Command Line

The screen brightness is set by writing a value to a file in the /sys/ virtual filesystem (sysfs). The sysfs exposes kernel and driver internal configuration to userspace. On my system, the file of interest is /sys/class/backlight/intel_backlight/brightness, but the exact path will vary depending on the graphics controller, etc.

To check the current brightness setting:

cat /sys/class/backlight/intel_backlight/brightness

This will output a number representing the current brightness setting. The range of numbers will vary from system to system, but to find the max value:

cat /sys/class/backlight/intel_backlight/max_brightness

On my system that outputs 7500. So to set my display to half brightness:

echo 3750 > /sys/class/backlight/intel_backlight/brightness

The above will work if you are running as root, but not as a normal user as normal users do not have write permissions to files in /sys/. So to accomplish the same thing from a normal users shell we have to do the following (assuming you have sudo installed):

echo 3750 | sudo tee /sys/class/backlight/intel_backlight/brightness

Instead of redirecting the stdout of the echo command to the file directly, we pipe it to the stdin of the sudo command which passes its stdin to the tee command which redirects its stdin to the file specified in its first argument. You might think the following would work, but you'd be wrong as the sudo command only elevates privileges for the echo command, not for the redirection to the file as it is the shell that does that and it is still running as a normal user.

# DOES NOT WORK
sudo echo 3750 > /sys/class/backlight/intel_backlight/brightness

light: a Convenient Utility

Now we know how brightness control works at the lowest level, but it is inconvenient to control it in this manner. It requires setting the brightness to specific levels within a system dependent range of values, and doesn't allow incrementing/decrementing the value like we want to do with the brightness function keys. We could write a script to handle this, but light is a convenient utility that makes all of this pretty simple. It handles finding the correct sysfs file to write to and also normalizes the range of settings so that to set the brightness to 50%, you just do:

sudo light -S 50

Or to increment by 10% you do:

sudo light -A 10

Or to decrement by 10% you do:

sudo light -U 10

It is available in most distribution package managers. In alpine, the following installs it:

sudo apk add light

No Sudo password

Even using light, sudo is still required, and on most systems, sudo requires a password. This is not going to work for binding to the brightness keys on the keyboard because there is no way to enter a sudo password when the key binding is triggered, and even if there was, that would not be convenient.

To get around this, we can add a line to the sudo config. To edit the sudo config, run sudo visudo. This will allow you to safely edit the /etc/sudoers file. Once in the editor add the following line and save and exit.

%wheel ALL=(root) NOPASSWD: /usr/bin/light

This allows all members of the wheel group run /usr/bin/light as root without entering a password. For this to work, your user needs to be a member of the wheel group. Alternatively, you could replace %wheel with your username.

Finding the Key Code for the Brightness Keys

A list of key codes for the brightness keys can be found by:

grep Brightness /usr/include/xkbcommon/xkbcommon-keysyms.h

This will list all of the key codes for the brightness keys:

#define XKB_KEY_XF86MonBrightnessUp    0x1008FF02  /* Monitor/panel brightness */
#define XKB_KEY_XF86MonBrightnessDown  0x1008FF03  /* Monitor/panel brightness */
#define XKB_KEY_XF86KbdBrightnessUp    0x1008FF05  /* Keyboards may be lit     */
#define XKB_KEY_XF86KbdBrightnessDown  0x1008FF06  /* Keyboards may be lit     */
#define XKB_KEY_XF86MonBrightnessCycle 0x1008FF07  /* Monitor/panel brightness */
#define XKB_KEY_XF86BrightnessAdjust  0x1008FF3B   /* Invoke brightness adj. UI   */
#define XKB_KEY_SunVideoLowerBrightness 0x1005FF7B
#define XKB_KEY_SunVideoRaiseBrightness 0x1005FF7C

The two we are interested in are XF86MonBrightnessUp and XF86MonBrightnessDown. We can either use those names or the actual key codes 0x1008FF02 and 0x1008FF03.

Binding the Keys in Sway

We are now armed with commands to increment/decrement the brightness, and the key codes for the keys we want to use to run those commands. All that is left is to bind those key codes to the appropriate commands. The sway config is typically at ~/.config/sway/config. Add the following lines to the file (the comments are just there for future reference):

# from /usr/include/xkbcommon/xkbcommon-keysyms.h
#define XKB_KEY_XF86MonBrightnessUp    0x1008FF02  /* Monitor/panel brightness */
#define XKB_KEY_XF86MonBrightnessDown  0x1008FF03  /* Monitor/panel brightness */
bindsym XF86MonBrightnessUp exec sudo light -A 10
bindsym XF86MonBrightnessDown exec sudo light -U 10

After saving the updated config, reload the config with $mod+Shift+c where $mod is your configured Sway mod key (unless you've configured the reload command to another keybinding). Your brightness function keys should now work!

Further Reading

  1. light github page
  2. Sway shortcut handling
  3. sudo: specific program without a password
  4. Arch Linux backlight wiki page