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>
39 lines
2.0 KiB
Bash
39 lines
2.0 KiB
Bash
echo "Supervise fcitx5 so CapsLock compose sequences can't silently die"
|
|
|
|
# fcitx5 was launched fire-and-forget from Hyprland's autostart. Nothing
|
|
# restarted it and nothing noticed when it went away, so a single lost start
|
|
# left every ~/.XCompose sequence (CapsLock m s -> emoji) dead for the rest of
|
|
# the session. It's a systemd user service with Restart=always now.
|
|
|
|
systemctl --user daemon-reload >/dev/null 2>&1 || true
|
|
|
|
# Enable without --now, and start by hand further down only when there is a
|
|
# session to start into. `systemctl enable` needs a live user manager, which an
|
|
# `omarchy update` from a TTY does not have, so fall back to writing exactly the
|
|
# symlink it would have written rather than silently leaving this unenabled.
|
|
if ! systemctl --user enable omarchy-fcitx5.service >/dev/null 2>&1; then
|
|
wants_dir="$HOME/.config/systemd/user/graphical-session.target.wants"
|
|
mkdir -p "$wants_dir"
|
|
ln -sfn /usr/lib/systemd/user/omarchy-fcitx5.service \
|
|
"$wants_dir/omarchy-fcitx5.service"
|
|
fi
|
|
|
|
# Outside a graphical session -- an update over SSH -- there is nothing to hand
|
|
# over: no autostart-launched fcitx5 to kill, and the unit's own
|
|
# ConditionEnvironment would skip the start anyway. The enablement above is the
|
|
# whole job; the next graphical login starts it.
|
|
if systemctl --user is-active --quiet graphical-session.target; then
|
|
# The service and the autostart-launched process can't coexist: a second
|
|
# fcitx5 sees the first owning org.fcitx.Fcitx5 and exits 0, which
|
|
# Restart=always would turn into a restart loop. Drop the stray first.
|
|
pkill -x fcitx5 >/dev/null 2>&1 || true
|
|
|
|
# Report what systemctl actually said. This kills a fcitx5 that was working a
|
|
# moment ago, so a start failure here has to be loud instead of leaving the
|
|
# session with no input method and a migration marked complete.
|
|
if ! error=$(systemctl --user start omarchy-fcitx5.service 2>&1); then
|
|
echo "Could not start omarchy-fcitx5.service: $error"
|
|
echo "Compose sequences (CapsLock m s) will not work until the next login."
|
|
fi
|
|
fi
|