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: ----------------------------------------------------------------------
This commit is contained in:
nicm
2026-06-08 20:41:21 +00:00
parent 34fd261a4f
commit fe986a52d6
4 changed files with 24 additions and 14 deletions

View File

@@ -2765,16 +2765,22 @@ void
screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
int cursor) int cursor)
{ {
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
struct window_pane *wp = ctx->wp; struct window_pane *wp = ctx->wp;
struct window_pane_resize *r, *r1;
if (wp != NULL && !options_get_number(wp->options, "alternate-screen")) if (wp != NULL && !options_get_number(wp->options, "alternate-screen"))
return; return;
screen_write_collect_flush(ctx, 0, __func__); 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) { 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); layout_fix_panes(wp->window, NULL);
server_redraw_window_borders(wp->window); server_redraw_window_borders(wp->window);
} }
@@ -2796,7 +2802,8 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
return; return;
screen_write_collect_flush(ctx, 0, __func__); 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) { if (wp != NULL) {
layout_fix_panes(wp->window, NULL); layout_fix_panes(wp->window, NULL);

View File

@@ -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 * Enter alternative screen mode. A copy of the visible screen is saved and the
* history is not updated. * history is not updated.
*/ */
void int
screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor) screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
{ {
u_int sx, sy; u_int sx, sy;
if (SCREEN_IS_ALTERNATE(s)) if (SCREEN_IS_ALTERNATE(s))
return; return 0;
sx = screen_size_x(s); sx = screen_size_x(s);
sy = screen_size_y(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->saved_flags = s->grid->flags;
s->grid->flags &= ~GRID_HISTORY; s->grid->flags &= ~GRID_HISTORY;
return 1;
} }
/* Exit alternate screen mode and restore the copied grid. */ /* Exit alternate screen mode and restore the copied grid. */
void int
screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor) screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
{ {
u_int sx = screen_size_x(s), sy = screen_size_y(s); 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; s->cx = screen_size_x(s) - 1;
if (s->cy > screen_size_y(s) - 1) if (s->cy > screen_size_y(s) - 1)
s->cy = screen_size_y(s) - 1; s->cy = screen_size_y(s) - 1;
return; return 0;
} }
/* Restore the saved grid. */ /* 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; s->cx = screen_size_x(s) - 1;
if (s->cy > screen_size_y(s) - 1) if (s->cy > screen_size_y(s) - 1)
s->cy = screen_size_y(s) - 1; s->cy = screen_size_y(s) - 1;
return 1;
} }
/* Get mode as a string. */ /* Get mode as a string. */

View File

@@ -1590,10 +1590,7 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
static void static void
server_client_check_pane_resize(struct window_pane *wp) server_client_check_pane_resize(struct window_pane *wp)
{ {
struct window_pane_resize *r; struct window_pane_resize *r, *r1, *first, *last;
struct window_pane_resize *r1;
struct window_pane_resize *first;
struct window_pane_resize *last;
struct timeval tv = { .tv_usec = 250000 }; struct timeval tv = { .tv_usec = 250000 };
if (TAILQ_EMPTY(&wp->resize_queue)) if (TAILQ_EMPTY(&wp->resize_queue))

6
tmux.h
View File

@@ -1147,6 +1147,8 @@ struct window_mode_entry {
struct screen *screen; struct screen *screen;
u_int prefix; u_int prefix;
int kill;
TAILQ_ENTRY(window_mode_entry) entry; 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_check_selection(struct screen *, u_int, u_int);
int screen_select_cell(struct screen *, struct grid_cell *, int screen_select_cell(struct screen *, struct grid_cell *,
const struct grid_cell *); const struct grid_cell *);
void screen_alternate_on(struct screen *, struct grid_cell *, int); int screen_alternate_on(struct screen *, struct grid_cell *, int);
void screen_alternate_off(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_mode_to_string(int);
const char *screen_print(struct screen *, int); const char *screen_print(struct screen *, int);