The display configurations set by xrandr and arandr will last for that session only. What you need here is some basic automation – in other words, configure your system to automatically execute those commands every time you log into your graphical session, and how you do this depends on your particular environment. If you use a display manager like lightdm, you can write a script, make it executable, and then add that script to your lightdm configuration file under: session-setup-script
For the full details, refer to lightdm’s documentation:
https://www.freedesktop.org/wiki/Software/LightDM/CommonConfiguration/
If you don’t use a display manager, but start your display session with xinit, add a line to launch the script to your .xinitrc.
This should be possible using the Screen variable. Refer to qtile’s documentation for more details.
https://docs.qtile.org/en/latest/manual/config/screens.html
Now, I’m going to share with you some of my tricks to configure multiple monitors on a window manager.
My current set up automates display configurations every time I start a display server. I’m using i3wm, not qtile, so the details might be a little bit different. However, the main idea is the same. Here is how I do it.
i3wm provides a mechanism to extend the main configuration file using an include directive, so I used that to my advantage. For example, if I add the following line to my main i3 configuration file:
include ~/.config/i3/additional_config
i3 will include the contents of the file ~/.config/i3/additional_config in my main i3 config file (much like the include directive in the C programming language) when i3 is launched.
On my system, the file ~/.config/i3/additional_config is actually a symbolic link to different configuration files, each providing different i3 configurations rules for a particular display combination (laptop screen only, laptop screen + HDMI, laptop screen + display port, etc). The reason I have it set up this way is because I have different keybindings, workspace assignments, and layout configurations depending on the number of displays that are connected to my system.
Currently, I have three sets of additional configurations (single display, double display, and triple display). Single display means no monitors are connected (just using the laptop display). Double display means one external monitor is connected, and so on.
To automate this, I just have to write a simple shell script to make the symlink ~/.config/i3/additional_config point to the correct configuration file every time I start a display server. That way, i3 will add the correct configurations depending on how many monitors I have connected to my laptop.
# Display names
LAPTOP="eDP"
HDMI="HDMI-A-0"
DISPLAY_PORT="DisplayPort-0"
# Configuration files
CONFIG_FILE_SINGLE_DISPLAY="~/.config/i3/single_display.conf"
CONFIG_FILE_DOUBLE_DISPLAY="~/.config/i3/double_display.conf"
CONFIG_FILE_TRIPLE_DISPLAY="~/.config/i3/triple_display.conf"
SYMLINK="~/.config/i3/additional_config"
# Display positions relative to laptop screen
TOP="$HDMI"
TOP_LEFT="$HDMI"
TOP_RIGHT="$DISPLAY_PORT"
reset_symlink(){
if [ -L "$1" ]
then
rm "$1"
fi
}
invoke_xrandr(){
state="$1"
case "$state" in
"Single Display")
xrandr --output "$LAPTOP" --auto --output "$HDMI" --off --output "$DISPLAY_PORT" --off
;;
"Two Displays")
# $TOP must be set before this function is called
xrandr --output "$TOP" --auto --above "$LAPTOP"
;;
"Three Displays")
xrandr --output "$TOP_LEFT" --auto --above "$LAPTOP" --output "$TOP_RIGHT" --auto --right-of "$TOP_LEFT"
;;
esac
}
setup_displays(){
# First, determine the state of each output device
display_port_state=$(xrandr | grep "^$DISPLAY_PORT" | cut -d " " -f 2)
hdmi_state=$(xrandr | grep "^$HDMI" | cut -d " " -f 2)
reset_symlink "$SYMLINK"
# Process the states
setup_type=""
config_file=""
if [ "$display_port_state" = "connected" ] && [ "$hdmi_state" = "connected" ]
then
# Both display ports and HDMI are connected (triple display)
config_file="$CONFIG_FILE_TRIPLE_DISPLAY"
setup_type="Three Displays"
elif [ "$display_port_state" = "connected" ] && [ "$hdmi_state" = "disconnected" ]
then
# Only display port is connected (double display)
# Must use display port as TOP
TOP="$DISPLAY_PORT"
config_file="$CONFIG_FILE_DOUBLE_DISPLAY"
setup_type="Two Displays"
elif [ "$display_port_state" = "disconnected" ] && [ "$hdmi_state" = "connected" ]
then
# Only hdmi is connected (double display)
# Must use hdmi as TOP
TOP="$HDMI"
config_file="$CONFIG_FILE_DOUBLE_DISPLAY"
setup_type="Two Displays"
else
# No external monitors connected (single display)
config_file="$CONFIG_FILE_SINGLE_DISPLAY"
setup_type="Single Display"
fi
# Set the symlink to point to the correct file.
ln -s "$config_file" "$SYMLINK"
invoke_xrandr "$setup_type"
}
setup_displays
The actual script is a bit more complicated than this, but that’s the gist of it. Since I’m not using a display manager, I just launch this script from my .xinitrc and it will run every time I start an X session.