From 22e894330e0fd53a509e464e810c28afe6d10556 Mon Sep 17 00:00:00 2001 From: dingo Date: Mon, 10 Aug 2026 12:58:28 +0700 Subject: [PATCH] Hand the session's identity to `systemd --user`, so portals work Pressing PrtScr said "COSMIC screenshot crashed". cosmic-screenshot was aborting on an unwrap, because org.freedesktop.portal.Screenshot had no implementation behind it. start-hyprcosmic exported XDG_CURRENT_DESKTOP=COSMIC, and the compositor had it. But an export only reaches processes started by this script, and the portal is not one of them: xdg-desktop-portal is launched by `systemd --user`, which is older than the session and carries its own environment block. Its copy had XDG_SESSION_TYPE and nothing else. xdg-desktop-portal chooses a backend by matching the `UseIn=` line of /usr/share/xdg-desktop-portal/portals/*.portal against XDG_CURRENT_DESKTOP. Unset, `UseIn=COSMIC` never matched, no backend loaded, and the Screenshot interface was never exported. Nothing anywhere logged a missing portal. The crash was the only symptom, and it pointed at the screenshot tool. `systemctl --user import-environment` fixes it, which is what start-cosmic has always done and this script had not. Ordering works out: the portal unit is `After=` and `Requisite=graphical-session.target`, which cosmic-session brings up later, so it cannot start ahead of the import. dbus-update-activation-environment as well, for any backend whose .service file has no `SystemdService=` line -- but only when a bus already exists, since in the dbus-run-session branch the bus is created after this point. Everything is `||:`. Losing a portal is bad; refusing to log in is worse. Verified by clearing all three variables out of the user manager, running the script's environment block, restarting xdg-desktop-portal, and watching the Screenshot interface come back and cosmic-screenshot exit 0 with a real PNG. --- data/start-hyprcosmic | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/data/start-hyprcosmic b/data/start-hyprcosmic index 218b956..7129288 100755 --- a/data/start-hyprcosmic +++ b/data/start-hyprcosmic @@ -66,6 +66,7 @@ export HYPRCOSMIC_PROFILE=hyprcosmic # key off this, and the compositor underneath really is COSMIC. export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-COSMIC}" export XDG_SESSION_DESKTOP="${XDG_SESSION_DESKTOP:-hyprcosmic}" +export XDG_SESSION_TYPE="${XDG_SESSION_TYPE:-wayland}" # Same hygiene as start-cosmic: a failed unit left by a previous graphical # session will otherwise block this one from starting. @@ -79,6 +80,43 @@ if command -v systemctl >/dev/null; then fi done done + + # Hand the session's identity to `systemd --user`, which is what actually + # launches the portal. + # + # Exporting XDG_CURRENT_DESKTOP above only reaches processes started *by + # this script*. The user manager is older than the session and has its own + # environment block, so anything it activates -- xdg-desktop-portal, and + # through it xdg-desktop-portal-cosmic, which is `SystemdService=` in its + # D-Bus service file -- never saw the variable. + # + # xdg-desktop-portal picks a backend by matching the `UseIn=` line of + # /usr/share/xdg-desktop-portal/portals/*.portal against + # XDG_CURRENT_DESKTOP. With the variable unset, `UseIn=COSMIC` did not + # match, no backend loaded, and org.freedesktop.portal.Screenshot was never + # exported -- so pressing PrtScr made cosmic-screenshot unwrap an error and + # abort with "COSMIC screenshot crashed". Nothing logged a missing portal; + # the only symptom was the crash. + # + # Ordering is fine: xdg-desktop-portal.service is `After=` and + # `Requisite=graphical-session.target`, which cosmic-session brings up + # later, so the portal cannot start before this import. + # + # `||:` throughout -- losing a portal is bad, refusing to log in is worse. + systemctl --user import-environment \ + XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE ||: +fi + +# Same variables again for dbus-daemon's own activation environment, which +# covers any backend whose .service file has no `SystemdService=` line. +# +# Only when a bus already exists. In the dbus-run-session branch below the bus +# is created *after* this point, so calling it here would talk to the wrong bus +# or none at all. That branch is the fallback path anyway; a normal graphical +# login arrives with DBUS_SESSION_BUS_ADDRESS already set. +if [[ -n "${DBUS_SESSION_BUS_ADDRESS}" ]] && command -v dbus-update-activation-environment >/dev/null; then + dbus-update-activation-environment \ + XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE ||: fi # cosmic-session takes the compositor to launch as its first argument