-
-
Notifications
You must be signed in to change notification settings - Fork 48
Non‐US Keyboard Layout Correction
Toshy can now correct keyboard behavior for people who use a layout other than standard US QWERTY (for example AZERTY, QWERTZ, Dvorak, or any national layout). This page explains what the correction does, how to turn it on, the options you can set, and a safe way to test it.
The feature is opt-in and off by default. If you use a US QWERTY layout you do not need it and nothing changes for you.
To understand the fix, it helps to know where the keymapper sits. It operates at
the evdev layer of Linux input, which means it only ever sees keycodes —
plain integers that represent physical key presses. It does not see letters or
symbols at all. The job of turning a keycode into a character (a, é, @)
belongs to a separate layer, XKB, which sits above the keymapper and holds all
the knowledge about keyboard layouts.
The keymapper has no concept of layouts. It doesn't know AZERTY exists, and it
doesn't even know it's "treating your keyboard as US QWERTY" — it has no notion
of US QWERTY either. What actually happens is simpler: when it reads your config,
strings like "C" and "A" get translated once into the integer keycodes that
sit at those positions on a standard layout. From then on the keymapper deals
purely in those integers. It never reconsiders them.
That works perfectly as long as XKB maps those same keycodes back to the same symbols. On a non-US layout it doesn't. XKB turns those keycodes into different symbols, but the keymapper has already committed to the integers and can't see the mismatch. So its keycode-level operations land on the "wrong" symbols. It isn't making a bad assumption — it's doing exactly what it was told, in a layer that has no way to know the layout underneath has changed.
This shows up in three specific places. Layout correction fixes all three by bridging the gap the keymapper itself can't see.
1. Matching your shortcuts.
A shortcut like Cmd+C is stored as "Cmd plus a particular keycode." On a layout
where that keycode now produces a different letter, the keymapper would be
watching for the wrong physical key. The shortcut fires from the wrong place, or
not where you expect. Correction makes the match track the key you actually mean,
so Cmd+C copies from wherever C lives on your layout.
2. Sending keys back out. When a shortcut emits a keystroke, the keymapper sends a keycode. On your layout that keycode may produce the wrong symbol. Correction adjusts the emitted keycode so the result is what was intended.
3. Typing macro text.
Some Toshy features type whole strings for you (these are called macros). A macro
that should type Class is, underneath, a sequence of keycodes. Send those raw
on AZERTY and you get Clqss, because the keycodes that spell Class on a US
layout spell something else on AZERTY. Correction works out which keycodes
actually produce the intended characters on your layout.
None of this touches your normal typing. When you type directly, your keypresses go up through XKB and your real layout is in charge — the keymapper's keycode translations aren't involved. Correction only affects the things the keymapper itself generates: shortcut matching, remapping, and macro output. That is why, depending on your layout, you may never have noticed these issues. They live entirely in keymapper-generated behavior, not in everyday typing.
In your Toshy config file (~/.config/toshy/toshy_config.py), find the
keyboard_layout_correction() call near the top, inside the
keymapper_api section. Set correction_enabled to True:
keyboard_layout_correction(
correction_enabled = True,
correct_number_row = False,
symbol_miss_policy = 'fold',
folded_miss_policy = 'placeholder',
symbol_placeholder = '?'
)That single switch turns on everything the feature can do. You do not need to tell Toshy which layout you use. Correction reads your active layout from XKB — the layer that actually knows about layouts — builds the keycode-to-symbol mapping it needs, and rebuilds it automatically when you switch layouts. There is no layout to set and no list to pick from.
After editing, restart Toshy so the change takes effect. You have a few ways to do this, and you can move freely between them — each one stops the existing Toshy process automatically before starting fresh:
- Tray icon menu — open the Toshy tray indicator and choose the option to restart the Toshy services. This is the simplest way for normal use.
-
toshy-services-restart— restarts the Toshy services from a terminal. This is the command-line equivalent of the tray menu option. -
toshy-debug— restarts Toshy and shows its verbose logging live in the terminal. This is the best choice while testing, because you can watch correction-related log lines as they happen. -
toshy-config-restart— runs just the keymapper process directly, without the services. This is mainly for systems that don't have systemd available to run the services.
Because each of these stops the running process first, you can, for example, be
watching toshy-debug in a terminal, then later restart from the tray menu, and
nothing is left double-running.
Correction only does anything if it can detect your active layout, and detection is handled per desktop environment. Coverage is not yet complete, but it includes the most popular environments, on both X11 and Wayland:
- KDE Plasma (X11 and Wayland)
- GNOME (X11 and Wayland)
- Cinnamon (X11 and Wayland)
- COSMIC (Wayland)
- Any other X11 desktop — a generic X11 reader covers desktops without a dedicated backend, so most X11 setups work even if not named above.
- Generic Wayland compositors (wlroots / Smithay based) — covered where the compositor re-sends keymap information to background clients. This works on some compositors and not others, depending on how they behave, so it's the least certain category.
If you enable correction in an environment with no working detection backend, the
feature stays inert rather than guessing — it simply does nothing, and says so in
the verbose log (toshy-debug). If your environment isn't covered and you'd like
it to be, that's useful to report, especially for Wayland compositors where
behavior varies.
If you installed Toshy before this feature existed, your config file's editable
sections will not contain the keyboard_layout_correction() call. The installer
preserves your customizations between the slice markers, but it does not reach
into them to insert new lines. You will need to add the call yourself, inside the
keymapper_api slice, copying it from the block above.
This is one more reason to test in a virtual machine first if you can (see below): a fresh install in a VM will already have the new call present, so you can see exactly where it belongs and what the defaults look like.
The master switch. False (default) means no correction at all and identical
behavior to before. True turns the feature on.
On some layouts the number row sits in the usual positions, but the digits are on
the shifted level — you press Shift to get 1, and the unshifted key gives a
punctuation mark or accented character instead. French AZERTY is the common
example. Setting this to True treats those keys as their digit base values, so
the keymapper's number-row handling lines up with what you'd expect. Leave it
False unless your layout flips the number row this way and you want it
corrected.
When a macro needs to type a character, correction looks that character up in a per-layout table and emits the keycodes that produce it on your active layout. Most characters are found directly. The options below decide what happens for a character that cannot be produced on your active layout — a "miss." There are two stages, because Toshy can try to rescue a missing character by folding it to something simpler before giving up.
What to do the first time a character can't be typed on your layout. Choices:
-
'fold'(default) — try to simplify the character into something your layout can type. Accented letters fold to their base letter (é→e), and some characters expand (ß→ss). This keeps macros working and readable even when a character isn't directly reachable, at the cost of dropping the accent or exact form. This is the friendliest default for most people. -
'refuse'— if any character in the macro can't be typed, type nothing at all and log which character caused it. The macro visibly does nothing, and the journal names the problem. This is the strict, no-surprises choice: you would rather a macro clearly fail than quietly come out altered. -
'placeholder'— substitute a stand-in character (seesymbol_placeholder) for the missing one and keep going. The gap is visible in the output so you can see exactly where something didn't fit.
This only applies when symbol_miss_policy = 'fold'. Folding fixes most
misses, but occasionally a character can't even be folded into something
typeable. This option decides what happens to those leftover characters:
-
'placeholder'(default) — drop in the placeholder character and continue. -
'refuse'— refuse the whole macro and log the character, exactly like the'refuse'policy above.
In short: symbol_miss_policy is your first line of defense, and
folded_miss_policy is the fallback for the rare character that even folding
can't reach.
The character used wherever a placeholder is substituted. Default is '?'. It
should be something your layout can always type (plain ASCII is safest). You can
set it to an empty string '' to drop missing characters silently instead of
marking them.
-
Most people: leave the defaults (
'fold'with a'placeholder'fallback). Macros keep working, and the rare unreachable character is marked rather than silently lost. -
You want macros to be exact or fail loudly: set
symbol_miss_policy = 'refuse'. Nothing is ever altered behind your back. -
You want to see gaps but never lose macro flow: set
symbol_miss_policy = 'placeholder'and pick asymbol_placeholderyou'll notice.
Layout correction handles the common Latin-layout cases well, but it is not magic, and a few things are outside what it can currently reach. None of these are bugs; they follow from how the correction works.
For shortcut matching and for sending keys back out, correction works by swapping one keycode for another. That kind of flat swap can only reach a symbol that sits as a plain, unshifted key on your active layout.
By default, correction deliberately leaves the number row alone, so that
shortcuts like Cmd+1 through Cmd+9 keep firing from the physical number keys
even on layouts (like AZERTY) that hide the digits behind Shift. The cost of that
choice is that any punctuation which has moved onto the number row on your
layout can't be reached on output while the number row is held in place.
The clearest example is AZERTY, where - lives on the physical 6 key. A remap
or macro that emits - will type the wrong character, because the key it would
need to use is one of the number-row keys being kept positional. Letters that
moved (like the keys behind Ctrl+Z/Ctrl+Y) still correct perfectly — this
only affects symbols that landed on the digit row.
Setting correct_number_row = True fixes these symbols, but in exchange the
positional digit shortcuts follow the relocated symbols instead. It's a genuine
either/or with the current mechanism: positional digit shortcuts, or reachable
number-row punctuation, not both at once. A future update aims to lift this
tradeoff, but for now it's one toggle.
More generally, the same flat-swap mechanism means that combo and bare-key output can only land on symbols that are reachable as a plain key on your layout. A symbol that needs Shift or AltGr (Level3) to produce on your active layout can't be reached by a keycode swap alone, because a swap can't add a held modifier.
Note this limit applies to combo/key output, not to macro text. Macro string
output (the Class-not-Clqss case) goes through a richer path that does know
about Shift and AltGr levels and dead keys, so typed strings can reach far more of
your layout than a bare combo can. If you have a choice, expressing something as
typed text rather than a raw key combo will reach more symbols.
Correction is built around mapping between Latin layouts (US QWERTY and its relatives). Layouts for non-Latin scripts are currently passed through without correction. If you switch to a non-Latin layout, run the macro tester on a Latin layout instead, since the test output assumes Latin characters.
Because of the number-row and base-level limits above, a punctuation character
used as a marker (for example in a placeholder or a diagnostic macro) might itself
be one of the symbols that can't be reached on some layout. If you're choosing a
symbol_placeholder or writing your own diagnostic macros, a plain letter such as
x is the safest marker — it produces a visible character on essentially every
layout regardless of correction, where punctuation may relocate or hide behind
Shift.
No problems are expected, but keyboard remapping sits close to the system, and a bad interaction on an unusual layout is exactly the kind of thing this test phase is meant to catch. If you can, test in a fresh virtual machine with snapshots first. Take a snapshot before enabling correction; if anything misbehaves you can roll straight back, and you'll have a clean state to report from. A VM also starts with the new config call already in place, so you can see where it belongs.
If you don't have a VM, you can still test on your real system — just know where
your config file is so you can set correction_enabled back to False and
restart Toshy if needed.
Toshy includes a built-in macro tester that types out a block of text including a deliberately tricky line of letters, digits, and symbols. Comparing its output with correction off versus on shows you exactly what the feature changes for your layout.
- Switch your system to your non-US keyboard layout.
- In your config, set
correction_enabled = Falseand restart Toshy. Runningtoshy-debugin a terminal is ideal here, so you can watch the log while you test. - Open a plain text editor and double-tap
Shift+Alt+Cmd+T. Toshy types a test block. Keep it (screenshot or save it). - Now set
correction_enabled = Trueand restart Toshy again (the runningtoshy-debugwill be stopped and replaced automatically if you start a new one, or use the tray menu). - Double-tap
Shift+Alt+Cmd+Tagain into the editor. - Compare the two blocks. With correction off, lines like the letters/symbols test may come out wrong for your layout; with it on, they should be correct.
Depending on your layout the difference may be dramatic or subtle — that comparison is the whole point, and either result is useful to report.
Macros are only one of the three things correction fixes. To see shortcut matching, try a few common shortcuts on your layout with correction on, for example:
-
Cmd+A(select all) -
Cmd+C/Cmd+V(copy / paste) -
Cmd+Q(quit)
On a layout like AZERTY, where letters sit in different places than US QWERTY, these are good probes for whether shortcuts are matching the right physical keys. Try them with correction off and on if you want to feel the difference directly.
Use the shortcut Shift+Alt+Cmd+H,H (Double-tap the "H") to see the
context Toshy has detected, including your keyboard. This is handy to include
when reporting results.
Please report what you find — both successes and problems are valuable while this is being tested. Helpful things to include:
- Your keyboard layout (e.g.
fr(azerty),de,dvorak). - Your distro, desktop environment, and session type (X11 or Wayland). The
Shift+Alt+Cmd+Idiagnostic captures most of this. - The before/after macro test blocks.
- If something broke: what you did, what happened, and any relevant lines from the journal. Correction-related log lines are marked so they're easy to spot.
Post results on the related issue, or open a new issue, on the appropriate repository.