diff --git a/config/systemd-user/singularity-session.target b/config/systemd-user/singularity-session.target new file mode 100644 index 0000000..13cc26f --- /dev/null +++ b/config/systemd-user/singularity-session.target @@ -0,0 +1,5 @@ +[Unit] +Description=Singularity Desktop session +BindsTo=graphical-session.target +Wants=graphical-session-pre.target +After=graphical-session-pre.target diff --git a/meson.build b/meson.build index c7f6c75..c04e84c 100644 --- a/meson.build +++ b/meson.build @@ -18,3 +18,14 @@ install_data( install_dir: get_option('datadir') / 'singularity' / 'labwc', install_mode: 'rwxr-xr-x', ) + +# BindsTo=graphical-session.target so starting it pulls the target in as a +# side effect -- graphical-session.target itself is systemd-hardened against +# direct manual start (RefuseManualStart), by design: it must be reached via +# a bound unit. singularity-desktop-session starts this unit; that is the +# only thing that makes every WantedBy=graphical-session.target unit (our +# own xdg-desktop-portal-singularity.service among them) launch at all. +install_data( + 'config/systemd-user/singularity-session.target', + install_dir: get_option('prefix') / 'lib' / 'systemd' / 'user', +) diff --git a/src/singularity-desktop-session b/src/singularity-desktop-session index 6a602e1..c95eb0e 100755 --- a/src/singularity-desktop-session +++ b/src/singularity-desktop-session @@ -61,6 +61,28 @@ nohup "$BIN/singularity-polkit-agent" >> "$_STATE/polkit.log" 2>&1 & if [ -x "$BIN/ush-broker" ]; then nohup "$BIN/ush-broker" >> "$_STATE/ush-broker.log" 2>&1 & fi +# Pull in graphical-session.target so every systemd --user unit declaring +# WantedBy=graphical-session.target actually launches: our own +# xdg-desktop-portal-singularity.service among them, plus foot-server. +# Without this the target sits permanently inactive and those units never +# start at all, regardless of anything the portal ROUTER does below -- +# confirmed live on O6N 2026-08-27: xdg-desktop-portal correctly resolved +# and routed Screenshot requests to the singularity backend (portals.conf +# staging from 2026-08-25 was working fine), but the backend process +# itself never started because nothing had ever started +# graphical-session.target on this system. +# +# graphical-session.target itself refuses direct manual start +# (systemd-hardened, RefuseManualStart) -- it must be reached via a unit +# that BindsTo= it. labwc ships labwc-session.target for exactly this +# (its own docs/autostart recommends starting it), but that unit is not +# actually installed by this build, so singularity-session.target +# (config/systemd-user/, installed by this repo's own meson.build) plays +# the same role: BindsTo=graphical-session.target, +# Wants=graphical-session-pre.target, so starting it gets the pre-target +# sequencing for free too. +systemctl --user --no-block start singularity-session.target 2>/dev/null || true + # Restart the portal so it picks up the live session environment, but do NOT # block on it: xdg-desktop-portal can hang ~25s on its settings-proxy timeout # waiting for our portal backend, which would delay the shell launch below.