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:
parent
888eedad39
commit
ca63bc9544
2 changed files with 27 additions and 54 deletions
|
|
@ -329,13 +329,12 @@ in
|
|||
hl.exec_cmd("wl-paste --type image --watch cliphist store")
|
||||
hl.exec_cmd("hyprctl setcursor Bibata-Modern-Ice 24")
|
||||
-- Spotify is NOT started here. It asks the Secret Service for its
|
||||
-- credentials the moment it launches, which at this point is
|
||||
-- before the lockscreen has been dismissed and therefore before
|
||||
-- the login keyring is unlocked. Lock.qml unlocks the keyring with
|
||||
-- --replace, and that kills the daemon spotify would already be
|
||||
-- mid-request with, leaving it stuck half-loaded. So Lock.qml
|
||||
-- launches it instead, right after the unlock succeeds. The window
|
||||
-- rule below still swallows it onto special:music, and the
|
||||
-- credentials the moment it launches, and at this point the
|
||||
-- lockscreen has not been dismissed yet, so the login keyring is
|
||||
-- still locked and it lands on gcr's unlock prompt instead of
|
||||
-- loading. Lock.qml starts it after pam accepts the password
|
||||
-- (pam_gnome_keyring unlocks the keyring in its auth phase). The
|
||||
-- window rule below still swallows it onto special:music, and the
|
||||
-- respawn-on-close rule above is unaffected.
|
||||
-- Scratchpad terminal: parked on special:scratch at
|
||||
-- login so SUPER+Return is always an instant toggle and the shell
|
||||
|
|
|
|||
|
|
@ -638,51 +638,22 @@ in
|
|||
onExited: code => { if (code === 0) { root.bootLock = true; lock.locked = true; } }
|
||||
}
|
||||
|
||||
// Chromium/Electron apps ask the Secret Service for their
|
||||
// credentials as soon as they launch — spotify autostarts, so
|
||||
// it hit gcr's unlock dialog every boot. The login keyring is
|
||||
// still locked at that point: greetd's autologin gave
|
||||
// pam_gnome_keyring no password to stash, and PamContext only
|
||||
// runs pam_authenticate, never the session phase that
|
||||
// auto_start unlocks from. So feed the daemon the password
|
||||
// ourselves once PAM has accepted it.
|
||||
// Nothing here unlocks the keyring — pam_gnome_keyring already
|
||||
// did it during the *auth* phase. gkr-pam-module.c's
|
||||
// pam_sm_authenticate calls unlock_keyring() directly and logs
|
||||
// "gkr-pam: unlocked login keyring"; the session phase is only
|
||||
// its fallback for when that fails. So PamContext's auth-only
|
||||
// run has always been enough, and an explicit
|
||||
// gnome-keyring-daemon --replace --unlock here was both
|
||||
// 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()
|
||||
// exists but is never called from gkd-main.c — only the
|
||||
// frob-control-* test binaries use it, and those aren't
|
||||
// installed — so nothing on the CLI can unlock a daemon that is
|
||||
// already running. --start would be the "talk to the running
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// The only real problem was ordering. Spotify asks the Secret
|
||||
// Service the moment it launches, and from hyprland.start that
|
||||
// is before the lockscreen has been dismissed — keyring still
|
||||
// locked, so it lands on gcr's unlock prompt. Start it here,
|
||||
// after PAM has accepted the password, instead.
|
||||
Process {
|
||||
id: spotifyStart
|
||||
// Via hyprland, not as a child of quickshell: a shell
|
||||
|
|
@ -700,10 +671,13 @@ in
|
|||
}
|
||||
onCompleted: result => {
|
||||
if (result === PamResult.Success) {
|
||||
keyringUnlock.secret = root.password;
|
||||
keyringUnlock.stdinEnabled = true;
|
||||
keyringUnlock.running = true;
|
||||
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;
|
||||
root.password = "";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue