Tuesday, January 7, 2014

Linux, retina / high-density displays, and external monitors

The issue

Currently most Linux desktop environments work rather poorly with high-density displays, and require a lot of manual tweaking. Recently, GNOME 3 added support for high-density displays, so the UI should automatically rescale itself properly for GNOME versions 3.10 and higher. Unfortunately, there's one slight issue: If you connect an external monitor, the text and icons are massive. This is because (as far as I know) GTK, X, and much of the substrata of renderers underlying the GUI only support a global DPI or scale setting for all monitors.

Workaround

However, there is (sort of) a workaround. We can manually rescale so that the the external monitor is correct, but the retina monitor has small text. (Presumably if you are using an external monitor, then your laptop monitor is not your main work monitor.) In this patch, we see that GNOME rescales windows based on the parameter scaling-factor in schema org.gnome.desktop.interface. Thus, all we have to do to manually set the scale factor is to run
gsettings set org.gnome.desktop.interface scaling-factor X
where X is 1 or 2, depending on how we want pixels to be normal-sized or enlarged. (If X is 0, then GNOME decides for you, but this may or may not be what you want.) For expedience, you can attach a hotkey to these commands, or you can detect xrandr events and rescale automatically.

Required packages

It turns out that only a very minimal set of packages need to be installed for this to work -- gnome-session and gnome-settings-daemon, at least version 3.10 or higher. Because of the sparse requirements, this can be adapted to work for all GTK applications in lightweight desktop environments / window managers (e.g. XMonad or awesome) so long as you start them via a minimal GNOME session. I also strongly recommend building xmonad-darcs and xmonad-contrib-darcs from the AUR because of a bug (see edit below).

Minimal .xinitrc + XMonad + GNOME example

A minimal way to get the above method working involves creating the following files:
~/.local/share/applications/xmonad.desktop:
[Desktop Entry]
Type=Application
Name=Xmonad
Exec=xmonad
NoDisplay=true
X-GNOME-WMName=XMonad
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=windowmanager

~/.config/gnome-session/sessions/xmonad.session:
[GNOME Session]
Name=Xmonad/GNOME
RequiredComponents=gnome-settings-daemon;xmonad
Make sure you use gnomeConfig in your xmonad.hs. Then end your ~/.xinitrc with
exec gnome-session --session=xmonad
This will execute a minimal GNOME session instance which only runs gnome-settings-daemon, xmonad, and almost nothing else.

Edit (2014-07-16): With the latest version of D-Bus and with XMonad 0.11, gnomeConfig from XMonad.Config.Gnome doesn't properly register XMonad to GNOME, so you'll see a GNOME error dialog upon starting your XMonad-Gnome session. This has been fixed in XMonad-Contrib 0.12 from the AUR.

1 comment:

  1. Thanks for sharing the info, keep up the good work going.... I really enjoyed exploring your site. good resource...modem router combo reviews

    ReplyDelete