Linux High DPI Settings

I recently got a laptop with a High DPI screen. These notes document what I had to do to make it usable with OpenBox. They should be relevant to other window managers as well. If you aren't using Linux, move along...nothing to see here.

I am told that with Windows or Mac, everything just works with a high resolution screen. Gnome and KDE are getting good at it too. But I run OpenBox with a boring theme, for one simple reason. When I take screen shots for a new edition of one of my books, I don't need to worry about changing window decorations and UI elements.

For many years, I didn't have to touch my window manager setup. But I recently got a new laptop with a “WQUXGA” display (3840 x 2400), and everything was teensy-tiny when I booted into OpenBox.

At first I didn't care because my external monitor didn't change, and just set the resolution to 1920x1200. But when I traveled over Christmas, I got curious. Would it be nicer at full resolution?

Yes, it was. The fonts were amazingly crisp. So I had to get to work.

Basic Settings

As always, the Arch wiki is an outstanding resource, even for users of other Linux flavors. (I use Ubuntu.) I was a bit overwhelmed by the level of detail, and it turns out I didn't need quite as much.

This article points out that 90% of the problems can be cured by setting the Xft.dpi setting used by the X11 font renderer.

~/.Xresources
Xft.dpi: 192

Now the fonts are correctly sized.

I have a script to switch between video modes. The script looks at the external monitor (if any) and dual screen options, then computes an optimal display layout. It sets Xft.dpi to 192 or 96 in ~/.Xresources, depending on the chosen resolution.

Unfortunately, apps do not use the font measurements to scale the user interface. In HiDPI, icons are tiny and scroll bars are skinny. With GTK based apps, set two environment variables:

~/.bashrc
RES=$(grep Xft.dpi ~/.Xresources | grep -Eo '[0-9]+')

if ((RES > 100)) ; then
  export GDK_SCALE=2
  export GDK_DPI_SCALE=0.5
else
  export GDK_SCALE=1
  export GDK_DPI_SCALE=1
fi

Some non-GTK apps also follow these settings.

For some GTK apps, you can dynamically switch settings by running:

  gsettings set org.gnome.settings-daemon.plugins.xsettings overrides "[{'Gdk/WindowScalingFactor', <$GDK_SCALE>}]"
  gsettings set org.gnome.desktop.interface scaling-factor $GDK_SCALE
  gsettings set org.gnome.desktop.interface text-scaling-factor $GDK_SCALE

For these to have an effect, you must have the daemon /usr/libexec/gsd-xsettings running. Or you could use xsettingsd, as explained here.

This is all you need for Emacs, Firefox, Electron apps (such as VS Code), and Java apps, provided you use a recent JVM. I use Java 17.

There are similar variables for KDE, but I don't currently use any KDE apps.

Support for fractional scaling is said to be poor. Fortunately for me, a HiDPI scale factor of 2 is perfect.

OpenBox Decorations

OpenBox knows nothing about DPI, and the window decoration images are in the archaic XBM format. I simply made two copies of my OpenBox theme. In one of them, I scaled up the XBM images with ImageMagick and adjusted the widths in themerc. Then I symlink either the original or the scaled theme, depending on whether I use only the laptop or an external monitor.

Pro tip: After changing .Xresources and the theme, run

openbox --restart

and it picks up the new values.

GTK3 Theme

It should be possible to find or make a single theme that is independent of DPI. The CSS files should use em/rem units instead of px, and the user interface images should be SVG. But I had an existing theme that I did not want to edit. I followed the same approach as with OpenBox, making an unscaled and a scaled copy. To change themes, call

gsettings set org.gnome.desktop.interface gtk-theme Cay-$DPI

Mouse Cursor

This Arch wiki has all the gory details about cursor themes. The cursor size is defined in two files:

~/.config/gtk-3.0/settings.ini
gtk-cursor-theme-size=16
~/.Xresources
Xcursor.size: 16

In HiDPI mode, I change both to 32. (OpenBox reads the latter setting.)

With GTK apps, you can dynamically change the cursor size with

gsettings set org.gnome.desktop.interface cursor-size $CURSOR_SIZE

Rofi

I use Rofi for an app switcher, app launcher, clipboard manager, and a logout dialog. As far as I can tell, it makes no effort to determine DPI, but it has a -dpi command-line option. I have ~/bin on my PATH and provide

~/bin/rofi
RES=$(grep Xft.dpi ~/.Xresources | grep -Eo '[0-9]+')
if [[ $(basename $0) == "dmenu" ]] ; then
  /usr/bin/rofi -dpi $RES -dmenu $@
else
  /usr/bin/rofi -dpi $RES $@
fi

Tint2

Does one need a panel? The area with an icon for each open application, and a “tray” of icons for the various gizmos that control networking, Bluetooth, battery, and so on. I think I could probably do without it, but out of habit, I have one. On the left, not the bottom, of the screen, because vertical screen real estate is precious. (When I had to use Windows at work, I was shocked to find out you can't put what they call the “task bar” on the left. )

I used to use lxpanel, but it doesn't support HiDPI, so I switched to tint2. Make the following setting:

~/.config/tint2/tint2rc
scale_relative_to_dpi = 96

Then tint2 figures out the actual DPI and scales accordingly.

Dunst

This utility handles notifications. The following setting enables autoscaling:

~/.config/dunst/dunstrc
scale = 0

To restart:

killall dunst
notify-send "DPI changed to $DPI"

Xfe

Does one need a file manager? I could just use Treemacs, and I often do. Still, I like to explore my file system outside Emacs, and my preferred file manager is X File Explorer (Xfe). It uses yet another weird toolkit that doesn't seem to be HiDPI aware. But there is a setting

~/.config/xfe/xferc
screenres=192

Swisswatch

.jpg

I like to have an analog clock on my desktop so that I can tell the time at a glance. This seems like a basic thing, but it is not an option in Windows, Mac OS, or the major Linux environments. All they give you is a lame digital clock that doesn't tell the time at a glance. I mean, what's faster? Looking at the clock to the right or decoding 12:40?

I use the venerable Swisswatch program that draws a replica of the Swiss railroad clock. The program is so ancient that it has no concept of anything but pixels. That's ok. I invoke it with a script

RES=$(grep Xft.dpi ~/.Xresources | grep -Eo '[0-9]+')
GEOMETRY="$((72*RES/96))x$((72*RES/96))-$((24*RES/96))+$((24*RES/96))"
swisswatch -geometry $GEOMETRY $@

The Console Font

When the laptop boots, or if one leaves X11 (with a key such as Ctrl+Alt+F1), the console font is tiny. To change it, run

sudo dpkg-reconfigure console-setup

Pick “Let the system select a suitable font”, then the size 16x32.

Conclusion

People always complain about the pain of the Linux desktop. And superficially, this blog post seems to back that up. It took me several days of tinkering to adapt to the HiDPI situation. Windows or Mac OS would have just taken care of it.

But there is a cost. I recently had to use a Windows laptop for an extended period, and found it intensely painful, even with WSL2. Taskbar on the bottom. Terrible app switcher. Crappy digital clock. WSL glitches with time synchronization. WSL terminals that die whenever Windows decides to update. Which is often. And of course, the inevitably changing window decorations. Or take my Mac. Please. No menu accelerators. Gratuitously different BSD commands. And of course, the inevitably changing window decorations.

The Linux desktop gives me control. (As Vladimir Lenin supposedly said: “Trust is good. Control is better.”) I get to choose the apps that work for me, and adapt them as necessary. A readily available scripting environment lets me automate menial configuration tasks. And I get to decide when to switch to the shiny new thing, or keep the boring old one.

Comments powered by Talkyard.