Give xterm a font that has Cyrillic glyphs - #5
Merged
Conversation
Typing Russian over RDP produced boxes instead of characters, while switching the host back to a Latin layout worked fine. That reads like a keyboard problem and is not one: the input path is correct end to end. The guest runs `services.xserver.xkb.layout = "us"` and never sees a Cyrillic keysym of its own - the host owns the layout, and xrdp translates through its own keymaps (km-00000419.ini for Russian ships with the image). The characters arrive intact; xterm simply cannot draw them. xterm's compiled-in default is the bitmap "fixed" font in ISO-8859-1, which contains no Cyrillic glyphs at all, so every one of them renders as a box. The fonts themselves were never missing - the image carries 75 Cyrillic-capable faces (DejaVu, Liberation) and the locale is en_US.UTF-8. X resources would be the usual fix, but nothing in this image loads them: there is no display manager session and no xrdb call anywhere, and ~/.Xresources would live on the persistent home disk rather than in Nix. So the defaults go into the binary that the Openbox menu actually invokes, with hiPrio so the wrapper wins the name collision against xterm in the system profile. The rest of the package (resize, uxterm) is untouched. Verified on the live VM by running both variants side by side in the same xrdp session: the stock xterm shows boxes for "Кириллица: АБВГДЕ абвгде", the wrapped one renders it correctly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Changing the keyboard layout on the Windows side has no effect on a running
session: xrdp applies the client's layout once, from the Client Info PDU at
connect time, and sends bare scancodes afterwards. Measured in a live session
whose guest config says `layout = "us"`:
$ setxkbmap -query
layout: ru
So the guest is not ignoring the client - it was told exactly once, and a later
switch on the host never reaches it. Reconnecting is currently the only way.
Wrap the session so that, after xrdp has applied the client's layout, a Latin
group is placed next to it together with a switch key. The layout list is
deliberately not hardcoded: whatever this particular client negotiated is what
gets the companion group, so a German client gets "us,de" and a Russian one
"us,ru", while a Latin-only client keeps its single group and sees no change.
Pinning "us,ru" into the image would have tied a redistributable appliance to
one person's keyboard.
Both ends are configurable via qubix.keyboard.latinGroup and .toggle. The
default toggle is grp:win_space_toggle to match the Windows shortcut.
Verified by hand in the live session: setxkbmap with these arguments produces
`layout: us,ru` / `options: grp:win_space_toggle` and switching works without
reconnecting or touching the host layout. The generated wrapper passes `sh -n`
and `nix flake check`, but has not yet run inside a rebuilt image -- that comes
with the next image build.
Two limits are documented in the README rather than papered over: Win keys only
reach the guest when mstsc is full screen, and reconnecting to an existing
session does not re-run the wrapper.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous commit forwarded services.xserver.xkb.options into the session's setxkbmap call. Its NixOS default is terminate:ctrl_alt_bksp, which xrdp never applies by itself -- so passing it through would newly arm Ctrl+Alt+Backspace to kill the X server. In a kiosk session that is not a debugging convenience: the RDP window simply disappears on a stray keypress, mid-track. Caught on the live VM: pressing the combination closed the session while the option was set by hand, and stopped doing anything after reconnecting, when xrdp had reset the keymap without it. Only the group toggle is set now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous attempt did not work on a rebuilt image, and hid why: it called
setxkbmap once from startwm.sh and ended the line with `|| true`, so the
failure went nowhere. On the live VM the result was visible as a missing
options line entirely:
$ setxkbmap -query
rules: base
model: pc104
layout: us
No grp:win_space_toggle at all, although running the same setxkbmap by hand in
that very session worked. X is simply not guaranteed to accept connections yet
when startwm.sh runs, and xrdp may also apply the client's layout after the
session script has started.
So do it from a background loop that checks the result and re-applies while the
toggle is missing, for a dozen rounds, and report failures on stderr instead of
swallowing them.
The second half of the problem was a design mistake. The dynamic default adds a
Latin group beside whatever xrdp negotiated, which is right for keeping the
image client-agnostic -- but RDP reports only the client's *active* layout, so
connecting from a US-layout Windows meant a single group and nothing to toggle
to, no matter how well the code ran. Add qubix.keyboard.layouts for naming the
list outright, keep the dynamic behaviour as the default, and set "us,ru" on
spotibox, which is a specific machine with a fixed address and a lab password
rather than a redistributable template.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Every `up` or `recreate` from a .gz leaves an unpacked copy behind, and release
downloads keep a directory per tag, so the cache grows without anything ever
clearing it. On the machine this was written on it had reached 5.89 GB of images
that no longer corresponded to anything installed.
qubixctl -Command gc # dry run: what would go, and how much
qubixctl -Command gc -Force # delete it
qubixctl -Command gc -Force -All # the installed image's cache too
Nothing is deleted without -Force, and the dry run reads only, so it needs no
elevation. The directory matching image-version.txt is kept by default, because
re-fetching a release means downloading the assets again; `local/` is always
dropped, since it only holds a copy unpacked from a file the caller still has.
Non-release markers ('file:...', 'wsl:...') cannot name a cache directory, so
they protect nothing -- which the unit checks pin down.
The VM directory is never a candidate: not the home disk, which is the only
state in the system, and not the live system disk.
Images staged by hand under vmRoot are reported and never deleted. Cleaning up
after the controller is one thing; deleting files a person placed themselves is
another, and the useful half is simply saying that 18 GB is sitting there.
The decision half is a pure function taking directory names, so it is unit
checked without a disk; sizing and the foreign-image scan are checked against a
temporary tree. 55 checks pass under both Windows PowerShell 5.1 and pwsh 7,
PSScriptAnalyzer is clean, and the dry run was exercised against the real cache.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Typing Russian in the guest terminal over RDP produced boxes; switching the host back to a Latin layout worked. That looks like a keyboard problem and isn't one.
What is actually wrong
The input path is correct end to end. The guest runs
services.xserver.xkb.layout = "us"and never sees a Cyrillic keysym of its own — the host owns the layout, and xrdp translates through its own keymaps (km-00000419.inifor Russian ships with the image, confirmed present in/etc/xrdp). The characters arrive intact.xtermjust cannot draw them.xterm's compiled-in default is the bitmapfixedfont in ISO-8859-1, which contains no Cyrillic glyphs, so each one renders as a box. The fonts were never missing either — the image carries 75 Cyrillic-capable faces (DejaVu, Liberation) and the locale isen_US.UTF-8:Why a wrapper and not X resources
X resources would be the idiomatic fix, but nothing in this image loads them: there is no display manager session and no
xrdbcall anywhere in the session path, and~/.Xresourceswould live on the persistent home disk rather than in Nix — exactly the kind of state this appliance is built to avoid.So the defaults go into the binary the Openbox menu actually invokes.
lib.hiPriomakes the wrapper win the name collision againstxtermin the system profile; the rest of the package (resize,uxterm) is untouched.Verification
Both variants launched side by side in the same live xrdp session, same text in each:
1-DEFAULT-FONTxtermКириллица: АБВГДЕ абвгде2-DEJAVU-U8-fa 'DejaVu Sans Mono' -fs 11 -u8nix flake checkpasses.🤖 Generated with Claude Code