fix(terminal): faithfully transfer terminals across windows (v1.2.7)#356
Merged
Conversation
2697bd0 to
40b9845
Compare
40b9845 to
47ffa84
Compare
A terminal dragged into its own window — or reopened on the next launch — came back wrong. Root causes and fixes: - Blank/garbled frame: the WebGL renderer initialized while the new window was still hidden, so its glyph atlas was built against a stale DPR and its buffer never painted. Force an atlas rebuild + repaint once the window is shown, and on every visibility transition. - Lost styling: scrollback was captured with translateToString(), which returns plain text and drops every color/bold. Capture now uses xterm's SerializeAddon (serializeTerminalState) — escape sequences that restore text, styling, wrapping and cursor verbatim. This is the SINGLE capture path for both live cross-window transfer and session/detached-window persistence; replay writes the serialized string verbatim. The old translateToString text path, its coalescing, and excludeCursorRow are gone. - Stale size + half-drawn TUIs: the reconnected PTY kept the source window's winsize, so commands like `ls` formatted for the old width and in-place renderers (Claude Code/Ink, vim, htop) never got the SIGWINCH they need to repaint. finalizeReconnect now nudges the winsize (one row short, then the real fitted size 150ms later) so the kernel always delivers a SIGWINCH. Adds @xterm/addon-serialize. Bump to v1.2.7.
47ffa84 to
d1acb7b
Compare
Two workspace tabs pointed at the same root would share its .cate/ workspace.json + session.json and clobber each other's autosave. The per-pid project lock can't catch this — two tabs in the same process always re-acquire it. - remoteSlice.setWorkspaceRootPath redirects to the workspace that already has the folder (focuses it; the empty outgoing tab is discarded on switch) instead of duplicating it. - workspaceManager backstops with a DUPLICATE_ROOT check on the RESOLVED path, catching symlink / trailing-slash aliases the renderer's raw string compare misses.
c5ed268 to
10643ef
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes a terminal dragged into its own window — or reopened on the next launch — come back exactly as it was, and folds in a workspace duplicate-root guard.
Terminals
Lost styling (the proper fix). Scrollback was captured with
translateToString(), which returns plain text and drops every color/bold. Capture now uses xterm's@xterm/addon-serialize(serializeTerminalState) — escape sequences that restore text, styling, wrapping and cursor verbatim. This is the single capture path for both live cross-window transfer and session/detached-window persistence; replay writes the serialized string verbatim. The oldtranslateToStringtext path, its wrapped-row coalescing, andexcludeCursorRoware gone.Blank/garbled frame. The WebGL renderer initialized while the new window was still hidden, so its glyph atlas was built against a stale DPR and its buffer never painted. Now we force an atlas rebuild + repaint once the window is shown, and on every visibility transition.
Stale size + half-drawn full-screen programs. The reconnected PTY kept the source window's winsize, so
lsformatted for the old width and in-place renderers (Claude Code/Ink, vim, htop) never got the SIGWINCH they need to repaint.finalizeReconnectnudges the winsize (one row short, then the real fitted size 150ms later), guaranteeing a SIGWINCH at the correct size.Adds
@xterm/addon-serialize.Workspace
Duplicate-root guard. Two tabs pointed at the same folder would share its
.cate/state and clobber each other's autosave (the per-pid project lock can't catch a same-process duplicate). The renderer now redirects to the tab that already has the folder; main backstops it with aDUPLICATE_ROOTcheck on the resolved path (catches symlink/trailing-slash aliases).Bumps to 1.2.7 + changelog.
Test