Skip to content

Keyboard & Input Methods

Marchyo provides a unified way to configure keyboard layouts, variants, input methods (IMEs), and XKB options across the system (TTY/console) and the desktop environment (Hyprland + fcitx5).

Out of the box:

  • layouts = [ { layout = "us"; variant = "altgr-intl"; } "fi" ]
  • options = [ "grp:win_space_toggle" ] (Super+Space switches layout/IME)
  • composeKey = "menu"

The altgr-intl variant (“English (US, intl., AltGr dead keys)”) behaves like a plain US layout for the unmodified keys — ', ", `, ~, ^ produce their normal characters, not dead keys. The international characters live behind the AltGr modifier (Right Alt).

Sequence Result
AltGr + - – (en dash)
AltGr + Shift + - — (em dash)
AltGr + 9 / AltGr + 0 ‘ / ’ (curly single quotes)
AltGr + Shift + 9 / AltGr + Shift + 0 “ / ” (curly double quotes)
AltGr + [ / AltGr + ] « / » (guillemets)
AltGr + 5 €
AltGr + 4 ¤ (currency)

The Menu key acts as Compose for everything else (Menu then ' then e → é, Menu then - - - → —, etc.).

If you want the stronger dead-key behavior of plain us(intl) (where ', ", `, ~, ^ wait for a follow-up letter):

marchyo.keyboard.layouts = [ { layout = "us"; variant = "intl"; } "fi" ];

If you have no Menu key, point Compose elsewhere (or disable it):

marchyo.keyboard.composeKey = "caps"; # or "rwin", "rctrl", or null

The marchyo.keyboard.layouts option accepts a list of layouts. Each can be a simple string or an attribute set for advanced configuration.

marchyo.keyboard.layouts = [
"us"
"fi"
"de"
];
marchyo.keyboard.layouts = [
"us"
{ layout = "us"; variant = "intl"; } # US International with dead keys
{ layout = "us"; variant = "dvorak"; }
];

For CJK languages and other complex input, specify an IME:

marchyo.keyboard.layouts = [
"us"
{ layout = "cn"; ime = "pinyin"; } # Chinese with Pinyin
{ layout = "jp"; ime = "mozc"; } # Japanese with Mozc
{ layout = "kr"; ime = "hangul"; } # Korean with Hangul
{ layout = "us"; ime = "chewing"; } # Traditional Chinese with Zhuyin
{ layout = "us"; ime = "cangjie"; } # Hong Kong Cangjie 5
];

When an entry includes ime, the engine is added to the fcitx5 group after the keyboard layouts. Input starts in Latin (the keyboard layout), not in the engine. Korean (layout = "kr" with hangul) uses the kr104 variant.

IME Language Required package
"pinyin" Chinese qt6Packages.fcitx5-chinese-addons
"mozc" Japanese fcitx5-mozc
"hangul" Korean fcitx5-hangul
"chewing" Traditional Chinese (Zhuyin) fcitx5-chewing
"cangjie" Hong Kong Chinese (Cangjie 5) fcitx5-table-extra
"unicode" Unicode picker —

Required packages are installed automatically when an IME is specified.

Option Type Default Description
layout string — Keyboard layout code (e.g., "us", "fi", "cn")
variant string "" Layout variant (e.g., "intl", "dvorak")
ime string or null null Input method engine
label string or null null Display label (auto-generated if null)

Use marchyo.keyboard.options for standard XKB options. Default: ["grp:win_space_toggle"] (Super+Space to switch layouts).

marchyo.keyboard.options = [
"grp:win_space_toggle" # Super+Space to switch inputs
"ctrl:swapcaps" # Swap Caps Lock and Left Control
"caps:escape" # Map Caps Lock to Escape
];

The compose key lets you type special characters via key sequences (e.g., Compose + ' + e = é).

marchyo.keyboard.composeKey = "shift-caps"; # Shift+Caps Lock (default: "menu")
Value Key
"menu" Menu key (default)
"shift-caps" Shift+Caps Lock (Hyprland only)
"ralt" Right Alt — avoid when using us(altgr-intl) or us(intl) (it needs Right Alt as AltGr)
"rwin" Right Super/Windows
"caps" Caps Lock
null Disable compose key

Input methods are off when a text field gets focus. Set autoActivateIME = true to start with the engine active:

marchyo.keyboard.autoActivateIME = true;
  • A lone Shift (left or right) toggles between the current engine and Latin.
  • Super+Space and every key in imeTriggerKey cycle through the keyboard layouts first, then the engines.
marchyo.keyboard.imeTriggerKey = [ "Super+I" ]; # Default

When an ime of mozc, hangul, pinyin, chewing or cangjie is configured, Noto CJK is installed and fontconfig appends the matching region to the sans-serif, serif and monospace families:

  • mozc: JP (ja)
  • hangul: KR (ko)
  • pinyin: SC (zh-cn)
  • chewing: TC (zh-tw)
  • cangjie: HK (zh-hk)

Text tagged with a language gets that language’s forms. Untagged text uses the region of the first configured engine.

marchyo.keyboard.fnMode = "media"; # top row sends media keys, Fn gives F1-F12
marchyo.keyboard.fnMode = "function"; # top row sends F1-F12, Fn gives media keys

null (default) leaves the firmware or driver default. This writes hid_apple fnmode (1 = media keys first, 2 = F-keys first) and hid_asus / asus_wmi fnlock_default to modprobe. Keyboards that keep Fn-lock in firmware ignore it. hid_asus and asus_wmi read it at load time, so it applies after a reboot.

marchyo.keyboard.backlight.enable (default true) binds XF86KbdBrightnessUp/Down, XF86KbdLightOnOff and Ctrl plus the display brightness keys to marchyo brightness --keyboard up|down|toggle. It acts on the first *kbd_backlight* LED and shows the shell OSD when the shell is installed. The level survives reboots through the stock systemd-backlight@leds:* service, so nothing extra is installed.

With composeKey = "shift-caps", Caps Lock stays Caps Lock and Shift+Caps Lock sends Compose. It cannot be combined with an option that remaps Caps Lock (ctrl:swapcaps, ctrl:nocaps, caps:escape). Marchyo installs a symbols file and an evdev rules extension in /etc/xkb and exports XKB_CONFIG_EXTRA_PATH=/etc/xkb, which libxkbcommon (Hyprland) reads. The console and X server do not see the option, so they get no compose key. The change applies to new sessions.

marchyo.keyboard = {
layouts = [
{ layout = "us"; variant = "altgr-intl"; }
{ layout = "fi"; }
{ layout = "us"; variant = "intl"; }
{ layout = "cn"; ime = "pinyin"; }
{ layout = "jp"; ime = "mozc"; }
];
options = [ "grp:win_space_toggle" ];
composeKey = "menu";
autoActivateIME = false;
imeTriggerKey = [ "Super+I" ];
};
  1. NixOS (services.xserver.xkb) — Basic layout codes and variants are applied to the console/TTY for fallback support outside the graphical environment.
  2. Hyprland (home.keyboard) — Layout and XKB options are passed to Hyprland’s input configuration.
  3. fcitx5 — Acts as the authoritative input manager in the graphical environment, managing layouts, IMEs, and layout switching.
Option Type Default Description
marchyo.keyboard.layouts list of strings or attrsets [{ layout = "us"; variant = "altgr-intl"; } "fi"] Keyboard layouts and input methods
marchyo.keyboard.options list of strings ["grp:win_space_toggle"] XKB keyboard options
marchyo.keyboard.composeKey string or null "menu" Compose key (the Menu key by default)
marchyo.keyboard.fnMode "media", "function" or null null Top-row default for Apple/ASUS keyboards
marchyo.keyboard.backlight.enable bool true Keyboard backlight key binds
marchyo.keyboard.autoActivateIME bool false Start with the IME engine active
marchyo.keyboard.imeTriggerKey list of strings ["Super+I"] Keys that cycle layouts, then engines
marchyo.keyboard.variant string "" Deprecated: sets the variant of the first layout and warns. Use { layout = "us"; variant = "intl"; } in layouts (migration)