The resize event was never deciding to actually resize the pane if there

was output in the pane faster than the timer would fire, so change how
it works to only defer the timer again if the pane was actually resized
within the last timer period. Reported by James Tai in GitHub issue
1880.
pull/1891/head
nicm 2019-08-28 07:34:32 +00:00
parent 39c55d5b6f
commit df0334d3b3
3 changed files with 46 additions and 32 deletions

View File

@ -44,6 +44,7 @@ static void server_client_set_title(struct client *);
static void server_client_reset_state(struct client *);
static int server_client_assume_paste(struct session *);
static void server_client_clear_overlay(struct client *);
static void server_client_resize_event(int, short, void *);
static void server_client_dispatch(struct imsg *, void *);
static void server_client_dispatch_command(struct client *, struct imsg *);
@ -1319,19 +1320,11 @@ server_client_resize_force(struct window_pane *wp)
return (1);
}
/* Resize timer event. */
/* Resize a pane. */
static void
server_client_resize_event(__unused int fd, __unused short events, void *data)
server_client_resize_pane(struct window_pane *wp)
{
struct window_pane *wp = data;
struct winsize ws;
evtimer_del(&wp->resize_timer);
if (!(wp->flags & PANE_RESIZE))
return;
if (server_client_resize_force(wp))
return;
struct winsize ws;
memset(&ws, 0, sizeof ws);
ws.ws_col = wp->sx;
@ -1346,35 +1339,55 @@ server_client_resize_event(__unused int fd, __unused short events, void *data)
wp->osy = wp->sy;
}
/* Start the resize timer. */
static void
server_client_start_resize_timer(struct window_pane *wp)
{
struct timeval tv = { .tv_usec = 250000 };
if (!evtimer_pending(&wp->resize_timer, NULL))
evtimer_add(&wp->resize_timer, &tv);
}
/* Resize timer event. */
static void
server_client_resize_event(__unused int fd, __unused short events, void *data)
{
struct window_pane *wp = data;
evtimer_del(&wp->resize_timer);
if (~wp->flags & PANE_RESIZE)
return;
log_debug("%s: %%%u timer fired (was%s resized)", __func__, wp->id,
(wp->flags & PANE_RESIZED) ? "" : " not");
if (wp->saved_grid == NULL && (wp->flags & PANE_RESIZED)) {
log_debug("%s: %%%u deferring timer", __func__, wp->id);
server_client_start_resize_timer(wp);
} else if (!server_client_resize_force(wp)) {
log_debug("%s: %%%u resizing pane", __func__, wp->id);
server_client_resize_pane(wp);
}
wp->flags &= ~PANE_RESIZED;
}
/* Check if pane should be resized. */
static void
server_client_check_resize(struct window_pane *wp)
{
struct timeval tv = { .tv_usec = 250000 };
if (!(wp->flags & PANE_RESIZE))
if (~wp->flags & PANE_RESIZE)
return;
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy);
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);
if (!evtimer_pending(&wp->resize_timer, NULL)) {
log_debug("%s: %%%u starting timer", __func__, wp->id);
server_client_resize_pane(wp);
server_client_start_resize_timer(wp);
} else
log_debug("%s: %%%u timer running", __func__, wp->id);
}
/* Check whether pane should be focused. */

1
tmux.h
View File

@ -843,6 +843,7 @@ struct window_pane {
#define PANE_STATUSDRAWN 0x400
#define PANE_EMPTY 0x800
#define PANE_STYLECHANGED 0x1000
#define PANE_RESIZED 0x2000
int argc;
char **argv;

View File

@ -953,7 +953,7 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
if (wme != NULL && wme->mode->resize != NULL)
wme->mode->resize(wme, sx, sy);
wp->flags |= PANE_RESIZE;
wp->flags |= (PANE_RESIZE|PANE_RESIZED);
}
/*