Skip to content

v1.0.11 — Twenty languages

Choose a tag to compare

@github-actions github-actions released this 07 Aug 09:15
· 33 commits to master since this release

Every one of the twenty languages has been typed into Kate on real hardware — pangram
plus that layout's currency symbols — saved with Ctrl+S, and the file compared character
by character with what was meant. All twenty pass.

Added

  • Key labels for twenty XKB layouts. English (US/UK), German, French, Spanish (Spain
    and Latin America), Italian, Portuguese (Portugal and Brazil), Dutch, Polish, Turkish,
    Russian, Ukrainian, Greek, Arabic, Hebrew, Hindi (Devanagari), Thai and Vietnamese.
    🌐 switches between the layouts KDE has configured and re-skins the keys to match.

    These are labels, not behaviour. The keyboard injects real keycodes, so what a key
    types was always decided by the OS layout — what was missing is the keyboard admitting
    it, by drawing й on the key that types й instead of q. A layout with no labels
    still works; it is just drawn with US captions.

    They are generated from xkeyboard-config
    and xorgproto's keysymdef.h by tools/build-locales.py, and committed. Typing them
    out by hand would have been twenty chances to be subtly wrong in scripts I cannot
    proofread. All twenty resolve all 47 keys — anything less is treated as a parser bug,
    which is how these were found:

    • Comments were counted when scanning for the end of a block. These files annotate keys
      with the characters they produce, and those annotations contain braces —
      key <AB03> {[...]}; // ؤ } — so the Arabic layout ended after three keys and
      silently lost the other seven, leaving v b n m , . / drawn in Latin.
    • Keysyms were resolved by their own U+ comment, but several names share a code and
      only one carries the annotation; the rest read "deprecated alias for …". That lost
      masculine and guillemotleft, and with them º on the Spanish layout and « »
      on the Portuguese one. Resolution now goes through the keysym code.
    • Greek redefines only levels 3 and 4 over gr(simple) using any for the first two,
      so replacing whole entries threw the alphabet away — levels merge individually now.
    • key <AD08> { type[group1] = "…", [ i, I ] } — that first bracket is not a symbol
      list, and taking it lost Turkish's dotted/dotless i.

    Three parser bugs, each of which shipped a layout that looked plausible and put
    characters on the wrong keys, is three too many to keep finding by eye — particularly
    in scripts I can't read. Every label is now checked against libxkbcommon, which is
    the same library the compositor uses to decide what a key actually types, by
    tools/verify-locales.py. A label that disagrees is a key drawn with a character it
    does not produce. All 940 key/level pairs across the twenty layouts agree, and CI
    re-checks it on every push.

  • AltGr. Most non-English layouts keep a third of their characters on the third level
    — Polish ą, French @, Turkish î, Italian [ — and without an AltGr key they were
    simply unreachable. Holding it re-skins the keys to show what they will type, rather
    than printing three glyphs on a key the size of a fingernail. Existing installs get the
    key added to their layout on upgrade.

  • A system tray icon. Tap it to show or hide the keyboard; right-click for restart,
    reset position, fix the trackpad pointer, and stop/start. The Show/Hide and Stop/Start
    entries say which one they'll do, rather than offering you the dead half of the pair.

    It speaks the StatusNotifierItem and DBusMenu protocols to Plasma directly rather than
    going through libappindicator — SteamOS is an immutable image with no pip and no
    appindicator package, so a dependency here would be one that cannot be installed. It
    runs as its own process, because its whole job is rescuing a misbehaving keyboard and
    "Restart" shouldn't mean killing yourself mid-click. The supervisor keeps it alive, so
    a Plasma restart doesn't take it away for good.

    Its own process turned out not to be enough. The supervisor runs as a transient systemd
    unit, and stopping a unit stops its whole cgroup — which contained the tray and the
    restart script the tray had just launched. The stop half ran, the start half never did,
    and the keyboard did not come back. start_new_session() does not help; a cgroup is not
    a session. The tray is now a unit in its own right, and handheld-kbd-ctl re-runs
    itself in a transient unit before touching anything, so it cannot be killed by the stop
    it just issued.

  • handheld-kbd-locales — list, add, remove or set the layouts KDE offers, since
    🌐 can only reach layouts KDE has been told about, and with one configured it has
    nowhere to go. Reports which have labels and which don't.

    Four layouts can be live at once, and the tool enforces that. An XKB keymap holds
    four groups — ask libxkbcommon for a fifth and it is discarded outright
    ([XKB-595] Unrecognized RMLVO layout "es" was ignored), so a longer list silently
    becomes its first four and the rest never appear. Twenty sets of labels ship; which
    four are live is a set plus a log out.

    It also shows which layouts KWin is actually running with, and offers to log you
    out. That distinction matters more than it sounds: KWin builds its xkb keymap when the
    session starts and there is no way to make it re-read the list — neither
    org.kde.KWin.reconfigure nor reloading kded's keyboard module works, both verified.
    So a freshly added layout sits in the config file looking configured while 🌐 refuses
    to reach it, which is a confusing few minutes if nothing says so.

Notes on what this can't do

  • Chinese, Japanese and Korean are absent and will stay absent. They are input methods,
    not keyboard layouts; no mapping of keycodes to characters produces them. Fcitx and IBus
    work with this keyboard exactly as with any other, because the keystrokes are real.
  • Vietnamese is a halfway case. The vn layout puts ă â ê ô ơ ư đ on the number row
    and tone marks on 59 — which costs you the digits and still cannot produce every
    syllable. Most Vietnamese typing uses an IME (Telex/VNI) over a US layout. That works
    here; the layout is shipped for those who want it.

Verified

Every one of the twenty languages typed into Kate through /dev/uinput, saved with
Ctrl+S, and the file read back off disk and compared character by character. Key
positions come from the locale files this keyboard ships, so a label on the wrong key
fails the test — in scripts nobody here can proofread. tools/kate-type.py.

All twenty pass. Spanish, Greek and Vietnamese type everything except the characters
needing dead-key or combining composition, as expected.

Added: handheld-kbd-locales --check

Shipping labels for twenty languages does not make twenty languages work. The layout
comes from xkeyboard-config and the glyphs from the system fonts, and a machine missing
either draws boxes or types the wrong thing. --check reports both per language, and the
installer runs it so you learn at install time rather than by discovery. Font coverage is
probed once per script through fontconfig, not guessed. Verified on a Legion Go 2: all
twenty layouts present, all scripts drawable — Arabic and Hebrew via DejaVu, Devanagari
and Thai via Noto.

Known: keep one Latin layout among your four

Application shortcuts are bound to Latin keysyms. With only non-Latin layouts loaded the
S key produces Cyrillic_yeru, and Ctrl+S never reaches Save — Ctrl+C and Ctrl+V go the
same way. KDE's Latin fallback covers global shortcuts, not an application's own. Found
by this test failing every save under ru ua gr ara, and passing the moment us was in
the group. handheld-kbd-locales now warns when a selection has no Latin layout.

Fixed

  • No key is labelled with a character it cannot type. A layout can define symbols on
    the third level and bind nothing to reach them, and Russian does exactly that: the
    rouble sits on level 3 of the 8 key while RALT stays Alt_R, so was drawn on a
    key no keypress could produce. Level-3 labels are now emitted only for layouts that
    actually provide an AltGr switch — which drops them for ru, and confirms us and
    th never had any. CI fails a locale that claims otherwise.

    Found by the language test typing each layout's currency symbols: was the one
    character out of twenty languages that went in and did not come back.

  • Uninstalling actually uninstalls. The removal list was written once and never kept
    up: by v1.0.11 it named seven of the eighteen files an install puts in ~/.local/bin,
    so "Uninstalled." left most of the program behind, along with two autostart entries and
    the bundled suggestion filter. It matches handheld-kbd-* now, which is what everything
    this project installs is called.

  • Uninstalling stops the keyboard for good. It used pkill, and the supervisor runs
    as a systemd unit — so the process died and a fresh one arrived two seconds later. The
    units are stopped first.

  • The KWin script is unloaded, not just deleted. It keeps running in the session after
    its file is gone, so the desktop was still being driven by a keyboard that no longer
    existed.

  • Upgrading no longer asks for a password you cannot type. The privileged step —
    the udev rule and input group that let the keyboard reach /dev/uinput — ran last,
    so on a handheld the prompt could arrive after the keyboard it was replacing had gone,
    with nothing to answer it with. It now runs first, while whatever keyboard you started
    with is still alive. On an upgrade it does not run at all: the rule and the group are
    already there, and the installer says so instead of asking.

  • The 🌐 key names the language, not the country. It showed the xkb code, and il
    is Israel rather than Hebrew, in is India rather than Hindi, latam did not fit, and
    us and gb are both English. Latin layouts keep the familiar two letters; the rest
    get their own script — עב, ع, हि, ไทย, РУ, УК, ΕΛ.

  • The logout prompt notices a swap. It compared how many layouts were configured
    against how many were running, so exchanging Russian for Vietnamese — four for four,
    and the most likely change anyone makes — looked like nothing had happened. It compares
    the two sets now.

  • The language picker shows what is in rotation before you change it, states the
    four-at-a-time rule up front, and confirms rather than silently truncating when you
    tick more, tick none, or tick four without a Latin layout among them.

  • Currency symbols are part of the language test. Most layouts keep theirs on the
    third level — on AltGr-E, , , , ฿, , — so typing them exercises
    AltGr and the level-3 labels in the place a user is most likely to notice being wrong.
    Symbols are taken from each layout's own data rather than assumed.

  • A label can no longer resize the keyboard. The key grid is column-homogeneous, so
    every column is as wide as the widest cell — and the 🌐 key reading 🌐LATAM inflated
    all thirty-six of them, pushing the window to 1728px on a 1280px desktop. GTK refuses
    to shrink a window below its natural width, so ⤓ re-docked to 1280, was refused, and
    looked broken. Labels (and predicted words, which had the same power) now ellipsize;
    the window's size is the dock's business alone.

  • The 🌐 badge names what the OS is actually typing. The layout list was read from
    kxkbrc and the index from the live session — but the file is what the next session
    loads. Edit it and list[index] names some other layout: the keyboard drew Brazilian
    labels while the OS typed US. Both halves now come from the live session.

  • "Keyboard languages…" in the tray. A kdialog checklist of all twenty languages —
    tick up to four, get offered the logout. Configuring the keyboard by typing commands
    was exactly backwards. Also handheld-kbd-locales --gui.

  • The four-layout ceiling is enforced and explained, rather than silently truncated
    by libxkbcommon.