Show input switching only for multiple layouts or methods

This commit is contained in:
David Heinemeier Hansson committed 2026-10-09 15:18:33 +02:00
1 parent 59fb2fd304
commit e8b1a1f874
6 files changed
+19 -8

No files matched your search

+2
View File
@@ -38,6 +38,8 @@ end
o.bind("SUPER + I", "Switch input language", function()
if has_input_method() then
hl.exec_cmd("fcitx5-remote --check -t")
else
hl.exec_cmd("omarchy-shell -q omarchy.keyboard-layout cycle")
end
end)
+1 -1
View File
@@ -10,7 +10,7 @@ The ISO carries the extra fields in `omarchy_install.input_method` and `omarchy_
`omarchy setup input` installs the selected engine, restarts the supervised Fcitx unit so it discovers new addons, and appends the engine through `InputMethodGroupInfo`, `SetInputMethodGroupInfo`, and `Save`. It keeps the group name, layout, existing methods, and their layout overrides. There is no parallel unsupervised daemon. A per-user D-Bus activation file delegates `org.fcitx.Fcitx5` to `omarchy-fcitx5.service`; it is loaded before live restart.
Shortcut defaults reserve Ctrl+Space for Tmux/Herdr, Super+Space for the menu, Super+Shift+Space for the bar, and Super+grave for the console. Hyprland owns Super+I to toggle input independently of Fcitx switching keys. Fcitx handles Zenkaku/Hankaku and Hangul; Henkan activates and Muhenkan deactivates. An existing configured list, including an empty list, is preserved. Stock generated lists are repaired only while the user still has the single-keyboard default profile. A terminal Ctrl+Space returns to direct input before the following key, with a 300 ms timeout and no D-Bus activation; a keyboard-only profile skips this step. Wayland and XCB addons do not override the compositor's XKB settings.
Shortcut defaults reserve Ctrl+Space for Tmux/Herdr, Super+Space for the menu, Super+Shift+Space for the bar, and Super+grave for the console. Hyprland owns Super+I to toggle input independently of Fcitx switching keys. With keyboard layouts alone, the same shortcut cycles the layouts through the bar widget, keeping matching devices in sync. The widget is enabled in the default right-hand bar layout and appears only when more than one input method or keyboard layout is configured. Fcitx handles Zenkaku/Hankaku and Hangul; Henkan activates and Muhenkan deactivates. An existing configured list, including an empty list, is preserved. Stock generated lists are repaired only while the user still has the single-keyboard default profile. A terminal Ctrl+Space returns to direct input before the following key, with a 300 ms timeout and no D-Bus activation; a keyboard-only profile skips this step. Wayland and XCB addons do not override the compositor's XKB settings.
The migration installs the standard engines and applies conservative defaults. It aligns an untouched Fcitx keyboard profile with the install layout, using the live controller when Fcitx is running. It leaves existing multilingual profiles and working trigger keys alone. Atomic file writes follow configuration symlinks, preserve file modes, and roll back on a failed seed or live setup so a retry can complete. Live rollback stops Fcitx before restoring disk, then reloads activation and restarts the unit. Migration bus errors defer profile alignment to the next login and do not restart input. If a pre-update daemon has not discovered a new engine, the migration aligns only its keyboard and prints the setup command.
@@ -91,6 +91,14 @@ BarWidget {
//
// Keyboards given their own kb_layout hold a different list and are left out:
// an index into this list would not mean the same layout to them.
ShellIpc {
target: "omarchy.keyboard-layout"
function cycle(): void {
root.cycleLayout()
}
}
function cycleLayout() {
if (!root.bar || root.layoutCount < 2 || root.syncNames.length === 0) return
const next = (root.layoutIndex + 1) % root.layoutCount
@@ -119,13 +119,12 @@ function inputLabel(state, fallback) {
function inputTooltip(state, layout, multipleLayouts) {
if (!state || !state.methods || state.methods.length < 2)
return layout + (multipleLayouts ? "" : "\nClick to set up an input language")
return layout + (multipleLayouts ? " · Super + I" : "")
return (state.name || layout).replace(/^Keyboard - /, "") + " · Super + I"
}
function showIndicator(layoutLabel, multipleLayouts, multipleInputs) {
return multipleInputs || (layoutLabel !== "" &&
(multipleLayouts || (layoutLabel !== "EN" && layoutLabel !== "ENG")))
return multipleInputs || (layoutLabel !== "" && multipleLayouts)
}
function layoutIndex(keyboard) {
+2 -2
View File
@@ -129,5 +129,5 @@ TEST_KEYBOARD_ONLY=true TEST_FCITX5_CONFIG=$freed assert_fires "keyboard-only pr
assert_fires "Super + I toggles configured input independently of custom Fcitx keys" \
"exec fcitx5-remote --check -t" "SUPER + I" "chromium"
TEST_KEYBOARD_ONLY=true assert_fires "Super + I leaves keyboard-only profiles alone" \
"" "SUPER + I" "foot" "terminal"
TEST_KEYBOARD_ONLY=true assert_fires "Super + I cycles keyboard layouts without an input engine" \
"exec omarchy-shell -q omarchy.keyboard-layout cycle" "SUPER + I" "foot" "terminal"
+4 -2
View File
@@ -17,12 +17,14 @@ assertEqual(model.inputLabel({ current: 'custom', language: 'vi' }, 'EN'), 'VI',
assertEqual(model.inputTooltip(japanese, 'English (US)', false), 'Mozc · Super + I', 'input tooltip shows only its name and shortcut')
assertEqual(model.inputTooltip(japanese, 'English (US)', true), 'Mozc · Super + I', 'multiple layouts keep the input tooltip compact')
assertEqual(model.inputTooltip({ ...japanese, current: 'keyboard-us', name: 'Keyboard - English (US)' }, 'English (US)', false), 'English (US) · Super + I', 'Latin input omits the redundant keyboard prefix')
assertEqual(model.inputTooltip({ methods: ['keyboard-fr'] }, 'French', false), 'French\nClick to set up an input language', 'one foreign mode offers input setup')
assertEqual(model.inputTooltip({ methods: ['keyboard-fr'] }, 'French', false), 'French', 'a single layout tooltip stays compact')
assertEqual(model.showIndicator('EN', false, false), false, 'English alone stays hidden')
assertEqual(model.showIndicator('ENG', false, false), false, 'English before the brief table loads stays hidden')
assertEqual(model.showIndicator('FR', false, false), true, 'a single non-English layout stays available')
assertEqual(model.showIndicator('FR', false, false), false, 'French alone stays hidden')
assertEqual(model.showIndicator('EN', false, true), true, 'Latin with another input mode stays available')
assertEqual(model.showIndicator('EN', true, false), true, 'multiple keyboard layouts stay available')
assertEqual(model.showIndicator('FR', true, false), true, 'French and English layouts stay available')
assertEqual(model.inputTooltip({ methods: ['keyboard-fr'] }, 'French', true), 'French · Super + I', 'multiple layouts advertise their switching shortcut')
// Trimmed from xkbcli list, keeping the format of every section it prints,
// including the options nested under an option group: those quote their