fix(client): copy-mode no longer blanks the window — paint a pane backdrop#84
Closed
phall1 wants to merge 1 commit into
Closed
fix(client): copy-mode no longer blanks the window — paint a pane backdrop#84phall1 wants to merge 1 commit into
phall1 wants to merge 1 commit into
Conversation
…kdrop Copy-mode is a *transparent* overlay: it must show the live pane content with the selection highlighted on top. But the overlay paint system hands every overlay a fresh blank Buffer (correct for modal overlays — help, palette, prompts — which draw their own surface), and the driver clears the screen before painting. Copy-mode's render() only styled the selected cells, so on a blank buffer it produced a blank window with just a status line. The bug was latent until phux-v6jw made copy-mode actually worth entering. Fix: give the copy-mode overlay a backdrop of the focused pane's visible glyphs and paint them under the highlight. - RenderOverlay gains two default-no-op hooks: `backdrop_dims()` (None for modal overlays) and `set_backdrop(grid)`. Only CopyModeOverlay overrides them — no churn on the other overlays, no downcasting. - CopyModeOverlay stores a `backdrop: Vec<Vec<char>>` and render() writes the pane glyph into every cell before applying the selection/anchor styling. - The driver refreshes the backdrop (read the focused pane's glyph grid via the renderer) immediately before each overlay paint, gated on `backdrop_dims()` — so it tracks entry, cursor moves, and live content updates, and is a no-op for modal overlays / no overlay. Cosmetic only: the copied text is still extracted from the engine (format_selection_alloc, phux-v6jw), never from these glyphs. Cell styling (colors) under copy-mode is not yet reproduced — plain glyphs — which is a clear win over a blank screen; styled backdrop is a follow-up. Test: render_paints_pane_backdrop_not_blank asserts the backdrop glyphs land in the buffer (the window is not blank). Gates: clippy --all-features -D warnings, cargo doc -D warnings, fmt, nextest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Owner
Author
|
Closing unmerged — the backdrop approach is the wrong layer (it re-paints a lossy copy of the screen). Replacing with the correct fix: render the selection highlight (reverse-video) inside the pane renderer so nothing on screen swaps and real colors are preserved. See follow-up PR. |
phall1
added a commit
that referenced
this pull request
Jun 8, 2026
Copy-mode was implemented as a modal overlay. Modal overlays (help, palette, prompts) clear the screen (ED2) and repaint their own surface from a fresh buffer — correct for them, wrong for copy-mode, which is a selection highlight *over* the live pane. The result was that entering copy-mode wiped the real content and repainted a degraded copy (blank, or — with the reverted backdrop hack — color-stripped). Render the selection where it belongs: inside the pane renderer. The cell-emit loop already walks every cell with its real style/fg/bg; when a cell falls in the copy-mode selection it now toggles `inverse` (reverse-video) before emitting. So the pane renders exactly as it always does — true colors, true content — and the selected cells just invert. Nothing on screen swaps. - `render.rs`: `SelectionRect` (pane-local, linear) + a transient `TerminalRenderer::selection` the driver sets only around a copy-mode paint; the cell loop reverse-videos selected cells. - copy-mode stops being a modal overlay: `RenderOverlay::copy_selection()` (default None; copy-mode returns Some) tells the driver to repaint the focused pane with the selection + a status line via `paint_active_overlay`, instead of the modal clear+overlay path. Copy-mode's own `render` is now a no-op; its key handling (arrows/Enter→OSC52 copy/Esc) is unchanged. Reverse-video preserves each cell's colors (just inverted) and is theme-native. Tests: `selection_emits_reverse_video_for_selected_cells` (real content + SGR 7 on the selection, none without), `selection_rect_contains_is_linear`, `copy_selection_tracks_normalized_range`. Supersedes the closed backdrop PR #84. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
phall1
added a commit
that referenced
this pull request
Jun 8, 2026
Copy-mode was implemented as a modal overlay. Modal overlays (help, palette, prompts) clear the screen (ED2) and repaint their own surface from a fresh buffer — correct for them, wrong for copy-mode, which is a selection highlight *over* the live pane. The result was that entering copy-mode wiped the real content and repainted a degraded copy (blank, or — with the reverted backdrop hack — color-stripped). Render the selection where it belongs: inside the pane renderer. The cell-emit loop already walks every cell with its real style/fg/bg; when a cell falls in the copy-mode selection it now toggles `inverse` (reverse-video) before emitting. So the pane renders exactly as it always does — true colors, true content — and the selected cells just invert. Nothing on screen swaps. - `render.rs`: `SelectionRect` (pane-local, linear) + a transient `TerminalRenderer::selection` the driver sets only around a copy-mode paint; the cell loop reverse-videos selected cells. - copy-mode stops being a modal overlay: `RenderOverlay::copy_selection()` (default None; copy-mode returns Some) tells the driver to repaint the focused pane with the selection + a status line via `paint_active_overlay`, instead of the modal clear+overlay path. Copy-mode's own `render` is now a no-op; its key handling (arrows/Enter→OSC52 copy/Esc) is unchanged. Reverse-video preserves each cell's colors (just inverted) and is theme-native. Tests: `selection_emits_reverse_video_for_selected_cells` (real content + SGR 7 on the selection, none without), `selection_rect_contains_is_linear`, `copy_selection_tracks_normalized_range`. Supersedes the closed backdrop PR #84. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
The bug
Entering copy-mode fully blanks the window. Copy-mode is a transparent overlay — it should show the live pane content with the selection highlighted on top — but the overlay paint system hands every overlay a fresh blank
Buffer(correct for modal overlays like help/palette/prompts, which draw their own surface) and the driver\x1b[2J-clears before painting. Copy-mode'srender()only styled the selected cells, so on a blank buffer it produced a blank window with just a status line.Latent until phux-v6jw made copy-mode actually worth entering.
The fix
Give the copy-mode overlay a backdrop of the focused pane's visible glyphs and paint them under the highlight.
RenderOverlaygains two default-no-op hooks:backdrop_dims() -> Option<(u16,u16)>(None for modal overlays) andset_backdrop(grid). OnlyCopyModeOverlayoverrides them — no churn on other overlays, no downcasting.CopyModeOverlaystoresbackdrop: Vec<Vec<char>>;render()writes the pane glyph into every cell before applying selection/anchor styling.backdrop_dims()— tracks entry, cursor moves, and live content updates; no-op for modal overlays.Scope notes
format_selection_alloc, phux-v6jw), never from these glyphs.Test
render_paints_pane_backdrop_not_blankasserts the backdrop glyphs land in the buffer (window is not blank).Gates
clippy --all-features -D warnings·cargo doc -D warnings·fmt·nextest.🤖 Generated with Claude Code