Return Caps Lock to normal and make Shift + Caps Lock the compose key (#14939)

* Return Caps Lock to normal and make Shift + Caps Lock the compose key

Caps Lock as compose, with both Shifts as Caps Lock, confused too many
people. Stock XKB has no option for compose on the shifted Caps key, so
Omarchy defines one in /etc/xkb, which libxkbcommon reads before the
system rules. The explicit actions keep the Shift level from toggling
Caps Lock. Lone Shift is no longer part of Caps Lock, which leaves it
free for input methods.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Require xkbcli so the keymap check cannot silently skip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier HanssonandClaude Opus 5.5 authored and GitHub committed 2026-10-11 09:06:59 +09:00
1 parent 0b9dace018
commit 1b5222be74
12 files changed
+64 -53

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@
-- input = {
-- -- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt.
-- kb_layout = "us,dk,eu",
-- kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",
-- kb_options = "omarchy:shift_caps_compose,grp:alts_toggle",
--
-- -- Use a specific keyboard variant if needed (e.g. intl for international keyboards).
-- kb_variant = "intl",
+3 -5
View File
@@ -11,11 +11,9 @@ local vconsole = keyboard.selected()
local kb_layout = vconsole.XKBLAYOUT or "us"
local kb_variant = vconsole.XKBVARIANT or ""
-- CapsLock is the compose key, so Caps Lock itself has to live somewhere else.
-- Both Shifts together is the usual home for it, but it's easy to hit by
-- accident while typing. The _cancel variant sets Caps Lock the same way and
-- releases it on the next lone Shift, so a misfire clears itself.
local kb_options = "compose:caps,shift:both_capslock_cancel"
-- Caps Lock is Caps Lock, and Shift + Caps Lock is the compose key. Stock XKB
-- has no such option, so Omarchy defines it in /etc/xkb.
local kb_options = "omarchy:shift_caps_compose"
-- Hyprland resolves keybindings against the first entry in kb_layout, not the
-- layout that's currently active, so Omarchy's Latin-keysym bindings (SUPER + W
+1 -1
View File
@@ -1,6 +1,6 @@
[Unit]
Description=Fcitx5 input methods and XCompose sequences
# fcitx5 turns the CapsLock compose sequences in ~/.XCompose into text for
# fcitx5 turns the Shift + CapsLock compose sequences in ~/.XCompose into text for
# Wayland clients.
#
# Wait for the compositor: fcitx5 needs WAYLAND_DISPLAY and DISPLAY, which uwsm
+2
View File
@@ -91,6 +91,8 @@ config/** ──► omarchy-settings /etc/skel/.config/
/usr/share/omarchy/config/** (resync source)
etc/fastfetch/config.jsonc ──► omarchy-settings /etc/fastfetch/config.jsonc
etc/xdg/kitty/kitty.conf ──► omarchy-settings /etc/xdg/kitty/kitty.conf
etc/xkb/{rules/evdev,symbols/omarchy}
──► omarchy-settings /etc/xkb/ (Shift + Caps Lock compose option)
applications/*.desktop ──► omarchy-settings /etc/skel/.local/share/applications/
/usr/share/omarchy/applications/
+6
View File
@@ -0,0 +1,6 @@
// Omarchy's own XKB option. libxkbcommon reads /etc/xkb before the system
// rules, which supply everything else.
! include %S/evdev
! option = symbols
omarchy:shift_caps_compose = +omarchy(shift_caps_compose)
+11
View File
@@ -0,0 +1,11 @@
// Caps Lock stays Caps Lock; Shift + Caps Lock is the Compose key. The actions
// are explicit so the Shift level never inherits the key's Lock modifier,
// which would toggle Caps Lock on every compose.
partial modifier_keys
xkb_symbols "shift_caps_compose" {
key <CAPS> {
type[Group1] = "TWO_LEVEL",
symbols[Group1] = [ Caps_Lock, Multi_key ],
actions[Group1] = [ LockMods(modifiers = Lock), NoAction() ]
};
};
+1 -1
View File
@@ -1,4 +1,4 @@
# Set default XCompose that is triggered with CapsLock
# Set default XCompose that is triggered with Shift + CapsLock
tee ~/.XCompose >/dev/null <<EOF
# Run omarchy-restart-xcompose to apply changes
+26 -26
View File
@@ -339,36 +339,36 @@ You can use `Super + Ctrl + E` to show a complete emoji picker that'll put the s
| Hotkey | EM | Clue |
| ------------ | -- | ---------- |
| `CapsLock M S` | 😄 | smile |
| `CapsLock M C` | 😂 | cry |
| `CapsLock M L` | 😍 | love |
| `CapsLock M V` | ✌️ | victory |
| `CapsLock M H` | ❤️ | heart |
| `CapsLock M Y` | 👍 | yes |
| `CapsLock M N` | 👎 | no |
| `CapsLock M F` | 🖕 | fuck |
| `CapsLock M W` | 🤞 | wish |
| `CapsLock M R` | 🤘 | rock |
| `CapsLock M K` | 😘 | kiss |
| `CapsLock M E` | 🙄 | eyeroll |
| `CapsLock M I` | 😉 | wink |
| `CapsLock M P` | 🙏 | pray |
| `CapsLock M D` | 🤤 | drool |
| `CapsLock M M` | 💰 | money |
| `CapsLock M X` | 🎉 | xellebrate |
| `CapsLock M 1` | 💯 | 100% |
| `CapsLock M T` | 🥂 | toast |
| `CapsLock M O` |👌 | ok |
| `CapsLock M G` |👋 | greeting |
| `CapsLock M A` |💪 | arm |
| `CapsLock M B` |🤯 | blowing |
| `Shift + CapsLock M S` | 😄 | smile |
| `Shift + CapsLock M C` | 😂 | cry |
| `Shift + CapsLock M L` | 😍 | love |
| `Shift + CapsLock M V` | ✌️ | victory |
| `Shift + CapsLock M H` | ❤️ | heart |
| `Shift + CapsLock M Y` | 👍 | yes |
| `Shift + CapsLock M N` | 👎 | no |
| `Shift + CapsLock M F` | 🖕 | fuck |
| `Shift + CapsLock M W` | 🤞 | wish |
| `Shift + CapsLock M R` | 🤘 | rock |
| `Shift + CapsLock M K` | 😘 | kiss |
| `Shift + CapsLock M E` | 🙄 | eyeroll |
| `Shift + CapsLock M I` | 😉 | wink |
| `Shift + CapsLock M P` | 🙏 | pray |
| `Shift + CapsLock M D` | 🤤 | drool |
| `Shift + CapsLock M M` | 💰 | money |
| `Shift + CapsLock M X` | 🎉 | xellebrate |
| `Shift + CapsLock M 1` | 💯 | 100% |
| `Shift + CapsLock M T` | 🥂 | toast |
| `Shift + CapsLock M O` |👌 | ok |
| `Shift + CapsLock M G` |👋 | greeting |
| `Shift + CapsLock M A` |💪 | arm |
| `Shift + CapsLock M B` |🤯 | blowing |
## Quick Completions
| Hotkey | Completion |
| ------------ | ---------- |
| `CapsLock Space Space` | — (mdash) |
| `CapsLock Space N` | Your name (as entered on setup) |
| `CapsLock Space E` | Your email (as entered on setup) |
| `Shift + CapsLock Space Space` | — (mdash) |
| `Shift + CapsLock Space N` | Your name (as entered on setup) |
| `Shift + CapsLock Space E` | Your email (as entered on setup) |
You can add more of your own by editing `~/.XCompose`, then running `omarchy-restart-xcompose` in the terminal to get the changes picked up.
+5 -5
View File
@@ -9,7 +9,7 @@ hl.config({
input = {
-- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt
kb_layout = "us,dk",
kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",
kb_options = "omarchy:shift_caps_compose,grp:alts_toggle",
-- Change speed of keyboard repeat
repeat_rate = 40,
@@ -37,7 +37,7 @@ o.window("(Alacritty|kitty|foot)", { scroll_touchpad = 1.5 })
You can [see all the input options](https://wiki.hypr.land/Configuring/Basics/Variables/#input) on the Hyprland wiki for inputs.
By default, Omarchy uses CapsLock as the compose key for [quick emojis](07-hotkeys.md#quick-emojis) and [other completions](07-hotkeys.md#quick-completions). If you'd rather use CapsLock as Caps Lock, move the compose key elsewhere by changing `compose:caps` in `kb_options`. For example, this moves the compose key to Right Alt:
CapsLock works as a normal Caps Lock, and `Shift + CapsLock` is the compose key for [quick emojis](07-hotkeys.md#quick-emojis) and [other completions](07-hotkeys.md#quick-completions). If you'd rather have the compose key elsewhere, replace `omarchy:shift_caps_compose` in `kb_options`. For example, this moves the compose key to Right Alt:
```lua
hl.config({
@@ -61,7 +61,7 @@ On Dell XPS laptops with a haptic touchpad, you can also set the click strength
Select Japanese, Korean, Chinese (Simplified, Pinyin), or Chinese (Traditional, Zhuyin) when the installer asks for your keyboard. Omarchy configures the keyboard and matching input engine automatically, including during offline first-boot setup. Japanese uses Mozc, Korean uses standard two-set Hangul, Simplified Chinese uses Pinyin, and Traditional Chinese uses Chewing's standard Zhuyin arrangement. Japanese (US keyboard) provides Mozc with a US keyboard layout.
Typing starts in Latin mode. Press `Super + I` to cycle through configured input methods, and `Super + Shift + I` to cycle back. On Japanese keyboards, 全角/半角 toggles input, 変換 turns it on, and 無変換 turns it off. On a Korean keyboard layout, dedicated 한/영 and 한자 keys switch Hangul and convert to Hanja. `Ctrl + Space` stays available for Tmux and Herdr; CapsLock stays the compose key.
Typing starts in Latin mode. Press `Super + I` to cycle through configured input methods, and `Super + Shift + I` to cycle back. On Japanese keyboards, 全角/半角 toggles input, 変換 turns it on, and 無変換 turns it off. On a Korean keyboard layout, dedicated 한/영 and 한자 keys switch Hangul and convert to Hanja. `Ctrl + Space` stays available for Tmux and Herdr; `Shift + CapsLock` stays the compose key.
The keyboard indicator appears on the right of the bar when you have multiple keyboard layouts or input methods. Click it to switch input languages; Japanese displays あ for hiragana. For Japanese character choices, switch to Japanese, type a word such as `nihongo`, then press Space twice. Press Enter to accept your choice. If you also have multiple keyboard layouts, right-click the indicator to cycle those.
@@ -69,7 +69,7 @@ Use _Setup > Typing > Keyboard Layouts_ to select layouts such as English and Fr
Run `omarchy setup keyboard` or `omarchy setup input` to open the same pickers. To append one language from the command line, use `omarchy setup input mozc`, `hangul`, `pinyin`, or `chewing`. Your custom switching keys are preserved. For alternative engine layouts or keys, install `fcitx5-configtool` with `omarchy pkg add fcitx5-configtool` and launch it from a terminal. Selecting an input language does not change the desktop language.
Use `Super + I` to cycle through input methods or keyboard layouts, and `Super + Shift + I` to go back the other way, so with three configured you can move between two neighbours. The input indicator appears on the right of the bar only when more than one input method or layout is configured. This desktop binding works alongside your existing Fcitx switching keys; you can override it in `~/.config/hypr/bindings.lua`. Tapping Shift alone is not an input switch: Omarchy uses both Shift keys for CapsLock, which changes how input methods see Shift release. Input engines and the CapsLock compose sequences use the [Fcitx5](https://fcitx-im.org/) service already running in every session.
Use `Super + I` to cycle through input methods or keyboard layouts, and `Super + Shift + I` to go back the other way, so with three configured you can move between two neighbours. The input indicator appears on the right of the bar only when more than one input method or layout is configured. This desktop binding works alongside your existing Fcitx switching keys; you can override it in `~/.config/hypr/bindings.lua`. Input engines and the compose sequences use the [Fcitx5](https://fcitx-im.org/) service already running in every session.
### Use ALT as SUPER
@@ -78,7 +78,7 @@ On some keyboards, it's not convenient to use the primary meta key (Windows/cmd
```lua
hl.config({
input = {
kb_options = "compose:caps,shift:both_capslock_cancel,altwin:swap_alt_win",
kb_options = "omarchy:shift_caps_compose,altwin:swap_alt_win",
},
})
```
-12
View File
@@ -10,18 +10,6 @@ Omarchy assumes a 2x high-resolution display, which requires setting `GDK_SCALE`
For Spotify, you can use `Ctrl + Minus` to shrink the UI (and `Ctrl + Plus` to make it bigger).
### Why isn't Caps Lock working?
In Omarchy, Caps Lock has been designated to be the xcompose key. That's how you get [quick emojis](07-hotkeys.md#quick-emojis) and [other autocompletions](07-hotkeys.md#quick-completions) done. If you really miss using Caps Lock, you can remap the xcompose key to something else by editing `~/.config/hypr/input.lua`, like setting it to the right alt key:
```
hl.config({
input = {
kb_options = "compose:ralt",
},
})
```
### My Wi-Fi, Bluetooth, audio, or trackpad just stopped working
Before you reboot, try restarting the offending subsystem on its own. _Update > Hardware_ in the Omarchy menu has Wi-Fi, Bluetooth, Audio, and Trackpad, and reloading one of those clears up the majority of "it worked five minutes ago" situations — a Bluetooth headset that won't reconnect, a trackpad that went dead after a suspend, sound that vanished when you unplugged a monitor.
+1 -1
View File
@@ -9,7 +9,7 @@ hl.config({
input = {
-- Use multiple keyboard layouts and switch between them with Left Alt + Right Alt
kb_layout = "us,fr",
kb_options = "compose:caps,shift:both_capslock_cancel,grp:alts_toggle",
kb_options = "omarchy:shift_caps_compose,grp:alts_toggle",
},
})
```
@@ -3,6 +3,7 @@
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
require_command lua
require_command xkbcli
resolved_input_for() {
local module="$1"
@@ -94,7 +95,7 @@ assert_greeter_input() {
assert_resolved_input resolved_greeter_input "$@"
}
base_options="compose:caps,shift:both_capslock_cancel"
base_options="omarchy:shift_caps_compose"
toggle_options="$base_options,grp:alts_toggle"
assert_input "missing vconsole.conf falls back to us" "[us] [] [$base_options]"
@@ -117,6 +118,11 @@ XKBVARIANT=phonetic
assert_input "non-latin layout in front gains us even when us trails" "[us,il,us] [,] [$toggle_options]" 'XKBLAYOUT=il,us
'
caps=$(xkbcli compile-keymap --include "$ROOT/etc/xkb" --include-defaults --layout us,ru --options omarchy:shift_caps_compose | grep -A5 'key <CAPS>')
[[ $caps == *"Caps_Lock,"*"Multi_key ]"* && $caps == *"LockMods(modifiers=Lock),"*"NoAction() ]"* ]] ||
fail "Shift + Caps Lock composes without toggling Caps Lock" "$caps"
pass "Shift + Caps Lock composes without toggling Caps Lock"
# The greeter takes no compose or capslock options: they're session comfort
# settings with nothing to do with typing a password.
assert_greeter_input "greeter falls back to us without vconsole.conf" "[us] [] []"