diff --git a/bin/omarchy-provision-owner b/bin/omarchy-provision-owner index 4c21ff49e20..13059146dc1 100755 --- a/bin/omarchy-provision-owner +++ b/bin/omarchy-provision-owner @@ -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 diff --git a/install/provisioning/setup-form.sh b/install/provisioning/setup-form.sh index f4265d1ddec..767436665f0 100644 --- a/install/provisioning/setup-form.sh +++ b/install/provisioning/setup-form.sh @@ -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])?$' diff --git a/manual/34-keyboard-mouse-trackpad.md b/manual/34-keyboard-mouse-trackpad.md index 648e7713d8d..c4f940e398d 100644 --- a/manual/34-keyboard-mouse-trackpad.md +++ b/manual/34-keyboard-mouse-trackpad.md @@ -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. diff --git a/test/shell.d/apply-keyboard-test.sh b/test/shell.d/apply-keyboard-test.sh new file mode 100755 index 00000000000..6d3390cd4e0 --- /dev/null +++ b/test/shell.d/apply-keyboard-test.sh @@ -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" diff --git a/test/shell.d/hyprland-keyboard-layout-test.sh b/test/shell.d/hyprland-keyboard-layout-test.sh index 8ed6fe3858f..ab8c7c2b37a 100644 --- a/test/shell.d/hyprland-keyboard-layout-test.sh +++ b/test/shell.d/hyprland-keyboard-layout-test.sh @@ -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 diff --git a/test/shell.d/setup-form-test.sh b/test/shell.d/setup-form-test.sh index 2b9878eb178..32b7047f5c2 100755 --- a/test/shell.d/setup-form-test.sh +++ b/test/shell.d/setup-form-test.sh @@ -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"