quickshell: drop redundant keyring unlock, pam already does it in auth

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-08-23 19:55:10 +01:00
parent 888eedad39
commit ca63bc9544
2 changed files with 27 additions and 54 deletions

View file

@ -329,13 +329,12 @@ in
hl.exec_cmd("wl-paste --type image --watch cliphist store") hl.exec_cmd("wl-paste --type image --watch cliphist store")
hl.exec_cmd("hyprctl setcursor Bibata-Modern-Ice 24") hl.exec_cmd("hyprctl setcursor Bibata-Modern-Ice 24")
-- Spotify is NOT started here. It asks the Secret Service for its -- Spotify is NOT started here. It asks the Secret Service for its
-- credentials the moment it launches, which at this point is -- credentials the moment it launches, and at this point the
-- before the lockscreen has been dismissed and therefore before -- lockscreen has not been dismissed yet, so the login keyring is
-- the login keyring is unlocked. Lock.qml unlocks the keyring with -- still locked and it lands on gcr's unlock prompt instead of
-- --replace, and that kills the daemon spotify would already be -- loading. Lock.qml starts it after pam accepts the password
-- mid-request with, leaving it stuck half-loaded. So Lock.qml -- (pam_gnome_keyring unlocks the keyring in its auth phase). The
-- launches it instead, right after the unlock succeeds. The window -- window rule below still swallows it onto special:music, and the
-- rule below still swallows it onto special:music, and the
-- respawn-on-close rule above is unaffected. -- respawn-on-close rule above is unaffected.
-- Scratchpad terminal: parked on special:scratch at -- Scratchpad terminal: parked on special:scratch at
-- login so SUPER+Return is always an instant toggle and the shell -- login so SUPER+Return is always an instant toggle and the shell

View file

@ -638,51 +638,22 @@ in
onExited: code => { if (code === 0) { root.bootLock = true; lock.locked = true; } } onExited: code => { if (code === 0) { root.bootLock = true; lock.locked = true; } }
} }
// Chromium/Electron apps ask the Secret Service for their // Nothing here unlocks the keyring pam_gnome_keyring already
// credentials as soon as they launch spotify autostarts, so // did it during the *auth* phase. gkr-pam-module.c's
// it hit gcr's unlock dialog every boot. The login keyring is // pam_sm_authenticate calls unlock_keyring() directly and logs
// still locked at that point: greetd's autologin gave // "gkr-pam: unlocked login keyring"; the session phase is only
// pam_gnome_keyring no password to stash, and PamContext only // its fallback for when that fails. So PamContext's auth-only
// runs pam_authenticate, never the session phase that // run has always been enough, and an explicit
// auto_start unlocks from. So feed the daemon the password // gnome-keyring-daemon --replace --unlock here was both
// ourselves once PAM has accepted it. // redundant and a trap: the replacement daemon inherits
// quickshell's stdout, holds the pipe open for the life of the
// session, and the Process therefore never reports exiting.
// //
// --replace is load-bearing, not decoration. gkd_control_unlock() // The only real problem was ordering. Spotify asks the Secret
// exists but is never called from gkd-main.c only the // Service the moment it launches, and from hyprland.start that
// frob-control-* test binaries use it, and those aren't // is before the lockscreen has been dismissed keyring still
// installed so nothing on the CLI can unlock a daemon that is // locked, so it lands on gcr's unlock prompt. Start it here,
// already running. --start would be the "talk to the running // after PAM has accepted the password, instead.
// daemon" flag, but parse_arguments() explicitly rejects it
// next to --unlock. Bare --unlock therefore just tries to become
// a second daemon and dies on the already-taken control socket,
// which is precisely what it did here. So: take over from the
// daemon greetd's PAM started, and unlock on the way up.
//
// No trailing newline on the write read_login_password() reads
// stdin to EOF and its own comment says "All data (including
// newlines) are part of the password".
Process {
id: keyringUnlock
property string secret: ""
command: [ "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon", "--replace", "--unlock" ]
onStarted: {
write(secret);
secret = "";
// EOF, or the daemon blocks on that read forever.
stdinEnabled = false;
}
// The Secret Service is up and unlocked by the time the
// parent exits (it forks, then exits 0 once the child
// signals ready). Only now is it safe to start spotify
// see the note in settings/hyprland.nix's startup handler
// for why it no longer autostarts there.
onExited: {
if (!root.bootLock) return;
root.bootLock = false;
spotifyStart.running = true;
}
}
Process { Process {
id: spotifyStart id: spotifyStart
// Via hyprland, not as a child of quickshell: a shell // Via hyprland, not as a child of quickshell: a shell
@ -700,10 +671,13 @@ in
} }
onCompleted: result => { onCompleted: result => {
if (result === PamResult.Success) { if (result === PamResult.Success) {
keyringUnlock.secret = root.password;
keyringUnlock.stdinEnabled = true;
keyringUnlock.running = true;
lock.locked = false; lock.locked = false;
// Boot lock only: a later manual lock/unlock must
// not spawn a second spotify.
if (root.bootLock) {
root.bootLock = false;
spotifyStart.running = true;
}
} else root.failed = true; } else root.failed = true;
root.password = ""; root.password = "";
} }