mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
00471dc783
@ -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)
|
||||
|
20
format.c
20
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. */
|
||||
|
16
input.c
16
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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
27
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"
|
||||
|
22
tmux.h
22
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 **);
|
||||
|
26
tty.c
26
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;
|
||||
|
82
window.c
82
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,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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user