From 888eedad39a0ab64001f786b95c02354a8e9d467 Mon Sep 17 00:00:00 2001 From: rope Date: Sun, 23 Aug 2026 19:37:40 +0100 Subject: [PATCH] spotify: start after keyring unlock, not at hyprland startup Co-Authored-By: Claude Opus 5 --- settings/hyprland.nix | 15 ++++++++++----- settings/quickshell.nix | 22 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/settings/hyprland.nix b/settings/hyprland.nix index c484977..ec8580f 100644 --- a/settings/hyprland.nix +++ b/settings/hyprland.nix @@ -328,11 +328,16 @@ in hl.exec_cmd("wl-paste --type text --watch cliphist store") hl.exec_cmd("wl-paste --type image --watch cliphist store") hl.exec_cmd("hyprctl setcursor Bibata-Modern-Ice 24") - -- Spotify starts hidden: the window rule below swallows it onto - -- special:music silently, so it never steals focus and SUPER+M is - -- always an instant toggle. - hl.exec_cmd(scratchpads["spotify"]) - -- Scratchpad terminal, same trick: parked on special:scratch at + -- 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 + -- 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 -- keeps its history/cwd between peeks. hl.exec_cmd(scratchpads["dev.fred.scratchpad"]) diff --git a/settings/quickshell.nix b/settings/quickshell.nix index e789447..9364823 100644 --- a/settings/quickshell.nix +++ b/settings/quickshell.nix @@ -617,6 +617,9 @@ in property alias locked: lock.locked property string password: "" property bool failed: false + // True only for the once-per-session lock below, so a later + // manual lock/unlock does not re-launch spotify. + property bool bootLock: false function submit(pw) { if (pam.active || pw === "") return; @@ -632,7 +635,7 @@ in Process { running: true command: ["mkdir", Quickshell.env("XDG_RUNTIME_DIR") + "/qs-boot-lock"] - onExited: code => { if (code === 0) lock.locked = true; } + onExited: code => { if (code === 0) { root.bootLock = true; lock.locked = true; } } } // Chromium/Electron apps ask the Secret Service for their @@ -668,6 +671,23 @@ in // 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 { + id: spotifyStart + // Via hyprland, not as a child of quickshell: a shell + // restart on rebuild must not take spotify down with it. + command: ["hyprctl", "dispatch", "exec", "spotify"] } PamContext {