summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2020-06-05 11:20:51 +0000
committernicm <nicm>2020-06-05 11:20:51 +0000
commitd919fa1ed0ea3b167ffc811abba26a2dbcd20631 (patch)
tree58ff37d45126b5f3f99e2535820e58257f6a6528
parent03b2998abe7712324a1a2ca254167dcc1ce28e4d (diff)
Change how panes are resized so that the code is clearer and if the pane
is resized multiple times during one event loop, it is forced to resize at the end. Also don't zoom/unzoom in switch-client if the pane hasn't changed. GitHub issue 2260.
-rw-r--r--cmd-switch-client.c2
-rw-r--r--server-client.c124
-rw-r--r--tmux.h6
-rw-r--r--window.c26
4 files changed, 80 insertions, 78 deletions
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index d062b946..fc7f9d75 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -116,7 +116,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
} else {
if (cmdq_get_client(item) == NULL)
return (CMD_RETURN_NORMAL);
- if (wl != NULL && wp != NULL) {
+ if (wl != NULL && wp != NULL && wp != wl->window->active) {
w = wl->window;
if (window_push_zoom(w, args_has(args, 'Z')))
server_redraw_window(w);
diff --git a/server-client.c b/server-client.c
index 1a02a240..89275caf 100644
--- a/server-client.c
+++ b/server-client.c
@@ -45,7 +45,6 @@ static void server_client_check_redraw(struct client *);
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_resize_event(int, short, void *);
static void server_client_dispatch(struct imsg *, void *);
static void server_client_dispatch_command(struct client *, struct imsg *);
@@ -1403,50 +1402,14 @@ server_client_check_window_resize(struct window *w)
resize_window(w, w->new_sx, w->new_sy, w->new_xpixel, w->new_ypixel);
}
-/* Check if we need to force a resize. */
-static int
-server_client_resize_force(struct window_pane *wp)
-{
- struct timeval tv = { .tv_usec = 100000 };
-
- /*
- * If we are resizing to the same size as when we entered the loop
- * (that is, to the same size the application currently thinks it is),
- * tmux may have gone through several resizes internally and thrown
- * away parts of the screen. So we need the application to actually
- * redraw even though its final size has not changed.
- */
-
- if (wp->flags & PANE_RESIZEFORCE) {
- wp->flags &= ~PANE_RESIZEFORCE;
- return (0);
- }
-
- if (wp->sx != wp->osx ||
- wp->sy != wp->osy ||
- wp->sx <= 1 ||
- wp->sy <= 1)
- return (0);
-
- log_debug("%s: %%%u forcing resize", __func__, wp->id);
- window_pane_send_resize(wp, -1);
-
- evtimer_add(&wp->resize_timer, &tv);
- wp->flags |= PANE_RESIZEFORCE;
- return (1);
-}
-
-/* Resize a pane. */
+/* Resize timer event. */
static void
-server_client_resize_pane(struct window_pane *wp)
+server_client_resize_timer(__unused int fd, __unused short events, void *data)
{
- log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, wp->sy);
- window_pane_send_resize(wp, 0);
-
- wp->flags &= ~PANE_RESIZE;
+ struct window_pane *wp = data;
- wp->osx = wp->sx;
- wp->osy = wp->sy;
+ log_debug("%s: %%%u resize timer expired", __func__, wp->id);
+ evtimer_del(&wp->resize_timer);
}
/* Start the resize timer. */
@@ -1455,49 +1418,74 @@ 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);
+ log_debug("%s: %%%u resize timer started", __func__, wp->id);
+ evtimer_add(&wp->resize_timer, &tv);
}
-/* Resize timer event. */
+/* Force timer event. */
static void
-server_client_resize_event(__unused int fd, __unused short events, void *data)
+server_client_force_timer(__unused int fd, __unused short events, void *data)
{
struct window_pane *wp = data;
- evtimer_del(&wp->resize_timer);
+ log_debug("%s: %%%u force timer expired", __func__, wp->id);
+ evtimer_del(&wp->force_timer);
+ wp->flags |= PANE_RESIZENOW;
+}
- 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->base.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;
+/* 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. */
static void
server_client_check_pane_resize(struct window_pane *wp)
{
+ if (!event_initialized(&wp->resize_timer))
+ evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
+ if (!event_initialized(&wp->force_timer))
+ evtimer_set(&wp->force_timer, server_client_force_timer, wp);
+
if (~wp->flags & PANE_RESIZE)
return;
+ log_debug("%s: %%%u needs to be resized", __func__, wp->id);
- if (!event_initialized(&wp->resize_timer))
- evtimer_set(&wp->resize_timer, server_client_resize_event, wp);
+ if (evtimer_pending(&wp->resize_timer, NULL)) {
+ log_debug("%s: %%%u resize timer is running", __func__, wp->id);
+ return;
+ }
+ server_client_start_resize_timer(wp);
- 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);
+ if (~wp->flags & PANE_RESIZEFORCE) {
+ /*
+ * The timer is not running and we don't need to force a
+ * resize, so just resize immediately.
+ */
+ log_debug("%s: resizing %%%u now", __func__, wp->id);
+ window_pane_send_resize(wp, 0);
+ wp->flags &= ~PANE_RESIZE;
+ } else {
+ /*
+ * The timer is not running, but we need to force a resize. If
+ * the force timer has expired, resize to the real size now.
+ * Otherwise resize to the force size and start the timer.
+ */
+ if (wp->flags & PANE_RESIZENOW) {
+ log_debug("%s: resizing %%%u after forced resize", __func__, wp->id);
+ window_pane_send_resize(wp, 0);
+ wp->flags &= ~(PANE_RESIZE|PANE_RESIZEFORCE|PANE_RESIZENOW);
+ } else if (!evtimer_pending(&wp->force_timer, NULL)) {
+ log_debug("%s: forcing resize of %%%u", __func__, wp->id);
+ window_pane_send_resize(wp, 1);
+ server_client_start_force_timer(wp);
+ }
+ }
}
/* Check pane buffer size. */
diff --git a/tmux.h b/tmux.h
index 0681100f..df63321d 100644
--- a/tmux.h
+++ b/tmux.h
@@ -928,9 +928,6 @@ struct window_pane {
u_int sx;
u_int sy;
- u_int osx;
- u_int osy;
-
u_int xoff;
u_int yoff;
@@ -951,7 +948,7 @@ struct window_pane {
#define PANE_STATUSDRAWN 0x400
#define PANE_EMPTY 0x800
#define PANE_STYLECHANGED 0x1000
-#define PANE_RESIZED 0x2000
+#define PANE_RESIZENOW 0x2000
int argc;
char **argv;
@@ -969,6 +966,7 @@ struct window_pane {
size_t base_offset;
struct event resize_timer;
+ struct event force_timer;
struct input_ctx *ictx;
diff --git a/window.c b/window.c
index 020ae4bf..523e9913 100644
--- a/window.c
+++ b/window.c
@@ -436,14 +436,21 @@ window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
}
void
-window_pane_send_resize(struct window_pane *wp, int yadjust)
+window_pane_send_resize(struct window_pane *wp, int force)
{
struct window *w = wp->window;
struct winsize ws;
- u_int sy = wp->sy + yadjust;
+ u_int sy;
if (wp->fd == -1)
return;
+
+ if (!force)
+ 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);
@@ -877,8 +884,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->xoff = 0;
wp->yoff = 0;
- wp->sx = wp->osx = sx;
- wp->sy = wp->osx = sy;
+ wp->sx = sx;
+ wp->sy = sy;
wp->pipe_fd = -1;
wp->pipe_event = NULL;
@@ -918,6 +925,8 @@ window_pane_destroy(struct window_pane *wp)
if (event_initialized(&wp->resize_timer))
event_del(&wp->resize_timer);
+ if (event_initialized(&wp->force_timer))
+ event_del(&wp->force_timer);
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
@@ -998,7 +1007,14 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
wme = TAILQ_FIRST(&wp->modes);
if (wme != NULL && wme->mode->resize != NULL)
wme->mode->resize(wme, sx, sy);
- wp->flags |= (PANE_RESIZE|PANE_RESIZED);
+
+ /*
+ * 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