From 8c8ce08d7927e6a83f0cb09388b2d1068fded529 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 18 Apr 2017 20:37:49 +0000 Subject: On terminals without DECSLRM, when a pane that is less than the full with of the terminal scrolls, tmux needs to redraw the entire pane. This results in a large amount of output data which can cause slow terminals to struggle, particularly when many lines are scrolled together quickly. This can be reduced by only redrawing when tmux doesn't hold any buffered data for the terminal. If a redraw is required and data is buffered, the redraw is deferred until all that data is consumed (it is checked after every event loop, a timer is used to ensure this happens at some point). While a redraw is pending, no additional data will be written to the terminal. The redraw still happens, now it is just pushed back if it is possible it would just add more data on top of a terminal that is already behind. This both gives the terminal a chance to catch up, and allows tmux to process more scrolling (that would require additional redraws) in the meantime. Helps with a problem reported by Greg Hurrell. --- server-client.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/server-client.c b/server-client.c index db8ba432..2279d43a 100644 --- a/server-client.c +++ b/server-client.c @@ -1201,6 +1201,14 @@ server_client_check_exit(struct client *c) c->flags &= ~CLIENT_EXIT; } +/* Redraw timer callback. */ +static void +server_client_redraw_timer(__unused int fd, __unused short events, + __unused void* data) +{ + log_debug("redraw timer fired"); +} + /* Check for client redraws. */ static void server_client_check_redraw(struct client *c) @@ -1208,11 +1216,53 @@ server_client_check_redraw(struct client *c) struct session *s = c->session; struct tty *tty = &c->tty; struct window_pane *wp; - int flags, masked; + int needed, flags, masked; + struct timeval tv = { .tv_usec = 1000 }; + static struct event ev; + size_t left; if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) return; + /* + * If there is outstanding data, defer the redraw until it has been + * consumed. We can just add a timer to get out of the event loop and + * end up back here. + */ + needed = 0; + if (c->flags & CLIENT_REDRAW) + needed = 1; + else { + TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { + if (wp->flags & PANE_REDRAW) { + needed = 1; + break; + } + } + } + if (needed) { + left = EVBUFFER_LENGTH(tty->out); + if (left != 0) { + log_debug("%s: redraw deferred (%zu left)", c->name, left); + if (evtimer_initialized(&ev) && evtimer_pending(&ev, NULL)) + return; + log_debug("redraw timer started"); + evtimer_set(&ev, server_client_redraw_timer, NULL); + evtimer_add(&ev, &tv); + + /* + * We may have got here for a single pane redraw, but + * force a full redraw next time in case other panes + * have been updated. + */ + c->flags |= CLIENT_REDRAW; + return; + } + if (evtimer_initialized(&ev)) + evtimer_del(&ev); + log_debug("%s: redraw needed", c->name); + } + if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { if (options_get_number(s->options, "set-titles")) server_client_set_title(c); -- cgit From f731ae4a2dc6aca565b20dffd6ddf661e585cbb5 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 18 Apr 2017 21:41:42 +0000 Subject: Revert use of DECSLRM on iTerm2, it doesn't help as much as we throught, and there are some question marks about it's support. --- tmux.h | 4 +--- tty-keys.c | 44 -------------------------------------------- tty.c | 4 ++-- 3 files changed, 3 insertions(+), 49 deletions(-) diff --git a/tmux.h b/tmux.h index 8933d356..3387798f 100644 --- a/tmux.h +++ b/tmux.h @@ -1071,7 +1071,6 @@ struct tty { TTY_VT220, TTY_VT320, TTY_VT420, - TTY_ITERM2, TTY_UNKNOWN } term_type; @@ -1086,8 +1085,7 @@ struct tty { struct tty_key *key_tree; }; #define TTY_TYPES \ - { "VT100", "VT101", "VT102", "VT220", "VT320", "VT420", "iTerm2", \ - "Unknown" } + { "VT100", "VT101", "VT102", "VT220", "VT320", "VT420", "Unknown" } /* TTY command context. */ struct tty_ctx { diff --git a/tty-keys.c b/tty-keys.c index 9cd61e19..a011fcab 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -46,8 +46,6 @@ static void tty_keys_callback(int, short, void *); static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *); static int tty_keys_device_attributes(struct tty *, const char *, size_t, size_t *); -static int tty_keys_iterm2_version(struct tty *, const char *, size_t, - size_t *); /* Default raw keys. */ struct tty_default_key_raw { @@ -555,17 +553,6 @@ tty_keys_next(struct tty *tty) goto partial_key; } - /* Or a response from iTerm2? */ - switch (tty_keys_iterm2_version(tty, buf, len, &size)) { - case 0: /* yes */ - key = KEYC_UNKNOWN; - goto complete_key; - case -1: /* no, or not valid */ - break; - case 1: /* partial */ - goto partial_key; - } - /* Is this a mouse key press? */ switch (tty_keys_mouse(tty, buf, len, &size)) { case 0: /* yes */ @@ -925,34 +912,3 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, types[type]); return (0); } - -/* - * Handle a version response from iTerm2. Returns 0 for success, -1 for - * failure, 1 for partial. - */ -static int -tty_keys_iterm2_version(struct tty *tty, const char *buf, size_t len, - size_t *size) -{ - struct client *c = tty->client; - u_int i; - - *size = 0; - - if (memcmp("\033[ITERM2 ", buf, (len > 9) ? 9 : len) != 0) - return (-1); - if (len < 10) - return (1); - for (i = 9; i < len; i++) { - if (buf[i] == 'n') - break; - } - if (i == len) - return (1); - *size = i + 1; - - tty_set_type(tty, TTY_ITERM2); - - log_debug("%s: this is iTerm2", c->name); - return (0); -} diff --git a/tty.c b/tty.c index 82fcbeba..73aeb91f 100644 --- a/tty.c +++ b/tty.c @@ -74,7 +74,7 @@ static void tty_default_attributes(struct tty *, const struct window_pane *, #define tty_use_acs(tty) \ (tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8)) #define tty_use_margin(tty) \ - ((tty)->term_type == TTY_VT420 || (tty)->term_type == TTY_ITERM2) + ((tty)->term_type == TTY_VT420) #define tty_pane_full_width(tty, ctx) \ ((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx) @@ -251,7 +251,7 @@ tty_start_tty(struct tty *tty) tty->flags |= TTY_FOCUS; tty_puts(tty, "\033[?1004h"); } - tty_puts(tty, "\033[c\033[1337n"); + tty_puts(tty, "\033[c"); } tty->flags |= TTY_STARTED; -- cgit