From fe986a52d6bc9f11b90e52f677d679b839fa4643 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 8 Jun 2026 20:41:21 +0000 Subject: [PATCH] When entering or leaving the alternate screen, discard any pending resizes. Improves flicking with scrollbars and programs that leave and enter the alternate screen on every WINCH like nano. GitHub issue 4772. Cvs: ---------------------------------------------------------------------- --- screen-write.c | 15 +++++++++++---- screen.c | 12 ++++++++---- server-client.c | 5 +---- tmux.h | 6 ++++-- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/screen-write.c b/screen-write.c index 47d6ebc9..9aa86c41 100644 --- a/screen-write.c +++ b/screen-write.c @@ -2765,16 +2765,22 @@ void screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, int cursor) { - struct tty_ctx ttyctx; - struct window_pane *wp = ctx->wp; + struct tty_ctx ttyctx; + struct window_pane *wp = ctx->wp; + struct window_pane_resize *r, *r1; if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) return; screen_write_collect_flush(ctx, 0, __func__); - screen_alternate_on(ctx->s, gc, cursor); + if (!screen_alternate_on(ctx->s, gc, cursor)) + return; if (wp != NULL) { + TAILQ_FOREACH_SAFE (r, &wp->resize_queue, entry, r1) { + TAILQ_REMOVE(&wp->resize_queue, r, entry); + free(r); + } layout_fix_panes(wp->window, NULL); server_redraw_window_borders(wp->window); } @@ -2796,7 +2802,8 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc, return; screen_write_collect_flush(ctx, 0, __func__); - screen_alternate_off(ctx->s, gc, cursor); + if (!screen_alternate_off(ctx->s, gc, cursor)) + return; if (wp != NULL) { layout_fix_panes(wp->window, NULL); diff --git a/screen.c b/screen.c index 3d9ead65..459ebcb2 100644 --- a/screen.c +++ b/screen.c @@ -655,13 +655,13 @@ screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor) * Enter alternative screen mode. A copy of the visible screen is saved and the * history is not updated. */ -void +int screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) { u_int sx, sy; if (SCREEN_IS_ALTERNATE(s)) - return; + return 0; sx = screen_size_x(s); sy = screen_size_y(s); @@ -677,10 +677,12 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) s->saved_flags = s->grid->flags; s->grid->flags &= ~GRID_HISTORY; + + return 1; } /* Exit alternate screen mode and restore the copied grid. */ -void +int screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) { u_int sx = screen_size_x(s), sy = screen_size_y(s); @@ -709,7 +711,7 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) s->cx = screen_size_x(s) - 1; if (s->cy > screen_size_y(s) - 1) s->cy = screen_size_y(s) - 1; - return; + return 0; } /* Restore the saved grid. */ @@ -731,6 +733,8 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) s->cx = screen_size_x(s) - 1; if (s->cy > screen_size_y(s) - 1) s->cy = screen_size_y(s) - 1; + + return 1; } /* Get mode as a string. */ diff --git a/server-client.c b/server-client.c index 481d5a71..a819e6f9 100644 --- a/server-client.c +++ b/server-client.c @@ -1590,10 +1590,7 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data) static void server_client_check_pane_resize(struct window_pane *wp) { - struct window_pane_resize *r; - struct window_pane_resize *r1; - struct window_pane_resize *first; - struct window_pane_resize *last; + struct window_pane_resize *r, *r1, *first, *last; struct timeval tv = { .tv_usec = 250000 }; if (TAILQ_EMPTY(&wp->resize_queue)) diff --git a/tmux.h b/tmux.h index 887d21bb..b618b3be 100644 --- a/tmux.h +++ b/tmux.h @@ -1147,6 +1147,8 @@ struct window_mode_entry { struct screen *screen; u_int prefix; + int kill; + TAILQ_ENTRY(window_mode_entry) entry; }; @@ -3335,8 +3337,8 @@ void screen_hide_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); int screen_select_cell(struct screen *, struct grid_cell *, const struct grid_cell *); -void screen_alternate_on(struct screen *, struct grid_cell *, int); -void screen_alternate_off(struct screen *, struct grid_cell *, int); +int screen_alternate_on(struct screen *, struct grid_cell *, int); +int screen_alternate_off(struct screen *, struct grid_cell *, int); const char *screen_mode_to_string(int); const char *screen_print(struct screen *, int);