Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions bin/omarchy-provision-owner
Original file line number Diff line number Diff line change
Expand Up @@ -612,10 +612,20 @@ confirm_reboot() {
# Load the layout on the live VT and persist it for the installed system.
# systemd-firstboot writes both the console KEYMAP and the XKB layout Hyprland
# reads, matching what the ISO's configure_keyboard does at install time. A
# keymap localectl doesn't know keeps the default rather than failing (defensive;
# the picker no longer offers any such layout).
# keymap localectl doesn't know keeps the default rather than failing (defensive).
#
# XKB-only picker values (OMARCHY_XKB_ONLY_LAYOUTS) are the exception: kbd
# ships no console map, so persist us (Latin passwords/LUKS) and then point
# XKBLAYOUT at the chosen layout for Hyprland.
apply_keyboard() {
local keymap="$1"

if omarchy_xkb_only_layout "$keymap"; then
apply_keyboard us
omarchy_write_xkblayout "$keymap"
return 0
fi

[[ $(tty 2>/dev/null) == /dev/tty* ]] && loadkeys "$keymap" 2>/dev/null || true

if localectl --no-pager list-keymaps 2>/dev/null | grep -qix "$keymap"; then
Expand Down
32 changes: 32 additions & 0 deletions install/provisioning/setup-form.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,41 @@ Spanish|es
Spanish (Latin American)|la-latin1
Swedish|sv-latin1
Tajik|tj_alt-UTF8
Thai (Kedmanee)|th
Turkish|trq
Ukrainian|ua'

# Picker values that are XKB layouts, not kbd console keymaps. The live
# console and LUKS prompt stay on us so Latin passwords remain typeable;
# XKBLAYOUT carries the choice into Hyprland. The ISO configurator parses
# this assignment the same way it reads OMARCHY_KEYBOARD_LAYOUTS.
OMARCHY_XKB_ONLY_LAYOUTS="th"

omarchy_xkb_only_layout() {
[[ " $OMARCHY_XKB_ONLY_LAYOUTS " == *" $1 "* ]]
}

omarchy_console_keymap_for() {
if omarchy_xkb_only_layout "$1"; then
printf '%s\n' us
else
printf '%s\n' "$1"
fi
}

# After a Latin console keymap is persisted, point XKBLAYOUT at an XKB-only
# picker value (no matching kbd map). Optional second arg is the vconsole file.
omarchy_write_xkblayout() {
local keymap=$1
local vconsole=${2:-/etc/vconsole.conf}

if grep -q '^XKBLAYOUT=' "$vconsole" 2>/dev/null; then
sed -i "s/^XKBLAYOUT=.*/XKBLAYOUT=$keymap/" "$vconsole"
else
echo "XKBLAYOUT=$keymap" >>"$vconsole"
fi
}

OMARCHY_USERNAME_PATTERN='^[a-z_][a-z0-9_-]*[$]?$'
OMARCHY_RESERVED_USERNAMES='^(root|bin|daemon|mail|ftp|http|nobody|dbus|systemd-coredump|systemd-network|systemd-oom|systemd-journal-remote|systemd-resolve|systemd-timesync|tss|uuidd|alpm|git|avahi|cups|cups-browsed|lp|_talkd|polkitd|rtkit|qemu|brltty|gluster|rpc|libvirt-qemu|pcscd|nvidia-persistenced|sddm)$'
OMARCHY_HOSTNAME_PATTERN='^[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?$'
Expand Down
6 changes: 6 additions & 0 deletions manual/34-keyboard-mouse-trackpad.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" })

On Dell XPS laptops with a haptic touchpad, you can also set the click strength to low, mid, or high under _Trigger > Hardware > Touchpad Haptics_.

### Typing in Thai

Pick _Thai (Kedmanee)_ as the keyboard layout during installation (or first-boot owner setup). The console, disk encryption prompt, and login password stay on the US layout so Latin passphrases remain typeable. The desktop comes up English until you press Left Alt and Right Alt together — the same switch as other non-Latin layouts — or click the layout chip on the menu bar. Caps Lock stays the compose key.

Thai is a regular keyboard layout, not an input method: you do not need fcitx5-configtool. Other Thai maps (Pattachote, Manoonchai) still go in `kb_variant` under _Setup > Input_.

### Typing in Chinese, Japanese, and other languages

Omarchy runs the [fcitx5](https://fcitx-im.org/) input method framework as part of every session — it's what powers the CapsLock compose sequences. That means the plumbing for non-Latin input is already in place: install an input engine like `fcitx5-mozc` (Japanese) or `fcitx5-chinese-addons` (Chinese) with `omarchy pkg add`, plus `fcitx5-configtool` to add the engine to your input methods and set the key that switches between them.
Expand Down
103 changes: 103 additions & 0 deletions test/shell.d/apply-keyboard-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

require_command lua

source "$ROOT/install/provisioning/setup-form.sh"

tmp_dir=$(mktemp -d)
trap 'rm -r "$tmp_dir"' EXIT

resolved_input() {
OMARCHY_PATH="$ROOT" OMARCHY_VCONSOLE="${1-}" lua <<'LUA'
package.path = os.getenv("OMARCHY_PATH") .. "/?.lua;" .. package.path

local vconsole = os.getenv("OMARCHY_VCONSOLE")
local real_open = io.open

io.open = function(path, mode)
if path ~= "/etc/vconsole.conf" then
return real_open(path, mode)
end

if not vconsole then
return nil
end

local file = io.tmpfile()
file:write(vconsole)
file:seek("set")
return file
end

hl = {
config = function(config)
local input = config.input
print(("[%s] [%s] [%s]"):format(input.kb_layout, input.kb_variant, input.kb_options))
end,
}

o = { window = function() end }

require("default.hypr.input")
LUA
}

toggle_options="compose:caps,shift:both_capslock_cancel,grp:alts_toggle"
owner="$ROOT/bin/omarchy-provision-owner"

# The original persist path must still be in apply_keyboard. Thai only adds a
# branch in front; it must not replace loadkeys / systemd-firstboot / localectl.
grep -q 'loadkeys "$keymap"' "$owner" || fail "apply_keyboard still loadkeys the chosen console map"
grep -q 'systemd-firstboot --keymap="$keymap" --force' "$owner" ||
fail "apply_keyboard still persists known console maps with systemd-firstboot"
grep -q 'localectl set-keymap "$keymap"' "$owner" ||
fail "apply_keyboard still falls back to localectl set-keymap"
grep -q 'keeping the default' "$owner" ||
fail "apply_keyboard still keeps the default for unknown console maps"
pass "apply_keyboard keeps the existing console persist path"

grep -q 'omarchy_xkb_only_layout "$keymap"' "$owner" ||
fail "apply_keyboard special-cases XKB-only picker values"
grep -q 'apply_keyboard us' "$owner" ||
fail "XKB-only layouts reuse apply_keyboard us for the Latin console"
grep -q 'omarchy_write_xkblayout "$keymap"' "$owner" ||
fail "XKB-only layouts then write XKBLAYOUT via the shared helper"
pass "Thai persist is an added branch, not a replacement of apply_keyboard"

# After apply_keyboard us, vconsole has KEYMAP=us and XKBLAYOUT=us. The new
# helper only rewrites XKBLAYOUT; that is the first-boot Thai step.
vconsole="$tmp_dir/vconsole.conf"
printf '%s\n' 'KEYMAP=us' 'XKBLAYOUT=us' 'FONT=default8x16' >"$vconsole"
omarchy_write_xkblayout th "$vconsole"
grep -qx 'KEYMAP=us' "$vconsole" || fail "writing XKBLAYOUT leaves KEYMAP=us" "$(<"$vconsole")"
grep -qx 'XKBLAYOUT=th' "$vconsole" || fail "writing XKBLAYOUT sets th" "$(<"$vconsole")"
[[ $(grep -c '^XKBLAYOUT=' "$vconsole") == 1 ]] || fail "a single XKBLAYOUT line remains"
grep -qx 'FONT=default8x16' "$vconsole" || fail "other vconsole lines are left alone"
pass "omarchy_write_xkblayout points XKBLAYOUT at th without touching KEYMAP"

desktop=$(resolved_input "$(<"$vconsole")")
[[ $desktop == "[us,th] [,] [$toggle_options]" ]] ||
fail "Hyprland duals Thai from the first-boot vconsole" "expected: [us,th] [,] [$toggle_options]
actual: $desktop"
pass "first-boot Thai vconsole becomes a us,th Hyprland session"

missing="$tmp_dir/missing.conf"
printf '%s\n' 'KEYMAP=us' >"$missing"
omarchy_write_xkblayout th "$missing"
grep -qx 'XKBLAYOUT=th' "$missing" || fail "helper appends XKBLAYOUT when the key is absent"
pass "omarchy_write_xkblayout appends XKBLAYOUT when it is missing"

printf '%s\n' "$OMARCHY_KEYBOARD_LAYOUTS" | grep -qx 'Thai (Kedmanee)|th' ||
fail "the picker lists Thai (Kedmanee)"
awk -F'|' '
$1 == "Tajik" { tajik = 1; next }
$1 == "Thai (Kedmanee)" { if (!tajik) exit 1; thai = 1; next }
$1 == "Turkish" { if (!thai) exit 1; exit 0 }
END { exit thai && tajik ? 0 : 1 }
' <<<"$OMARCHY_KEYBOARD_LAYOUTS" ||
fail "Thai (Kedmanee) sits alphabetically between Tajik and Turkish"
pass "Thai (Kedmanee) is on the shared picker between Tajik and Turkish"
3 changes: 3 additions & 0 deletions test/shell.d/hyprland-keyboard-layout-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ XKBVARIANT=intl
assert_input "latin layouts are left alone" "[de] [nodeadkeys] [$base_options]" 'XKBLAYOUT=de
XKBVARIANT=nodeadkeys
'
assert_input "thai duals as us,th from XKBLAYOUT" "[us,th] [,] [$toggle_options]" 'KEYMAP=us
XKBLAYOUT=th
'
assert_input "non-latin layout gains us in front" "[us,ara] [,] [$toggle_options]" 'XKBLAYOUT=ara
'
assert_input "prepended us keeps variants aligned" "[us,ru] [,phonetic] [$toggle_options]" 'XKBLAYOUT=ru
Expand Down
16 changes: 16 additions & 0 deletions test/shell.d/setup-form-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,22 @@ assert_status 0 "keyboard prompt succeeds"
grep -qF -- '--selected English (US)' "$GUM_ARGS" || fail "keyboard prompt preselects English (US)"
pass "keyboard prompt maps the chosen label to its keymap"

run_prompt omarchy_prompt_keyboard "0:Thai (Kedmanee)"
assert_status 0 "keyboard prompt accepts Thai (Kedmanee)"
[[ $(field keyboard) == "th" ]] ||
fail "Thai (Kedmanee) resolves to th, the XKB marker apply_keyboard persists in place of a console keymap kbd does not ship"
[[ $(field keyboard_label) == "Thai (Kedmanee)" ]] || fail "keyboard prompt keeps the Thai label for the summary"
grep -qx 'Thai (Kedmanee)' "$tmp_dir/stdin.1" || fail "keyboard prompt offers Thai (Kedmanee)"
pass "keyboard prompt maps Thai (Kedmanee) to the th marker"

omarchy_xkb_only_layout th || fail "th is an xkb-only layout"
if omarchy_xkb_only_layout us; then
fail "us is a console keymap, not xkb-only"
fi
[[ $(omarchy_console_keymap_for th) == "us" ]] || fail "xkb-only layouts load the US console map"
[[ $(omarchy_console_keymap_for de) == "de" ]] || fail "console keymaps load themselves"
pass "xkb-only layouts keep a Latin console"

run_prompt omarchy_prompt_keyboard "1:"
assert_status "$OMARCHY_FORM_BACK" "keyboard prompt reports Esc as back"
assert_returned "keyboard prompt survives Esc under set -e"
Expand Down