All features

Each window remembers where it was

Try the real interface

Explore this workspace.

Real Torbie UI · mock sessions
Tab bar
Loading Torbie…
Technical background

Upstream keeps one saved rectangle that every window reads and writes, which is invisible with one window and wrong the moment there are two: the second opens exactly on top of the first, and whichever closes last overwrites the other. Geometry is now per window, and a window whose title bar would land off screen is pulled back into a work area instead of being restored somewhere you cannot reach it.

The problem

Upstream keeps one windowBoundaries key that every window reads and writes. With one window that is invisible; with two it is wrong immediately — the second opens exactly on top of the first, and whichever closes last overwrites the other. Multi-window is fork-added here; the persistence is upstream's and was never scoped to it.

How it works

Position and size are remembered per window, in <config dir>/window.json under windowGeometries. The identity is the window ordinal, because it is the only one Tabby already has — slots are claimed lowest-free and released on close, so open order decides them and close order cannot disturb them.

Details
  • "On screen" is decided by the title bar, not by area. The old check only fired when the saved rectangle missed the nearest display entirely, so a window whose title bar was above the top of the screen was restored exactly there and could not be dragged back. A rectangle now needs 120px of width and a 32px strip of its top edge inside some work area.
  • A frameless window reports back 2px taller than the size its constructor was given. Measured, consistently — so a window only ever opened and closed grew 2px and crept down the screen every launch. Upstream has this too. setBounds is exact, so the restored rectangle is applied once more after construction.
  • No DPI is stored. Windows Terminal's version of this keeps physical pixels and rescales them; Electron's screen coordinates are already per-display DIPs, so rescaling would introduce exactly the drift it exists to prevent.
  • A slot with nothing saved cascades 28px off the newest live window, wrapping at the work area edge, rather than opening on top of it.
  • Slot 1 is mirrored back to windowBoundaries, so a build without slots — upstream, or an older one of ours — still finds the main window's place.
  • Every placement writes a record to diagnostics.log, and an adjusted one says what was wrong. "Why did my window open there" is otherwise unanswerable from outside the process.
What this does not claim
  • Closing window 1 and opening another mid-session hands the new one slot 1, so it lands where window 1 was. Open order at launch is not a guess — app.on('ready') creates exactly one window — but nothing else about a window survives a restart to key off.
  • No setting. The reference fork gates its equivalent behind rememberWindowGeometry because there it is new behaviour; here geometry has always been remembered and this only fixes who it belongs to, so a toggle would be a way to ask for the bug back.
  • Geometry is written on close and 2s after the last move or resize — so a crash, a session ending, and the watchdog's own app.exit() all skip the close write.
Source commits
SessionsAdded 2026-08-105 files+970 / −25 lines