Quickshell segfaulted mid-session -- a Qt image-teardown bug, three cores in the journal -- and the desktop stayed bar-less until a person noticed and knew what to type, because the shell ran as a bare compositor child and panama-crash-watch's report had no notification server left to arrive on. The shell is now panama-quickshell.service, started per-session by autostart.lua like every other Panama unit and never enabled globally: Restart=on-failure turns the same crash into a two-second flicker, verified by sending the running shell a real SIGSEGV and watching it return, and the crash report now lands because the restarted shell is serving the bus by the time the watcher looks. The two contracts that restart the shell learned to do it through the unit, or the unit's own restart races them with a second shell. Recordings can hear: a recorderAudio preference -- none by default, GNOME's default too, because a screencast that silently captured the microphone is an incident -- adds system audio or the microphone through PulseAudio's @DEFAULT_*@ aliases, so the capture follows whatever device Sound settings has chosen. The bar shows the active keyboard layout whenever more than one is configured, mapped from xkb's own registry (evdev.lst) because deriving a code from a description guesses wrong immediately -- "German" is de, not ge -- and updated live from Hyprland's activelayout event. One layout, no indicator, which is GNOME's behavior too. And presentation mode: Caffeine plus Do Not Disturb as one quick-settings tile, restoring both exactly as found -- the half you forget to arm before plugging into a projector is the one that fires a message preview onto the big screen. Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
99 lines
6.2 KiB
Lua
99 lines
6.2 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.
|
|
-- A supervised unit rather than a compositor child, for the one property
|
|
-- a child cannot have: if the shell crashes, systemd restarts it in two
|
|
-- seconds instead of leaving a desktop with no bar until someone knows
|
|
-- what to type. The unit ships in config/local/share/systemd/user and is
|
|
-- started per-session here like every other Panama unit.
|
|
hl.exec_cmd("systemctl --user start panama-quickshell.service")
|
|
|
|
-- 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
|