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:
@@ -243,11 +243,12 @@ describe("dropTarget", () => {
|
||||
describe("chrome over a pane, with no dialog open", () => {
|
||||
/** Everything that is painted over a pane and is not a blocker. */
|
||||
const CHROME: Array<[string, () => HTMLElement]> = [
|
||||
// `TerminalView`'s "▼ Following / ▽ Paused" toggle: `absolute top-2
|
||||
// right-4 z-50`, rendered unconditionally, and a *sibling* of the xterm
|
||||
// host — so "does the pane contain what is painted here?" made the
|
||||
// terminal's top-right corner a dead zone no user action could clear.
|
||||
["the Following/Paused toggle", () => document.createElement("button")],
|
||||
// `TerminalView`'s mouse-release badge: `absolute top-2 right-4 z-50`,
|
||||
// and a *sibling* of the xterm host — so "does the pane contain what is
|
||||
// painted here?" made the terminal's top-right corner a dead zone no
|
||||
// user action could clear. (The retired Following toggle held the same
|
||||
// corner and produced the original bug.)
|
||||
["the mouse-release badge", () => document.createElement("button")],
|
||||
// `ToastHost`: `fixed bottom-4 right-4 z-[60]`, 24rem wide, over every
|
||||
// pane, and its error cards stay until dismissed.
|
||||
["a toast card", () => document.createElement("div")],
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
*
|
||||
* - Asking `el.contains(document.elementFromPoint(x, y))` — "is the thing
|
||||
* painted here mine?" — refused drops onto anything painted *over* a pane
|
||||
* that is not part of it: `TerminalView`'s always-rendered "▼ Following"
|
||||
* toggle (a sibling of the xterm host), the URL toast, `ToastHost`'s stack.
|
||||
* that is not part of it: `TerminalView`'s mouse-release badge (a sibling
|
||||
* of the xterm host), the URL toast, `ToastHost`'s stack.
|
||||
* Permanent dead zones no user action could clear.
|
||||
* - Replacing that with "is a *blocking overlay* painted here?" removed the
|
||||
* dead zones and opened a hole instead. `elementFromPoint` returns the
|
||||
|
||||
Reference in New Issue
Block a user