The One and the Many

Configuring mixed DPI monitors with xrandr

I've recently started using a high DPI laptop together with a regular DPI monitor in a dual monitor setup. While there are GUI tools to configure dual monitors, I wanted to do it through the CLI. The usual way to configure monitor settings via the CLI in Linux is with a program called xrandr. As it took me a bit of trial and error to get everything working well, I thought it would be useful to write about the commands I settled on and how they work.

The setup

The laptop sits on the left of the monitor. The tops of both line up.

Usually I want to use both monitors at the same time. However I've found it necessary to disable one of them, usually the laptop, when I want to share my screen. This means it is important that I can easily switch back and forth between dual and single monitors.

It is also important that I retain the ability to use the laptop without the external monitor.

The tricky parts

There were two aspects I found problematic:

First, the fact that the two monitors have differing DPI means each monitor needs different settings to account for that. xrandr allows setting the DPI via --dpi, but this applies globally to all monitors. I dealt with this by setting the global DPI to that of the highest DPI monitor, and then used --scale to adjust the lower DPI monitor.

Second, switching back and forth between dual monitors to one monitor lead to interesting behaviour. For example, I kept losing the scale setting on the lower DPI monitor.

I had a semi-working setup with little trouble, but it involved restarting X when I wanted to switch between dual and single monitors. This worked, but obviously was inconvenient. I wanted a solution that would work without restarts.

The solution

I came up with two xrandr commands. One configures to use both monitors, and the other configures to use only the external monitor.

Dual monitors

When I want to use both monitors, this is the command I run:

xrandr --dpi 276 --fb 7040x3960 \
    --output eDP-1 --mode 3200x1800 \
    --output DP-1-2 --scale 2x2 --pos 3200x0 --panning 3840x2160+3200+0

Here's an explanation of the options:

Single monitor (external)

If I want to use only the lower DPI monitor, then I run this command:

xrandr --dpi 276 --fb 3840x2160 \
    --output eDP-1 --off \
    --output DP-1-2 --scale 2x2 --panning 3840x2160

Most of these options are similar to the first command's. The main difference is disabling the laptop monitor with --output eDP-1 --off.

Note 3840x2160 comes from 1920*2 x 1080*2.

You might wonder why I set high DPI and scale the lower DPI monitor here. Wouldn't it be simpler to set a lower DPI and use the monitor's native resolution? That's possible, but since I've configured other things (such as my X terminal fonts) to a size suitable for a high DPI screen, I'd have to adjust settings elsewhere. Keeping the DPI the same and continuing to scale allows me to avoid that. Since I'm scaling, I need to configure a large screen and set panning for the same reasons as before.

Single monitor (laptop)

This is the default state prior to running any xrandr commands. In theory I could have another command for this, but so far I haven't needed to switch to this.

A final note: --mode vs --auto

I initially tried using --output eDP-1 --auto when I wanted to enable the laptop monitor after disabling it. However, I found this lost the --scale setting, so I had to either restart X or run the same xrandr command twice. Using --mode does not have this problem.

Resources

I did a bunch of searching figuring out this setup. The two best resources I found were these:

Tags: Linux, cli, xrandr, monitors, laptop