Build an adaptive 256-colour palette with median cut instead of using a fixed colour cube. Apply Floyd-Steinberg error diffusion while mapping pixels to reduce banding and preserve image detail.
Retain the padded canonical pixel canvas separately from the image content. Scale only the populated portion of partial edge cells so an image keeps its exact raster size on the originating terminal while retaining its cell footprint.
A resize may temporarily leave the terminal cell pixel dimensions unknown while tmux queries the terminal. Schedule another client redraw when the pixel geometry response arrives so the graphical backend replaces the temporary text fallback.
Enable the sixel feature when WezTerm is detected and clarify that the kitty terminal feature requires Unicode placeholder support rather than only the basic graphics protocol.
Two more fixes based on Michael K. Darling's branch
(github.com/darlingm/tmux, pr5516-regression-fixes), taken as-is -
neither is caught by any test in regress/ yet, found by code review
rather than a failing test:
- screen_write_redraw_cb() (screen-write.c) reported damage for only a
single row, using ttyctx->ocy as if every fallback redraw were a
single-cell write. But it's also the callback for cases that can
legitimately span many rows - a large scroll-region fallback
(tty_redraw_region(), when tty_large_region() or the pane is
obscured), a full reset, and entering/leaving the alternate screen.
For those, only the top row of the affected area ever got marked as
damaged, leaving the rest stale until an unrelated redraw happened to
cover it. Changed the shared tty_ctx_redraw_cb typedef to carry
(py, ny) - the actual row range - and updated every call site to pass
the range it actually knows about, instead of hardcoding a single
row.
- window_pane_redraw_floating() (window.c) never refreshed the status
line after moving/resizing a floating pane, so a status format
depending on that pane's geometry (e.g. #{pane_width}) could go
stale until an unrelated status refresh happened. Added a
server_status_window(w) call.
Also confirmed the window_pane_scrollbar_intersects() parameter
naming cleanup (loop -> wp) discussed earlier was already done in an
earlier "Cleanup." commit - nothing left to do there.
All 9 tests in regress/ plus the two pre-existing floating-pane tests
plus a further 19-test sweep of redraw/tty/input/sync-adjacent
regress tests pass.
Co-Authored-By: Michael K. Darling <darlingm@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixes the four bugs caught by the regression tests added in aed1209c
(popup-drag-status-line.sh, popup-drag-wide-character.sh,
popup-drag-pane-prompt.sh, switch-client-redraw.sh), based on fixes
from Michael K. Darling (github.com/darlingm/tmux, pr5516-regression-
fixes), reviewed and adapted:
- server-client.c: server_client_set_session()'s check for whether the
client's window actually changed compared old->curw to s->curw, but
when old == s these read the same, already-updated field, so a
same-session window switch was never detected. Compare against the
client's own cached redraw scene instead (redraw_client_has_window(),
new in screen-redraw.c/tmux.h). Taken from darlingm as-is.
- popup.c: popup_damage() only translated a popup's client-coordinate
rectangle into window coordinates, so a popup dragged across the
status line never triggered a status-line redraw once it moved away -
status_redraw()'s own "skip if content unchanged" optimization
suppressed it, since only the popup moved, not the status content.
Now detects overlap with the status line and forces a redraw via the
existing (previously unused) CLIENT_REDRAWSTATUSALWAYS flag, and
properly clips the reported rectangle to the pane area for
status-at-top/bottom/off. Taken from darlingm as-is.
- screen-redraw.c: redraw_draw_damage_rect() clipped a span to a damage
rectangle's raw geometric edges, which have no idea what's in the
grid, so a clip edge could land mid-character and tear a wide
character in half. Added redraw_damage_grow_span_clip(): widen the
clip by one cell on each edge that isn't already at the span's own
boundary. Reimplemented simpler than darlingm's version (which walked
grid cells per span type via a switch and direct grid lookups) -
since no grid cell is ever wider than two columns, an unconditional
one-cell margin is always enough to pull a split character back in,
with no need to inspect grid content at all.
- screen-redraw.c: redraw_draw_damage_rect() also never re-overlaid a
pane's active in-pane prompt after drawing its underlying content, so
damage crossing a prompt row erased it until an unrelated redraw
restored it. Factored the existing full-redraw prompt-building code
into a shared redraw_make_pane_prompt() helper and added
redraw_damage_draw_pane_prompt(), which recomposes the prompt over
the drawn range. Taken from darlingm as-is.
All 9 regression tests in regress/ now pass. redraw_damage_grow_span_clip
was verified independently by disabling it and confirming
popup-drag-wide-character.sh reproduces its original failure.
Co-Authored-By: Michael K. Darling <darlingm@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
From github.com/darlingm/tmux, branch pr5516-regression-fixes. Adds 9
regression tests covering gaps found in the redraw-damage-rectangles
branch: screen-write full/region redraw fallback, same-session window
switches, wide-character clipping at damage edges, pane prompts and
status lines surviving damage, floating-pane status format refresh,
and multi-client damage delivery.
redraw-multiclient.sh is adapted here to use ASCII pane borders
(pane-border-lines simple) instead of darlingm's original UTF-8
borders: the original reliably "failed" under this test's nested
tmux-in-tmux harness (relaying through an outer tmux client) due to
that harness mis-rendering a cell that held a multi-byte UTF-8 border
character being overwritten by later plain content - confirmed to be
a nested-relay artifact, not a real bug, by replaying the identical
drag sequence against a real terminal (xterm), where it never
reproduces. ASCII borders avoid the artifact; the test still reliably
catches the real "damage consumed by only one client" bug it targets
(verified by reintroducing that bug and confirming the test fails).
The other 8 tests are added verbatim from darlingm's branch. Four of
them (popup-drag-status-line.sh, popup-drag-wide-character.sh,
popup-drag-pane-prompt.sh, switch-client-redraw.sh) currently FAIL on
this branch, since the source fixes they test for have not been
merged yet - only the tests are being added here.
Co-Authored-By: Michael K. Darling <darlingm@gmail.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* refs/remotes/tmux-openbsd/master:
Correct a comparison ('\0' should be 0).
If a pane has no scrollbar, don't bother to redraw it, and if redraw is deferred change scrollbar redraws into redraw-all-scrollbars not redraw entire window. GitHub issue 5529.
* refs/remotes/tmux-openbsd/master:
Always use synchronized updates in copy mode (like when not in the active pane), since copy mode will almost always moved the cursor. From Artem Goldenberg in GitHub issue 5525.
* refs/remotes/tmux-openbsd/master:
Do not leak cached status line, from Jeong, Heon.
Free pane fallback range when freeing pane, from Jeong, Heon.
Do not leak path when destroying client, from Jeong, Heon.
Do not leak format when drawing preview, from Jeong, Heon.
Do not leak buffer name on failure, from Jeong, Heon.