mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
* fix(restore): keep a restored screen out of ConPTY's viewport On Windows a restored pane came back with its shell drawing in the wrong place: the prompt stopped responding where it stood and the restored text filled with fragments of whatever was being typed. A ConPTY does not hand the terminal a stream, it hands it a rendering of a screen buffer conhost owns, addressed absolutely and counted from that buffer's top-left, which starts blank with the cursor at (0,0). PSReadLine redraws the line being typed as `ESC[6;20H ... ESC[6;26H` on every keystroke, and conhost frames what it paints the same way. Those row numbers are only right if the client's viewport is conhost's buffer, row for row. Restored output is output conhost never produced and knows nothing about. Left on screen it shifts every row conhost names, so the first repaint of the input line lands on the old text. Nothing the client can do fixes it afterwards: the offset is not constant, and it would have to be unpicked from every absolute address in the stream. So the restore preamble now ends by scrolling the restored screen out of the way. `ESC[2J` on the primary screen scrolls the viewport into history rather than erasing it, so the screen the daemon restored is one scroll up rather than gone, and `ESC[H` leaves the cursor where a fresh ConPTY expects to find it. Unix keeps the old behaviour: a shell there positions itself relatively, so the restored screen can stay where it can be seen. * fix(restart): stop Restart Server taking the window with it Clicking Restart Server made the whole app disappear, with a double-lease panic in the crash log: cannot read Tty7App while it is already being updated. The work that puts the window back together after the restart ran inside `update_in` on this window's own entity, and it ends by rebuilding every local window from the machine tree. The first thing that rebuild asks each window is which tabs it is showing, which it reads back out of the window registry — so the first window it reaches for is the one the closure already holds leased, and gpui answers a double lease by panicking, which on the main thread is the process. Split into `settle_after_restart`: the window's own state first, then the resync outside the lease, then the focus. The resync still runs either way the restart went, because a refused handoff leaves the daemon serving the panes this window already dropped (#554). --------- Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>