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 276
sets the DPI to276
.--fb 7040x3960
creates one screen with resolution7040x3960
. This is the combined resolution of the two monitors. The high DPI monitor has3200x1800
resolution. The lower DPI monitor has1920x1080
resolution, 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 3200x1800
says 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 2x2
is similar to zooming out. This is necessary as we set the DPI globally to that of the high DPI monitor.--pos
positions it to the right of the laptop monitor.--panning
allows 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
xrandr
examples.
Tags: Linux, cli, xrandr, monitors, laptop