X11 Multiple Monitor DPI trick
One issue with x11 is that there is no per monitor dpi property, there is only a global dpi property. Hidpi content doesn’t work properly on windows either as windows will simply upscale windows when using different dpi per monitor, making the window content blurry, unless the application supports different dpi per monitor. This is also an issue under wayland as currently compositors simply upscale xwayland applications, making them blurry. A solution for this with x11 is to set the monitor scale with xrandr to make a monitor behave as if it’s using a large resolution than it actually is and then setting programs dpi scaling with
Xft.dpi. This will downscale windows instead, which results in better quality than upscaling.
Assuming you have a 3840x2160 (4k) monitor and a 1920x1080 (full hd) monitor and you want to set dpi to 200% for the 4k monitor because otherwise everything looks to small, then you can set
~/.Xresources (a value of
96 is the default dpi (100%)). The
~/.Xresources file should be applied in your
~/.xinitrc file by calling
xrdb -merge ~/.Xresources (if you use a minimal window manager such as dwm). However that will now make everything too large on the full hd monitor. To downscale the full hd monitor we can use
xrandr --output DP-2 --mode 1920x1080 --pos 3840x0 --filter bilinear --scale-from 3840x2160 (use
--pos with your own values to offset the monitor to the left/right/top/bottom of the other monitor and set the
--output to your full hd monitor).
This can also be done using the nvidia-settings gui by going into
X Server Display Configuration and changing
Panning for the 1920x1080 monitor to 3840x2160.
The general idea is to set a
Xft.dpi value that works best for your highest resolution monitor and then using xrandr’s
--scale-from option for the other monitors with a value that matches the resolution of the highest resolution monitor.
The bilinear filter is not perfect, but it looks much better than upscaling a window. There is a better filter called convolution but its not supported by xrandr or glamor. Adding support for a convolution filter for xrandr and glamor could be done trivially easy and all applications will look about as crisp as without any scaling without having to modify any client applications.
Here is a video that demonstrates what changing dpi to 200% looks like when using a 3840x2160 monitor and a 1920x1080 monitor:The full hd monitor on the right has too high dpi. We want content on both monitors to look the same size. To fix that, we downscale the full hd monitor from 3840x2160 to 1920x1080 using the
--scale-from 3840x2160xrandr option with the full hd monitor. The result can be seen here: