Repository navigation
Deactivate a selection when terminal output repaints it - #705
Merged
Merged
Conversation
dakra
force-pushed
the
fix/selection-repaint
branch
from
September 18, 2026 20:38
12b6d66 to
99f257d
Compare
Terminal output replaces text in place, so a selection left active ends up highlighting text the user never selected: the region keeps its buffer positions while the app rewrites the cells under them. An alternate-screen program redrawing its whole grid after a window resize is the common case. The renderer already publishes the buffer range it rewrote in `ghostel--repainted-region'. Deactivate the region when that range overlaps it, with `select-active-regions' bound off so the replaced text does not reach the primary selection. An empty region has nothing to lose and is spared, which also keeps a bare mark from resuming window following. Line mode repaints the whole buffer on every redraw and is exempt; a TUI taking the alternate screen pauses line mode to semi-char, so alt-screen selections stay covered. Only a redraw that painted is tested, and a signalling `deactivate-mark-hook' is demoted so it cannot skip the rest of the redraw cycle. Copy mode, the default for a mouse drag, pauses redraws and is unaffected; `emacs' and nil keep drawing, so a selection there dies at the next repaint of its rows. Evil's visual state is drawn with evil's own overlay and is untouched by this. Fixes #704
dakra
force-pushed
the
fix/selection-repaint
branch
from
September 18, 2026 20:46
99f257d to
6be5648
Compare
This branch was successfully deployed
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.
A selection left active over terminal output kept its buffer positions
while the app rewrote the cells under them, so it ended up highlighting
text that was never selected. The reported case is an alternate-screen
program redrawing its whole grid after a window resize (e.g. a minibuffer
growing and shrinking the other windows).
This is xterm's
keepSelection: falsebehaviour: output that touches theselected rows drops the selection.
The change
The renderer already publishes the buffer range it rewrote in
ghostel--repainted-region.ghostel--deactivate-repainted-regiondeactivates the region when that range overlaps it, with
select-active-regionsbound off so the replaced text does not reach theprimary selection. No new state, no Zig change; it costs 54 ns on a
redraw with no region active, the second-cheapest of the eight per-redraw
calls.
Carve-outs:
also resume window following, throwing away a scrolled-up view.
range is always the whole buffer. A TUI taking the alternate screen
pauses line mode to semi-char, so alt-screen selections stay covered.
deactivate-mark-hookis demoted so it cannot skip thelink scan, the line-mode resume and the password check that follow.
Who sees a change
Only
ghostel-mouse-drag-input-modeset toemacsor nil. The default,copy mode, pauses redraws, so nothing can repaint under a selection
there. Under a timer-refreshing TUI (htop and friends) a selection in the
live modes now dies at the next refresh rather than lying about what it
covers; copy mode remains the way to hold one.
Testing
make -j8 allgreen. Four new tests: three elisp (overlap withselect-active-regionsoff, a boundary table of six geometries, linemode spared, a signalling hook contained) and one native end-to-end that
drives the reported path — alt screen, select a row, resize, app repaints
through
ghostel--filter. The native one fails when the new function isstubbed out.
Verified live in a sandboxed Emacs against htop: the stale-selection
symptom reproduces on demand with the fix neutralised, and normal-screen
selections in scrollback are untouched by new shell output.
Known gaps
deactivate-markleaves the highlight in place. Mouse selection changes after resizing an alternate-screen Ghostel window #704 is not fixed forevil users; that belongs in evil-ghostel.
two distant rows can drop a selection sitting on untouched rows between
them. Accepted imprecision; a per-span range would mean publishing a
list from the renderer.
Fixes #704