mirror of
https://github.com/tmux/tmux.git
synced 2026-02-14 10:09:16 +00:00
Add support for applications to use synchronized output mode (DECSET
2026) to prevent screen tearing during rapid updates. When an application sends SM ?2026, tmux buffers output until RM ?2026 is received or a 1-second timeout expires. From Chris Lloyd with the assistance of Claude Code, GitHub issue 4744.
This commit is contained in:
@@ -894,6 +894,52 @@ screen_write_mode_clear(struct screen_write_ctx *ctx, int mode)
|
||||
log_debug("%s: %s", __func__, screen_mode_to_string(mode));
|
||||
}
|
||||
|
||||
/* Sync timeout callback. */
|
||||
static void
|
||||
screen_write_sync_callback(__unused int fd, __unused short events, void *arg)
|
||||
{
|
||||
struct window_pane *wp = arg;
|
||||
|
||||
log_debug("%s: %%%u sync timer expired", __func__, wp->id);
|
||||
evtimer_del(&wp->sync_timer);
|
||||
|
||||
if (wp->base.mode & MODE_SYNC) {
|
||||
wp->base.mode &= ~MODE_SYNC;
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start sync mode. */
|
||||
void
|
||||
screen_write_start_sync(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
|
||||
|
||||
if (wp == NULL)
|
||||
return;
|
||||
|
||||
wp->base.mode |= MODE_SYNC;
|
||||
if (!event_initialized(&wp->sync_timer))
|
||||
evtimer_set(&wp->sync_timer, screen_write_sync_callback, wp);
|
||||
evtimer_add(&wp->sync_timer, &tv);
|
||||
|
||||
log_debug("%s: %%%u started sync mode", __func__, wp->id);
|
||||
}
|
||||
|
||||
/* Stop sync mode. */
|
||||
void
|
||||
screen_write_stop_sync(struct window_pane *wp)
|
||||
{
|
||||
if (wp == NULL)
|
||||
return;
|
||||
|
||||
if (event_initialized(&wp->sync_timer))
|
||||
evtimer_del(&wp->sync_timer);
|
||||
wp->base.mode &= ~MODE_SYNC;
|
||||
|
||||
log_debug("%s: %%%u stopped sync mode", __func__, wp->id);
|
||||
}
|
||||
|
||||
/* Cursor up by ny. */
|
||||
void
|
||||
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
|
||||
@@ -1692,6 +1738,9 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
u_int y, cx, cy, last, items = 0;
|
||||
struct tty_ctx ttyctx;
|
||||
|
||||
if (s->mode & MODE_SYNC)
|
||||
return;
|
||||
|
||||
if (ctx->scrolled != 0) {
|
||||
log_debug("%s: scrolled %u (region %u-%u)", __func__,
|
||||
ctx->scrolled, s->rupper, s->rlower);
|
||||
@@ -1985,7 +2034,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
}
|
||||
|
||||
/* Write to the screen. */
|
||||
if (!skip) {
|
||||
if (!skip && !(s->mode & MODE_SYNC)) {
|
||||
if (selected) {
|
||||
screen_select_cell(s, &tmp_gc, gc);
|
||||
ttyctx.cell = &tmp_gc;
|
||||
|
||||
Reference in New Issue
Block a user