Merge branch 'obsd-master'

pull/615/head
Thomas Adam 2016-10-19 12:01:11 +01:00
commit 28a31201d3
6 changed files with 179 additions and 134 deletions

248
alerts.c
View File

@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <event.h> #include <event.h>
#include <stdlib.h>
#include "tmux.h" #include "tmux.h"
@ -29,13 +30,16 @@ static int alerts_enabled(struct window *, int);
static void alerts_callback(int, short, void *); static void alerts_callback(int, short, void *);
static void alerts_reset(struct window *); static void alerts_reset(struct window *);
static void alerts_run_hook(struct session *, struct winlink *, int); static int alerts_check_all(struct window *);
static int alerts_check_all(struct session *, struct winlink *); static int alerts_check_bell(struct window *);
static int alerts_check_bell(struct session *, struct winlink *); static int alerts_check_activity(struct window *);
static int alerts_check_activity(struct session *, struct winlink *); static int alerts_check_silence(struct window *);
static int alerts_check_silence(struct session *, struct winlink *); static void printflike(2, 3) alerts_set_message(struct session *, const char *,
...);
static void alerts_ring_bell(struct session *); static void alerts_ring_bell(struct session *);
static TAILQ_HEAD(, window) alerts_list = TAILQ_HEAD_INITIALIZER(alerts_list);
static void static void
alerts_timer(__unused int fd, __unused short events, void *arg) alerts_timer(__unused int fd, __unused short events, void *arg)
{ {
@ -49,53 +53,28 @@ alerts_timer(__unused int fd, __unused short events, void *arg)
static void static void
alerts_callback(__unused int fd, __unused short events, __unused void *arg) alerts_callback(__unused int fd, __unused short events, __unused void *arg)
{ {
struct window *w; struct window *w, *w1;
struct session *s; int alerts;
struct winlink *wl;
int flags, alerts;
RB_FOREACH(w, windows, &windows) { TAILQ_FOREACH_SAFE(w, &alerts_list, alerts_entry, w1) {
RB_FOREACH(s, sessions, &sessions) { alerts = alerts_check_all(w);
RB_FOREACH(wl, winlinks, &s->windows) { log_debug("@%u alerts check, alerts %#x", w->id, alerts);
if (wl->window != w)
continue;
flags = w->flags;
alerts = alerts_check_all(s, wl); w->alerts_queued = 0;
TAILQ_REMOVE(&alerts_list, w, alerts_entry);
log_debug("%s:%d @%u alerts check, alerts %#x, " window_remove_ref(w);
"flags %#x", s->name, wl->idx, w->id,
alerts, flags);
}
}
} }
alerts_fired = 0; alerts_fired = 0;
} }
static void
alerts_run_hook(struct session *s, struct winlink *wl, int flags)
{
if (flags & WINDOW_BELL)
notify_winlink("alert-bell", s, wl);
if (flags & WINDOW_SILENCE)
notify_winlink("alert-silence", s, wl);
if (flags & WINDOW_ACTIVITY)
notify_winlink("alert-activity", s, wl);
}
static int static int
alerts_check_all(struct session *s, struct winlink *wl) alerts_check_all(struct window *w)
{ {
int alerts; int alerts;
alerts = alerts_check_bell(s, wl); alerts = alerts_check_bell(w);
alerts |= alerts_check_activity(s, wl); alerts |= alerts_check_activity(w);
alerts |= alerts_check_silence(s, wl); alerts |= alerts_check_silence(w);
if (alerts != 0) {
alerts_run_hook(s, wl, alerts);
server_status_session(s);
}
return (alerts); return (alerts);
} }
@ -105,7 +84,7 @@ alerts_check_session(struct session *s)
struct winlink *wl; struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows) RB_FOREACH(wl, winlinks, &s->windows)
alerts_check_all(s, wl); alerts_check_all(wl->window);
} }
static int static int
@ -163,6 +142,12 @@ alerts_queue(struct window *w, int flags)
log_debug("@%u alerts flags added %#x", w->id, flags); log_debug("@%u alerts flags added %#x", w->id, flags);
} }
if (!w->alerts_queued) {
w->alerts_queued = 1;
TAILQ_INSERT_TAIL(&alerts_list, w, alerts_entry);
w->references++;
}
if (!alerts_fired && alerts_enabled(w, flags)) { if (!alerts_fired && alerts_enabled(w, flags)) {
log_debug("alerts check queued (by @%u)", w->id); log_debug("alerts check queued (by @%u)", w->id);
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL); event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
@ -171,112 +156,157 @@ alerts_queue(struct window *w, int flags)
} }
static int static int
alerts_check_bell(struct session *s, struct winlink *wl) alerts_check_bell(struct window *w)
{ {
struct window *ws;
struct winlink *wl;
struct session *s;
struct client *c; struct client *c;
struct window *w = wl->window;
int action, visual; int action, visual;
if (!(w->flags & WINDOW_BELL)) if (~w->flags & WINDOW_BELL)
return (0);
if (s->curw != wl) {
wl->flags |= WINLINK_BELL;
w->flags &= ~WINDOW_BELL;
}
if (s->curw->window == w)
w->flags &= ~WINDOW_BELL;
action = options_get_number(s->options, "bell-action");
if (action == BELL_NONE)
return (0); return (0);
visual = options_get_number(s->options, "visual-bell"); TAILQ_FOREACH(wl, &w->winlinks, wentry)
TAILQ_FOREACH(c, &clients, entry) { wl->session->flags &= ~SESSION_ALERTED;
if (c->session != s || c->flags & CLIENT_CONTROL)
continue; TAILQ_FOREACH(wl, &w->winlinks, wentry) {
if (!visual) { if (wl->flags & WINLINK_BELL)
if ((action == BELL_CURRENT &&
c->session->curw->window == w) ||
(action == BELL_OTHER &&
c->session->curw->window != w) ||
action == BELL_ANY)
tty_putcode(&c->tty, TTYC_BEL);
continue; continue;
s = wl->session;
if (s->curw != wl) {
wl->flags |= WINLINK_BELL;
notify_winlink("alert-bell", s, wl);
}
if (s->flags & SESSION_ALERTED)
continue;
s->flags |= SESSION_ALERTED;
action = options_get_number(s->options, "bell-action");
if (action == BELL_NONE)
return (0);
visual = options_get_number(s->options, "visual-bell");
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s || c->flags & CLIENT_CONTROL)
continue;
ws = c->session->curw->window;
if (action == BELL_CURRENT && ws != w)
action = BELL_NONE;
if (action == BELL_OTHER && ws != w)
action = BELL_NONE;
if (!visual) {
if (action != BELL_NONE)
tty_putcode(&c->tty, TTYC_BEL);
continue;
}
if (action == BELL_CURRENT)
status_message_set(c, "Bell in current window");
else if (action != BELL_NONE) {
status_message_set(c, "Bell in window %d",
wl->idx);
}
} }
if (action == BELL_CURRENT && c->session->curw->window == w)
status_message_set(c, "Bell in current window");
else if (action == BELL_ANY || (action == BELL_OTHER &&
c->session->curw->window != w))
status_message_set(c, "Bell in window %d", wl->idx);
} }
return (WINDOW_BELL); return (WINDOW_BELL);
} }
static int static int
alerts_check_activity(struct session *s, struct winlink *wl) alerts_check_activity(struct window *w)
{ {
struct client *c; struct winlink *wl;
struct window *w = wl->window; struct session *s;
if (s->curw->window == w) if (~w->flags & WINDOW_ACTIVITY)
w->flags &= ~WINDOW_ACTIVITY;
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
return (0); return (0);
if (s->curw == wl)
return (0);
if (!options_get_number(w->options, "monitor-activity")) if (!options_get_number(w->options, "monitor-activity"))
return (0); return (0);
if (options_get_number(s->options, "bell-on-alert")) TAILQ_FOREACH(wl, &w->winlinks, wentry)
alerts_ring_bell(s); wl->session->flags &= ~SESSION_ALERTED;
wl->flags |= WINLINK_ACTIVITY;
if (options_get_number(s->options, "visual-activity")) { TAILQ_FOREACH(wl, &w->winlinks, wentry) {
TAILQ_FOREACH(c, &clients, entry) { if (wl->flags & WINLINK_ACTIVITY)
if (c->session != s) continue;
continue; s = wl->session;
status_message_set(c, "Activity in window %d", wl->idx); if (s->curw != wl) {
wl->flags |= WINLINK_ACTIVITY;
notify_winlink("alert-activity", s, wl);
} }
if (s->flags & SESSION_ALERTED)
continue;
s->flags |= SESSION_ALERTED;
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
if (options_get_number(s->options, "visual-activity"))
alerts_set_message(s, "Activity in window %d", wl->idx);
} }
return (WINDOW_ACTIVITY); return (WINDOW_ACTIVITY);
} }
static int static int
alerts_check_silence(struct session *s, struct winlink *wl) alerts_check_silence(struct window *w)
{ {
struct client *c; struct winlink *wl;
struct window *w = wl->window; struct session *s;
if (s->curw->window == w) if (~w->flags & WINDOW_SILENCE)
w->flags &= ~WINDOW_SILENCE;
if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
return (0); return (0);
if (s->curw == wl) if (!options_get_number(w->options, "monitor-silence"))
return (0); return (0);
if (options_get_number(w->options, "monitor-silence") == 0) TAILQ_FOREACH(wl, &w->winlinks, wentry)
return (0); wl->session->flags &= ~SESSION_ALERTED;
if (options_get_number(s->options, "bell-on-alert")) TAILQ_FOREACH(wl, &w->winlinks, wentry) {
alerts_ring_bell(s); if (wl->flags & WINLINK_SILENCE)
wl->flags |= WINLINK_SILENCE; continue;
s = wl->session;
if (options_get_number(s->options, "visual-silence")) { if (s->curw != wl) {
TAILQ_FOREACH(c, &clients, entry) { wl->flags |= WINLINK_SILENCE;
if (c->session != s) notify_winlink("alert-silence", s, wl);
continue;
status_message_set(c, "Silence in window %d", wl->idx);
} }
if (s->flags & SESSION_ALERTED)
continue;
s->flags |= SESSION_ALERTED;
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
if (!options_get_number(s->options, "visual-silence"))
alerts_set_message(s, "Silence in window %d", wl->idx);
} }
return (WINDOW_SILENCE); return (WINDOW_SILENCE);
} }
static void
alerts_set_message(struct session *s, const char *fmt, ...)
{
struct client *c;
va_list ap;
char *message;
va_start(ap, fmt);
xvasprintf(&message, fmt, ap);
va_end(ap);
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == s)
status_message_set(c, "%s", message);
}
free(message);
}
static void static void
alerts_ring_bell(struct session *s) alerts_ring_bell(struct session *s)
{ {

View File

@ -296,7 +296,6 @@ key_bindings_init(void)
"bind -Tcopy-mode C-Up send -X scroll-up", "bind -Tcopy-mode C-Up send -X scroll-up",
"bind -Tcopy-mode C-Down send -X scroll-down", "bind -Tcopy-mode C-Down send -X scroll-down",
"bind -Tcopy-mode-vi C-b send -X page-up",
"bind -Tcopy-mode-vi C-c send -X cancel", "bind -Tcopy-mode-vi C-c send -X cancel",
"bind -Tcopy-mode-vi C-d send -X halfpage-down", "bind -Tcopy-mode-vi C-d send -X halfpage-down",
"bind -Tcopy-mode-vi C-e send -X scroll-down", "bind -Tcopy-mode-vi C-e send -X scroll-down",

View File

@ -851,6 +851,7 @@ server_client_loop(void)
struct client *c; struct client *c;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
int focus;
TAILQ_FOREACH(c, &clients, entry) { TAILQ_FOREACH(c, &clients, entry) {
server_client_check_exit(c); server_client_check_exit(c);
@ -864,11 +865,13 @@ server_client_loop(void)
* Any windows will have been redrawn as part of clients, so clear * Any windows will have been redrawn as part of clients, so clear
* their flags now. Also check pane focus and resize. * their flags now. Also check pane focus and resize.
*/ */
focus = options_get_number(global_options, "focus-events");
RB_FOREACH(w, windows, &windows) { RB_FOREACH(w, windows, &windows) {
w->flags &= ~WINDOW_REDRAW; w->flags &= ~WINDOW_REDRAW;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd != -1) { if (wp->fd != -1) {
server_client_check_focus(wp); if (focus)
server_client_check_focus(wp);
server_client_check_resize(wp); server_client_check_resize(wp);
} }
wp->flags &= ~PANE_REDRAW; wp->flags &= ~PANE_REDRAW;
@ -945,10 +948,6 @@ server_client_check_focus(struct window_pane *wp)
struct client *c; struct client *c;
int push; int push;
/* Are focus events off? */
if (!options_get_number(global_options, "focus-events"))
return;
/* Do we need to push the focus state? */ /* Do we need to push the focus state? */
push = wp->flags & PANE_FOCUSPUSH; push = wp->flags & PANE_FOCUSPUSH;
wp->flags &= ~PANE_FOCUSPUSH; wp->flags &= ~PANE_FOCUSPUSH;

View File

@ -336,6 +336,7 @@ session_new(struct session *s, const char *name, int argc, char **argv,
xasprintf(cause, "index in use: %d", idx); xasprintf(cause, "index in use: %d", idx);
return (NULL); return (NULL);
} }
wl->session = s;
env = environ_create(); env = environ_create();
environ_copy(global_environ, env); environ_copy(global_environ, env);
@ -372,6 +373,7 @@ session_attach(struct session *s, struct window *w, int idx, char **cause)
xasprintf(cause, "index in use: %d", idx); xasprintf(cause, "index in use: %d", idx);
return (NULL); return (NULL);
} }
wl->session = s;
winlink_set_window(wl, w); winlink_set_window(wl, w);
notify_session_window("window-linked", s, w); notify_session_window("window-linked", s, w);
@ -408,8 +410,8 @@ session_has(struct session *s, struct window *w)
{ {
struct winlink *wl; struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows) { TAILQ_FOREACH(wl, &w->winlinks, wentry) {
if (wl->window == w) if (wl->session == s)
return (1); return (1);
} }
return (0); return (0);
@ -678,6 +680,7 @@ session_group_synchronize1(struct session *target, struct session *s)
/* Link all the windows from the target. */ /* Link all the windows from the target. */
RB_FOREACH(wl, winlinks, ww) { RB_FOREACH(wl, winlinks, ww) {
wl2 = winlink_add(&s->windows, wl->idx); wl2 = winlink_add(&s->windows, wl->idx);
wl2->session = s;
winlink_set_window(wl2, wl->window); winlink_set_window(wl2, wl->window);
notify_session_window("window-linked", s, wl2->window); notify_session_window("window-linked", s, wl2->window);
wl2->flags |= wl->flags & WINLINK_ALERTFLAGS; wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
@ -728,6 +731,7 @@ session_renumber_windows(struct session *s)
/* Go through the winlinks and assign new indexes. */ /* Go through the winlinks and assign new indexes. */
RB_FOREACH(wl, winlinks, &old_wins) { RB_FOREACH(wl, winlinks, &old_wins) {
wl_new = winlink_add(&s->windows, new_idx); wl_new = winlink_add(&s->windows, new_idx);
wl_new->session = s;
winlink_set_window(wl_new, wl->window); winlink_set_window(wl_new, wl->window);
wl_new->flags |= wl->flags & WINLINK_ALERTFLAGS; wl_new->flags |= wl->flags & WINLINK_ALERTFLAGS;

8
tmux.h
View File

@ -891,12 +891,16 @@ struct window {
#define WINDOW_STYLECHANGED 0x8000 #define WINDOW_STYLECHANGED 0x8000
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
int alerts_queued;
TAILQ_ENTRY(window) alerts_entry;
struct options *options; struct options *options;
struct grid_cell style; struct grid_cell style;
struct grid_cell active_style; struct grid_cell active_style;
u_int references; u_int references;
TAILQ_HEAD(, winlink) winlinks;
RB_ENTRY(window) entry; RB_ENTRY(window) entry;
}; };
@ -905,6 +909,7 @@ RB_HEAD(windows, window);
/* Entry on local window list. */ /* Entry on local window list. */
struct winlink { struct winlink {
int idx; int idx;
struct session *session;
struct window *window; struct window *window;
size_t status_width; size_t status_width;
@ -918,6 +923,7 @@ struct winlink {
#define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_SILENCE) #define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_SILENCE)
RB_ENTRY(winlink) entry; RB_ENTRY(winlink) entry;
TAILQ_ENTRY(winlink) wentry;
TAILQ_ENTRY(winlink) sentry; TAILQ_ENTRY(winlink) sentry;
}; };
RB_HEAD(winlinks, winlink); RB_HEAD(winlinks, winlink);
@ -992,6 +998,7 @@ struct session {
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */ #define SESSION_UNATTACHED 0x1 /* not attached to any clients */
#define SESSION_PASTING 0x2 #define SESSION_PASTING 0x2
#define SESSION_ALERTED 0x4
int flags; int flags;
u_int attached; u_int attached;
@ -2071,7 +2078,6 @@ struct window *window_create(u_int, u_int);
struct window *window_create_spawn(const char *, int, char **, const char *, struct window *window_create_spawn(const char *, int, char **, const char *,
const char *, const char *, struct environ *, const char *, const char *, struct environ *,
struct termios *, u_int, u_int, u_int, char **); struct termios *, u_int, u_int, u_int, char **);
void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int); struct window_pane *window_get_active_at(struct window *, u_int, u_int);
struct window_pane *window_find_string(struct window *, const char *); struct window_pane *window_find_string(struct window *, const char *);
int window_has_pane(struct window *, struct window_pane *); int window_has_pane(struct window *, struct window_pane *);

View File

@ -60,6 +60,8 @@ static u_int next_window_pane_id;
static u_int next_window_id; static u_int next_window_id;
static u_int next_active_point; static u_int next_active_point;
static void window_destroy(struct window *);
static struct window_pane *window_pane_create(struct window *, u_int, u_int, static struct window_pane *window_pane_create(struct window *, u_int, u_int,
u_int); u_int);
static void window_pane_destroy(struct window_pane *); static void window_pane_destroy(struct window_pane *);
@ -184,6 +186,11 @@ winlink_add(struct winlinks *wwl, int idx)
void void
winlink_set_window(struct winlink *wl, struct window *w) winlink_set_window(struct winlink *wl, struct window *w)
{ {
if (wl->window != NULL) {
TAILQ_REMOVE(&wl->window->winlinks, wl, wentry);
window_remove_ref(w);
}
TAILQ_INSERT_TAIL(&w->winlinks, wl, wentry);
wl->window = w; wl->window = w;
w->references++; w->references++;
} }
@ -193,12 +200,14 @@ winlink_remove(struct winlinks *wwl, struct winlink *wl)
{ {
struct window *w = wl->window; struct window *w = wl->window;
if (w != NULL) {
TAILQ_REMOVE(&w->winlinks, wl, wentry);
window_remove_ref(w);
}
RB_REMOVE(winlinks, wwl, wl); RB_REMOVE(winlinks, wwl, wl);
free(wl->status_text); free(wl->status_text);
free(wl); free(wl);
if (w != NULL)
window_remove_ref(w);
} }
struct winlink * struct winlink *
@ -313,6 +322,7 @@ window_create(u_int sx, u_int sy)
w->options = options_create(global_w_options); w->options = options_create(global_w_options);
w->references = 0; w->references = 0;
TAILQ_INIT(&w->winlinks);
w->id = next_window_id++; w->id = next_window_id++;
RB_INSERT(windows, &windows, w); RB_INSERT(windows, &windows, w);
@ -350,9 +360,12 @@ window_create_spawn(const char *name, int argc, char **argv, const char *path,
return (w); return (w);
} }
void static void
window_destroy(struct window *w) window_destroy(struct window *w)
{ {
if (!TAILQ_EMPTY(&w->winlinks))
fatalx("window destroyed with winlinks");
RB_REMOVE(windows, &windows, w); RB_REMOVE(windows, &windows, w);
if (w->layout_root != NULL) if (w->layout_root != NULL)
@ -1436,19 +1449,13 @@ window_pane_find_right(struct window_pane *wp)
void void
winlink_clear_flags(struct winlink *wl) winlink_clear_flags(struct winlink *wl)
{ {
struct session *s; struct winlink *loop;
struct winlink *wl_loop;
RB_FOREACH(s, sessions, &sessions) { wl->window->flags &= ~WINDOW_ALERTFLAGS;
RB_FOREACH(wl_loop, winlinks, &s->windows) { TAILQ_FOREACH(loop, &wl->window->winlinks, wentry) {
if (wl_loop->window != wl->window) if ((loop->flags & WINLINK_ALERTFLAGS) != 0) {
continue; loop->flags &= ~WINLINK_ALERTFLAGS;
if ((wl_loop->flags & WINLINK_ALERTFLAGS) == 0) server_status_session(loop->session);
continue;
wl_loop->flags &= ~WINLINK_ALERTFLAGS;
wl_loop->window->flags &= ~WINDOW_ALERTFLAGS;
server_status_session(s);
} }
} }
} }