diff options
| author | Arpit Chakladar <arpitchakladar@gmail.com> | 2026-09-10 20:14:14 +0530 |
|---|---|---|
| committer | Arpit Chakladar <arpitchakladar@gmail.com> | 2026-09-10 20:14:14 +0530 |
| commit | b34430acf020a59d8fb09e138497d66d5fcf225f (patch) | |
| tree | 6bf64306985b8cda0fc8f658d5f95f42c64c31ba /modules | |
| parent | e483a7d255fc27aea1d1d1a7963ea4b93ad0c47e (diff) | |
| download | home-manager-config-b34430acf020a59d8fb09e138497d66d5fcf225f.tar.gz home-manager-config-b34430acf020a59d8fb09e138497d66d5fcf225f.zip | |
fix(desktop/eww): fixed the niri-status.lua script from crashing
The niri-status.lua script stopped when niri msg -j event-stream stops
like when niri goes to sleep. This lead to a broken pipe for deflisten
for bar. Now it infinitely loops with delay to restart niri msg -j
event-stream if it ever stops.
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/desktop/eww/bar/niri-status.lua | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/modules/desktop/eww/bar/niri-status.lua b/modules/desktop/eww/bar/niri-status.lua index 771a12c..6e214c3 100644 --- a/modules/desktop/eww/bar/niri-status.lua +++ b/modules/desktop/eww/bar/niri-status.lua @@ -10,6 +10,14 @@ -- event across both scripts. Here there's one event-stream subscription, -- and one shared windows/workspaces fetch per event, significantly reducing -- the total number of spawned processes and resting children. +-- +-- The event-stream subscription is wrapped in a reconnect loop: if niri +-- restarts, sleeps, or its IPC socket otherwise drops, `niri msg -j +-- event-stream` hits EOF and would normally kill this whole script (which +-- kills eww's deflisten listener along with it, requiring a manual eww +-- restart). Instead we detect the EOF, back off briefly, and keep retrying +-- until niri is reachable again, re-emitting fresh state on every +-- reconnect so the bar catches up automatically. local cjson = require("cjson") @@ -208,7 +216,7 @@ local function build_state() for idx, w in ipairs(ws_windows) do lines[#lines + 1] = string.format("%d. %s: %s", idx, (w.app_id and w.app_id ~= "" and w.app_id) or "unknown", (w.title and w.title ~= "" and w.title) or "(untitled)") end - + workspaces_result[#workspaces_result + 1] = { idx = ws.idx, id = ws.id, @@ -243,12 +251,51 @@ local RELEVANT_EVENTS = { WorkspaceUrgencyChanged = true, WorkspaceActiveWindowChanged = true } -local proc = io.popen("niri msg -j event-stream") +local function sleep(seconds) + os.execute("sleep " .. tostring(seconds)) +end + +-- Subscribe to one event-stream session. Returns true if at least one +-- event line was received (i.e. niri was genuinely up and running for a +-- while), false if the pipe produced nothing before EOF (niri unreachable +-- or the socket isn't up yet). +local function run_event_stream_session() + local proc = io.popen("niri msg -j event-stream 2>/dev/null") + if not proc then return false end + + local got_any_line = false + for line in proc:lines() do + got_any_line = true + local ok, obj = pcall(cjson.decode, line) + if ok and obj then + local key = next(obj) + if RELEVANT_EVENTS[key] then emit_state() end + end + end + proc:close() + return got_any_line +end + emit_state() -for line in proc:lines() do - local ok, obj = pcall(cjson.decode, line) - if ok and obj then - local key = next(obj) - if RELEVANT_EVENTS[key] then emit_state() end + +local retry_delay = 1 +while true do + local got_any_line = run_event_stream_session() + + -- Whether this was niri restarting, waking from sleep, or the socket + -- just briefly hiccuping: refresh the bar's view of the world as soon + -- as we notice, rather than waiting for the next real event. + emit_state() + + if got_any_line then + -- We were genuinely connected for a while; go back to fast retries + -- if the connection drops again. + retry_delay = 1 + else + -- niri isn't reachable yet (asleep / mid-restart) -- back off so we + -- don't spawn `niri msg` in a tight loop while waiting for it. + retry_delay = math.min(retry_delay * 2, 8) end + + sleep(retry_delay) end |
