summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2015-05-13 09:44:11 +0100
committerThomas Adam <thomas@xteddy.org>2015-05-13 09:44:11 +0100
commit00471dc78358bde092df65de5e2c375bf9be7437 (patch)
tree4db96614bbc7e70dcdeaa307a3280103beee2f9e
parent4165ed96f8f0c494c7bd4f793176e508b6b6581d (diff)
parent3f4ee98162cd5bb7000f93fec0e631e123b1281d (diff)
Merge branch 'obsd-master'
-rw-r--r--cmd-show-messages.c48
-rw-r--r--format.c20
-rw-r--r--input.c16
-rw-r--r--options-table.c18
-rw-r--r--server-window.c11
-rw-r--r--tmux.127
-rw-r--r--tmux.h22
-rw-r--r--tty.c26
-rw-r--r--window.c76
9 files changed, 136 insertions, 128 deletions
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index ccc11c92..681ff261 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -46,11 +46,11 @@ const struct cmd_entry cmd_server_info_entry = {
cmd_show_messages_exec
};
-void cmd_show_messages_server(struct cmd_q *);
-void cmd_show_messages_terminals(struct cmd_q *);
-void cmd_show_messages_jobs(struct cmd_q *);
+int cmd_show_messages_server(struct cmd_q *);
+int cmd_show_messages_terminals(struct cmd_q *, int);
+int cmd_show_messages_jobs(struct cmd_q *, int);
-void
+int
cmd_show_messages_server(struct cmd_q *cmdq)
{
char *tim;
@@ -62,10 +62,12 @@ cmd_show_messages_server(struct cmd_q *cmdq)
cmdq_print(cmdq, "socket path %s", socket_path);
cmdq_print(cmdq, "debug level %d", debug_level);
cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
+
+ return (1);
}
-void
-cmd_show_messages_terminals(struct cmd_q *cmdq)
+int
+cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
{
struct tty_term *term;
const struct tty_term_code_entry *ent;
@@ -75,8 +77,11 @@ cmd_show_messages_terminals(struct cmd_q *cmdq)
n = 0;
LIST_FOREACH(term, &tty_terms, entry) {
- cmdq_print(cmdq,
- "Terminal %u: %s [references=%u, flags=0x%x]:",
+ if (blank) {
+ cmdq_print(cmdq, "%s", "");
+ blank = 0;
+ }
+ cmdq_print(cmdq, "Terminal %u: %s [references=%u, flags=0x%x]:",
n, term->name, term->references, term->flags);
n++;
for (i = 0; i < NTTYCODE; i++) {
@@ -105,21 +110,26 @@ cmd_show_messages_terminals(struct cmd_q *cmdq)
}
}
}
+ return (n != 0);
}
-void
-cmd_show_messages_jobs(struct cmd_q *cmdq)
+int
+cmd_show_messages_jobs(struct cmd_q *cmdq, int blank)
{
struct job *job;
u_int n;
n = 0;
LIST_FOREACH(job, &all_jobs, lentry) {
- cmdq_print(cmdq,
- "Job %u: %s [fd=%d, pid=%d, status=%d]",
+ if (blank) {
+ cmdq_print(cmdq, "%s", "");
+ blank = 0;
+ }
+ cmdq_print(cmdq, "Job %u: %s [fd=%d, pid=%d, status=%d]",
n, job->cmd, job->fd, job->pid, job->status);
n++;
}
+ return (n != 0);
}
enum cmd_retval
@@ -129,23 +139,19 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c;
struct message_entry *msg;
char *tim;
- int done;
+ int done, blank;
- done = 0;
+ done = blank = 0;
if (args_has(args, 'I') || self->entry == &cmd_server_info_entry) {
- cmd_show_messages_server(cmdq);
+ blank = cmd_show_messages_server(cmdq);
done = 1;
}
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
- if (done)
- cmdq_print(cmdq, "%s", "");
- cmd_show_messages_terminals(cmdq);
+ blank = cmd_show_messages_terminals(cmdq, blank);
done = 1;
}
if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
- if (done)
- cmdq_print(cmdq, "%s", "");
- cmd_show_messages_jobs(cmdq);
+ cmd_show_messages_jobs(cmdq, blank);
done = 1;
}
if (done)
diff --git a/format.c b/format.c
index d045a253..e5f9d28c 100644
--- a/format.c
+++ b/format.c
@@ -495,6 +495,8 @@ format_defaults_session(struct format_tree *ft, struct session *s)
{
struct session_group *sg;
time_t t;
+ struct winlink *wl;
+ char alerts[256], tmp[16];
ft->s = s;
@@ -519,6 +521,24 @@ format_defaults_session(struct format_tree *ft, struct session *s)
format_add(ft, "session_attached", "%u", s->attached);
format_add(ft, "session_many_attached", "%d", s->attached > 1);
+
+ *alerts = '\0';
+ RB_FOREACH (wl, winlinks, &s->windows) {
+ if ((wl->flags & WINLINK_ALERTFLAGS) == 0)
+ continue;
+ snprintf(tmp, sizeof tmp, "%u", wl->idx);
+
+ if (*alerts != '\0')
+ strlcat(alerts, ",", sizeof alerts);
+ strlcat(alerts, tmp, sizeof alerts);
+ if (wl->flags & WINLINK_ACTIVITY)
+ strlcat(alerts, "#", sizeof alerts);
+ if (wl->flags & WINLINK_BELL)
+ strlcat(alerts, "!", sizeof alerts);
+ if (wl->flags & WINLINK_SILENCE)
+ strlcat(alerts, "~", sizeof alerts);
+ }
+ format_add(ft, "session_alerts", "%s", alerts);
}
/* Set default format keys for a client. */
diff --git a/input.c b/input.c
index 384ab45d..886d561d 100644
--- a/input.c
+++ b/input.c
@@ -1069,7 +1069,6 @@ input_c0_dispatch(struct input_ctx *ictx)
struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
- u_int trigger;
log_debug("%s: '%c", __func__, ictx->ch);
@@ -1081,7 +1080,7 @@ input_c0_dispatch(struct input_ctx *ictx)
break;
case '\010': /* BS */
screen_write_backspace(sctx);
- goto count_c0;
+ break;
case '\011': /* HT */
/* Don't tab beyond the end of the line. */
if (s->cx >= screen_size_x(s) - 1)
@@ -1098,10 +1097,10 @@ input_c0_dispatch(struct input_ctx *ictx)
case '\013': /* VT */
case '\014': /* FF */
screen_write_linefeed(sctx, 0);
- goto count_c0;
+ break;
case '\015': /* CR */
screen_write_carriagereturn(sctx);
- goto count_c0;
+ break;
case '\016': /* SO */
ictx->cell.set = 1;
break;
@@ -1114,15 +1113,6 @@ input_c0_dispatch(struct input_ctx *ictx)
}
return (0);
-
-count_c0:
- trigger = options_get_number(&wp->window->options, "c0-change-trigger");
- if (trigger != 0 && ++wp->changes >= trigger) {
- wp->flags |= PANE_DROP;
- window_pane_timer_start(wp);
- }
-
- return (0);
}
/* Execute escape sequence. */
diff --git a/options-table.c b/options-table.c
index 756931db..f4a4879a 100644
--- a/options-table.c
+++ b/options-table.c
@@ -48,7 +48,7 @@ const char *options_table_status_position_list[] = {
"top", "bottom", NULL
};
const char *options_table_bell_action_list[] = {
- "none", "any", "current", NULL
+ "none", "any", "current", "other", NULL
};
/* Server options. */
@@ -295,7 +295,7 @@ const struct options_table_entry session_options_table[] = {
{ .name = "set-titles-string",
.type = OPTIONS_TABLE_STRING,
- .default_str = "#S:#I:#W - \"#T\""
+ .default_str = "#S:#I:#W - \"#T\" #{session_alerts}"
},
{ .name = "status",
@@ -484,20 +484,6 @@ const struct options_table_entry window_options_table[] = {
"#{?pane_dead,[dead],}"
},
- { .name = "c0-change-trigger",
- .type = OPTIONS_TABLE_NUMBER,
- .default_num = 250,
- .minimum = 0,
- .maximum = USHRT_MAX
- },
-
- { .name = "c0-change-interval",
- .type = OPTIONS_TABLE_NUMBER,
- .default_num = 100,
- .minimum = 1,
- .maximum = USHRT_MAX
- },
-
{ .name = "clock-mode-colour",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 4
diff --git a/server-window.c b/server-window.c
index 4385dd90..1b3938d3 100644
--- a/server-window.c
+++ b/server-window.c
@@ -77,13 +77,18 @@ server_window_check_bell(struct session *s, struct winlink *wl)
if (c->session != s || c->flags & CLIENT_CONTROL)
continue;
if (!visual) {
- if (c->session->curw->window == w || action == BELL_ANY)
+ if ((action == BELL_CURRENT &&
+ c->session->curw->window == w) ||
+ (action == BELL_OTHER &&
+ c->session->curw->window != w) ||
+ action == BELL_ANY)
tty_bell(&c->tty);
continue;
}
- if (c->session->curw->window == w)
+ if (action == BELL_CURRENT && c->session->curw->window == w)
status_message_set(c, "Bell in current window");
- else if (action == BELL_ANY)
+ else if (action == BELL_ANY || (action == BELL_OTHER &&
+ c->session->curw->window != w))
status_message_set(c, "Bell in window %d", wl->idx);
}
diff --git a/tmux.1 b/tmux.1
index 6114b7d2..a987693e 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2379,16 +2379,18 @@ Set the base index from which an unused index should be searched when a new
window is created.
The default is zero.
.It Xo Ic bell-action
-.Op Ic any | none | current
+.Op Ic any | none | current | other
.Xc
Set action on window bell.
.Ic any
means a bell in any window linked to a session causes a bell in the current
window of that session,
.Ic none
-means all bells are ignored and
+means all bells are ignored,
.Ic current
-means only bells in windows other than the current window are ignored.
+means only bells in windows other than the current window are ignored and
+.Ic other
+means bells in the current window are ignored but not those in other windows.
.It Xo Ic bell-on-alert
.Op Ic on | off
.Xc
@@ -2890,24 +2892,6 @@ used when the
.Ic automatic-rename
option is enabled.
.Pp
-.It Ic c0-change-interval Ar interval
-.It Ic c0-change-trigger Ar trigger
-These two options configure a simple form of rate limiting for a pane.
-If
-.Nm
-sees more than
-.Ar trigger
-C0 sequences that modify the screen (for example, carriage returns, linefeeds
-or backspaces) in one millisecond, it will stop updating the pane immediately and
-instead redraw it entirely every
-.Ar interval
-milliseconds.
-This helps to prevent fast output (such as
-.Xr yes 1 )
-overwhelming the terminal.
-The default is a trigger of 250 and an interval of 100.
-A trigger of zero disables the rate limiting.
-.Pp
.It Ic clock-mode-colour Ar colour
Set clock colour.
.Pp
@@ -3325,6 +3309,7 @@ The following variables are available, where appropriate:
.It Li "pane_width" Ta "" Ta "Width of pane"
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
+.It Li "session_alerts" Ta "" Ta "List of window indexes with alerts"
.It Li "session_attached" Ta "" Ta "Number of clients session is attached to"
.It Li "session_activity" Ta "" Ta "Integer time of session last activity"
.It Li "session_activity_string" Ta "" Ta "String time of session last activity"
diff --git a/tmux.h b/tmux.h
index 725b915f..054a859a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -60,6 +60,16 @@ extern char **environ;
*/
#define UTF8_SIZE 9
+/*
+ * READ_SIZE is the maximum size of data to hold from a pty (the event high
+ * watermark). READ_BACKOFF is the amount of data waiting to be output to a tty
+ * before pty reads will be backed off. READ_TIME is how long to back off
+ * before the next read (in microseconds) if a tty is above READ_BACKOFF.
+ */
+#define READ_SIZE 1024
+#define READ_BACKOFF 512
+#define READ_TIME 100
+
/* Fatal errors. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
@@ -79,6 +89,7 @@ extern char **environ;
#define BELL_NONE 0
#define BELL_ANY 1
#define BELL_CURRENT 2
+#define BELL_OTHER 3
/* Special key codes. */
#define KEYC_NONE 0xfff
@@ -848,12 +859,9 @@ struct window_pane {
char tty[TTY_NAME_MAX];
int status;
- u_int changes;
- struct event changes_timer;
- u_int changes_redraw;
-
int fd;
struct bufferevent *event;
+ struct event timer;
struct input_ctx *ictx;
@@ -1602,8 +1610,9 @@ void tty_draw_line(struct tty *, const struct window_pane *, struct screen *,
int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
-void tty_write(
- void (*)(struct tty *, const struct tty_ctx *), struct tty_ctx *);
+void tty_write(void (*)(struct tty *, const struct tty_ctx *),
+ struct tty_ctx *);
+int tty_client_ready(struct client *, struct window_pane *wp);
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
void tty_cmd_cell(struct tty *, const struct tty_ctx *);
void tty_cmd_clearendofline(struct tty *, const struct tty_ctx *);
@@ -2111,7 +2120,6 @@ struct window_pane *window_pane_find_by_id_str(const char *);
struct window_pane *window_pane_find_by_id(u_int);
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
void window_pane_destroy(struct window_pane *);
-void window_pane_timer_start(struct window_pane *);
int window_pane_spawn(struct window_pane *, int, char **,
const char *, const char *, int, struct environ *,
struct termios *, char **);
diff --git a/tty.c b/tty.c
index a9f49c9b..a58ca937 100644
--- a/tty.c
+++ b/tty.c
@@ -723,9 +723,23 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
tty_update_mode(tty, tty->mode, s);
}
+int
+tty_client_ready(struct client *c, struct window_pane *wp)
+{
+ if (c->session == NULL || c->tty.term == NULL)
+ return (0);
+ if (c->flags & CLIENT_SUSPENDED)
+ return (0);
+ if (c->tty.flags & TTY_FREEZE)
+ return (0);
+ if (c->session->curw->window != wp->window)
+ return (0);
+ return (1);
+}
+
void
-tty_write(
- void (*cmdfn)(struct tty *, const struct tty_ctx *), struct tty_ctx *ctx)
+tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
+ struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
struct client *c;
@@ -740,13 +754,7 @@ tty_write(
return;
TAILQ_FOREACH(c, &clients, entry) {
- if (c->session == NULL || c->tty.term == NULL)
- continue;
- if (c->flags & CLIENT_SUSPENDED)
- continue;
- if (c->tty.flags & TTY_FREEZE)
- continue;
- if (c->session->curw->window != wp->window)
+ if (!tty_client_ready(c, wp))
continue;
ctx->xoff = wp->xoff;
diff --git a/window.c b/window.c
index e3925f4f..d07a813d 100644
--- a/window.c
+++ b/window.c
@@ -740,8 +740,8 @@ window_pane_destroy(struct window_pane *wp)
{
window_pane_reset_mode(wp);
- if (event_initialized(&wp->changes_timer))
- evtimer_del(&wp->changes_timer);
+ if (event_initialized(&wp->timer))
+ evtimer_del(&wp->timer);
if (wp->fd != -1) {
#ifdef HAVE_UTEMPTER
@@ -885,6 +885,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
window_pane_error_callback, wp);
+
+ bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
free(cmd);
@@ -892,57 +894,44 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
}
void
-window_pane_timer_start(struct window_pane *wp)
+window_pane_timer_callback(unused int fd, unused short events, void *data)
{
- struct timeval tv;
-
- tv.tv_sec = 0;
- tv.tv_usec = 1000;
-
- evtimer_del(&wp->changes_timer);
- evtimer_set(&wp->changes_timer, window_pane_timer_callback, wp);
- evtimer_add(&wp->changes_timer, &tv);
+ window_pane_read_callback(NULL, data);
}
void
-window_pane_timer_callback(unused int fd, unused short events, void *data)
+window_pane_read_callback(unused struct bufferevent *bufev, void *data)
{
struct window_pane *wp = data;
- struct window *w = wp->window;
- u_int interval, trigger;
+ struct evbuffer *evb = wp->event->input;
+ char *new_data;
+ size_t new_size, available;
+ struct client *c;
+ struct timeval tv;
- interval = options_get_number(&w->options, "c0-change-interval");
- trigger = options_get_number(&w->options, "c0-change-trigger");
+ if (event_initialized(&wp->timer))
+ evtimer_del(&wp->timer);
- if (wp->changes_redraw++ == interval) {
- wp->flags |= PANE_REDRAW;
- wp->changes_redraw = 0;
- }
+ log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb));
- if (trigger == 0 || wp->changes < trigger) {
- wp->flags |= PANE_REDRAW;
- wp->flags &= ~PANE_DROP;
- } else
- window_pane_timer_start(wp);
- wp->changes = 0;
-}
+ TAILQ_FOREACH(c, &clients, entry) {
+ if (!tty_client_ready(c, wp))
+ continue;
-void
-window_pane_read_callback(unused struct bufferevent *bufev, void *data)
-{
- struct window_pane *wp = data;
- char *new_data;
- size_t new_size;
+ available = EVBUFFER_LENGTH(c->tty.event->output);
+ if (available > READ_BACKOFF)
+ goto start_timer;
+ }
- new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
+ new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off;
if (wp->pipe_fd != -1 && new_size > 0) {
- new_data = EVBUFFER_DATA(wp->event->input);
+ new_data = EVBUFFER_DATA(evb);
bufferevent_write(wp->pipe_event, new_data, new_size);
}
input_parse(wp);
- wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
+ wp->pipe_off = EVBUFFER_LENGTH(evb);
/*
* If we get here, we're not outputting anymore, so set the silence
@@ -951,11 +940,22 @@ window_pane_read_callback(unused struct bufferevent *bufev, void *data)
wp->window->flags |= WINDOW_SILENCE;
if (gettimeofday(&wp->window->silence_timer, NULL) != 0)
fatal("gettimeofday failed.");
+ return;
+
+start_timer:
+ log_debug("%%%u backing off (%s %zu > %d)", wp->id, c->ttyname,
+ available, READ_BACKOFF);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = READ_TIME;
+
+ evtimer_set(&wp->timer, window_pane_timer_callback, wp);
+ evtimer_add(&wp->timer, &tv);
}
void
-window_pane_error_callback(
- unused struct bufferevent *bufev, unused short what, void *data)
+window_pane_error_callback(unused struct bufferevent *bufev, unused short what,
+ void *data)
{
struct window_pane *wp = data;