My xrandr/arandr display rotation settings reset upon reboot

Hey, I’ve been using endeavouros with qtile for a few months and have had a great experience! recently, I rotated my left display to a portrait-style aspect ratio, but every time I reboot, it resets back to how it used to be. I used both xrandr and arandr to set my display settings, but nothing else.

Something else that I want to note is that I’m dual booting linux and windows with separate drives (I rarely use the latter, but I keep it strictly for gaming). I think the issue may lie here because my primary display through my bios isn’t the primary display through xrandr in my linux drive. I’m unsure how I could change that, though, because I didn’t see any options to modify it from the bios settings.

I’d really appreciate any help or guidance to overcome this annoying issue!

As a bonus question, I’m also wondering if anyone has experience changing the tiling layout depending on the different display. I’d want my left monitor to tile horizontally first (top and bottom), but that’s not my main concern right now.

Thanks, everyone!

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.

1 Like

thank you so much for the suggestions!! I’ll be giving this a shot today – I’m new to automation scripting and linux, but I’m happy to learn this stuff. i really appreciate the tips, thanks!

yup you’re a legend lol… the script worked!! this was my first time doing something like this, thanks a lot! I’m having a slight issue, though:

the script works as expected in the greeter (login) screen, but there’s an issue with the display positioning once I’m signed in. I’m assuming I need the script to run again once my session is started, but it isn’t working for me

the script should look something like this:

#!/usr/bin/env sh
xrandr --output DVI-D-0 --off --output HDMI-0 --mode 1920x1080 --pos 0x0 --rotate left --output DP-0 --primary --mode 1920x1080 --pos 1080x420 --rotate normal --output DP-1 --off

but instead the positioning looks like this when my session starts:

#!/bin/sh
xrandr --output DVI-D-0 --off --output HDMI-0 --mode 1920x1080 --pos 0x0 --rotate left --output DP-0 --primary --mode 1920x1080 --pos 1080x0 --rotate normal --output DP-1 --off

Whenever I execute my script, it makes it look as expected, but the positioning gets changed when ran through my lightdm config.

Here’s what my lightdm config looks like:

[LightDM]
logind-check-graphical=true

[SeatDefaults]
greeter-session=lightdm-slick-greeter
allow-user-switching=true
display-setup-script=/home/nico/scripts/setup-display.sh
greeter-setup-script=/home/nico/scripts/setup-display.sh
session-setup-script=/home/nico/scripts/setup-display.sh

Any ideas of what could be going wrong here? Thanks again

Update: problem is resolved

You don’t have to set the script for all three options. Doing so will likely cause the same script to be executed multiple times.

According to lightdm’s documentation, the external script to be used to set up displays should be specified under display-setup-script. And the script must satisfy a few conditions:

  1. It must be placed under the /usr/share directory.
  2. It must be owned by the lightdm user and lightdm group.
  3. It shouldn’t echo or write log files to a location not accessible to lightdm

The first condition is easy. Just create a lightdm directory inside /usr/share and then place your script in it.

sudo mkdir /usr/share/lightdm
sudo cp ~/scripts/setup-display.sh /usr/share/lightdm
sudo chmod +x /usr/share/lightdm/setup-display.sh

To change the owner and group of the script to lightdm:

sudo chown lightdm:lightdm /usr/share/lightdm/setup-display.sh

Set the display-setup-script inside lightdm’s config file:

[SeatDefaults]
display-setup-script=/usr/share/lightdm/setup-display.sh
1 Like

Thanks, Anthony, this method worked!!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.