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:
- Global options:
--dpi 276sets the DPI to276.--fb 7040x3960creates one screen with resolution7040x3960. This is the combined resolution of the two monitors. The high DPI monitor has3200x1800resolution. The lower DPI monitor has1920x1080resolution, but I double it as I scale it by 2 (see below). Combine these like so:3200+1920*2 x 1800+1080*2 = 7040x3960. Both monitors share this screen.
- High DPI monitor options (
--output eDP-1):--mode 3200x1800says to use resolution3200x1800. This is the default, but specifying it is necessary if the monitor is disabled (as it is when using the external monitor by itself) as it enables the monitor.
- Lower DPI monitor options (
--output DP-1-2):--scale 2x2is similar to zooming out. This is necessary as we set the DPI globally to that of the high DPI monitor.--pospositions it to the right of the laptop monitor.--panningallows our pointer to access the whole area.
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:
- The
xrandr(1)man page. It breaks downxrandr's options by those that apply globally vs. those that apply per output which I found helpful. - The Arch Linux wiki HiDPI
article. This article has
a lot of good high DPI related information, including many
xrandrexamples.
Tags: Linux, cli, xrandr, monitors, laptop