Give the mouse back, retire the follow controls, update Claude per session
Secret Scan / scan (push) Successful in 4s
Build App (Preview) / compute-version (pull_request) Successful in 3s
Secret Scan / scan (pull_request) Successful in 4s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m44s
Build App (Preview) / build-linux (pull_request) Successful in 5m8s
Build App (Preview) / build-windows (pull_request) Successful in 6m28s
Build App (Preview) / prune-previews (pull_request) Successful in 2s
Build Container / build-container (pull_request) Failing after 14m49s
Secret Scan / scan (push) Successful in 4s
Build App (Preview) / compute-version (pull_request) Successful in 3s
Secret Scan / scan (pull_request) Successful in 4s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m44s
Build App (Preview) / build-linux (pull_request) Successful in 5m8s
Build App (Preview) / build-windows (pull_request) Successful in 6m28s
Build App (Preview) / prune-previews (pull_request) Successful in 2s
Build Container / build-container (pull_request) Failing after 14m49s
Three things the terminal was getting wrong. **A program that grabs the mouse and dies used to freeze the tab.** A TUI sets DECSET ?1000/?1002/?1003; if it exits without resetting them, xterm keeps routing clicks, drags and — under ?1003 — every pointer *move* to the PTY. Text selection dies and escape bytes flood the prompt. The only exit was closing the tab. `TerminalView` now reconciles a flag against `term.modes.mouseTrackingMode` in the `term.write()` callback — the mode only changes because the container printed a sequence, so one check per write catches every transition with no polling — and `Ctrl+Shift+X` or a status-bar button writes the resets back through `term.write`, never `sendInput`: the reset belongs to xterm's parser, and a still-live TUI told about it would just re-grab on its next repaint. The control is in the status bar deliberately. Mouse tracking is the *normal* state of htop, vim, lazygit and Claude Code, so a badge over the terminal would be on screen for the whole life of those programs and would swallow clicks aimed at their own top-right corner. `macOptionClickForcesSelection` is also on now: xterm's force-select is Shift everywhere except macOS, where it is Option and is gated behind that option, which defaults to false — so until now Mac users had no way to select text while a program held the mouse. **"Following" and "Jump to Current" are gone.** Claude Code draws on the alternate screen, which has no scrollback, so `viewportY` always equalled `baseY` and neither control could do anything. They did still work in bash tabs; xterm's native follow covers that, and the per-write `scrollToBottom()` went with them because it fought exactly that. What remains, on activate and after a refit, now samples `viewportY >= baseY` *before* the fit, so opening the Notes dock no longer yanks a reader to the tail. **`claude update` runs before every Claude session, not just at container start.** Containers here stop/start and often just keep running, so a long-lived one never re-checked. Both copies take the same flock: the entrypoint prints "container ready" only after its own update finishes, so opening a tab immediately would otherwise run two updaters against the same ~/.claude/bin, with `|| echo` hiding a half-written install one line before `exec claude` ran it. This turns the non-Bedrock path from a bare argv into a `bash -c` wrapper, so flags and session names are shell-interpolated now and must go through `shell_quote_arg`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0145mQi9NZiCDrznBUEEDE4n
This commit is contained in:
+14
-10
@@ -205,16 +205,20 @@ interface AppState {
|
||||
// UI state
|
||||
terminalHasSelection: boolean;
|
||||
setTerminalHasSelection: (has: boolean) => void;
|
||||
// Whether a program in the active terminal is holding mouse reporting open,
|
||||
// and how to take it back. Surfaced so the release control can live in the
|
||||
// status bar: painted over the terminal it would sit on top of whatever TUI
|
||||
// is asking for the mouse, and swallow clicks aimed at that program's own
|
||||
// top-right corner for as long as it ran. Only the active TerminalView
|
||||
// writes these.
|
||||
terminalMouseCaptured: boolean;
|
||||
setTerminalMouseCaptured: (captured: boolean) => void;
|
||||
releaseActiveMouse: () => void;
|
||||
setReleaseActiveMouse: (fn: () => void) => void;
|
||||
// STT toggle for the active session, registered by App so the terminal's
|
||||
// Ctrl+Shift+M shortcut can trigger the single status-bar mic instance.
|
||||
sttToggle: () => void;
|
||||
setSttToggle: (fn: () => void) => void;
|
||||
// Active terminal scroll state, surfaced so the status bar can host the
|
||||
// "Jump to Current" control. Only the active TerminalView writes these.
|
||||
terminalAtBottom: boolean;
|
||||
setTerminalAtBottom: (v: boolean) => void;
|
||||
scrollActiveToBottom: () => void;
|
||||
setScrollActiveToBottom: (fn: () => void) => void;
|
||||
sidebarView: "projects" | "settings";
|
||||
setSidebarView: (view: "projects" | "settings") => void;
|
||||
sidebarCollapsed: boolean;
|
||||
@@ -496,12 +500,12 @@ export const useAppState = create<AppState>((set) => ({
|
||||
// UI state
|
||||
terminalHasSelection: false,
|
||||
setTerminalHasSelection: (has) => set({ terminalHasSelection: has }),
|
||||
terminalMouseCaptured: false,
|
||||
setTerminalMouseCaptured: (captured) => set({ terminalMouseCaptured: captured }),
|
||||
releaseActiveMouse: () => {},
|
||||
setReleaseActiveMouse: (fn) => set({ releaseActiveMouse: fn }),
|
||||
sttToggle: () => {},
|
||||
setSttToggle: (fn) => set({ sttToggle: fn }),
|
||||
terminalAtBottom: true,
|
||||
setTerminalAtBottom: (v) => set({ terminalAtBottom: v }),
|
||||
scrollActiveToBottom: () => {},
|
||||
setScrollActiveToBottom: (fn) => set({ scrollActiveToBottom: fn }),
|
||||
sidebarView: "projects",
|
||||
setSidebarView: (view) => set({ sidebarView: view }),
|
||||
sidebarCollapsed: loadSidebarCollapsed(),
|
||||
|
||||
Reference in New Issue
Block a user