Supervise fcitx5 so XCompose sequences can't silently die
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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
03902f2460
commit
6e07fd0e82
@@ -46,3 +46,33 @@ grep -F 'omarchy-migrate-notify.service' "$first_run_units" >/dev/null ||
|
||||
grep -F 'omarchy-update-user-notify' "$first_run_units" >/dev/null &&
|
||||
fail "first-run still enables the retired notifier units"
|
||||
pass "first-run enables the login-only migration notifier"
|
||||
|
||||
fcitx_service="$ROOT/default/systemd/user/omarchy-fcitx5.service"
|
||||
grep -Fx 'ExecStart=/usr/bin/fcitx5 --disable notificationitem' "$fcitx_service" >/dev/null
|
||||
grep -Fx 'Restart=always' "$fcitx_service" >/dev/null ||
|
||||
fail "fcitx5 exits 0 on a duplicate bus name, so on-failure would leave the user with no input method"
|
||||
grep -Fx 'After=graphical-session.target' "$fcitx_service" >/dev/null ||
|
||||
fail "fcitx5 needs WAYLAND_DISPLAY, which uwsm imports before it reaches graphical-session.target"
|
||||
grep -Fx 'PartOf=graphical-session.target' "$fcitx_service" >/dev/null ||
|
||||
fail "fcitx5 must stop with the compositor instead of lingering against a dead wayland socket"
|
||||
grep -Fx 'WantedBy=graphical-session.target' "$fcitx_service" >/dev/null ||
|
||||
fail "fcitx5 is never pulled in at login without a WantedBy"
|
||||
grep -Fx 'ConditionEnvironment=WAYLAND_DISPLAY' "$fcitx_service" >/dev/null ||
|
||||
fail "an update over SSH has a live user manager and no display; starting fcitx5 there wedges the unit active-but-blind, and Wants= will not replace it at graphical login"
|
||||
|
||||
fcitx_migration="$ROOT/migrations/1785167800.sh"
|
||||
grep -F 'is-active --quiet graphical-session.target' "$fcitx_migration" >/dev/null ||
|
||||
fail "migration kills fcitx5 and starts the unit outside a graphical session"
|
||||
grep -F 'systemctl --user enable omarchy-fcitx5.service' "$fcitx_migration" >/dev/null ||
|
||||
fail "migration must enable without --now; --now starts the unit before the session-gate check"
|
||||
grep -F 'Could not start omarchy-fcitx5.service' "$fcitx_migration" >/dev/null ||
|
||||
fail "migration pkills a working fcitx5, so a failed handover must be reported instead of marked complete"
|
||||
|
||||
grep -F 'pkill -x fcitx5' "$ROOT/bin/omarchy-restart-xcompose" >/dev/null ||
|
||||
fail "restart-xcompose cannot reload a fcitx5 running outside the unit, so it silently keeps serving the old table"
|
||||
|
||||
grep -F 'omarchy-fcitx5.service' "$first_run_units" >/dev/null ||
|
||||
fail "first-run does not enable the input method, so ~/.XCompose sequences never resolve"
|
||||
grep -F 'fcitx5' "$ROOT/default/hypr/autostart.lua" >/dev/null &&
|
||||
fail "fcitx5 is autostarted from Hyprland; an unsupervised launch dies silently and takes every compose sequence with it"
|
||||
pass "fcitx5 runs supervised, so a lost input method comes back instead of killing XCompose until logout"
|
||||
|
||||
Reference in New Issue
Block a user