What the core practical problems with HiDPI seem to be on Linux

April 24, 2018

As I've been planning for some time, I recently got a new high-resolution, high pixel density monitor now that my new home machine can drive one. Specifically I got the 27" Dell P2715Q, which still appears to be the best overall choice for a 4K HiDPI monitor. As I expected, switching over to a HiDPI display in my unusual fvwm-based X environment has not been a trouble-free experience where things just worked. After wrestling with various issues, I have formed some opinions on what the core problems seem to be.

The first issue is the mess of telling things about the display's DPI. There are four places where this can be specified that I know of; there is the X server's own information about the DPI (as visible in eg xdpyinfo), the separate set of information xrandr can tell you about, the Xft.dpi X resource, and XSettings settings, which can apparently set both the XFT DPI and a separate Gdk/UnscaledDPI setting that may override that. As it turns out, there is also a Gdk/WindowScalingFactor XSetting (see the list in gdksettings.c). The interaction of these various settings is somewhat confusing and contradictory. To add additional fun, many programs ignore some of them, especially the server's listed DPI, because it's historically been inaccurate.

What the DPI directly affects is how modern XFT fonts get rendered by Fontconfig and FreeType. In theory, if the DPI is set correctly your fonts are now the right size for your HiDPI display, and in practice this more or less works. However, fonts are at most half of your problems on HiDPI displays.

The second and larger issue is that you also need programs to scale up their user interface elements, such as icons, and, unlike DPI, there is nothing that even pretends to be a global setting for this. Since this scaling is independent of DPI, it's quite possible to get into a situation where your fonts are correct but programs are rendering their controls in miniature. How this happens (or doesn't happen) varies from toolkit to toolkit and desktop to desktop, and is generally complicated.

If your DPI is high enough and your display has enough pixels, it seems to be common for programs and toolkits to automatically engage a scaling mode. This example from Fedora's Anaconda seems to be typical; it doubles things if, well, let me quote from the comment:

Check if this monitor is high DPI, using heuristics from gnome-settings-dpi. If the monitor has a height >= 1200 pixels and a resolution > 192 dpi in both x and y directions, apply a scaling factor of 2 so that anaconda isn't all tiny[.]

Now my life gets awkward. The honest DPI setting for the Dell P2715Q is 163 DPI, which is under the 192 DPI that will trigger automatic scaling. However, the Dell definitely needs scaling; unscaled UI elements are far too small. One option is to lie about the display DPI; however, this distorts all font sizing, including in programs and toolkits that don't expose any good way of adjusting the font size by hand (at least, not outside of their desktop environment).

(This heuristic is also not guaranteed to work in all toolkits and for all programs.)

Fortunately there are often ways to manually tell things to scale their UI up, as covered in the Arch Wiki entry on HiDPI. What you want to do depends on the toolkit, and it also depends on whether various magic bits of the toolkit work right (the QT automatic scaling doesn't seem to work for me, for example). Another gotcha is how this interacts with the DPI settings, as illustrated by GDK 3. If you want ordinary, non-toolkit applications that use XFT fonts to scale their fonts correctly, you must set the X DPI to a suitable high value (whether honest or otherwise). This will also scale fonts in GDK 3 applications, but it won't scale GDK 3 UI elements (unless your DPI is above the magic threshold). If you want to explicitly scale GDK 3 UI elements, you must force scaling:

export GDK_SCALE=2

However, this scales everything in GDK 3 applications, including their fonts, which are already properly scaled because of the X DPI; the result is a decent sized UI but giant fonts. In order to return fonts back to where they started, you must tell GDK 3 to un-scale the text again:

export GDK_DPI_SCALE=0.5

(Fiddling with XSettings might work around this.)

If you don't set the DPI to a high value (as GDK 3 sees it), then force scaling, and don't force scaling the DPI down again, your GDK 3 applications will probably look mostly correct but your setup is subtly wrong and some programs may turn out to not work quite right. This is easy to overlook, especially since GDK 3 may be looking at a different source of DPI information than other programs are.

(You might have one DPI set in the X server and in the Xft.dpi X resource, while having another old one in XSettings.)

Another problem with scaling in general is that many environments only support scaling by integers at the moment, and this scaling is generally applied to pixel sizes. You can have a 2x or 3x GDK UI, but you can't have, say, a 1.5x GDK UI. This is relevant due to two things. First, you may not be doubling your DPI; I'm moving from a 94 DPI U2412M to a 163 DPI P2715Q, for an actual ratio of about 1.73. Second, you may well have wound up with an X setup where some toolkits and desktops were ignoring the DPI information and assuming 96 DPI. For me this makes only a slight difference (a 1.69 scaling factor instead of 1.73), but it can leave you further away from a 2x scaling than before.

(This assumption of 96 DPI coupled with a simple 2x scaling explains the heuristic of engaging scaling at 192 DPI. Note that it's surprisingly hard to get a true 192 DPI in a desktop display that you want to use; even a 24" 16:9 4K display is only about 184 DPI. To reach 192 DPI, I believe you're looking at a 5K display in general or a 21" 4K display.)

Individual applications may have options to fine-tune either their font sizing or their UI or both. Large and complex applications like Firefox and Chrome may or may not behave in the same way as other desktop or toolkit applications, even with the same settings, because they have their own set of heuristics and hacks (cf) in order to work around issues that they can't wait for the toolkits and desktops to fix. On the positive side, you can probably make them work even in non-mainstream environments like mine.

If we're lucky, Wayland will fix all of this by blowing up the world.

PS: I'm ignoring the issue of web browsers deciding how and when to scale images (or CSS pixels), and by how much. Just hope they get it acceptably right.

PPS: Sometimes HiDPI leads to fun Emacs bugs. Yes, I'm grumpy, although I have to admit that this display does look pretty nice when everything is going well.

Comments on this page:

By James (trs80) at 2018-04-25 10:38:29:

Yeah, 4K on 27" is right in the bad zone for Retina: https://bjango.com/articles/macexternaldisplays/

Written on 24 April 2018.
« ZFS's recordsize as an honest way of keeping checksum overhead down
An implementation difference in NSS netgroups between Linux and Solaris »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Apr 24 01:54:46 2018
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.