-
-
Notifications
You must be signed in to change notification settings - Fork 48
Creating a Custom Keyboard Layout (and How It Works with Toshy)
Sometimes you want certain keys on your keyboard to type different characters
than your current layout gives them. The reasons vary: adding the US-position
brackets and braces ([ ] { }) to a German layout for programming, putting a
currency symbol or an accented letter somewhere you can reach it, turning Caps
Lock into Escape or Control, or any other case of "I want this key to produce
that."
Whatever the specific change, the right tool is a small custom keyboard layout — not a Toshy remap. A layout change happens at the level that actually decides which character a key produces, so it is system-wide and permanent: it works in every application, at the login screen, on a text console, and — importantly — when Toshy is not running at all. (If you've solved something like this before with a Toshy config remap, a custom layout replaces it with an approach that no longer depends on Toshy being active.)
This guide walks through the whole process — it comes down to one short file in your home directory — using a single concrete change as the running example: a German keyboard that gains the US-position brackets and braces for programming while keeping German typing intact. The same steps apply to any character change you want; just substitute your own keys and symbols.
There are two different problems people often mix up:
- "My shortcuts fire the wrong action on my non-US layout." That is what Toshy's layout correction already handles automatically — you don't need to do anything in this guide.
- "I want some keys to type different characters." That is a layout change, and that is what this guide covers.
The two are independent and they cooperate (see Section 8), so making a custom layout does not interfere with Toshy.
This matters, because the easy method only works on one of them.
The home-directory method below works on Wayland sessions, which use
libxkbcommon to build the keymap and read your personal files. It does not
work on X11 sessions, because the X server only looks in system directories.
If you are on X11, skip to Section 7.
Check which one you are on:
echo $XDG_SESSION_TYPE # prints "wayland" or "x11"The rest of Sections 3–6 assume Wayland.
You only need three facts:
- The keyboard system searches your personal folder,
~/.config/xkb/, before the system folders, so anything you put there is used first. - A layout is a file inside
symbols/. A variant is a named section inside that file. - You will create one file, put your changes in a named section, and reference
it as
layout(variant).
That is enough to follow every step.
Make the folder and create one file:
mkdir -p ~/.config/xkb/symbolsCreate ~/.config/xkb/symbols/custom with this content:
// ~/.config/xkb/symbols/custom
// A German layout with US-position brackets/braces added on AltGr.
partial alphanumeric_keys
xkb_symbols "programming" {
include "de(basic)"
name[Group1] = "German (US braces, programming)";
// Each key lists four levels: [ base, Shift, AltGr, Shift+AltGr ]
// The first two keep the normal German characters; the last two add the
// brackets and braces. FOUR_LEVEL makes the AltGr levels reachable.
key <AD11> { type[Group1]="FOUR_LEVEL",
[ udiaeresis, Udiaeresis, bracketleft, braceleft ] };
key <AD12> { type[Group1]="FOUR_LEVEL",
[ plus, asterisk, bracketright, braceright ] };
};What each part does:
-
include "de(basic)"starts from the standard German layout, so every key you don't touch behaves exactly as before. -
name[Group1]is the label that shows up in layout switchers (and the name Toshy will read for this layout). - Each
keyline replaces one key with four levels.<AD11>is the key that is[on a US keyboard (üon German);<AD12>is the US]key (+on German). Levels 1–2 keep the Germanü/Üand+/*; levels 3–4 (AltGr and Shift+AltGr) add the brackets and braces.
Two things worth knowing:
-
Give the file a new name like
custom. Do not name itde— a file nameddein your home folder would hide the entire system German layout instead of building on it. - For a key whose base character is a letter (like
üabove), useFOUR_LEVEL_SEMIALPHABETICinstead ofFOUR_LEVELif you want Caps Lock to still capitalize it. For bracket keys it makes no difference.
Adapt freely: pick whatever keys and levels suit you, and replace any keysym
with the character you want. A list of keysym names (bracketleft,
braceright, and so on) is in the system file
/usr/share/X11/xkb/keysymdef.h or the standard X keysym tables online.
A broken layout can leave you unable to type, so check it in a safe, offline way
first. The xkbcli tool (Fedora package libxkbcommon-utils, similarly named
elsewhere) compiles your layout without applying it:
xkbcli compile-keymap --layout custom --variant programming | grep -i group1If your file is valid you'll see your label:
name[1]="German (US braces, programming)";
You can also confirm the brackets landed where you intended:
xkbcli compile-keymap --layout custom --variant programming | grep -i bracketleftIf you instead get an error, fix the file and run it again. Nothing has changed on your live keyboard yet, so you can iterate safely.
How you activate a layout depends on your environment.
Sway / Hyprland and similar (apply it directly — no registration needed):
Sway, in your config:
input "type:keyboard" {
xkb_layout "custom"
xkb_variant "programming"
}
Hyprland, in your config:
input {
kb_layout = custom
kb_variant = programming
}
GNOME / KDE Plasma (register it so it appears in Settings):
Full desktops pick layouts from a registry, so for your custom layout to show up
in the keyboard-settings list you register it by adding a few small files under
~/.config/xkb/rules/ (an evdev, evdev.xml, and evdev.lst entry), then log
out and back in. Rather than reproduce that here, follow one of these, which walk
through it with working examples:
- libxkbcommon's official guide: https://xkbcommon.org/doc/current/custom-configuration.html
- A step-by-step write-up: https://codeaffen.org/2023/09/16/custom-keyboard-layouts-with-xkb/
A note on setxkbmap: it only affects X11 and XWayland applications, not native
Wayland apps, so it is not a reliable way to apply a layout on a Wayland session.
Use your compositor's or desktop's own setting as above.
The home-directory method does not apply: an X server reads only the system
location, /usr/share/X11/xkb/. To add a custom layout on X11 you edit the files
there (as root) and register it in the system rules — which also means your
changes are overwritten whenever the xkeyboard-config package updates, so
you'll need to reapply them.
Because that path is well covered already, follow an established guide rather than duplicating it here:
- The Arch Wiki's keyboard configuration page (distribution-agnostic): https://wiki.archlinux.org/title/Xorg/Keyboard_configuration
- libxkbcommon's customization guide also describes the system-wide variant: https://xkbcommon.org/doc/current/custom-configuration.html
The symbols-file content from Section 4 is the same; only where it lives and how it is registered differ.
A custom layout and Toshy do different jobs and stay out of each other's way:
- Your custom layout decides which characters your keys type.
- Toshy corrects which shortcuts fire, so your macOS-style shortcuts keep working regardless of layout.
Toshy reads your layout's actual compiled keys, so it adapts to a custom layout on its own. In the example here you only added characters on the AltGr levels and left the base keys untouched, so Toshy sees the same base layout as before and nothing about its behavior changes. If a custom layout instead moves base-level keys around, Toshy notices and adjusts its shortcut correction to match — no configuration needed either way.
And because this is a real layout rather than a running remap, your characters are there even when Toshy is stopped, on the login screen, or on a fresh machine where Toshy isn't installed yet.
-
AltGr doesn't produce the brackets. Your session may not be using Right Alt
as the AltGr (level-3) key. Add the option
lv3:ralt_switchin your compositor/desktop keyboard settings, or confirm which key is your AltGr. - The layout doesn't appear in GNOME/KDE Settings. That list comes from the registry — complete the registration step in Section 6 and log out and back in.
-
Something looks wrong. Re-run the
xkbcli compile-keymapcheck from Section 5; it reports the exact line of any mistake. -
You're stuck with a bad layout. Switch back to a normal layout through your
desktop's keyboard settings (or your compositor config), then fix the file and
re-test with
xkbclibefore turning it on again.