Zmiana DPI w Openbox/Xorg dla monitora HiDPI

Spis treści

Jeśli mieliśmy do czynienia z monitorami wysokiej rozdzielczości, to za pewne natrafiliśmy na problem zbyt małych czcionek, które czyniły interfejs aplikacji w naszym linux'ie mało czytelnym. W przypadku środowisk graficznych takich jak GNOME czy KDE5/Plasma5 skalowanie interfejsu i czcionek powinno odbywać się automatycznie (jeśli nasz ekran ma 192+ DPI i rozdzielczość 1200+ pikseli) lub też za sprawą drobnej zmiany w konfiguracji, tak by użytkownik mógł w miarę komfortowo korzystać z systemu. O ile w przypadku tych pełnowymiarowych środowisk graficznych można w zasadzie przełączyć tylko jedną opcję i wszystkie jego aplikacje powinny zostać z powodzeniem odpowiednio zeskalowane, o tyle problem zaczyna się w momencie, gdy mamy mieszane aplikacje lub też zwyczajnie używamy jedynie prostego menadżera okien dla Xserver'a, np. Openbox i do tego jeszcze nasz wyświetlacz ma mniejsze DPI niż 192. W takiej sytuacji konfiguracja interfejsu użytkownika i czcionek dla ekranów wysokiej rozdzielczości może być nie lada wyzwaniem.

Skalowanie interfejsu w Openbox

Środowisko, w którym użytkownik linux'a pracuje, można podzielić na graficzne oraz tekstowe (TTY), do którego można się przełączyć za pomocą klawiszy ctrl+alt+F1 . Spora część użytkowników tego alternatywnego systemu korzysta z gotowych rozwiązań pokroju KDE5/Plasma5 czy też GNOME ale są też wśród nas tacy użytkownicy, który lubią konfigurować sobie środowisko pracy samodzielnie i używają jedynie prostego menadżera okien typu Openbox.

Niezależnie jednak od wykorzystywanego środowiska mamy możliwość korzystania z przeróżnych aplikacji, np. tych mających interfejs GTK3 lub QT. W ich przypadku przy pomocy pewnych zmiennych systemowych można wpłynąć na wygląd appki wykorzystującej określony interfejs graficzny. Niemniej jednak, niektóre programy zdają się ignorować ustawienia systemowe i trzeba do nich podejść indywidualnie, np. aplikacje GTK2.

Widać zatem, że w przypadku Openbox konfiguracja interfejsu aplikacji oraz czcionek na ekranach wysokiej rozdzielczości może być ździebko problematyczna. Dlatego też poniżej postanowiłem zebrać do kupy wszystkie te informacje, które mogą pomóc w konfiguracji DPI w takich monitorach.

Jak wyliczyć optymalny DPI

Po przesiadce ze startego laptopa na nowy okazało się, że zmianie uległa nie tylko przekątna ekranu (17" -> 14"), ale również i rozdzielczość (1360x768 -> 1600x900). Zatem z jednej strony zmniejszeniu uległy wymiary wyświetlacza, a jednocześnie wzrosła ilość pikseli. Tego typu sytuacja efektywnie zwiększyła DPI (Dots Per Inch) monitora, przez co te same elementy, które miałem na pulpicie starego laptopa, teraz były sporo mniejsze i komfortowo na nie się patrzeć już nie daje. Jak bardzo zatem zmieniło się DPI?

Standardowo w linux wyświetlacz ma 96x96 DPI. Znając rozdzielczość ekranu oraz jego wymiary, można to DPI wyliczyć. Wszystkie potrzebne nam wartości można zwykle wydobyć z xdpyinfo :

$ xdpyinfo | grep -B2 resolution
screen #0:
  dimensions:    1600x900 pixels (423x238 millimeters)
  resolution:    96x96 dots per inch

Trzeba jednak tutaj uważać, bo wymiary podane wyżej w dimensions są określane na podstawie tej wartości co siedzi w resolution . Zatem nie zawsze te fizyczne wymiary wyświetlacza mogą być prawidłowe i w tym przypadku nie są.

Jeśli mamy wątpliwości, to rzućmy okiem również na wyjście xrandr :

$ xrandr | grep -w connected
LVDS-1 connected primary 1600x900+0+0 (normal left inverted right x axis y axis) 309mm x 174mm

Tu z kolei mamy 309x174 mm.

Możemy też spróbować wyliczyć te wymiary w oparciu o twierdzenie Pitagorasa i natywną rozdzielczość ekranu, choć nie zawsze dla każdego monitora się to da zrobić:

$ echo 'scale=5;sqrt(1600^2+900^2)' | bc
1835.75597

$ echo 'scale=5;(14/1836)*1600*25.4' | bc
309.67680

$ echo 'scale=5;(14/1836)*900*25.4' | bc
174.19320

Jak widać, wynik jest bardzo zbliżony do tego, który został określony przez xrandr . A jakie wymiary ma wyświetlacz tego laptopa w rzeczywistości? Okazuje się, że po zmierzeniu go metodą manualną ma jakieś 310x174 mm. Można zatem przyjąć, że wartości, które zwrócić xrandr są prawidłowe, a ewentualne różnice zwalić na błędy pomiarowe albo błędy przyrządów pomiarowych. Tak czy inaczej, dysponując wiarygodnymi wymiarami ekranu możemy wyliczyć jego DPI w poniższy sposób:

3096/254 = 12.19
1742/254 = 6.86

Wartości 3096 i 1742 to pomnożone przez 10 wymiary monitora w mm (i do tego zaokrąglone), a 254 to 2.54 (1 cal) pomnożone przez 100. Teraz wystarczy podzielić rozdzielczość w pikselach przez te wyżej otrzymane wymiary w calach:

1600/12.19 ≈ 131.25
900/6.86 = 131.19

Można zatem przyjąć, że DPI dla tego monitora to 132x132, a nie 96x96. Zatem interfejs aplikacji i tekst powinny zostać zeskalowane do 137,5%, by były mniej więcej takiej samej wielkości co na ekranie starego laptopa.

Zgodnie z tym co można wyczytać na wiki Archlinux, to możemy sobie ustawić dowolną wartość DPI. Powinniśmy jednak się trzymać wartości 96 (+0%), 120 (+25%), 144 (+50%), 168 (+75%), 192 (+100%) i podobnych. Gdy zamierzamy korzystać z innych niestandardowych DPI, takich jak nasz 132, to mogą wystąpić problemy w przypadku interfejsów aplikacji wykorzystujących bitmapy. Zatem jeśli chodzi o monitor w tym laptopie, to najlepiej by było się posłużyć wartością DPI 144 albo 120. Niemniej jednak, zeskalowany interfejs w oparciu o te 120 DPI w przypadku tego monitora, to trochę za dużo i postanowiłem ustawić DPI na 108. Póki co nie zaobserwowałem żadnych problemów natury wizualnej.

DPI dla Xorg i SDDM

Konfigurację DPI najlepiej rozpocząć od skonfigurowania Xorg'a, a ta sprowadza się do podania argumentu -dpi w poleceniu uruchamiającym Xserver. Pytanie tylko jak uruchamiany jest Xserver? Zwykle wykorzystywany jest do tego celu jakieś menadżer logowania, np. SDDM. W takiej sytuacji trzeba wyedytować konfigurację SDDM i zmienić w pliku /etc/sddm.conf.d/sddm.conf poniższą linijkę:

ServerArguments=-nolisten tcp -dpi 108

Warto w tym miejscu wspomnieć, że SDDM niby jest w stanie włączyć automatyczne skalowanie interfejsu aplikacji QT dla ekranów wysokiej rozdzielczości za sprawą opcji EnableHiDPI w [Wayland]/[X11] ale w moim przypadku to automatyczne skalowanie nie działa za dobrze. A poza tym, to i tak ono dotyczy jedynie aplikacji QT. Dlatego też odradzałbym ustawianie EnableHiDPI w konfiguracji SDDM.

Po określeniu -dpi w ServerArguments trzeba zrestartować środowisko graficzne, by zmiany zaczęły obowiązywać. Jeśli interfejs zdaje się być za bardzo powiększony, to możemy nieco obniżyć wartość parametru -dpi . W razie problemów lub wątpliwości zajrzymy do pliku /var/log/Xorg.0.log , bo tam powinna znajdować się informacja o DPI ustawionym przez Xserver:

# egrep DPI /var/log/Xorg.0.log
[    83.172] (++) modeset(0): DPI set to (108, 108)

DPI dla startx

Jeśli zaś korzystamy ze startx , to musimy edytować plik /etc/X11/xinit/xserverrc i w nim dopisać parametr -dpi :

exec /usr/bin/X -nolisten tcp -dpi 108 "$@"

DPI w Openbox

Jeśli chodzi zaś o samego Openbox'a, to tutaj zbytnio nie konfiguruje się DPI, bo wszystkie ustawienia powinny być dziedziczone od Xserver'a, jeśli tylko oczywiście określiliśmy mu parametr -dpi . Możemy za to, określić DPI dla konkretnego monitora dopisując w pliku autostartu ~/.config/openbox/autostart tę poniższą linijkę:

xrandr --dpi 108/LVDS

Jeśli zaś chodzi o LVDS , to wyciągamy tę wartość z wyjścia xrandr :

$ xrandr | grep connected
LVDS-1 connected primary 1600x900+0+0 (normal left inverted right x axis y axis) 309mm x 174mm
VGA-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-2 disconnected (normal left inverted right x axis y axis)
HDMI-3 disconnected (normal left inverted right x axis y axis)
DP-2 disconnected (normal left inverted right x axis y axis)
DP-3 disconnected (normal left inverted right x axis y axis)

Aplikacje QT i GTK2/GTK3

Jeśli mamy problemy z czcionkami w przypadku aplikacji wykorzystujących interfejsy QT i GTK3, to musimy w nich osobno skonfigurować DPI i do tego celu będzie nam potrzebny zestaw zmiennych środowiskowych. Te zmienne trzeba będzie wyeksportować w dwóch miejscach. Pierwszym z nich jest konfiguracja shell'a (zwykle ~/.bashrc lub ~/.zshrc ), a drugim jest plik ~/.config/openbox/environment . Poniżej są potrzebne zmienne:

export GDK_SCALE="1"
export GDK_DPI_SCALE="1.125"

#export QT_AUTO_SCREEN_SCALE_FACTOR="0"
#export QT_SCALE_FACTOR="1.125"
export QT_SCREEN_SCALE_FACTORS="LVDS-1=1.125;"
export QT_FONT_DPI="108"

Skalowanie aplikacji GTK3 jest określane przez zmienne GDK_SCALE oraz GDK_DPI_SCALE . Ta pierwsza zmienna przyjmuje jedynie całkowite wartości i w moim przypadku ustawienie tutaj 2 powiększało interfejs dość znacznie, dlatego tutaj ustawiłem 1 . Z kolei GDK_DPI_SCALE ma wartość wskazywaną przez DPI, które ustawiliśmy wcześniej (108/96=1.125).

Problemem natomiast mogą być aplikacje GTK2, w których nie ma wsparcia dla skalowania interfejsu. Jedyną opcją w ich przypadku jest zmigrowanie na odpowiednik GTK3, bo wiele aplikacji takowym dysponuje.

Jeśli zaś chodzi o zmienne dotyczące interfejsu QT, to mamy tam w zasadzie QT_AUTO_SCREEN_SCALE_FACTOR , który odpowiada za automatyczne skalowanie interfejsu (to samo co było w konfiguracji SDDM) i w tym przypadku zostało wyraźnie określone, że nie chcemy autoskalowania interfejsu, bo mamy do czynienia z monitorem, który ma DPI mniejsze niż 192. Dlatego też trzeba ustawić albo QT_SCREEN_SCALE_FACTORS , albo QT_SCALE_FACTOR . Różnic między tymi dwiema zmiennymi jest kilka. Jeśli ustawimy QT_SCALE_FACTOR , to zarówno interfejs jak i czcionki zostaną przeskalowane i to na wszystkich podłączonych monitorach. Określenie samego QT_SCREEN_SCALE_FACTORS wpłynie jedynie na skalowanie interfejsu dla konkretnego monitora (pary argument=wartości trzeba oddzielić ; ). Jeśli dodatkowo czcionki mają ulec skalowaniu, to trzeba określić również QT_FONT_DPI w stosunku do QT_SCREEN_SCALE_FACTORS . Mając dwie osobne zmienne można inaczej zeskalować interfejs aplikacji, jak i tekst jeśli tego typu funkcjonalność nas interesuje.

Pozostałe aplikacje GUI

Te powyższe ustawienia powinny w zasadzie zeskalować interfejs sporej części aplikacji, z których korzystamy na co dzień. Niemniej jednak, nie wszystkie aplikacje będą nam szły na rękę i rysować się zgodnie z podanymi im instrukcjami. Pomijając aplikacje GTK2, które nie mają zaimplementowanego wsparcia dla skalowania, to niektóre appki mogą albo ignorować wszystkie te powyższe ustawienia, albo też nie do końca ustawiać je poprawnie. Poniżej jest lista tych aplikacji, które u mnie sprawiały problemy i wymagały dodatkowego dostosowania.

Firefox i Thunderbird

W zasadzie te aplikacje wykorzystują interfejs GTK3 i skalują się bez problemu ale trochę za bardzo -- ich interfejs jest ździebko za duży w stosunku do pozostałych aplikacji. Jeśli nam nie odpowiada nowy wygląd Firefox'a czy Thunderbird'a, to w ich zaawansowanych ustawieniach ( about:config ) można określić ten poniższy klucz:

layout.css.devPixelsPerPx = 1.125

Domyślnie layout.css.devPixelsPerPx przyjmuje wartość -1 , która nakazuje Firefox'owi i Thundebird'owi korzystać z ustawień systemowych. Każda inna wartość sprawi, że te aplikacje przeskalują swój interfejs niezależnie.

Tint2

Tint2, to aplikacja GTK2. Na szczęście deweloperzy umożliwili skalowanie elementów panelu przy pomocy poniższego parametru, który trzeba określić w pliku ~/.config/tint2/tint2rc :

scale_relative_to_dpi = 108

Jeśli dodatkowo ikonki zdają się być za małe, to możemy albo im zwiększyć rozmiar, albo też włączyć im autoskalowanie:

launcher_icon_size = 0
systray_icon_size = 0

Xresources i URXVT oraz conky

Jeśli mamy w systemie aplikacje, które nie używają interfejsów GTK3 i QT, to można jeszcze spróbować dla nich ustawić konfigurację czcionek w pliku ~/.Xresources , a konkretnie chodzi o dodanie w nim poniższej linijki:

Xft.dpi: 108

Jeśli dokonujemy zmian w pliku ~/.Xresources , to trzeba przeładować bazę ustawień poniższym poleceniem:

$ xrdb  ~/.Xresources

Dla pewności dobrze jest zweryfikować, czy DPI zostało poprawnie ustawione:

$ xrdb -query | grep dpi
Xft.dpi:        108

Telegram

Żadne z tych powyżej skonfigurowanych ustawień nie wpłynęło w żaden sposób na aplikację Telegram. W jej przypadku pozostaje w zasadzie konfiguracja czcionek w ustawieniach tej appki. By to zrobić, wchodzimy w Settings i przewijamy do pozycji Default interface scale . Jeśli zaznaczenie tej opcji (i zrestartowanie Telegrama) nic nam nie da, to pozostaje nam ustawienie skalowania na sztywno w opcjach tejże appki.

Konfiguracja DPI pod TTY

Osobnym aspektem pracy na linux jest tryb tekstowy w postaci konsoli TTY. Tam te powyższe ustawienia nie zadziałają i trzeba sobie tę konsolę skonfigurować za pomocą narzędzi dostarczanych na Debianie w pakiecie console-setup . Można to zrobić przy pomocy poniższego polecenia:

# dpkg-reconfigure console-setup

lub też przez edycję pliku /etc/default/console-setup dodając lub zmieniając te poniższe wartości:

ACTIVE_CONSOLES="/dev/tty[1-6]"

CHARMAP="UTF-8"

CODESET="Lat2"
FONTFACE="Terminus"
FONTSIZE="16x32"

VIDEOMODE=

Bez znaczenia jest sposób, który sobie wybierzemy, grunt by ustawić odpowiednio zmienną FONTSIZE . Domyślnie jest Terminus 8x16 , no i jak łatwo można się domyśleć, dla ekranów mających DPI 192 można tutaj ustawić Terminus 16x32 .

Konsola podczas startu maszyny

Jeśli mamy do czynienia z DPI większymi lub równymi 192, to można też pokusić się o ustawienie w kernelu opcji CONFIG_FONTS oraz CONFIG_FONT_TER16x32 , tak by komunikaty podczas startu systemu (jak i też konsola odzyskiwania) miały nieco bardziej przyjazny dla oka rozmiar. Mając te parametry ustawione, określamy jeszcze w kernel cmd opcję fbcon=font:TER16x32 .

Problemy z aplikacjami po zmianie DPI

Prawdopodobnie niektóre aplikacje będą miały jakieś większe lub mniejsze problemy z wyświetlaniem czcionek po zmianie DPI. Poniżej znajduje się lista aplikacji, które miały jakieś problemy z wyświetlaniem czcionek. Warto też rzucić okiem na artykuł poświęcony konfiguracji czcionek na Debianie, gdyby te poniższe rady nie przyniosły żadnego rezultatu.

Poszarpane czcionki w qpdfview

W przypadku qpdfview wystąpił bardzo dziwny problem, w którym jedynie tekst dokumentów PDF był strasznie poszarpany, rozmyty i bardzo nieczytelny. Ta aplikacja wykorzystuje interfejs QT, zatem sprawdziłem czy usunięcie zmiennych QT_ ze środowiska poprawi sytuację i poprawiło. Jednocześnie inne aplikacje QT, w tym przeglądarka PDF okular , nie doświadczały tego typu problemów z czcionkami.

Problem tkwił w automatycznym współczynniku piksela (pixel ratio), który domyślnie jest dobierany w qpdfview . Wystarczy zaznaczyć opcję Use device pixel ratio przechodząc kolejno w menu Edit -> Settings -> Graphics -> General. Efekt powinien być zauważalny natychmiast po zastosowaniu ustawień.

Aplikacje uruchamiane jako root

Jeśli uruchamiamy aplikacje jako root, np. graficzny edytor tekstu, to może on nie stosować się do tych ustawień skalowania, które sobie ustawiliśmy. W takim przypadku trzeba w konfiguracji shell'a dla użytkownika root wyeksportować te zmienne, które eksportowaliśmy dla zwykłego użytkownika.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.