image_redraw_start() was called with a pane's full nominal geometry
rather than the cells it actually owns in the current scene. When a
floating pane occluded part of that rectangle, the erase blanked the
floating pane's on-screen content, and the following text redraw
correctly skipped those cells (not owned by this pane), leaving them
blank with nothing to restore them.
Replace the per-cell image marker with sparse placement spans attached to
grid lines. A placement owns all of its spans and records the input
protocol, application image and placement IDs, z-index, and creation order.
This retains overlapping image layers without storing a list in every grid
cell. Grid operations move, split, clip, and remove only the affected spans.
Use the input protocol to determine image/text interaction: later text
damages SIXEL spans, while Kitty placements remain and are ordered by their
z-index. Rendering then adapts that one logical scene for each client,
rather than changing its semantics according to whether the outer terminal
uses Kitty or SIXEL.
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>
Introduce a per-window list of damaged rectangles (struct redraw_damage)
and redraw_damage_window() to record them, redraw_client_damage() to
consume them by composing exactly the damaged cells (via a new
redraw_draw_damage_rect(), which also force-refreshes any pane-status
span it touches, since window_make_pane_status()'s content-diff check
has no way to know the physical cells were disturbed by something else).
redraw_draw_span() now takes an explicit [clip_x, clip_x + clip_n) range
instead of always drawing a span's full width, so a damage rectangle can
redraw just the portion of a span it actually covers.
screen_write_redraw_cb() - the fallback when a write can't be applied
directly to the terminal - now reports damage for just the affected row
via this mechanism, instead of unconditionally flagging the whole pane
for a full redraw.
* refs/remotes/tmux-openbsd/master:
Extend fill-character to allow inside and outside to be separate and use a different default (filled characters rather than dots) for inside.
* refs/remotes/tmux-openbsd/master:
Clip floating panes exactly at window edge, don't let the border creep into the first outside column.
Invalidate scene when window is resized.
Add a -C flag to new-pane to have a modal pane close when the mouse is clicked outside it, GitHub issue 5400.
* refs/remotes/tmux-openbsd/master:
If drawing border but not actually on a border, use the default line style.
Add copy-mode-current-line-style to set style for current line in copy mode, GitHub issue 5391 from Leo Henon.
* refs/remotes/tmux-openbsd/master:
Remove the active-pane flag for now, there are some gaps in how this works and I don't like it. May come back in a different form (maybe just for windows).
* refs/remotes/tmux-openbsd/master:
Switch menus also to be attached to the window instead of an overlay and drawn as part of the client's scene. This means removing the popup menu.
* refs/remotes/tmux-openbsd/master:
build: don't exit
build: always attempt portable merge
build: capture openbsd-base before filtering
build: fetch cutover master before merge
Use _exit in child after fork, from Yayo Razo in GitHub issue 5376.
Add missing calloc check and use fatal. Prompted by a similar change from Yayo Razo.
actions: use published openbsd-git as base update
github actions: automate updates
Do not make pty fds blocking again until all the data has been consumed or control mode clients can get stuck, GitHub issue 5356 from Ben Maurer.
Add formats and events for OSC 133 commmands, as well as a -T flag to set-hook -B to only fire when the format is true.
Replace the notification system with events. Events can carry a payload of additional payload (to reduce problems with lifetime of objects) and are delivered to one or more event sinks. This is more powerful and reduces the complex dependencies between control mode and hooks. Events are now used for hooks, control mode notifications and for monitors (set-hook -B).
additional payload (to reduce problems with lifetime of objects) and are
delivered to one or more event sinks. This is more powerful and reduces the
complex dependencies between control mode and hooks. Events are now used for
hooks, control mode notifications and for monitors (set-hook -B).
wait-for can now wait for an event to fire (-E flag, with -F to for filter),
with -v to print the payload, as well as listing (-l) waiting clients on an
event and forcing one to wake (-w).
A few additional hooks are also now available (pane-created, pane-resized, etc)
and some of the existing ones have additional format variables available.
replaces the previous "modal" behaviour where the pane would be resized,
which tended to make a mess. Instead, the scrollbar appears when
scrolling or when hovered over with the mouse and disappears a
(configurable) short period later. From Michael Grant.
are now wrapped up in prompt*.c and do not depend on a client. These
functions are used to provide the original client prompt but also to
allow panes to have their own prompts, which works much much better for
floating panes. The mode prompts for both the tree modes and copy mode
are switched over to be per pane.
There are some visible changes (some of these may be changed if they
don't seem to be working well):
- Prompts in modes now appear in the bottom line, covering whatever
content was there.
- command-prompt has a -P flag to open a pane prompt.
- Because they cover the content, the default style for prompts in modes
now does not fill the entire line; the main command prompt stays the
same.
- The old completion menu has gone, and completions are now shown after
the text. Builtin aliases are no longer completed.
- Clicking the mouse on the prompt now moves the cursor or selects a
completion.
is generated and cached in the client: it holds positions and sizes of
panes, borders and so on. The scene is invalidated when a pane is moved
or resized or relevant option is changed. This scene is then drawn to
the client as needed and text and colours are filled in. With Michael
Grant.