yast / yast-installation

YaST module installation
http://en.opensuse.org/Portal:YaST
GNU General Public License v2.0
16 stars 44 forks source link

Use a larger Font for xterm during Installation via X Resources #1085

Closed shundhammer closed 1 year ago

shundhammer commented 1 year ago

Bugzilla

https://bugzilla.suse.com/show_bug.cgi?id=1211267

Trello

https://trello.com/c/T3uqjJEw/

Problem

For debugging, you can start an xterm during a YaST Qt installation with the Ctrl-Shift-Alt X key combination. But since the X11 environment in the inst-sys is minimalistic, and xterm is a very old (almost 40 years) X application, it falls back to built-in very small pixel fonts.

That makes that xterm really hard to use even on normal-sized modern displays; on HiDPI displays, it's too tiny to be usable.

Fix

This adds an old-fashioned ~/.Xdefaults file to set the font size for xterm via X resources:

! Fonts for xterm during a YaST Qt UI installation
! (You can start an xterm with Ctrl-Shift-Alt X)
XTerm*faceName:  DejaVu Sans Mono
XTerm*faceSize:  12

Notice that the comment character in X resource files is '!', not '#' as in most file types.

Even though xterm is one of the oldest X11 applications ever, it received support for modern scalable fonts; see man xterm for the resource names.

DPI Dependency

This falls back to a font size of 12, but it takes the DPI (which we calculate anyway) into account:

We may have to fine-tune this fallback cascade, but it's much better than the old built-in tiny pixel font.

Overriding from the Environment / at the Boot Prompt

As @lslezak suggested, this also supports setting the value from the environment, which in most cases will mean to set it when booting the installation:

XTERM_FONT_SIZE=21

linuxrc exports all additional parameters to the shell environment.

Test

Test in the Development Environment

Just like with the Qt scale factor, invoke the YaST2.call script with FAKE_MON_WIDTH_MM; it will just calculate the values and then exit. Also check /var/log/y2start.log.

FAKE_MON_WIDTH_MM=324 ./YaST2.call  
*** DPI Debug mode ***
DPI: 144
XTERM_FONT_SIZE=12
QT_SCALE_FACTOR=1.0
QT_SCALE_FACTOR_ROUNDING_POLICY=PassThrough
Done.

/var/log/y2start.log:

: HiDPI Check...
: ==============
    |-- Monitor size: DVI-D-0 connected 1920x1200+0+0 (normal left inverted right x axis y axis) 519mm x 324mm
    |-- Monitor width px: 1920
    |-- Monitor width mm: 519
    |-- OVERRIDING the monitor width in mm with 324
    |-- Monitor DPI: 144
    |-- Reference DPI: 144
    |-- QT_SCALE_FACTOR: 1.0
    |-- QT_SCALE_FACTOR_ROUNDING_POLICY: PassThrough
    |-- XTERM_FONT_SIZE: 12 for 144 dpi

To actually write the file in that test mode, uncomment the # add_x11_resources line and check /root/.Xdefaults.

        calculate_xterm_font_size $DPI
        env | grep -E "^(QT_SCALE|XTERM)"
        # add_x11_resources
        echo "Done."

Test in the Inst-Sys

Stage [call]: HiDPI Check...
Stage [call]: ==============
    |-- Monitor size: Virtual-1 connected primary 800x600+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
    |-- Monitor width px: 800
    |-- Monitor width mm: 0
    |-- Monitor width in mm is unknown, using 96 dpi as default
    |-- (Use YAST_MON_WIDTH_MM=xx at the boot prompt to set manually)
    |-- Monitor DPI: 96
    |-- Reference DPI: 144
    |-- No Qt scaling needed.
    |-- XTERM_FONT_SIZE: 10 for 96 dpi
    |-- Adding X resources for xterm to /root/.Xdefaults
Stage [call]: ================
Stage [call]: Starting YaST...
Stage [call]: ================
    |-- Allow big memory allocation: overcommit_memory=1
    |-- MODULE_NAME: installation
    |-- MODE_FLAGS:
    |-- MODULE_ARGS: --arg initial
    |-- MODE: qt
    |-- UI_ARGS: --noborder --auto-fonts --fullscreen
    |-- QT_IM_MODULE: xim
! Fonts for xterm during a YaST Qt UI installation
! (You can start an xterm with Ctrl-Shift-Alt X)
XTerm*faceName:  DejaVu Sans Mono
XTerm*faceSize:  10

Caveat: Always Appending

To avoid clobbering somebody's carefully hand-crafted /root/.Xdefaults file, this always appends to that file; so calling this repeatedly keeps adding more of those same lines.

But that should not matter at all, since we are using the RAM disk in the inst-sys, and this will be invoked only once. Also, later entries overwrite earlier ones, so duplicates don't do any harm.

Background: X Resources

X Resources used to be the tool of choice to configure X clients back in the 1990s and early 2000s. They were used heavily by older toolkits such as the Athena Widgets (the archaic ones that xterm and Tcl/Tk used) and OSF/Motif, but they largely fell out of use with the advent of Qt and Gtk.

The mechanisms how to get an X resource (a single configuration item) to an X client are complicated, and they changed over time. Sometimes you can use an -xrm comand line argument. But mostly it was in a number of files that used to be checked one by one.

The default location was a file in /usr/share/X11/app-defaults that used the class of the application (not the binary name!); XTerm for xterm, Emacs for emacs etc.; that's the system-wide X resources.

Then there was a mind-boggling fallback cascade of other files. One of the oldest of those is a file .Xdefaults in the user's home directory.

Then somebody realized that it takes a while to read all those files one by one, and the idea was born to store X resources in the X server: That's what xrdb <filename> does, and that quickly became the default. Once something is loaded into the X server, you can change the resource files all you want: It will always be ignored. If you want to activate the changes, you have to use xrdb <filename> again or use xrdb -merge <filename> (check with xrdb -query what's loaded into the X server).

But in the inst-sys, we don't have that. Or rather, we don't have that anymore; we used to load some few resources like Xft.dpi into the X server, but we changed that a while ago: Now we only set some environment variables like QT_SCALE_FACTOR.

But if we start again to use xrdb in the inst-sys, we need to take care to add the values that we are now dynamically adding to /root/.Xdefaults as well.

coveralls commented 1 year ago

Coverage Status

Coverage: 40.768%. Remained the same when pulling 64355e1bd543a848410d9500395fbda429be0695 on huha-xterm-font into 3182e0147e28cfc9527a8234e384e3b5fe6257c7 on master.

hramrach commented 1 year ago

I was wondering why you invent such baroque scheme when you can take a base value like 12 and multiply it by the Qt scaling factor to get consistent results.

But it looks like you are doing this in shell code and cannot easily multiply by a fractional number.

shundhammer commented 1 year ago

I was wondering why you invent such baroque scheme when you can take a base value like 12 and multiply it by the Qt scaling factor to get consistent results.

I am very sceptical that the Qt scaling factor would be a good multiplier here: The xterm font size doesn't quite fit even with smaller resolutions today, so I really want to start at 10, use 12 for standard resolutions and something larger (right now 14) for HiDPI or resolutions approaching HiDPI.

We also have a lower and an upper limit for the Qt scaling factor.

There is still room for optimization for those font sizes., of course.

But it looks like you are doing this in shell code and cannot easily multiply by a fractional number.

We already shell out to Ruby to calculate that scaling factor; that would not really be the problem.

hramrach commented 1 year ago

There you go https://github.com/yast/yast-installation/pull/1086/files

yast-bot commented 1 year ago

:heavy_check_mark: Public Jenkins job #253 successfully finished :heavy_check_mark: Created OBS submit request #1087181

lslezak commented 1 year ago

JFYI: simplified testing in inst-sys, directly patching the installer with the code from GitHub: