Authors Top

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

1. Overview

In this tutorial, we’ll learn about changing the primary monitor in X and Wayland using the Linux terminal.

2. Changing the Primary Monitor in X

The X windows system (e.g., X/X11) is responsible for providing basic graphics support for the majority of Linux distributions. There are multiple ways to change the primary monitor in X11, but one of the most widely used ways is through the use of xrandr.

If we want to set the primary display using xrandr, we should first obtain the output name of the monitor we want to change. To get a list of outputs and their associated information, we can simply call xrandr without any options:

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

The results from this command show us the names of the various outputs along with which ones are currently connected. At the beginning of an output’s name is the port it is connected to (e.g., DVI-D).

We specify the display we want to modify by passing its name to xrandr –output. Then we include the –primary flag to indicate we want it to be changed to the primary display:

$ xrandr --verbose --output "DVI-D-0" --primary 
crtc 1: 1920x1080 60.00 +1920+0 "DVI-D-0"

On successful execution, xrandr typically does not write anything to stdout, but since we used the –verbose flag, we get some basic information about the output we modified. Since our command was successful, we got information about the display we modified.

Output names are not stable and can change between X sessions. This is why it is important to obtain the name of the output we want to modify each time the X11 server restarts.

2.1. Permanently Setting the Primary Monitor

xrandr only changes the settings of the current session of a running X11 server. This means any settings changed using xrandr are lost when the X server is powered off.

Therefore if we want to persistently define the primary output, the associated xrandr command must be called every time the X11 server starts. This can be accomplished by modifying the ~/.xinitrc file.

All commands must be inserted into the file before the exec line which starts the window manager. Let’s set our DVI-D-0 output as the primary display by inserting the command into our ~/.xinitrc file:

xrandr --output "DVI-D-0" --primary
# Do not add anything below this point
exec $(get_session i3wm)

The changes made will go into effect the next time the X11 server starts. This command only works as long as the output name happens to stay the same.

Therefore, we should modify our command to make sure we get the name of the display we want to change instead of just hardcoding it in. We can do this by parsing the output of xrandr for the port type of the monitor we want to set. In this case, we are looking for the display connected to the DVI port:

dname="$(xrandr | grep -Po '(DVI).+(?= connected)')"
xrandr --verbose --output "${dname}" --primary
# Do not add anything below this point
exec $(get_session i3wm)

The first line uses grep to search the output of xrandr for the name of the connected monitor on the DVI port. Then the second line passes that name to our xrandr command to set the primary monitor.

This method should work as long as we do not have another output on the same type of port, such as another monitor connected through DVI. In that case, we have to use a different method of differentiating between outputs.

2.2. Setting Primary Monitor Using EDID

If we have two or more monitors using one type of output (i.e., DVI), we will not be able to use just the output name to differentiate between displays.

Instead, we should use the connected monitor’s Extended Display Identification Data (EDID) to determine the output we want to change. If we want to print the EDID information of the connected outputs we can call xrandr with the –prop flag:

$ xrandr --prop
...
DVI-D-0 connected 1920x1080+1920+0 (normal left inverted right x axis y axis) 476mm x 268mm
    EDID: 
        00ffffffffffff0004721903c1b82750
        0219010380301b782a16c5a456509f26
        125054b30c00714f818081c081009500
        b300d1c00101023a801871382d40582c
        4500dc0c1100001e000000fd00324c1e
        5011000a202020202020000000ff004c
        58324141303032343231300a000000fc
        0041636572204832323648514c0a008b
...

The output of this command includes information about the outputs on our computer and the EDID of each output.

The EDID structure is a series of hexadecimal, with a pair corresponding to one byte of information. Since the EDID includes its serial number and other unique identifiers, it should be unique to a specific monitor, even for monitors of the same model.

Let’s put our target monitor’s EDID into a text file for easy access. Then let’s create a bash script that sets the primary display to the output with the matching EDID:

#!/bin/bash

MY_EDID="$(cat "${1:-/home/$USER/.config/EDID.txt}" | tr -d [[:space:]])"
IFS=$'\n'
arr=( $(xrandr --props) )
i="0"
while [[ -n "${arr[i]}" ]] ; do
    if [[ "${arr[i]}" =~ ^[a-Z0-9] ]] ; then
        current_out="$(echo "${arr[i]}" | grep -Pio '^[a-zA-Z0-9\-]+')"
    elif [[ "${arr[i]}" =~ EDID: ]] ; then
        Z=""
        while [[ "${arr[++i]}" =~ $'\t\t' ]] ; do
            Z+="$(tr -d [[:space:]] <<< ${arr[i]})"
        done
        if [[ "${Z}" = "${MY_EDID}" ]] ; then
            xrandr --output "${current_out}" --primary
            exit "$?"
        fi
    fi
    i=$((i+1))
done
exit 1

In this script, we can either supply a text file through user input or use the text file $HOME/.config/EDID.txt. After that, we simply obtain the output from xrandr –props and compare it to our text file until we get a match.

Only alphanumeric characters matter in an EDID, so we can ignore any whitespace or newlines when comparing EDIDs. If we find a match, we set the primary monitor to the corresponding output; Otherwise, we exit with an error code.

3. Changing the Primary Monitor in Wayland

Unlike changing the primary monitor in X, Wayland does not have the concept of a primary display. Instead, the primary monitor must be implemented by the compositor.

Typically most compositors will use a different tool to set the primary display. Each compositor also has its own output naming scheme through its implementation of wl_output::name. Typically these tools are not provided by default and must be installed by the user.

3.1. Changing the Primary Monitor in KDE Plasma

KDE Plasma supports Wayland using its own compositor, KWIn. Let’s use the kscreen-doctor command, part of the libkscreen package, to set the primary display. We can start by printing information about our various outputs using the –outputs flag with kscreen-doctor:

$ kscreen-doctor --outputs
Output: 1 Hewlett Packard HP 22cwa/6CM6501C14 enabled connected HDMI Modes: 0:[email protected]*! 1:[email protected]
...
Output: 2 Acer Technologies Acer H226HQL/LX2AA0024210 enabled connected primary DVI Modes: 0:[email protected]*!

The number used to identify each output is located after “Output:”. Next, there are the manufacturer, model name, and serial number, which may also be used to identify an output.

In this example, we can also see that the primary monitor is the one connected to the DVI port. If we want to assign a different primary monitor, we may use the command kscreen-doctor output.”${Name}”.primary with ${Name} being the section outputted by kscreen-doctor –outputs indicating manufacturer, model name, and serial number (i.e. “Hewlett Packard HP 22cwa/6CM6501C14”).

Let’s try assigning this monitor as the primary display using this format:

$ kscreen-doctor output.'Hewlett Packard HP 22cwa/6CM6501C14'.primary
kscreen.doctor: setop exec returned KScreen::Config( 
KScreen::Output(1, "Hewlett Packard HP 22cwa/6CM6501C14", connected enabled primary, ... )
KScreen::Output(2, "Acer Technologies Acer H226HQL/LX2AA0024210", connected enabled, ... ))

The output shows the new configuration with the monitor on the HDMI port as the new primary monitor. This should work between sessions even when using another monitor of the same model on the same type of port.

3.2. Changing the Primary Monitor in GNOME

GNOME supports Wayland with the compositor Mutter. Just like with KWIN, Mutter has implemented the concept of a primary monitor into their implementation of Wayland. A tool that can be used to set the primary monitor in GNOME is gnome-randr. This tool mimics the function of xrandr for Wayland.

To get information about our current monitor configuration and outputs, we can run gnome-randr without any options:

$ gnome-randr
...
logical monitor 0:
x: 0, y: 0, scale: 1, rotation: normal, primary: no
associated physical monitors:
	DVI-D-1 ACR Acer H226HQL LX2AA0024210

logical monitor 1:
x: 1920, y: 0, scale: 1, rotation: normal, primary: yes
associated physical monitors:
	HDMI-1 HWP HP 22cwa 6CM6501C14
...

The output from this command gives us information about the displays, including their output name in a similar format to xrandr (e.g., DVI-D-1). Now let’s set our DVI-connected monitor as the primary display using the structure gnome-randr modify “${Name}” –primary:

$ gnome-randr modify "DVI-D-1" --primary
setting monitor as primary

To modify an output, we use the gnome-randr modify command and specify the output we want to configure. Since we want this to be our primary monitor, we use the –primary flag.

4. Conclusion

In this article, we learn about changing the primary monitor in X using the xrandr command. To make these changes permanent, we should put our command in the ~/.xinitrc file. In addition, we can use the EDID to uniquely identify each output on a system.

On the other hand, Wayland does not provide the concept of a primary monitor. Instead, it is up to the compositor to do so. Because of this, the methods and tools used to set the primary display differ between Wayland implementations. In KDE Plasma, we can use the kscreen-doctor command, and in GNOME, we can use gnome-randr.

Authors Bottom

If you have a few years of experience in the Linux ecosystem, and you’re interested in sharing that experience with the community, have a look at our Contribution Guidelines.

Comments are closed on this article!