1. Overview

There are many different methods for adjusting the screen brightness in Linux. However, most of these methods require root privileges, making them unusable as bindings in the i3 window manager.

In this tutorial, we cover how to adjust screen brightness without root. Finally, we’ll learn how to create i3 bindings to adjust the backlight.

2. Setting Brightness With xrandr

xrandr is a tool used to configure outputs for X11. It has many different uses including setting resolution, orientation, or brightness of displays.

2.1. Installing xrandr

Ubuntu provides xrandr in the x11-xserver-utils package. Let’s install this package using apt:

# apt install x11-xserver-utils

Additionally, x11-xserver-utils provides other programs such as xrdb and xgamma allowing for further configuration of X11.

2.2. Setting Brightness of a Display

Now that we’ve installed xrandr on our system, let’s run xrandr without any arguments:

$ xrandr
Screen 0: minimum 320 x 200, current 3840 x 1920, maximum 16384 x 16384
HDMI-1 disconnected (normal left inverted right x axis y axis)
DP-1 connected primary 1920x1080+1080+0 (normal left inverted right x axis y axis) 476mm x 268mm
...

As we can see, running xrandr displays the total screen size and the names of all outputs.

To output only a list of active outputs, we can run xrandr with the –listactivemonitors flag:

$ xrandr --listactivemonitors
Monitors: 2
 0: +*DP-1 1920/476x1080/268+1080+0  DP-1
 1: +HDMI-2 1080/531x1920/299+0+0  HDMI-2

The output of this command is a list-separated list of connected monitors, with their resolution, orientation, and output names at the end of each line.

To set the brightness of one of our outputs, we can use xrandr:

$ xrandr --output DP-1 --brightness 0.7

As can be seen in this example, we use xrandr to specify the output to configure with –output. Next, we set the brightness using –brightness and a number between 0 and 1 corresponding to the brightness.

2.3. Setting Brightness of All Displays

To automatically adjust the brightness of our displays, let’s create a simple script. The first step is getting the output names of each connected display:

$ xrandr --listactivemonitors | tail +2 | grep -o '[^ ]*$'
DP-1
HDMI-2

We run xrandr –listactivemonitors to get a list of output names and their settings. Then we pipe to tail with the +2 option to remove the first line of the output. Finally, we pipe to grep to get just the output names.

Let’s break down this grep command:

  • -o – output only the matched string of each line
  • [^ ]*** – match on repeating non-whitespace characters
  • $ – match on the end of the line

Now, let’s loop through the output of our previous command to set the brightness of all displays:

$ while read -r -d $'\n' output ; do
    xrandr --output "${output}" --brightness 0.9
done < <(xrandr --listactivemonitors | tail +2 | grep -o '[^ ]*$' )

We redirect the output of our xrandr command to our while loop, reading each inputted line into the output variable with read. In our loop, we set the display, *$*output, to brightness 0.9.

2.4. Creating a Script

Once, we know how to set the brightness of our displays, we can create a script to automate this process.

Let’s take a look at our script:

$ cat set_brightness.sh
#!/usr/bin/bash
set_brightness() {
    local output
    while read -r -d $'\n' output ; do
        xrandr --output "${output}" --brightness "${1}"
    done < <(xrandr --listactivemonitors | tail +2 | grep -o '[^ ]*$')
}
set_brightness "${@}"

At the beginning of the file is a shebang, #!/usr/bin/bash, setting the command to execute the script. Next, we define a function set_brightness that has the code shown earlier to set the brightness of all displays.

However, we replace the constant brightness 0.9 as an argument to our function ${1}. This allows the brightness level to be specified when the function is called. Lastly, we call our function, passing command line arguments with ${@}.

Once we have created our script file, we need to make sure it’s executable:

$ chmod +x set_brightness.sh

Using chmod with +x, we set executable permissions on set_brightness.sh.

Finally, let’s run our script, passing the brightness level to set out displays to:

$ . set_brightness.sh 0.9

We run our script with . and the path to the script file, passing the brightness level as the first argument.

Additionally, we can make the script callable through just its filename by adding it to the PATH environment variable.

3. Creating Bindings in i3 to Adjust Brightness

Now that we have our script, let’s create key bindings in our i3 configuration file to execute our script. In i3, keyboard shortcuts (bindings) are defined in the configuration file. Bindings in i3 can do various things including executing external programs or scripts.

In this section, we learn how to create bindings to adjust the brightness of our displays automatically. First, we learn how to create a binding to set the brightness to a set value. Afterward, covering how to create a binding for setting the brightness to a user-inputted value.

3.1. Binding to Adjust Brightness

To start, we first must locate our i3 configuration file. The default location of the i3 configuration file is ~/.config/i3/config.

Now, let’s create our bindings by appending it to our configuration file:

$ echo 'bindsym $mod+b exec "$HOME/set_brightness.sh 0.9' >> ~/.config/i3/config

In this example, we append a line in our i3 configuration file with echo, defining a binding $mod+b calling our script. Now, we can set the brightness of our displays by pressing $mod+b, or Alt+b by default.

Let’s break down this binding a little further:

  • bindsym $mod+b – create binding for $mod+b
  • exec – execute a program or script
  • “$HOME/set_brightness.sh 0.9” – the full path of our script and its arguments

Note, that we must reference the full path of our script, otherwise, i3 may not be able to find it.

3.2. Brightness Binding With i3-input

Instead of setting the brightness to a constant value, we may want to set the brightness to a value inputted by the user. This can be accomplished using *i3-*input.

Let’s begin by running i3-input without any arguments:

$ i3-input

As can be seen, the result of this command is a box that takes input from the user, exiting after they press the key.

We can i3-input to run a command using the inputted value from the user. Let’s do this now to set the brightness with our script:

$ i3-input -F 'exec $HOME/set_brightness.sh %s' -P 'brightness: '

We should now see a box that contains the string ‘brightness: ‘ on the left. We can input the brightness level and press  to set the brightness of our displays.

Finally, let’s add this is a binding in our i3 configuration:

$ echo 'bindsym $mod+Shift+b exec i3-input -F "exec /home/maceurt/set_brightness.sh %s" -P "brightness: "' >> ~/.config/i3/config

In this example, we add the binding for $mod+Shift+b to execute our i3-input command. Since i3-input is located in the system path, we don’t have to reference its full path.

4. Conclusion

In this article, we learned how to adjust the backlight levels with i3 bindings.

To begin with, we learn how to adjust the backlight levels of one display using xrandr and then all displays. Then, we go over automatically adjusting the brightness of all displays using a script. Finally, we learned how to create a binding in i3 to adjust brightness using a set value and an inputted value.