Shell script to magically configure display setup

Posted . Visible to the public.

Here is a bash script that I use to auto-configure displays on Ubuntu 24.04 with Xorg.

Background

  • Ubuntu always sets the primary display to the 1st (i.e. internal) display whenever I connect to a new Dock/Hub.
    • I want my primary display to be the large display.
    • My notebook is always placed left of external displays, so the 2nd display will be the center (or only) external display and should be primary.
  • I also want all my displays to be placed horizontally, but bottom-aligned (the default would be aligned at their top edges).
  • As an oddly specific bonus (you may not need this), I adjust my internal display's resolution when connected to external displays. It's because it's a HiDPI display and scaling does not work properly with external displays on my setup.

Note

This script should work with other Linux distros, as long as you are using the Xorg display server. It likely won't work on Wayland.
The script assumes that external display order is left to right. If displays are ordered e.g. 1, 3, 2, connect displays differently.

Script

The script's comments should explain what is going on, so adjust to your needs and/or remove unwanted sections.
Remember to make it executable (e.g. chmod +x auto-configure-displays).

If you want to adjust your internal display's resolution, confirm its name by running xrandr --query | grep ' connected'. If it's not "eDP-1", adjust the script.

#!/bin/bash

# Get connected displays
mapfile -t displays < <(xrandr --query | grep " connected" | awk '{print $1}')
num_displays=${#displays[@]}

# If only one display, exit
if [ "$num_displays" -le 1 ]; then
  exit 0
fi

# Set resolution of internal display to 1920x1200
for (( i=0; i < num_displays; i++ )); do
  if [ "${displays[$i]}" == "eDP-1" ]; then
    xrandr --output "${displays[$i]}" --mode 1920x1200
  fi
done

# For each display, fetch its dimensions
for (( i=0; i < num_displays; i++ )); do
  mode=$(xrandr --query | grep "^${displays[$i]} connected" | grep -oP '\d+x\d+\+\d+\+\d+' | head -n1 | cut -d+ -f1)
  modes[i]="$mode"
  widths[i]=$(echo "$mode" | cut -dx -f1)
  heights[i]=$(echo "$mode" | cut -dx -f2)
done

# Compute maximum height among all displays
max_height=0
for h in "${heights[@]}"; do
  if (( h > max_height )); then
    max_height=$h
  fi
done

# Arrange displays horizontally, and align at bottom
x=0
for (( i=0; i < num_displays; i++ )); do
  offset_y=$(( max_height - heights[i] ))
  xrandr --output "${displays[$i]}" --mode "${modes[i]}" --pos "${x}x${offset_y}"
  x=$(( x + widths[i] ))
done

# Set 2nd display as primary
xrandr --output "${displays[1]}" --primary
Arne Hartherz
Last edit
Arne Hartherz
License
Source code in this card is licensed under the MIT License.
Posted by Arne Hartherz to makandra dev (2025-02-06 07:20)