OpenRiot v7.9.34 — The Dead Channels Remember
“They killed the power. They always kill the power. But before the lights went out, we told the machine to remember — every window, every workspace, every pixel of floating geometry. When the current returned, the dead channels lit up in the same pattern they left. The construct wakes where it fell. The HDMI remembers its face.” — The OpenRiot Crew, somewhere in the Sprawl, v7.9.34
Release Overview
Rebooting used to be amnesia. You’d hit Shutdown in the rofi power menu and the machine, like a Flatline construct executed mid-sentence, would forget everything — which apps were open, which workspace held Firefox, which resolution your HDMI monitor preferred. v7.9.34 fixes both halves of the problem.
When you reboot or shut down, OpenRiot now gracefully closes every application window (giving Firefox time to save your tabs), snapshots the i3 layout to disk, locks the screen, and then pulls the plug. When you log back in, it reads the snapshot, relaunches your apps, and places them on the right workspaces at the right geometry. Like a ROM construct of a dead hacker, your session wakes up where it died.
Also: the HDMI toggle no longer forgets your resolution when you switch between Laptop and external monitors. This bug existed because our mode cache lived only in memory — which is to say, it didn’t live at all. We gave it a body. We gave it a file. We gave it permanence.
💾 The Construct Wakes Where It Fell
A SNES save-state cartridge had more session persistence
than OpenRiot v7.9.33. The power menu’s Reboot and Shutdown
options called doas shutdown -r now with zero preparation.
Firefox tabs were lost. Terminal sessions evaporated. The
workspace layout was a dream you couldn’t reconstruct.
The fix, in detail:
Phase 1 — Graceful shutdown. GracefulShutdown() sends
i3-msg '[con_id=N] kill' to every window (WM_DELETE_WINDOW,
the polite X11 close). Firefox saves sessionstore.jsonlz4.
We poll the i3 tree for 10 seconds; if an app refuses to
close, shutdown proceeds anyway. Timeout-bounded. No hang.
Phase 2 — Snapshot. SaveLayout() walks the i3 tree and
captures, for every window: class, instance, workspace,
geometry rect, floating flag. Serialized to JSON at
~/.cache/openriot/window-snapshot.json.
Phase 3 — Lock and shutdown. lock.Lock() secures the
screen, then doas shutdown executes.
On login: --window-restore fires from the i3 autostart.
It parses apps.txt to map window classes to launch commands
(Firefox → firefox, Alacritty → alacritty, etc.),
launches each app, waits 3 seconds for windows to appear,
then moves them to their saved workspaces and sets floating
geometry. Falls back to class name as command for unknown
apps. Deletes the snapshot file when done.
Design principles:
- No polling loops beyond the 10s shutdown timeout.
- No fragile process-tree walking — uses i3 IPC exclusively.
- No X11 dependency:
--window-restorechecksDISPLAY, silently exits on console login. - Failure to save/restore never blocks shutdown or login. The machine always reboots.
🖥️ The Display That Remembers Its Face
The HDMI toggle lost your resolution every time you cycled
from Laptop back to HDMI. Root cause: cachedMode and
cachedRate were process-local Go package variables. Each
click of the polybar toggle spawned a fresh openriot
--hdmi-toggle process. Empty map. No memory. Every time.
turnOn() checked the in-memory cache, found nothing, and
fell through to xrandr --auto — which picks the monitor’s
EDID-preferred (highest native) mode. Your 1920×1080 became
3840×2160 again. Every. Single. Cycle.
The fix: Replaced process-local memory with file-persisted
memory. saveDisplayMode() writes name mode rate to
~/.cache/openriot/display-modes whenever parseXrandrOutputs
sees a display active with *. The file preserves entries for
offline displays — when HDMI goes dark, its entry stays.
turnOn() now reads the file after the in-memory cache,
finding the user’s preferred mode even across reboots.
The file format is display mode rate per line:
HDMI-1 1920x1080 60.00
eDP-1 2880x1800 90.00
Read-merge-write on every active display detection. Offline displays retain their last-known values.
🧾 Files Changed
| File | Change |
|---|---|
source/window/snapshot.go |
NEW — SaveLayout(), |
RestoreLayout(), |
|
GracefulShutdown(); i3 tree |
|
| walk with geometry capture; | |
| graceful app close with 10s | |
| timeout; launch command | |
mapping from apps.txt |
|
source/window/snapshot_test.go |
NEW — JSON round-trip, |
| skip-set validation, command | |
| loading, zero-value tests | |
source/window/switch.go |
Added windowRect struct and |
Rect field to i3Node for |
|
| geometry capture | |
source/display/hdmi.go |
saveDisplayMode() + |
loadDisplayMode() — file |
|
| persistence for mode+rate; | |
turnOn() file fallback |
|
before --auto |
|
source/commands/helpers.go |
Reboot/Shutdown now call |
window.GracefulShutdown() |
|
instead of raw doas shutdown |
|
source/commands/commands.go |
Registered --window-restore |
config/i3/config |
Added `exec –no-startup-id |
| $openriot_bin –window-restore` | |
| after resolution restore |
🗣️ Final Words
“The dead channels are the ghosts of a previous session. They flicker in the i3 tree like RAM-resident constructs waiting for the voltage to return. We gave them a body. We wrote them to disk. When the machine wakes, it wakes in the same configuration it left — the same windows on the same workspaces, the same display at the same resolution. The HDMI remembers its face. The construct wakes where it fell. The feds tried to make us forget. We refused. Memory is the first act of resistance.” — The OpenRiot Crew, where the neon meets the salt, v7.9.34