diff --git a/server-client.c b/server-client.c index f61cfa38..311b2d3b 100644 --- a/server-client.c +++ b/server-client.c @@ -763,11 +763,13 @@ server_client_loop(void) } } -/* Check if pane should be resized. */ -void -server_client_check_resize(struct window_pane *wp) +static void +server_client_resize_event(__unused int fd, __unused short events, void *data) { - struct winsize ws; + struct window_pane *wp = data; + struct winsize ws; + + evtimer_del(&wp->resize_timer); if (!(wp->flags & PANE_RESIZE)) return; @@ -792,6 +794,36 @@ server_client_check_resize(struct window_pane *wp) wp->flags &= ~PANE_RESIZE; } +/* Check if pane should be resized. */ +void +server_client_check_resize(struct window_pane *wp) +{ + struct timeval tv = { .tv_usec = 250000 }; + + if (!(wp->flags & PANE_RESIZE)) + return; + + if (!event_initialized(&wp->resize_timer)) + evtimer_set(&wp->resize_timer, server_client_resize_event, wp); + + /* + * The first resize should happen immediately, so if the timer is not + * running, do it now. + */ + if (!evtimer_pending(&wp->resize_timer, NULL)) + server_client_resize_event(-1, 0, wp); + + /* + * If the pane is in the alternate screen, let the timer expire and + * resize to give the application a chance to redraw. If not, keep + * pushing the timer back. + */ + if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL)) + return; + evtimer_del(&wp->resize_timer); + evtimer_add(&wp->resize_timer, &tv); +} + /* Check whether pane should be focused. */ void server_client_check_focus(struct window_pane *wp) diff --git a/tmux.h b/tmux.h index b745f863..995e310f 100644 --- a/tmux.h +++ b/tmux.h @@ -896,6 +896,8 @@ struct window_pane { int fd; struct bufferevent *event; + struct event resize_timer; + u_int wmark_size; u_int wmark_hits; diff --git a/window.c b/window.c index b40f9fe1..d91e52bf 100644 --- a/window.c +++ b/window.c @@ -806,6 +806,9 @@ window_pane_destroy(struct window_pane *wp) close(wp->pipe_fd); } + if (event_initialized(&wp->resize_timer)) + event_del(&wp->resize_timer); + RB_REMOVE(window_pane_tree, &all_window_panes, wp); free((void *)wp->cwd);