summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server-client.c48
-rw-r--r--server-window.c36
-rw-r--r--tmux.h7
-rw-r--r--tty.c4
4 files changed, 56 insertions, 39 deletions
diff --git a/server-client.c b/server-client.c
index b8ccbeff..059a5c89 100644
--- a/server-client.c
+++ b/server-client.c
@@ -492,6 +492,50 @@ server_client_check_exit(struct client *c)
c->flags &= ~CLIENT_EXIT;
}
+/*
+ * Check if the client should backoff. During backoff, data from external
+ * programs is not written to the terminal. When the existing data drains, the
+ * client is redrawn.
+ *
+ * There are two backoff phases - both the tty and client have backoff flags -
+ * the first to allow existing data to drain and the latter to ensure backoff
+ * is disabled until the redraw has finished and prevent the redraw triggering
+ * another backoff.
+ */
+void
+server_client_check_backoff(struct client *c)
+{
+ struct tty *tty = &c->tty;
+ size_t used;
+
+ used = EVBUFFER_LENGTH(tty->event->output);
+
+ /*
+ * If in the second backoff phase (redrawing), don't check backoff
+ * until the redraw has completed (or enough of it to drop below the
+ * backoff threshold).
+ */
+ if (c->flags & CLIENT_BACKOFF) {
+ if (used > BACKOFF_THRESHOLD)
+ return;
+ c->flags &= ~CLIENT_BACKOFF;
+ return;
+ }
+
+ /* Once drained, allow data through again and schedule redraw. */
+ if (tty->flags & TTY_BACKOFF) {
+ if (used != 0)
+ return;
+ tty->flags &= ~TTY_BACKOFF;
+ c->flags |= (CLIENT_BACKOFF|CLIENT_REDRAWWINDOW|CLIENT_STATUS);
+ return;
+ }
+
+ /* If too much data, start backoff. */
+ if (used > BACKOFF_THRESHOLD)
+ tty->flags |= TTY_BACKOFF;
+}
+
/* Check for client redraws. */
void
server_client_check_redraw(struct client *c)
@@ -520,6 +564,10 @@ server_client_check_redraw(struct client *c)
if (c->flags & CLIENT_REDRAW) {
screen_redraw_screen(c, 0, 0);
c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
+ } else if (c->flags & CLIENT_REDRAWWINDOW) {
+ TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry)
+ screen_redraw_pane(c, wp);
+ c->flags &= ~CLIENT_REDRAWWINDOW;
} else {
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
if (wp->flags & PANE_REDRAW)
diff --git a/server-window.c b/server-window.c
index f8bf27d8..634a1b8a 100644
--- a/server-window.c
+++ b/server-window.c
@@ -29,31 +29,6 @@ int server_window_check_activity(struct session *, struct winlink *);
int server_window_check_content(
struct session *, struct winlink *, struct window_pane *);
-/* Check if this window should suspend reading. */
-int
-server_window_backoff(struct window_pane *wp)
-{
- struct client *c;
- u_int i;
-
- if (!window_pane_visible(wp))
- return (0);
-
- for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
- c = ARRAY_ITEM(&clients, i);
- if (c == NULL || c->session == NULL)
- continue;
- if ((c->flags & (CLIENT_SUSPENDED|CLIENT_DEAD)) != 0)
- continue;
- if (c->session->curw->window != wp->window)
- continue;
-
- if (EVBUFFER_LENGTH(c->tty.event->output) > BACKOFF_THRESHOLD)
- return (1);
- }
- return (0);
-}
-
/* Window functions that need to happen every loop. */
void
server_window_loop(void)
@@ -69,17 +44,6 @@ server_window_loop(void)
if (w == NULL)
continue;
- TAILQ_FOREACH(wp, &w->panes, entry) {
- if (wp->fd == -1)
- continue;
- if (!(wp->flags & PANE_FREEZE)) {
- if (server_window_backoff(wp))
- bufferevent_disable(wp->event, EV_READ);
- else
- bufferevent_enable(wp->event, EV_READ);
- }
- }
-
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
s = ARRAY_ITEM(&sessions, j);
if (s == NULL)
diff --git a/tmux.h b/tmux.h
index e1cd0b7e..af731ff7 100644
--- a/tmux.h
+++ b/tmux.h
@@ -59,8 +59,8 @@ extern char **environ;
/* Automatic name refresh interval, in milliseconds. */
#define NAME_INTERVAL 500
-/* Maximum data to buffer for output before suspending reading from panes. */
-#define BACKOFF_THRESHOLD 1024
+/* Maximum data to buffer for output before suspending writing to a tty. */
+#define BACKOFF_THRESHOLD 16384
/*
* Maximum sizes of strings in message data. Don't forget to bump
@@ -1017,6 +1017,7 @@ struct tty {
#define TTY_UTF8 0x8
#define TTY_STARTED 0x10
#define TTY_OPENED 0x20
+#define TTY_BACKOFF 0x40
int flags;
int term_flags;
@@ -1126,6 +1127,8 @@ struct client {
#define CLIENT_DEAD 0x200
#define CLIENT_BORDERS 0x400
#define CLIENT_READONLY 0x800
+#define CLIENT_BACKOFF 0x1000
+#define CLIENT_REDRAWWINDOW 0x2000
int flags;
struct event identify_timer;
diff --git a/tty.c b/tty.c
index fa2cd552..bf0a48b0 100644
--- a/tty.c
+++ b/tty.c
@@ -578,7 +578,9 @@ tty_write(void (*cmdfn)(
continue;
if (c->session->curw->window == wp->window) {
- if (c->tty.flags & TTY_FREEZE || c->tty.term == NULL)
+ if (c->tty.term == NULL)
+ continue;
+ if (c->tty.flags & (TTY_FREEZE|TTY_BACKOFF))
continue;
cmdfn(&c->tty, ctx);
}