Two of Section F. Hooks are the pressure valve. "Can Panama also do X when the theme changes" is now a five-line file in ~/.config/panama/hooks rather than a fork, a feature request, or a patch somebody rebases forever. Each name takes a single file and a .d directory so several things can react without fighting over one, and a broken hook is reported and stepped over: somebody's script must never cost a theme change, an upgrade or a login. Wired at theme-set, post-upgrade and post-migrate. This is the thirty-line version of the plugin host the upstream ledger defers, and it has no API to keep stable beyond "we will run your script and tell you what happened". Testing it caught a real bug the reading would not have: run_one captured the script path but never shifted it off, so every hook got its own filename as $1 and the real arguments arrived one place late. A hook reading $1 as the colour scheme got a path. The crash watcher notices when a program dumps core and says so. Under GNOME, ABRT does this; here nothing did, and applications died silently, which is most of how "Linux is flaky" gets earned. Once per program per session is the entire design, not a nicety. This machine's portal backend crashes between eleven and sixty times a day, and a notification per crash would be one every few minutes for something nobody can act on. The first is news; the fortieth is why people turn notifications off. The health page keeps the running count. It waits for the notification server before reporting, because the crash most worth hearing about is the one that took the shell with it, and it names the executable rather than the kernel's comm field, which truncates at fifteen characters. Verified against real segfaults.
95 lines
5.8 KiB
Lua
95 lines
5.8 KiB
Lua
-- ─────────────────────────────────────────────────────────────────────────────
|
|
-- Autostart
|
|
--
|
|
-- `exec-once` no longer exists in 0.56; startup is an event handler.
|
|
--
|
|
-- Session: Fedora installs two sessions, "Hyprland" and "Hyprland
|
|
-- (uwsm-managed)". Panama targets the uwsm one, because
|
|
-- xdg-desktop-portal-hyprland's systemd unit requires graphical-session.target
|
|
-- and Fedora ships no hyprland-session.target -- without uwsm, screen sharing
|
|
-- in OBS/Sunshine/Zoom silently fails. The target is started explicitly below
|
|
-- so the plain session works too.
|
|
--
|
|
-- Anything that ships a systemd user unit is started as a unit rather than as
|
|
-- a compositor child. That is not cosmetic: under uwsm, units get the correct
|
|
-- activation environment (see uwsm/env), they restart on failure, and they
|
|
-- shut down in order. Panama's `change-settings` script enables them once;
|
|
-- the explicit starts here make a fresh clone work before that has run.
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
hl.on("hyprland.start", function()
|
|
-- Publish the session environment to systemd and D-Bus so user units and
|
|
-- the portals can see WAYLAND_DISPLAY. Cheap, and essential without uwsm.
|
|
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=Hyprland")
|
|
hl.exec_cmd("systemctl --user start hyprland-session.target")
|
|
|
|
-- Units: polkit prompts, wallpaper, launcher daemon, idle/lock. All four
|
|
-- carry `ConditionEnvironment=WAYLAND_DISPLAY`, and hl.exec_cmd fires
|
|
-- commands without waiting for them to finish, so the dbus-update call
|
|
-- above racing this one is not safe to assume complete -- a lost race
|
|
-- leaves the Condition unmet and the unit silently never starts (exit 0,
|
|
-- no error). hypridle is the only listener for the logind Lock signal,
|
|
-- so that failure mode is "lock-session goes to nobody". Re-import
|
|
-- synchronously in the same shell invocation first so the Condition
|
|
-- always sees it, regardless of how the dbus-update call above scheduled.
|
|
-- panama-polkit-agent replaces hyprpolkitagent, whose prompt is compiled
|
|
-- into its binary and cannot be themed. Only one agent may register per
|
|
-- session, so they must not both start. hyprpolkitagent stays INSTALLED as
|
|
-- the fallback: `systemctl --user start hyprpolkitagent` restores the stock
|
|
-- prompt if Panama's ever fails to come up.
|
|
hl.exec_cmd("systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP && systemctl --user start panama-polkit-agent.service hyprpaper.service vicinae.service hypridle.service")
|
|
|
|
-- Pending repairs for this machine, if any. Oneshot: it checks, tells the
|
|
-- user when there is something to tell, and exits. Started here rather
|
|
-- than enabled so it belongs to the Hyprland session; see the unit.
|
|
hl.exec_cmd("systemctl --user start panama-migrate-notify.service")
|
|
|
|
-- Notices when a program dumps core and says so once per session. Under
|
|
-- GNOME, ABRT does this; here nothing did, and applications died silently.
|
|
hl.exec_cmd("systemctl --user start panama-crash-watch.service")
|
|
|
|
-- Text expansion. change-settings runs `espanso service register`, which
|
|
-- writes and enables espanso's own user unit; the explicit start makes the
|
|
-- first Hyprland login after a fresh install work rather than the second.
|
|
-- Started on its own line: unlike the units above it carries no
|
|
-- ConditionEnvironment, and a missing unit (espanso not yet registered)
|
|
-- must not muddy the start of the four that lock and wallpaper depend on.
|
|
hl.exec_cmd("systemctl --user start espanso.service")
|
|
|
|
-- The shell: bar, dock, overview, quick settings, notifications, capture.
|
|
-- No systemd unit ships with quickshell, so it runs as a compositor child.
|
|
hl.exec_cmd("quickshell --daemonize")
|
|
|
|
-- Removable-media automounting. GNOME did this invisibly via gvfs+udisks;
|
|
-- outside GNOME something has to ask udisks to mount. No tray icon: the
|
|
-- Quickshell bar already has a tray, and udiskie's own icon would be
|
|
-- redundant. -f opens Nautilus when you click the mount notification.
|
|
hl.exec_cmd("udiskie --automount --notify --no-tray --file-manager nautilus")
|
|
|
|
-- Keyring unlock, for Nextcloud and Bitwarden credential storage.
|
|
hl.exec_cmd("/usr/bin/gnome-keyring-daemon --start --components=secrets,ssh,pkcs11")
|
|
|
|
-- Nextcloud and Bitwarden are NOT started here. Both ship a
|
|
-- ~/.config/autostart/*.desktop entry, and systemd's own
|
|
-- systemd-xdg-autostart-generator turns every such entry into a
|
|
-- `PartOf=graphical-session.target` unit (`[email protected]`,
|
|
-- `[email protected]`) that fires once the uwsm
|
|
-- session brings up graphical-session.target -- confirmed live via
|
|
-- `systemctl --user list-units 'app-*@autostart.service'`. An explicit
|
|
-- second launch here used to duplicate that: for Bitwarden specifically,
|
|
-- each `flatpak run` gets its own sandbox instance, so the two starts
|
|
-- didn't just race, they left two competing processes fighting over the
|
|
-- app's single-instance lock, with neither reliably owning a usable
|
|
-- window. Trust the generator instead of re-launching.
|
|
--
|
|
-- RustDesk is deliberately absent too: it ships an enabled *system*
|
|
-- service (`rustdesk --service`) that spawns --server and --tray for the
|
|
-- session on its own. Starting it here as well would give you two trays.
|
|
end)
|
|
|
|
hl.on("hyprland.shutdown", function()
|
|
hl.exec_cmd("systemctl --user stop hyprland-session.target")
|
|
end)
|
|
|
|
return true
|