version 1.13, 2016/10/16 22:18:04 |
version 1.14, 2016/10/19 09:22:07 |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
|
|
#include <event.h> |
#include <event.h> |
|
#include <stdlib.h> |
|
|
#include "tmux.h" |
#include "tmux.h" |
|
|
|
|
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) |
{ |
{ |
|
|
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); |
} |
} |
|
|
|
|
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 |
|
|
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); |
|
|
} |
} |
|
|
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); |
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"); |
TAILQ_FOREACH(wl, &w->winlinks, wentry) |
if (action == BELL_NONE) |
wl->session->flags &= ~SESSION_ALERTED; |
return (0); |
|
|
|
visual = options_get_number(s->options, "visual-bell"); |
TAILQ_FOREACH(wl, &w->winlinks, wentry) { |
TAILQ_FOREACH(c, &clients, entry) { |
if (wl->flags & WINLINK_BELL) |
if (c->session != s || c->flags & CLIENT_CONTROL) |
|
continue; |
continue; |
if (!visual) { |
s = wl->session; |
if ((action == BELL_CURRENT && |
if (s->curw != wl) { |
c->session->curw->window == w) || |
wl->flags |= WINLINK_BELL; |
(action == BELL_OTHER && |
notify_winlink("alert-bell", s, wl); |
c->session->curw->window != w) || |
} |
action == BELL_ANY) |
|
tty_putcode(&c->tty, TTYC_BEL); |
if (s->flags & SESSION_ALERTED) |
continue; |
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 |