Commit Graph
5 Commits
Author SHA1 Message Date
gitops bdff38edac Start gnome-keyring, so the session has an ssh-agent
PAM starts the daemon at login but brings up only its `control` socket.
Nothing else brought up the rest, so a HyprCosmic session had no agent at
all: SSH_AUTH_SOCK unset, every SSH operation asking for the passphrase
again, and callers of the secrets API finding nothing listening. Under the
stock COSMIC session the same machine works, which makes it look like a
key problem rather than a session-script omission.

`--start` attaches to the daemon that is already running and brings up the
missing components; on this machine that created `pkcs11` and `ssh`
alongside the existing `control`.

Where the socket path comes from is the part worth writing down.
start-cosmic evals the daemon's stdout, but the eval is
`eval "$(... > /dev/null 2>&1)"` -- the redirect is inside the
substitution, so it always evaluates the empty string, and the block works
only because of the socket checks after it. Rather than repair that by
evaluating whatever a daemon writes to stdout, this reads out the single
variable we want and keeps the fixed paths as the fallback. The daemon
also writes chatter to stderr, so the 2>/dev/null is load-bearing for the
parse rather than tidiness.

start-cosmic's rule is kept intact: set the correct socket or set none at
all, never a wrong one. A plain file sitting where the socket belongs is
rejected by the `-S` test, and a machine with no keyring directory skips
the block entirely.

SSH_AUTH_SOCK then joins the systemd and D-Bus activation environments for
the same reason XDG_CURRENT_DESKTOP did: a user unit or an activated app
looks there, not in this script's environment. `import-environment` ignores
an unset name and exits 0, so a machine without a keyring still logs in.
2026-08-10 15:09:07 +07:00
gitops 22e894330e 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.
2026-08-10 12:58:28 +07:00
gitops c67cb01f2d Backport the session log block from the installed copy
/usr/bin/start-hyprcosmic gained this during the blank-screen debugging and
the versioned copy never did, so the next install from this repository would
have silently removed it. Found by diffing the two while writing an installer;
the installer's --check exists so that the next one is not found by hunch.

What it does, unchanged from the copy that has been running: redirect the
session's own output to ~/.cache/hyprcosmic/session.log. A session that fails
drops you at the greeter taking its stderr with it, and by then the journal
cannot be read from inside a session that no longer exists.

A plain redirect rather than tee into a process substitution -- tee would be a
child the session writes through, so its death would deliver SIGPIPE, and
nothing about diagnostics should be able to kill the desktop. Every step is
guarded, so a failure here starts the session with no log rather than refusing
to log in. The previous log is kept as .1 so a second attempt does not erase
the evidence from the first.
2026-08-10 11:48:50 +07:00
gitops 1c3e3c3e53 Give profile extras real argv, and point the session entry at the fork
Two defects in the previous commit, both of which would have failed silently
at the greeter rather than loudly at build time.

`start_component` passes its whole string to `Process::with_executable`, which
treats it as the program name. An autostart line like `waybar -c <path>` was
therefore looked up as a binary literally called "waybar -c <path>", and the
bar would simply never appear. The unit test asserting that "rofi -show drun"
parses as one entry implied arguments worked; they did not. Extras are now
split into argv and spawned through a `start_process` helper, which is
upstream's `start_component` body with args threaded through --
`start_component` keeps its signature so no upstream call site changes.

The splitter honours quoting, because config paths contain spaces, and treats
`#` as a comment only where a word would start, so `--color=#1a1b26` survives.
It expands nothing else: no variables, globs or command substitution, so a
file that names programs cannot be escalated into running arbitrary shell.

`start-hyprcosmic` also defaulted HYPRCOSMIC_SESSION_BIN to
/usr/bin/cosmic-session -- the stock binary, which has no profile module. The
session would have come up as ordinary COSMIC with the gating apparently doing
nothing. It now points at /usr/libexec/hyprcosmic, so the fork installs
alongside the packaged COSMIC instead of over it, a dnf update cannot clobber
it, and the stock entry stays as the escape hatch. It fails loudly with a
pointer back to that entry if the binary is missing.

Verified: 9 unit tests, including a regression test for the argv defect and
one asserting nothing is expanded; `cargo build -j1` clean.
2026-08-10 08:35:57 +07:00
gitops 80958c24da Add session profiles so HyprCosmic can replace the COSMIC shell
Upstream hardcodes the set of cosmic-* components a session launches.
HyprCosmic needs cosmic-comp for window management but waybar and rofi in
place of cosmic-panel and cosmic-launcher, so `profile` gates that set.

The default profile is upstream behaviour exactly, and it is what an
unconfigured build gets; the alternate set is opt-in through
HYPRCOSMIC_PROFILE, which only the new session entry sets. So installing
this fork cannot change how the stock session boots, and a broken
HyprCosmic config is always one logout away from being escaped.

Gating lives at the single definition of `start_component` rather than at
its call sites, keeping the diff against upstream small enough to rebase
against a fast-moving tree. cosmic-panel and cosmic-notifications are the
exception: they are started as a coupled pair sharing notification fds and
cannot go through that path, so they are gated where they are spawned
(hence the re-indentation in the diff).

cosmic-greeter is deliberately never disabled - a display manager is the
easiest thing to lock yourself out of. cosmic-osd and cosmic-idle stay too,
since HyDE's equivalents are separate programs a user may not have and
neither competes with waybar for layer-shell space.

Verified: 5 unit tests over profile selection and extras parsing; `cargo
check -j1` and `cargo build -j1` clean.

NOT verified: the gating has never been observed at runtime. Two attempts
to run this session nested inside the live desktop logged the developer out
instead, so runtime confirmation is deferred to logging into the
hyprcosmic.desktop entry from the greeter. Two hazards found along the way
and worth recording: name-matching (pkill/pgrep) cannot distinguish this
fork's processes from the live session's, and a nested cosmic-session steals
the well-known D-Bus name com.system76.CosmicSession from the running
session unless it is given a private bus.
2026-08-10 08:24:25 +07:00