Fixed
Hang on wake from display sleep — zurm could freeze permanently (requiring a force-quit) after a display slept and woke: closing the laptop lid in clamshell mode, a monitor power-cycling, or the display idle-timeout. When idle, zurm skipped the GPU present to save CPU; on macOS 14+ that stranded Ebitengine’s display-link callback thread, which then deadlocked the main thread inside QuartzCore the next time a display was reconfigured. zurm now re-presents the last frame every tick so the present loop never stalls.
Tick rate not restored after sleep — after a sleep/wake cycle the engine could keep running at 60 TPS instead of the configured
[performance] tpsvalue, raising idle CPU. The configured rate is now always restored on wake.Crash on display sleep or disconnect — zurm could panic (
ebiten: width at NewImage must be positive but 0) when a display went to sleep or an external monitor was unplugged: with no screen attached the window reports a0×0size, which zurm then tried to allocate render buffers for. Resizes to a zero-sized window are now ignored; layout recommits automatically once a display is back.Scroll jumped on focus change — with smooth scrolling enabled, clicking a pane to focus it (or switching tabs) could snap its viewport up or down at random. The scroll animation tracked the previous pane’s position and forced it onto the newly focused pane. Each pane now keeps its own scroll position across focus and tab changes.
Window not resized when moved to another display — dragging zurm onto a different monitor could leave the content stranded at its old size in the top-left corner with the rest of the window black. The render surface was sized from
ebiten.WindowSize(), which lags the framebuffer that actually drives rendering when the window crosses displays. Render geometry is now committed from the size ebiten renders against, so content fills the window after a move.Crash on invalid font size — a
font.sizeof zero or below in config (including via a typo during a live config edit, which hot-reloads) collapsed the glyph cell to 0×0 and panicked with an integer divide-by-zero. Font size is now clamped to a renderable range (6–72 points) on every load, and the renderer guards against a zero-sized cell as a final safeguard.Crash on invalid window dimensions — a
window.columnsorwindow.rowsof zero or below panicked at startup when allocating the terminal buffer. Window columns/rows are now clamped to a minimum of 1 and padding to a minimum of 0 on load, and the screen buffer floors its own dimensions as a final safeguard.Click-count carried across panes — clicking to select in one pane then quickly clicking the same cell in another pane could register as a double/triple click. Click tracking now resets when focus changes panes.
Crash restoring a corrupt session — a session file with an out-of-range active tab index (e.g. negative, from manual editing or corruption) panicked at startup, preventing launch until the file was deleted. The restored active-tab index is now clamped to a valid range.