* Unify input methods with the installer keyboard selection
* Preserve inherited input keys and later keyboard changes
* Exercise input engines across desktop toolkits
* Show input modes in the keyboard indicator
* Keep Pinyin setup prompts visible
* Remember input selections before an app gains focus
* Remove the Japanese input welcome notification
* Show explicit choices on notification cards
* Suppress the Cloudpinyin first-use prompt
* Show the input switching shortcut in keyboard hints
* Verify input setup and composition stay quiet
* Use Super+I for input switching independently of Fcitx keys
* Restore linked input settings and attribute test notifications to Fcitx
* Correct the input setup shortcut hint
* Keep input tooltips to the name and switching shortcut
* Place the input language selector with the right bar widgets
* Show input switching only for multiple layouts or methods
* Unify input method and keyboard layout switching
* Select keyboard layouts and input methods in the Typing menu
* Apply typing selections immediately from the menu
* Use installer keyboard choices and keep typing selections accurate
* Queue typing changes and wait for saved selections
* Keep queued typing selections when reopening the menu
* Cycle keyboard layouts alongside composition engines
* Avoid shadowing Python typing and retain pending mixed input selections
* Keep input clicks working through controller and compositor failures
* Move the keyboard layout widget to the right side of existing bars
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Map keyboard choices to the layouts the installer sets
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep the switching order when changing input methods
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Set input method fonts only after the selection saves
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Restore confirmed picker checks when an immediate change fails
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Route Super+I through the shell's input reader so unfocused choices stick
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Restore the input group when the font preference cannot be written
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop the azerty conversion now that the installer no longer offers it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Apply the owner's keyboard layout once before persisting the input choice
A quattro merge kept a second apply_keyboard after the retry loop, which
re-ran loadkeys and firstboot, ignored their failure, and overwrote the
XKB layout setup supplies for keymaps kbd-model-map lacks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Give the Lao keyboard choice a Lao desktop layout
The row used la-latin1, kbd's Latin American Spanish keymap, so Lao
installs typed Spanish. There is no Lao console keymap; like Korean, the
console stays US and the desktop gets la, which Omarchy keeps behind US
as a non-Latin layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Load engines installed after Fcitx started when they are selected
The Typing menu refused an engine whose package an update had installed,
since Fcitx discovers engines only at startup. Restart input once and wait
for the engine; name the package when it really is not installed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Cycle input methods back with Super+Shift+I
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop notification action buttons now that the Pinyin prompt is suppressed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Cycle input only through the shell's reader
Without the shell there is no bar or menu either, so the one-shot cycling
path only duplicated the reader's logic.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add engines from the command line through the Typing menu's path
omarchy setup input <engine> had its own restart, append, select and
live-rollback code in configure.py, parallel to the menu's. It now
installs the packages and appends through typing_setup, leaving
configure.py with install-time seeding and update defaults.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Keep Ctrl+Space out of Fcitx's toggles instead of probing for it
The terminal prefix bind read the Fcitx config and profile on every press
to avoid fighting a Ctrl+Space toggle. configure --defaults now removes
that key from every trigger list, so the bind only checks for a terminal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Run the input-method scripts with the system Python
A bare python resolves through PATH, so a mise, pyenv or venv interpreter
could run them without the system's PyGObject.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The Thunderbolt approval watcher is enabled by its setup command, a
migration and first-run, but no package put it in a user unit folder and
nothing installed it. On edge the migration failed with "Unit
omarchy-thunderbolt-authorization.service does not exist", so every later
migration stayed pending. First-run failed too, and enabled none of its
units: given a list, systemctl enables nothing when one unit is unknown.
The units are now shipped by the settings packages (omarchy-pkgs#922).
Here, first-run enables its units one at a time, so a unit missing from a
build costs only that unit, and config-test fails when a unit under
default/systemd/user is enabled without being shipped or installed first.
* Offer an AI diagnosis when a process crashes
systemd-coredump journals every core dump under a known MESSAGE_ID with the
crashing program, pid, and signal as structured fields. omarchy-crash-watch
follows that stream and raises a "Process crashed: <program>" toast; clicking it
opens omarchy-agent-crash, which briefs the default agent on the crash.
The toast goes through omarchy-notification-send --exec rather than a libnotify
action, because the shell runs clicks from its own omarchy-exec hint and never
emits ActionInvoked. It keeps the default "omarchy-action" app name too, the
only one shouldBypassDnd() lets through -- a crash being the last notification
worth swallowing. It stays quiet until an agent is configured, since a
diagnosis is all it offers.
The method lives in a diagnose-crash skill rather than the prompt, so it is
edited in one place and works with whichever agent is default. It covers
investigating the core, and reporting a confirmed Omarchy bug upstream: scoped
to bugs Omarchy controls, searched for duplicates first, only with the user's
agreement, and signed with the model and harness that produced it.
A migration reaches existing installs, whose skill symlinks and unit enablement
would otherwise sit behind one-time setup paths.
* Let the diagnosis clean up the core it extracted
"Do not modify or delete anything" contradicted the symbolization step right
above it, which writes a core to a temp file and deletes it on exit. Read
literally, the core survives -- and the same section warns it holds passwords
and tokens. The prohibition is about the system, not about your own scratch.
* Do not spend a crash toast on a dead notification server
The shell owns org.freedesktop.Notifications, so its own crash takes the
notification server down with it -- and a shell crash is exactly what you want
told about. The toast was sent once into that gap and the dedupe window was
recorded regardless, so the rest of the crash loop went quiet for a minute and
`journalctl -n 0` never replays what was missed.
It now waits for the restarted shell to reclaim the bus name, as
omarchy-migrate-notify already does, and only a delivered toast starts the
dedupe window.
fcitx5 is what turns the CapsLock compose sequences in ~/.XCompose into
text for Wayland clients -- CapsLock m s for an emoji, CapsLock space n
for your name. It was launched fire-and-forget from Hyprland's autostart
via uwsm-app, so nothing supervised it, nothing restarted it, and it
logged nowhere. When it went away, every compose sequence stopped
working for the rest of the session with no visible symptom beyond
"emoji input is busted", and no record of why.
That is not hypothetical: it was found dead on a running machine with no
coredump, no OOM kill, and nothing in the journal to explain it.
Move it to a systemd user service:
- Restart=always, not on-failure. fcitx5 exits 0 when it finds another
instance already owning org.fcitx.Fcitx5, and a clean exit still
leaves the user with no input method.
- After=/PartOf=graphical-session.target. It needs WAYLAND_DISPLAY and
DISPLAY, which uwsm imports into the user manager before reaching the
target, and its wayland connection dies with the compositor.
- ConditionEnvironment=WAYLAND_DISPLAY. After= is ordering only and does
not stop the unit from being started while the target is inactive. An
update over SSH has a live user manager (pam_systemd) and no graphical
session, and a fcitx5 started there comes up blind -- then stays
active, so the later target activation won't pull in a working one,
because Wants= does not restart what is already running. Skipping the
start leaves the unit enabled and healthy for the next graphical login.
The migration hands over inside a live session only: it enables without
--now, and only when graphical-session.target is active does it drop the
autostart-launched process and start the unit. Because that kills a
fcitx5 that was working a moment ago, a failed start is reported instead
of leaving the session mute with the migration marked complete.
omarchy-restart-xcompose now drives the unit. It still clears any fcitx5
running outside it first: that process owns the bus name, so the unit's
instance would exit on arrival and the stale one would keep serving the
old table -- a restart that reports success and changes nothing.
Side benefit: fcitx5 now logs to the journal under its own unit, so the
next disappearance leaves a record.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
omarchy-update-user-notify.path watched /usr/share/omarchy/migrations, but
pacman writes that directory during every update, including the blessed
omarchy update, which runs omarchy-migrate a step later. The watcher fired a
critical notification for the migrations the update was already applying in
the visible terminal. A watcher cannot tell that apart from a bypassed
pacman -Syu, so the only trigger that never collides with a running update is
a once-per-login check.
The service that already ran at graphical-session.target is now the whole
mechanism, renamed after the command it runs. That is also all the second-user
case needs: markers are per-user, so anyone who did not run the update finds
them missing at their next login.
Login timing means the toast can be sent before the shell has claimed
org.freedesktop.Notifications, so the notifier waits for a live server first.
The wait is omarchy-first-run's, lifted into omarchy-notification-wait rather
than duplicated.
The package keeps omarchy-update-user-notify.service as a symlink onto the new
unit. Existing users hold an absolute wants symlink to the old path, and the
migration that repoints it only runs for users who run an update, which is the
opposite of who the notifier is for.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
omarchy-update-user-notify.path used PathExistsGlob= on the packaged
migrations directory. That directive is level-triggered: systemd re-checks
it every time the triggered unit deactivates and fires again while the glob
still matches. Since applied migrations stay on disk forever (state lives in
~/.local/state/omarchy/migrations), the glob always matches, so the oneshot
notifier re-triggered itself in a tight loop (~26-66 starts/sec) — burning
about a core and flooding the journal for the whole session.
The loop existed since the unit was introduced, but the default start-rate
limit killed it after 5 iterations, taking the .path unit down with
'unit-start-limit-hit'. That symptom was reported as #6174 and fixed
yesterday by setting StartLimitIntervalSec=0 — which removed the only brake
and turned the capped hiccup into an unbounded busy-loop.
Fix the actual cause instead:
* Drop PathExistsGlob= from the .path unit, keeping the edge-triggered
PathModified= watch for updates that land mid-session.
* Revert the StartLimitIntervalSec=0 override; with the level trigger gone
there is no self-re-fire to trip the limit, and the default limit is a
useful backstop again.
* Preserve the once-per-login pending check the glob used to provide by
giving the service its own WantedBy=graphical-session.target, enabled at
first-run alongside the other user units.
* Add a migration that daemon-reloads, revives a rate-limit-killed .path,
restarts the watcher, and enables the login-time notifier on existing
installs.
Verified with transient path/service units: the old config runs the service
200 times in 3 seconds; the new config runs it zero times while idle and
exactly once when a new migration file lands.
Thanks to @HANCORE-Linux for finding and diagnosing the problem.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
systemctl --user enable only writes the .wants symlinks; the services
don't actually run until next login. Switching to --now enables AND
starts them, so the first session has bt-agent (bluetooth pairing) and
omarchy-sleep-lock active immediately rather than waiting a reboot.
omarchy-recover-internal-monitor is Type=oneshot with a
ConditionPathExists guard, so --now is harmless for it (it'll skip if
the toggle isn't set).
Reorganizes Omarchy 4 around three layers for populating $HOME:
Seed: omarchy-settings ships defaults to /etc/skel; useradd -m
copies them on user creation
Finalize: omarchy-finalize-user (renamed from omarchy-setup-user)
handles only the runtime tweaks /etc/skel can't do — skill
symlinks, xdg-user-dirs, default browser/mailto, vconsole→hypr
keyboard sync, and install/user/all.sh
Resync: omarchy-reinstall-configs is the explicit, destructive
resync of /etc/skel into an existing user's $HOME
Package-owned files move out of config/ into default/, where the
omarchy-settings PKGBUILD installs them to real system paths:
config/environment.d/fcitx.conf -> /usr/lib/environment.d/
config/fontconfig/fonts.conf -> /usr/share/fontconfig/conf.avail/
config/mimeapps.list -> /usr/share/applications/
config/omarchy.ttf -> /usr/share/fonts/omarchy/
config/systemd/user/*.service -> /usr/lib/systemd/user/
config/uwsm/default -> /usr/share/omarchy/default/uwsm/
config/uwsm/env -> /usr/share/uwsm/env.d/10-omarchy
config/xdg-terminals.list -> /usr/share/xdg-terminal-exec/
omarchy-upgrade-to-4 grows a 'retire' action (renamed from 'move' to
clarify nothing is copied — the system path is owned by the new package
once the user's hash-matched ~/.config copy is removed). Mismatched
copies are kept as backups so user overrides survive the upgrade.
Other simplifications:
- Single env bootstrap at default/bash/env-bootstrap sourced by
/etc/profile.d/omarchy.sh, /etc/skel/.bashrc,
/usr/share/uwsm/env.d/10-omarchy, and default/bash/envs. PATH
prepend only in dev-link mode (production uses /usr/bin/omarchy-*).
- omarchy-refresh-config reads from /etc/skel/.config so refresh
means 'snap to skel'.
- omarchy-reinstall-configs collapses to 'cp -af /etc/skel/. ~/'
plus limine/plymouth/nvim refresh.
- omarchy-font-set uses awk against our own 30-omarchy.conf instead
of xmlstarlet; xmlstarlet dropped from omarchy-base.packages.
- Defer user systemd enables (bt-agent, sleep-lock,
recover-internal-monitor) to first-run via
install/user/first-run/enable-user-units.sh; delete
omarchy-user-systemctl-enable and the per-hardware install
scripts that called it.
- Wireplumber bluetooth-a2dp-autoconnect.conf moves to config/ so
/etc/skel ships it; install/user/hardware/bluetooth.sh deleted.
- Default terminal switched to foot.desktop.
- docs/file-layout.md documents the three-layer model and the
build-time repo→path map.