Dec 24, 2020 Tags: workflow
This post is at least a year old.
I recently switched my home office to a 2-by-4K HiDPI setup, like so:
As part of that switch, I needed to configure parts of my Linux environment (which was originally stock Ubuntu, but is now i3 with a heavily customized userspace) to function correctly on HiDPI displays.
This post will document most of the changes I applied. Hopefully others will find it useful for their own HiDPI setups.
As it turns out, there’s a (nearly) one-stop location for configuring the default DPI for
X11 applications: the Xft.dpi
setting.
There are lots of ways to configure X11, but I personally use an ~/.Xresources
file:
1
2
3
Xft.dpi: 163
# not used directly; more on this later
janus.fractionalDpi: 1.63
Where 163
and 1.63
are my DPI and its fractional form, respectively.
On my system, ~/.Xresources
gets loaded into the X resource database automatically by some
magic that I never configured. However, if yours doesn’t (or you use a different resource file),
you can always tell i3 (or your WM of choice) to load it explicitly with xrdb
.
For example, in ~/.config/i3/config
:
1
exec --no-startup-id xrdb ~/.Xresources
With just this, about 90% of my applications (including GTK based ones, like Firefox) scaled correctly and were usable without any font or custom scaling changes. Not bad for a single line!
Spotify’s Linux application is a CEF
shell. For reasons that are unclear to me, it doesn’t respect Xft.dpi
while normal Chromium
(via snap
or apt
) does.
To get it to scale correctly, I needed to pass --force-device-scale-factor=1.63
to it:
1
spotify --force-device-scale-factor=1.63
At this point, it became clear to me that the fractional form of my DPI would be nice to set in
as few places as possible, to avoid duplication. Hence the janus.fractionalDpi
1 above,
and
this little spotify
wrapper:
1
2
3
4
5
6
# see the actual script linked above for some program-finding stupidity
real_spotify=/snap/bin/spotify
# grab the correct fractional DPI from the X resource DB
dpi=$(xrdb -query | grep "$(hostname).fractionalDpi" | cut -f2)
"${real_spotify}" --force-device-scale-factor="${dpi}" "${@}"
I use Sublime Text 3 as my primary editor. As far as I can tell
it doesn’t use either GTK or Qt (or any other open-source GUI framework), which is probably why
it doesn’t respect Xft.dpi
.
To get Sublime Text to scale correctly, I had to set ui_scale
to the appropriate fractional DPI
in my user preferences (~/.config/sublime-text-3/Preferences.sublime-settings
):
1
2
3
{
"ui_scale": 1.63,
}
Some lingering pain points:
Sublime Text’s input is noticeably laggy when the UI is scaled. It’s not so laggy as to be unusable, but it’s definitely noticeable even if you aren’t sensitive to latencies (I’m not).
Mousing between Sublime Text and other windows causes noticeable stutter/hiccuping during
video playback. I haven’t dug into the X events yet, but my guess is that it’s got some kind
of pessimistic (and serial) XFlush
or XSync
that takes a decent bit of time on a larger window
buffer. It doesn’t happen with smaller windows (either floating or fixed).
I haven’t used it recently, but I used to use OBS to stream myself working on open source projects.
When I switched monitors, I noticed that the embedded preview window for my scenes had stopped working. OBS itself was still fully functional and the separate preview window still worked, but the embedded preview was always filled in with black pixels.
After a decent bit of hair-pulling, I found a Qt environment variable that “fixed” it:
1
QT_AUTO_SCREEN_SCALE_FACTOR=0 obs
I still don’t understand why that fixed it, but now my OBS is scaled correctly and has a functional preview embed. I also posted this fix to the OBS forum.
I use feh
as my image viewer. By default, it seems to use
a bitmap font that’s incredibly small on HiDPI displays.
To fix it, I modified by default theme to use my distro supplied Ubuntu Roman-face font in 14pt.
In ~/.config/feh/themes
:
1
2
feh --borderless --scale-down --conversion-timeout 1 \
--fontpath /usr/share/fonts/truetype/ubuntu --menu-font Ubuntu-R/14
One thing I haven’t figured out: when I open some higher-resolution images in feh
, they’re
occasionally shifted to the right with transparent pixels where some of the image should be.
Clicking and dragging inside the image window causes it to re-render correctly, as does
resizing the window. Not a huge deal, but slightly annoying.
I use dunst
as my notification daemon.
It didn’t need any HiDPI-specific configuration, but I took the opportunity to make its notifications slightly more readable on these newer displays.
In ~/.config/dunst/dunstrc
(among many other settings):
1
2
3
4
5
6
monitor = 0
follow = mouse
geometry = "600x120-30+20"
icon_position = left
max_icon_size = 64
icon_path = /usr/share/icons/gnome/64x64/status/:/usr/share/icons/gnome/64x64/devices/
My new displays are individually larger and significantly more dense than my previous ones, making
my mouse feel sluggish. I originally configured my mouse acceleration with
xset
, but at some point my
system switched to libinput
and libinput
-based inputs apparently don’t respect xset
anymore
(or never did?). Sigh.
The fix is to use xinput
instead, with either symbolic names or XIDs for the device and setting
being controlled. For example, this is what I use to set my mouse’s acceleration to the maximum
(1.0
):
1
xinput --set-prop "USB Optical Mouse" "libinput Accel Speed" 1.0
Your device and setting names may vary, of course, as may their value ranges (mine happened to be
0.0
to 1.0
). You can use xinput
on its own to list the names and XIDs of your devices;
xinput list-props <XID-or-name>
can be used to dump a particular device’s properties and
their current values.
I use i3’s layout saving/restoring functionality to automatically load all of my workspaces and their applications when I log in.
Those layouts are stored in a (relaxed) JSON format via i3-save-tree
, and contain hardcoded
coordinates. To update them for my new monitors, I just had to recreate each of my workspaces
once on my new monitors and dump them:
1
2
# for each workspace (1A, 1B, ...)
i3-save-tree --workspace 1A > ~/.config/i3/workspaces/1A.json
…and then fix them up manually to enable the appropriate application swallowing rules.
I use HexChat for IRC.
HexChat’s config file includes individual offsets for each of the sub-panes in the GUI,
which means that it breaks badly if you change your monitor dimensions. I couldn’t figure out
how to fix them, so I ended up deleting my main ~/.config/hexchat/hexchat.conf
entirely and
recreating my preferred layout from memory. YMMV.
I didn’t have to make any changes with respect to my system icon sizes, which is probably because I actually see very few icons during normal i3 usage. Once again, YMMV.
Switching from a set of 3 FHD monitors to two 4K HiDPI ones was relatively painless. The problems that I had, unsurprisingly, were primarily with the few proprietary applications I use needing to be spoon-feed DPI information in their own ways — every other problem was either a bug (OBS + Qt) or a matter of more general reconfiguration.
janus
is my desktop’s hostname. ↩