Find sway's socket when the environment is stale

Running wl-pick from certain terminals failed outright:

  wl-pick: cannot reach sway (No such file or directory (os error 2))

swayipc takes the path from I3SOCK or SWAYSOCK and falls back to asking sway
directly only when neither is set. A variable that is set but stale is used
as it stands, and fails -- which is what happens to every shell descended
from a process that outlived the sway that started it. One long-running
daemon in the ancestry is enough, and nothing about the failure points at
the environment.

The running compositor is the one we want in any case, so look for its
socket in XDG_RUNTIME_DIR when the environment's path does not connect.
Sockets are named sway-ipc.<uid>.<pid>.sock, so the pid says which are worth
trying, checked against /proc for a process that really is a sway, since pids
are reused. Several live compositors is a real situation -- a nested sway --
so that asks for SWAYSOCK rather than guessing.

The environment still wins when it points at something that exists. Its
lookup is no longer delegated to swayipc at all, because that spawns
`sway --get-socketpath` when the variables are unset and lets the child
print "sway socket not detected." over anything we would rather say.
This commit is contained in:
Milad Alizadeh
2026-09-07 17:37:48 +01:00
parent c607fc9a1c
commit 8e317682a1
3 changed files with 114 additions and 3 deletions
+1 -3
View File
@@ -76,9 +76,7 @@ fn run() -> Result<ExitCode, Box<dyn Error>> {
// One IPC conversation: the window list, and the displays the grid sizes
// itself against. It is closed again before the overlay maps.
let (targets, opts) = {
let mut sway = swayipc::Connection::new().map_err(|e| {
format!("cannot reach sway ({e}); wl-pick reads the window list from its IPC socket")
})?;
let mut sway = sway::connect()?;
// The displays come first: the grid is sized against the one it will
// appear on, so every percentage in the config resolves per monitor.
let displays = sway::displays(&mut sway)?;