diff --git a/screen-write.c b/screen-write.c index a9dbe4501..9983c0709 100644 --- a/screen-write.c +++ b/screen-write.c @@ -146,7 +146,7 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c) if (wp->layout_cell == NULL) return (0); - if (wp->flags & (PANE_REDRAW|PANE_DROP)) + if (wp->flags & (PANE_REDRAW|PANE_DROP|PANE_REDRAWDEFER)) return (-1); if (c->flags & CLIENT_REDRAWWINDOW) { /* @@ -3017,6 +3017,7 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc, if (!TAILQ_EMPTY(&wp->resize_queue)) { window_pane_send_resize(wp, wp->sx, wp->sy); window_pane_clear_resizes(wp, NULL); + window_pane_defer_redraw(wp); } server_redraw_window_borders(wp->window); } diff --git a/server-client.c b/server-client.c index f170396ec..4715e2759 100644 --- a/server-client.c +++ b/server-client.c @@ -2245,6 +2245,18 @@ server_client_any_pane_redraw(struct client *c) return (0); } +static int +server_client_redraw_deferred(struct window *w) +{ + struct window_pane *wp; + + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp->flags & PANE_REDRAWDEFER) + return (1); + } + return (0); +} + /* Check for client redraws. */ static void server_client_check_redraw(struct client *c) @@ -2260,6 +2272,8 @@ server_client_check_redraw(struct client *c) if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) return; + if (server_client_redraw_deferred(w)) + return; if (c->flags & CLIENT_ALLREDRAWFLAGS) { log_debug("%s: redraw%s%s%s%s", c->name, (c->flags & CLIENT_REDRAWWINDOW) ? " window" : "", diff --git a/tmux.h b/tmux.h index 863a41eca..2deaaf767 100644 --- a/tmux.h +++ b/tmux.h @@ -1293,6 +1293,7 @@ struct window_pane { #define PANE_THEMECHANGED 0x2000 #define PANE_UNSEENCHANGES 0x4000 #define PANE_REDRAWSCROLLBAR 0x8000 +#define PANE_REDRAWDEFER 0x10000 u_int sb_slider_y; u_int sb_slider_h; @@ -1320,6 +1321,7 @@ struct window_pane { struct window_pane_resizes resize_queue; struct event resize_timer; + struct event redraw_timer; struct event sync_timer; struct input_ctx *ictx; @@ -3584,6 +3586,8 @@ int window_pane_destroy_ready(struct window_pane *); void window_pane_resize(struct window_pane *, u_int, u_int); void window_pane_clear_resizes(struct window_pane *, struct window_pane_resize *); +void window_pane_defer_redraw(struct window_pane *); +void window_pane_finish_redraw(struct window_pane *); int window_pane_set_mode(struct window_pane *, struct window_pane *, const struct window_mode *, struct cmd_find_state *, struct args *); diff --git a/window.c b/window.c index 341aefd4e..7415294e2 100644 --- a/window.c +++ b/window.c @@ -72,6 +72,7 @@ static struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); static void window_pane_destroy(struct window_pane *); static void window_pane_scrollbar_timer(int, short, void *); +static void window_pane_redraw_timer(int, short, void *); static void window_pane_full_size_offset(struct window_pane *wp, int *xoff, int *yoff, u_int *sx, u_int *sy); @@ -1234,6 +1235,8 @@ window_pane_destroy(struct window_pane *wp) if (event_initialized(&wp->resize_timer)) event_del(&wp->resize_timer); + if (event_initialized(&wp->redraw_timer)) + event_del(&wp->redraw_timer); if (event_initialized(&wp->sync_timer)) event_del(&wp->sync_timer); if (event_initialized(&wp->sb_auto_timer)) @@ -1261,6 +1264,9 @@ window_pane_read_callback(__unused struct bufferevent *bufev, void *data) char *new_data; size_t new_size; struct client *c; + int deferred; + + deferred = (wp->flags & PANE_REDRAWDEFER); if (wp->pipe_fd != -1) { new_data = window_pane_get_new_data(wp, wpo, &new_size); @@ -1276,6 +1282,8 @@ window_pane_read_callback(__unused struct bufferevent *bufev, void *data) control_write_output(c, wp); } input_parse_pane(wp); + if (deferred) + window_pane_finish_redraw(wp); bufferevent_disable(wp->event, EV_READ); } @@ -1320,6 +1328,35 @@ window_pane_clear_resizes(struct window_pane *wp, } } +static void +window_pane_redraw_timer(__unused int fd, __unused short events, void *arg) +{ + window_pane_finish_redraw(arg); +} + +void +window_pane_defer_redraw(struct window_pane *wp) +{ + struct timeval tv = { .tv_usec = 50000 }; + + wp->flags |= PANE_REDRAWDEFER; + if (!event_initialized(&wp->redraw_timer)) + evtimer_set(&wp->redraw_timer, window_pane_redraw_timer, wp); + evtimer_del(&wp->redraw_timer); + evtimer_add(&wp->redraw_timer, &tv); +} + +void +window_pane_finish_redraw(struct window_pane *wp) +{ + if (~wp->flags & PANE_REDRAWDEFER) + return; + evtimer_del(&wp->redraw_timer); + wp->flags &= ~PANE_REDRAWDEFER; + wp->flags |= PANE_REDRAW; + server_redraw_window(wp->window); +} + void window_pane_resize(struct window_pane *wp, u_int sx, u_int sy) {