HiDPI display s ľahkým deskopovým prostredím (awesome)

20.03.2022 | 06:51 | Mirecove dristy | Miroslav Bendík

V dnešnom článku sa pozrieme, na aké problémy je možné naraziť pri používaní HiDPI displaya s ľahkým desktopovým prostredím a ako sa dá väčšina z nich vyriešiť.

Na začiatok predstavím trochu display, ktorý mám. Panel vyrába CSOT (nie tá s jogurtmi, okrem toho píše sa trochu inak). Konkrétne je to panel MNE001EA1-5. Pôvodne som ani nechcel HiDPI display kvôli vysokej spotrebe, ale thinkpady s 10-bitovým panelom, 500 cd/m² svietivosťou a gamutom 100% DCI-P3 mali len UHD panely. Aj v súčasnosti je Lenovo schopné do high end modelov namontovať panel so svietivosťou 250 cd/m² a gamutom 45% NTSC.

Pre lepšiu predstavu pripomínam, že tento display má rozlíšenie 315 PPI. Na bežnom monitore zvyknem používať písmo s výškou 8 pixelov. Ak by som text tejto veľkosti na tomto displayi mal by výšku 174 mm / 2160 * 8 = 0.64 mm.

Základná otázka znie, funguje HiDPI display v linuxe v pohode? Ani náhodou. Presnejšie povedané v desktopovom prostredí so všetkými aplikáciami z jedného grafického toolkitu to ako-tak funguje. V ľahkom prostredí ani náhodou. Stojí HiDPI display vôbec za námahu? Podľa mňa rozhodne áno!

Porovnanie displayov
Obrázok 1: Porovnanie displayov

Text je pri rovnakej veľkosti s vyšším rozlíšením rozhodne čitateľnejší. Nie je to však len o estetike. Môžem bez problémov zmenšiť ovládacie prvky o 30% oproti starému notebooku a vďaka vynikajúcej ostrosti to nezhorší čitateľnosť. V podstate tým získavam 30% priestoru navyše.

Nastavenie desktopu pre HiDPI

Ako užívateľ awesome WM som nepotreboval nastaviť nič, aby mi prostredie nabehlo so správnou veľkosťou elementov. To je síce fajn, že sa DPI zistí automaticky z EDID displaya, ale u väčšiny aplikácií to nie je tak jednoduché.

Aplikácie a toolkity najčastejšie načítavajú hodnotu DPI z databázy xrdb. Základná hodnota DPI je 96. Pre 2x škálovanie (preferujem celočíselné hodnoty, aby zostali ikony aplikácií pekne ostré) zvolím hodnotu 192. Zároveň je vhodné nastaviť aj väčší kurzor. Po nastavení DPI a veľkosti kurzora v súbore ~/.Xresources a načítaní databázy (xrdb -merge ~/.Xresources) by väčšina novo spustených aplikácií mala fungovať relatívne dobre.

Xcursor.theme: Simple-Black
Xcursor.size: 48
Xft.dpi: 192

GTK3

Veľkosť textu sa automaticky načítava z xrdb. Zvyšné ovládacie prvky zostávajú malé. Pre mňa síce fajn, pretože neznášam GTK-čkovu rozťahanosť, ale inak je to nesprávne. Riešením je nastavenie premennej prostredia GDK_SCALE=2. Vlastne ani nie … táto premenná síce zväčší všetky prvky, ale zároveň zväčší aj fonty, ktoré už sú automaticky väčšie podľa hodnoty z xrdb. Celkovo sú potom fonty 4x väčšie a ovládacie prvky 2x väčšie. Našťastie je tu GDK_DPI_SCALE=0.5, čo spolu s GDK_SCALE=2 dá správnu veľkosť fontov a ovládacích prvkov. Pri takom nastavení nie je možné meniť DPI počas behu aplikácie, preto túto možnosť neodporúčam.

Qt

Veľkosť textu je rovnako, ako v prípade GTK načítaná z xrdb. Ovládacie prvky majú niekedy správnu veľkosť, inokedy sú malé. S premennou prostredia QT_AUTO_SCREEN_SCALE_FACTOR=1 všetky veľkosti fungujú správne. Presnejšie povedané, nenarazil som na aplikáciu, ktorá by robila problém.

Firefox / Chrome

Tu som nezaznamenal žiadne problémy. Aplikácie fungujú korektne a načítajú hodnotu DPI z xrdb.

Java

Java nevie načítavať xrdb. Každý toolkit nastavuje veľkosť inak. Napríklad AWT/Swing používa parameter java -Dsun.java2d.uiScale=2, zatiaľ čo JavaFX sa musí volať s java -Dglass.gtk.uiScale=2.0. Nastavenie cez parametre prostredia nefunguje. Zábavné to začne byť až u aplikácií, ktoré majú nejaký spúšťací shell skript (čo je asi väčšina). V praxi to znamená, že pre väčšinu aplikácií sa musí upraviť spúšťací skript. Naposledy som takto musel do súboru launch.sh projektu ghidra pridať VMARG_LIST+=" -Dsun.java2d.uiScale=2".

Ostatné aplikácie

Podpora DPI je v aplikáciách, ktoré nepoužívajú GTK/Qt rôzna. Niektoré ako-tak fungujú, iné vôbec. Vždy závisí od konkrétnej aplikácie.

Pripájame externý monitor s iným DPI

Rôzne DPI na rôznych monitoroch je v aktuálnom X.org nemožné. Vážne, nefunguje to. Na Linuxe je rozbité aj statické nastavenie DPI. Akákoľvek podpora 2 monitorov s rôznymi DPI je sci-fi.

Jediné, čo môžem odporúčať je nastavenie škálovania cez xrandr. Ak má môj HiDPI display identifikátor eDP, potom stačí tento príkaz pre zníženie rozlíšenia na polovicu:

xrandr --output eDP --scale 0.5x0.5 --filter nearest

Teraz už stačí len zmeniť DPI. Problém je, že aplikácie a desktop kontrolujú hodnotu xrdb len pri štarte.

Nastavenie DPI nefunguje

Zmena veľkosti bez reštartu aplikácií

Notifikovať aplikácie o zmene vlastnosti, akou je napr. DPI má na starosti protokol XSETTINGS. Zvyčajne je implementovaný v desktopovom prostredí, ale neplatí to pre ľahké prostredia. Preto existuje utilitka xsettingsd. Aplikácia xsettingsd funguje ako daemon, ktorý po poslaní signálu HUP načíta konfiguráciu a notifikuje aplikácie o zmene vlastnosti.

Hodnota DPI v xsettings je 1024-násobkom želanej hodnoty. Pre nastavenie 192 bude v konfiguračnom ~/.xsettings 196608:

Xft/DPI 196608

Ak chcem zmeniť hodnotu DPI na 96, upravím číslo v ~/.xsettingsd na 98304, pošlem signál HUP príkazom killall -HUP xsettingsd a väčšina aplikácií zmení veľkosť prvkov. Väčšina, ale nie všetky.

Awesome

Najjednoduchším riešením je úprava xrdb databázy a reštart awesome:

echo -e "Xft.dpi: 192\nXcursor.size: 24\n"|xrdb -merge
echo 'awesome.restart()' | awesome-client

Zmeniť DPI je možné aj bez reštartu. Ja som kvôli tomu exportoval funkciu change_dpi a volám ju namiesto awesome.restart:

echo "local beautiful=require('beautiful'); beautiful.change_dpi(96)"|awesome-client

Problémom je veľkosť kurzora, ktorá sa bez reštartu awesome nedá zmeniť. Musel som kvôli tomu upraviť zdrojové kódy awesome. Výsledkom je tento patch s funkciou set_cursor_size.

Kurzory v aplikáciách

Zmena kurzora sa prejaví až u novo spustených aplikácií. V už bežiacich aplikáciách sa dajú nahradiť bitmapy cez škaredý hack. Nie je to pekné, niekedy to nefunguje kvôli cache, ale väčšinou to stačí. Téma a veľkosť kurzoru sa mení príkazom $AWESOME_DIR/tools/set_cursor_theme téma veľkosť.

rxvt-unicode

Novo naštartované inštancie urxvt akceptujú nastavenia z xrdb, ale už bežiace inštancie nepodporujú zmenu DPI. Jediným použiteľným riešením je odoslanie escape sekvencie pre zmenu fontu každej bežiacej inštancii:

urxvt_font_size=$(echo "scale = 5; ($dpi*8*100/75)/96"|bc)
find /dev/pts -user $USER -exec bash -c "echo -ne \"\e]710;xft:DejaVu\ Sans\ Mono:style=normal:pixelsize=${urxvt_font_size}\a\" > {}" \;

Záver

Výsledkom mojich úprav je možnosť používať HiDPI a zároveň možnosť pripojiť externý monitor a zmeniť DPI bez nutnosti reštartovať prostredie, či aplikácie. Hodnota DPI sa nastavuje podľa monitora s nižším DPI (dá sa to aj opačne, ale sú s tým väčšie problémy pri zapnutom hintingu).

Výmena wifi
Video 1: Zmena DPI bez reštartu prostredia
    • RE: HiDPI display s ľahkým deskopovým prostredím (awesome) 20.03.2022 | 08:33
      Avatar Livan Manjaro s XFCE, Q4OS s KDE  Používateľ

      Ozaj veľmi zaujímavý článok. Len mi nie je celkom jasná táto veta, citujem: "Pri takom nastavení nie je možné meniť DPI počas behu aplikácie, preto túto možnosť neodporúčam.". Však bežný smrteľník si toto raz nastaví na optimálne hodnoty a tak to používa. Jeden reštart po nastavení nevadí. Prečo by niekto za chodu menil DPI?

      • RE: HiDPI display s ľahkým deskopovým prostredím (awesome) 20.03.2022 | 11:28
        Avatar Miroslav Bendík Gentoo  Administrátor

        Tá veta je správne. Po nastavení premenných prostredia nie je možné zmeniť DPI bez reštartu aplikácie.

        Za chodu musím meniť, pretože mám notebook. Chvíľu pracujem so vstavaným LCD, chvíľu s ext monitorom. Bolo by vážne blbé reštartovať len preto, že som pripojil / odpojil monitor.

    • RE: HiDPI display s ľahkým deskopovým prostredím (awesome) 21.03.2022 | 08:42
      Avatar TcK   Používateľ

      Mňa by ani nenapadlo meniť DPI to už je pre fajnšmekrov.... Vadšinou aplikácie si samé nastavujú DPI. Ale pekný článok s dobrým vysvetlením. ✌

      Tešilo ma. Zbohom