HiDPI on dual 4K monitors with Linux

Vincent Bernat

I have been using a Lenovo Thinkpad X1 Carbon laptop (210 DPI) for four years and a Nokia 8 phone (550 DPI) for a year. I enjoy their HiDPI screens: text is crisp and easy to read. To get a similar experience for my workstation, I bought a pair of Dell P2415Q monitors:

Two Dell P2415Q
Dual screen setup with two Dell P2415Q monitors

Monitors⚓︎

The Dell P2415Q is a 24” display featuring an IPS panel with a 3840×2160 resolution (185 DPI) and a complete coverage of the sRGB color space. It was released in 2015 and its price is now below $400. It received positive reviews.

One of my units arrived with a dead pixel. I thought it was a problem from the past but Dell policy on dead pixels says:

During LCD manufacturing process, it is not uncommon for one or more sub-pixels to become fixed in an unchanging state. A display with a 1 to 5 fixed sub-pixel is considered normal and within industry standards.

Update (2018.12)

Three new dead pixels have appeared. Therefore, I definitely do not recommend these screens.

Another issue is the presence of faint horizontal grey lines, (barely) visible on white background. The issue seems to not be uncommon but Dell is dismissive about it. If I sit correctly, the lines become invisible.

I am a bit disappointed by these issues, but I think they are bearable and it is an opportunity to help fix my obsession over such details.

Graphic card⚓︎

To drive a 4K display at 60 Hz, you need at least either HDMI 2.0 or DisplayPort 1.2. The Dell P2415Q has been upgraded to HDMI 2.0 in 2016 and also provides a DP 1.2 input. There is a port for daisy-chaining a second monitor but, without support for DP 1.3, the refresh rate would drop to 30 Hz.

There is currently no available Radeon card around $100 able to drive two 4K displays. On the Nvidia side, the GeForce GT 1030 fits the bill with a power consumption of 20 W for the DDR4 version. I opted for a passively cooled model from MSI. On Linux, the result is quite disappointing:

  • The nouveau driver has still rudimentary support for the this generation of Nvidia chips. The result was unbearably slow and the HDMI 2.0 port was not handled correctly.

  • The proprietary Nvidia driver exhibits poor performances. It’s difficult to know if this is due to the graphic card itself,1 or to the drivers. I’ve tested 390, 396, 410, 415 and 418. Moreover, suspend-to-RAM is broken.

Update (2019.05)

I have switched to an ASUS Phoenix Radeon RX 550. With such a card, everything runs smoothly, using the open source driver amdgpu. The card comes with a fan but it is PWM-controlled. See ArchWiki for more details. In automatic mode, when /sys/class/drm/card0/device/hwmon/hwmon1/pwm1_enable is set to 2, it spins at 1050 RPM:

$ sensors amdgpu-pci-0100
amdgpu-pci-0100
Adapter: PCI adapter
vddgfx:       +0.88 V
fan1:        1047 RPM
temp1:        +51.0°C  (crit = +94.0°C, hyst = -273.1°C)
power1:       17.20 W  (cap =  35.00 W)

HiDPI support on Linux with X11⚓︎

Gnome and KDE now supports HiDPI displays out of the box when running with X11. For other environments, it’s quite easy to setup, thanks to xsettingsd. The following snippet should be invoked from ~/.xsession or when the DPI value changes:

# Target DPI
dpi=192

# For applications supporting XSettings, `Xft/DPI' sets font scaling
# (and sometimes interface scaling), `Gdk/WindowScalingFactor' sets
# interface scaling with GTK 3, and `Gdk/UnscaledDPI' undo font scaling
# for GTK 3 applications.
> ~/.xsettingsd cat <<EOF
Xft/DPI $(( $dpi*1024 ))
Gdk/WindowScalingFactor $(( $dpi/96 ))
Gdk/UnscaledDPI $(( $dpi*1024/($dpi/96) ))
EOF
pkill -HUP xsettingsd || xsettingsd &

# For QT applications.
export QT_AUTO_SCREEN_SCALE_FACTOR=1

# For miscellaneous applications.
echo Xft.dpi: $dpi | xrdb -merge

Then, it is up to each application to know how to render on a HiDPI display. The table below gives an overview of HiDPI support for various ones, using the above settings. “Text scaling” indicates if an application is able to adapt the font size. This is usually the most essential feature. “Interface scaling” tells if it is able to scale the whole interface, including the icons. Ideally, applications are also expected to be able to dynamically update scaling when notified through XSettings, which is useful when switching to an external display.

Application Text scaling Interface scaling No restart needed?
Most QT 5 apps ✔️ ✔️ ✔️
Chromium2 ✔️ ✔️ ✔️
Most Electron apps4 ✔️ ✔️ ✔️
Firefox3 (GTK 3) ✔️ ✔️ ✔️
Blender5 ✔️ ✔️
Emacs 26.1 (GTK 3) ✔️ 😐 ✔️
VTE terminals (GTK 3) ✔️ 😐 ✔️
Most GTK 3 apps ✔️ 😐 ✔️
Gimp (GTK 2) ✔️ ✔️
Inkscape (GTK 2) ✔️ ✔️
Most GTK 2 apps ✔️ ✔️
Most Java apps6 🙄 🙄
xterm and rxvt (with Xft) ✔️ n/a
Most other applications

QT 5 applications offer very good support. GTK 3 applications can currenly only scale their interfaces using an integer factor, which is annoying when you need an 1.5× factor. GTK 2 applications will only scale the text and there are still many of them—notably Gimp. For more details, have a look at the dedicated page on ArchWiki. Beyond X11, Wayland is able to provide per-monitor scaling and to scale applications without HiDPI support.

In conclusion, today’s situation still depends heavily on the applications you run. As I spend most of my time in a VTE terminal, in Emacs and in Firefox, I am mostly happy with the result.


  1. Compared to my previous setup, the number of pixels is quadrupled. The card is using 4-lane links over PCI 3.0 which translates to a bandwidth of 25 Gbits/s. This barely allows the transfer of 7680×2160 pixels at 60 Hz using 24-bit colors. Also, the use of DDR4 for such a graphic card is seen as a cheap move↩︎

  2. To detect changes, Chromium watches for RandR events. They may be caught before XSettings variables are updated. ↩︎

  3. Firefox only watches the scaling factor but adapt its interface to match Xft/DPI. It needs a restart when the DPI changes but the window scaling stays the same. See bug #1554850↩︎

  4. If it doesn’t work, try with the --force-device-scale-factor=2 flag. ↩︎

  5. Blender relies on the Xft.dpi resource value. ↩︎

  6. Java applications need to be invoked with the GDK_SCALE=2 environment variable. Otherwise, they don’t scale. ↩︎

Share this article