Merge branch 'obsd-master'

pull/1/head
Thomas Adam 2015-05-13 09:44:11 +01:00
commit 00471dc783
9 changed files with 139 additions and 131 deletions

View File

@ -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)

View File

@ -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. */

16
input.c
View File

@ -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;
@ -1113,15 +1112,6 @@ input_c0_dispatch(struct input_ctx *ictx)
break;
}
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);
}

View File

@ -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

View File

@ -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);
}

27
tmux.1
View File

@ -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"

22
tmux.h
View File

@ -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 **);

26
tty.c
View File

@ -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;

View File

@ -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,64 +885,53 @@ 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);
return (0);
}
void
window_pane_timer_start(struct window_pane *wp)
{
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);
}
void
window_pane_timer_callback(unused int fd, unused short events, void *data)
{
struct window_pane *wp = data;
struct window *w = wp->window;
u_int interval, trigger;
interval = options_get_number(&w->options, "c0-change-interval");
trigger = options_get_number(&w->options, "c0-change-trigger");
if (wp->changes_redraw++ == interval) {
wp->flags |= PANE_REDRAW;
wp->changes_redraw = 0;
}
if (trigger == 0 || wp->changes < trigger) {
wp->flags |= PANE_REDRAW;
wp->flags &= ~PANE_DROP;
} else
window_pane_timer_start(wp);
wp->changes = 0;
window_pane_read_callback(NULL, data);
}
void
window_pane_read_callback(unused struct bufferevent *bufev, void *data)
{
struct window_pane *wp = data;
char *new_data;
size_t new_size;
struct window_pane *wp = data;
struct evbuffer *evb = wp->event->input;
char *new_data;
size_t new_size, available;
struct client *c;
struct timeval tv;
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
if (event_initialized(&wp->timer))
evtimer_del(&wp->timer);
log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb));
TAILQ_FOREACH(c, &clients, entry) {
if (!tty_client_ready(c, wp))
continue;
available = EVBUFFER_LENGTH(c->tty.event->output);
if (available > READ_BACKOFF)
goto start_timer;
}
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;