mirror of
https://github.com/tmux/tmux.git
synced 2024-12-12 17:38:48 +00:00
Change resize timers and flags into one timer and a queue to fix problems with
vim when resized multiple times. GitHub issue 2677.
This commit is contained in:
parent
ce8c56cc97
commit
cf6034da92
117
server-client.c
117
server-client.c
@ -1447,84 +1447,79 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
|
|||||||
evtimer_del(&wp->resize_timer);
|
evtimer_del(&wp->resize_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the resize timer. */
|
|
||||||
static void
|
|
||||||
server_client_start_resize_timer(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct timeval tv = { .tv_usec = 250000 };
|
|
||||||
|
|
||||||
log_debug("%s: %%%u resize timer started", __func__, wp->id);
|
|
||||||
evtimer_add(&wp->resize_timer, &tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Force timer event. */
|
|
||||||
static void
|
|
||||||
server_client_force_timer(__unused int fd, __unused short events, void *data)
|
|
||||||
{
|
|
||||||
struct window_pane *wp = data;
|
|
||||||
|
|
||||||
log_debug("%s: %%%u force timer expired", __func__, wp->id);
|
|
||||||
evtimer_del(&wp->force_timer);
|
|
||||||
wp->flags |= PANE_RESIZENOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start the force timer. */
|
|
||||||
static void
|
|
||||||
server_client_start_force_timer(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct timeval tv = { .tv_usec = 10000 };
|
|
||||||
|
|
||||||
log_debug("%s: %%%u force timer started", __func__, wp->id);
|
|
||||||
evtimer_add(&wp->force_timer, &tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if pane should be resized. */
|
/* Check if pane should be resized. */
|
||||||
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 *r1;
|
||||||
|
struct window_pane_resize *first;
|
||||||
|
struct window_pane_resize *last;
|
||||||
|
struct timeval tv = { .tv_usec = 250000 };
|
||||||
|
|
||||||
|
if (TAILQ_EMPTY(&wp->resize_queue))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!event_initialized(&wp->resize_timer))
|
if (!event_initialized(&wp->resize_timer))
|
||||||
evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
|
evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
|
||||||
if (!event_initialized(&wp->force_timer))
|
if (evtimer_pending(&wp->resize_timer, NULL))
|
||||||
evtimer_set(&wp->force_timer, server_client_force_timer, wp);
|
|
||||||
|
|
||||||
if (~wp->flags & PANE_RESIZE)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_debug("%s: %%%u needs to be resized", __func__, wp->id);
|
log_debug("%s: %%%u needs to be resized", __func__, wp->id);
|
||||||
|
TAILQ_FOREACH(r, &wp->resize_queue, entry) {
|
||||||
if (evtimer_pending(&wp->resize_timer, NULL)) {
|
log_debug("queued resize: %ux%u -> %ux%u", r->osx, r->osy,
|
||||||
log_debug("%s: %%%u resize timer is running", __func__, wp->id);
|
r->sx, r->sy);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
server_client_start_resize_timer(wp);
|
|
||||||
|
|
||||||
if (~wp->flags & PANE_RESIZEFORCE) {
|
/*
|
||||||
/*
|
* There are three cases that matter:
|
||||||
* The timer is not running and we don't need to force a
|
*
|
||||||
* resize, so just resize immediately.
|
* - Only one resize. It can just be applied.
|
||||||
*/
|
*
|
||||||
log_debug("%s: resizing %%%u now", __func__, wp->id);
|
* - Multiple resizes and the ending size is different from the
|
||||||
window_pane_send_resize(wp, 0);
|
* starting size. We can discard all resizes except the most recent.
|
||||||
wp->flags &= ~PANE_RESIZE;
|
*
|
||||||
|
* - Multiple resizes and the ending size is the same as the starting
|
||||||
|
* size. We must resize at least twice to force the application to
|
||||||
|
* redraw. So apply the first and leave the last on the queue for
|
||||||
|
* next time.
|
||||||
|
*/
|
||||||
|
first = TAILQ_FIRST(&wp->resize_queue);
|
||||||
|
last = TAILQ_LAST(&wp->resize_queue, window_pane_resizes);
|
||||||
|
if (first == last) {
|
||||||
|
/* Only one resize. */
|
||||||
|
window_pane_send_resize(wp, first->sx, first->sy);
|
||||||
|
TAILQ_REMOVE(&wp->resize_queue, first, entry);
|
||||||
|
free(first);
|
||||||
|
} else if (last->sx != first->osx || last->sy != first->osy) {
|
||||||
|
/* Multiple resizes ending up with a different size. */
|
||||||
|
window_pane_send_resize(wp, last->sx, last->sy);
|
||||||
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
|
free(r);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* The timer is not running, but we need to force a resize. If
|
* Multiple resizes ending up with the same size. There will
|
||||||
* the force timer has expired, resize to the real size now.
|
* not be more than one to the same size in succession so we
|
||||||
* Otherwise resize to the force size and start the timer.
|
* can just use the last-but-one on the list and leave the last
|
||||||
|
* for later. We reduce the time until the next check to avoid
|
||||||
|
* a long delay between the resizes.
|
||||||
*/
|
*/
|
||||||
if (wp->flags & PANE_RESIZENOW) {
|
r = TAILQ_PREV(last, window_pane_resizes, entry);
|
||||||
log_debug("%s: resizing %%%u after forced resize",
|
window_pane_send_resize(wp, r->sx, r->sy);
|
||||||
__func__, wp->id);
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
window_pane_send_resize(wp, 0);
|
if (r == last)
|
||||||
wp->flags &= ~(PANE_RESIZE|PANE_RESIZEFORCE|PANE_RESIZENOW);
|
break;
|
||||||
} else if (!evtimer_pending(&wp->force_timer, NULL)) {
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
log_debug("%s: forcing resize of %%%u", __func__,
|
free(r);
|
||||||
wp->id);
|
|
||||||
window_pane_send_resize(wp, 1);
|
|
||||||
server_client_start_force_timer(wp);
|
|
||||||
}
|
}
|
||||||
|
tv.tv_usec = 10000;
|
||||||
}
|
}
|
||||||
|
evtimer_add(&wp->resize_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check pane buffer size. */
|
/* Check pane buffer size. */
|
||||||
static void
|
static void
|
||||||
server_client_check_pane_buffer(struct window_pane *wp)
|
server_client_check_pane_buffer(struct window_pane *wp)
|
||||||
|
25
tmux.h
25
tmux.h
@ -919,7 +919,7 @@ struct window_mode_entry {
|
|||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
u_int prefix;
|
u_int prefix;
|
||||||
|
|
||||||
TAILQ_ENTRY (window_mode_entry) entry;
|
TAILQ_ENTRY(window_mode_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Offsets into pane buffer. */
|
/* Offsets into pane buffer. */
|
||||||
@ -927,6 +927,18 @@ struct window_pane_offset {
|
|||||||
size_t used;
|
size_t used;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Queued pane resize. */
|
||||||
|
struct window_pane_resize {
|
||||||
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
|
|
||||||
|
u_int osx;
|
||||||
|
u_int osy;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(window_pane_resize) entry;
|
||||||
|
};
|
||||||
|
TAILQ_HEAD(window_pane_resizes, window_pane_resize);
|
||||||
|
|
||||||
/* Child window structure. */
|
/* Child window structure. */
|
||||||
struct window_pane {
|
struct window_pane {
|
||||||
u_int id;
|
u_int id;
|
||||||
@ -951,8 +963,8 @@ struct window_pane {
|
|||||||
#define PANE_REDRAW 0x1
|
#define PANE_REDRAW 0x1
|
||||||
#define PANE_DROP 0x2
|
#define PANE_DROP 0x2
|
||||||
#define PANE_FOCUSED 0x4
|
#define PANE_FOCUSED 0x4
|
||||||
#define PANE_RESIZE 0x8
|
/* 0x8 unused */
|
||||||
#define PANE_RESIZEFORCE 0x10
|
/* 0x10 unused */
|
||||||
#define PANE_FOCUSPUSH 0x20
|
#define PANE_FOCUSPUSH 0x20
|
||||||
#define PANE_INPUTOFF 0x40
|
#define PANE_INPUTOFF 0x40
|
||||||
#define PANE_CHANGED 0x80
|
#define PANE_CHANGED 0x80
|
||||||
@ -961,7 +973,6 @@ struct window_pane {
|
|||||||
#define PANE_STATUSDRAWN 0x400
|
#define PANE_STATUSDRAWN 0x400
|
||||||
#define PANE_EMPTY 0x800
|
#define PANE_EMPTY 0x800
|
||||||
#define PANE_STYLECHANGED 0x1000
|
#define PANE_STYLECHANGED 0x1000
|
||||||
#define PANE_RESIZENOW 0x2000
|
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
@ -978,8 +989,8 @@ struct window_pane {
|
|||||||
struct window_pane_offset offset;
|
struct window_pane_offset offset;
|
||||||
size_t base_offset;
|
size_t base_offset;
|
||||||
|
|
||||||
|
struct window_pane_resizes resize_queue;
|
||||||
struct event resize_timer;
|
struct event resize_timer;
|
||||||
struct event force_timer;
|
|
||||||
|
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
@ -997,7 +1008,7 @@ struct window_pane {
|
|||||||
struct screen status_screen;
|
struct screen status_screen;
|
||||||
size_t status_size;
|
size_t status_size;
|
||||||
|
|
||||||
TAILQ_HEAD (, window_mode_entry) modes;
|
TAILQ_HEAD(, window_mode_entry) modes;
|
||||||
|
|
||||||
char *searchstr;
|
char *searchstr;
|
||||||
int searchregex;
|
int searchregex;
|
||||||
@ -2756,7 +2767,7 @@ void window_redraw_active_switch(struct window *,
|
|||||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||||
u_int, int);
|
u_int, int);
|
||||||
void window_resize(struct window *, u_int, u_int, int, int);
|
void window_resize(struct window *, u_int, u_int, int, int);
|
||||||
void window_pane_send_resize(struct window_pane *, int);
|
void window_pane_send_resize(struct window_pane *, u_int, u_int);
|
||||||
int window_zoom(struct window_pane *);
|
int window_zoom(struct window_pane *);
|
||||||
int window_unzoom(struct window *);
|
int window_unzoom(struct window *);
|
||||||
int window_push_zoom(struct window *, int, int);
|
int window_push_zoom(struct window *, int, int);
|
||||||
|
51
window.c
51
window.c
@ -425,25 +425,18 @@ window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_send_resize(struct window_pane *wp, int force)
|
window_pane_send_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
{
|
{
|
||||||
struct window *w = wp->window;
|
struct window *w = wp->window;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
u_int sy;
|
|
||||||
|
|
||||||
if (wp->fd == -1)
|
if (wp->fd == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!force)
|
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, sx, sy);
|
||||||
sy = wp->sy;
|
|
||||||
else if (wp->sy <= 1)
|
|
||||||
sy = wp->sy + 1;
|
|
||||||
else
|
|
||||||
sy = wp->sy - 1;
|
|
||||||
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, sy);
|
|
||||||
|
|
||||||
memset(&ws, 0, sizeof ws);
|
memset(&ws, 0, sizeof ws);
|
||||||
ws.ws_col = wp->sx;
|
ws.ws_col = sx;
|
||||||
ws.ws_row = sy;
|
ws.ws_row = sy;
|
||||||
ws.ws_xpixel = w->xpixel * ws.ws_col;
|
ws.ws_xpixel = w->xpixel * ws.ws_col;
|
||||||
ws.ws_ypixel = w->ypixel * ws.ws_row;
|
ws.ws_ypixel = w->ypixel * ws.ws_row;
|
||||||
@ -867,29 +860,19 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
wp->id = next_window_pane_id++;
|
wp->id = next_window_pane_id++;
|
||||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||||
|
|
||||||
wp->argc = 0;
|
|
||||||
wp->argv = NULL;
|
|
||||||
wp->shell = NULL;
|
|
||||||
wp->cwd = NULL;
|
|
||||||
|
|
||||||
wp->fd = -1;
|
wp->fd = -1;
|
||||||
wp->event = NULL;
|
|
||||||
|
|
||||||
wp->fg = 8;
|
wp->fg = 8;
|
||||||
wp->bg = 8;
|
wp->bg = 8;
|
||||||
|
|
||||||
TAILQ_INIT(&wp->modes);
|
TAILQ_INIT(&wp->modes);
|
||||||
|
|
||||||
wp->layout_cell = NULL;
|
TAILQ_INIT (&wp->resize_queue);
|
||||||
|
|
||||||
wp->xoff = 0;
|
|
||||||
wp->yoff = 0;
|
|
||||||
|
|
||||||
wp->sx = sx;
|
wp->sx = sx;
|
||||||
wp->sy = sy;
|
wp->sy = sy;
|
||||||
|
|
||||||
wp->pipe_fd = -1;
|
wp->pipe_fd = -1;
|
||||||
wp->pipe_event = NULL;
|
|
||||||
|
|
||||||
screen_init(&wp->base, sx, sy, hlimit);
|
screen_init(&wp->base, sx, sy, hlimit);
|
||||||
wp->screen = &wp->base;
|
wp->screen = &wp->base;
|
||||||
@ -905,6 +888,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
static void
|
static void
|
||||||
window_pane_destroy(struct window_pane *wp)
|
window_pane_destroy(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
|
struct window_pane_resize *r;
|
||||||
|
struct window_pane_resize *r1;
|
||||||
|
|
||||||
window_pane_reset_mode_all(wp);
|
window_pane_reset_mode_all(wp);
|
||||||
free(wp->searchstr);
|
free(wp->searchstr);
|
||||||
|
|
||||||
@ -929,8 +915,10 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
if (event_initialized(&wp->resize_timer))
|
if (event_initialized(&wp->resize_timer))
|
||||||
event_del(&wp->resize_timer);
|
event_del(&wp->resize_timer);
|
||||||
if (event_initialized(&wp->force_timer))
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
event_del(&wp->force_timer);
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
|
free(r);
|
||||||
|
}
|
||||||
|
|
||||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||||
|
|
||||||
@ -999,9 +987,18 @@ void
|
|||||||
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme;
|
struct window_mode_entry *wme;
|
||||||
|
struct window_pane_resize *r;
|
||||||
|
|
||||||
if (sx == wp->sx && sy == wp->sy)
|
if (sx == wp->sx && sy == wp->sy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
r = xmalloc (sizeof *r);
|
||||||
|
r->sx = sx;
|
||||||
|
r->sy = sy;
|
||||||
|
r->osx = wp->sx;
|
||||||
|
r->osy = wp->sy;
|
||||||
|
TAILQ_INSERT_TAIL (&wp->resize_queue, r, entry);
|
||||||
|
|
||||||
wp->sx = sx;
|
wp->sx = sx;
|
||||||
wp->sy = sy;
|
wp->sy = sy;
|
||||||
|
|
||||||
@ -1011,14 +1008,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
wme = TAILQ_FIRST(&wp->modes);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
if (wme != NULL && wme->mode->resize != NULL)
|
if (wme != NULL && wme->mode->resize != NULL)
|
||||||
wme->mode->resize(wme, sx, sy);
|
wme->mode->resize(wme, sx, sy);
|
||||||
|
|
||||||
/*
|
|
||||||
* If the pane has already been resized, set the force flag and make
|
|
||||||
* the application resize twice to force it to redraw.
|
|
||||||
*/
|
|
||||||
if (wp->flags & PANE_RESIZE)
|
|
||||||
wp->flags |= PANE_RESIZEFORCE;
|
|
||||||
wp->flags |= PANE_RESIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user