=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/alerts.c,v retrieving revision 1.13 retrieving revision 1.14 diff -c -r1.13 -r1.14 *** src/usr.bin/tmux/alerts.c 2016/10/16 22:18:04 1.13 --- src/usr.bin/tmux/alerts.c 2016/10/19 09:22:07 1.14 *************** *** 1,4 **** ! /* $OpenBSD: alerts.c,v 1.13 2016/10/16 22:18:04 nicm Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: alerts.c,v 1.14 2016/10/19 09:22:07 nicm Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott *************** *** 19,24 **** --- 19,25 ---- #include #include + #include #include "tmux.h" *************** *** 29,41 **** static void alerts_callback(int, short, void *); static void alerts_reset(struct window *); ! static void alerts_run_hook(struct session *, struct winlink *, int); ! static int alerts_check_all(struct session *, struct winlink *); ! static int alerts_check_bell(struct session *, struct winlink *); ! static int alerts_check_activity(struct session *, struct winlink *); ! static int alerts_check_silence(struct session *, struct winlink *); static void alerts_ring_bell(struct session *); static void alerts_timer(__unused int fd, __unused short events, void *arg) { --- 30,45 ---- static void alerts_callback(int, short, void *); static void alerts_reset(struct window *); ! static int alerts_check_all(struct window *); ! static int alerts_check_bell(struct window *); ! static int alerts_check_activity(struct window *); ! static int alerts_check_silence(struct window *); ! static void printflike(2, 3) alerts_set_message(struct session *, const char *, ! ...); static void alerts_ring_bell(struct session *); + static TAILQ_HEAD(, window) alerts_list = TAILQ_HEAD_INITIALIZER(alerts_list); + static void alerts_timer(__unused int fd, __unused short events, void *arg) { *************** *** 49,101 **** static void alerts_callback(__unused int fd, __unused short events, __unused void *arg) { ! struct window *w; ! struct session *s; ! struct winlink *wl; ! int flags, alerts; ! RB_FOREACH(w, windows, &windows) { ! RB_FOREACH(s, sessions, &sessions) { ! RB_FOREACH(wl, winlinks, &s->windows) { ! if (wl->window != w) ! continue; ! flags = w->flags; ! alerts = alerts_check_all(s, wl); ! ! log_debug("%s:%d @%u alerts check, alerts %#x, " ! "flags %#x", s->name, wl->idx, w->id, ! alerts, flags); ! } ! } } 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 ! alerts_check_all(struct session *s, struct winlink *wl) { int alerts; ! alerts = alerts_check_bell(s, wl); ! alerts |= alerts_check_activity(s, wl); ! alerts |= alerts_check_silence(s, wl); ! if (alerts != 0) { ! alerts_run_hook(s, wl, alerts); ! server_status_session(s); ! } ! return (alerts); } --- 53,80 ---- static void alerts_callback(__unused int fd, __unused short events, __unused void *arg) { ! struct window *w, *w1; ! int alerts; ! TAILQ_FOREACH_SAFE(w, &alerts_list, alerts_entry, w1) { ! alerts = alerts_check_all(w); ! log_debug("@%u alerts check, alerts %#x", w->id, alerts); ! w->alerts_queued = 0; ! TAILQ_REMOVE(&alerts_list, w, alerts_entry); ! window_remove_ref(w); } alerts_fired = 0; } static int ! alerts_check_all(struct window *w) { int alerts; ! alerts = alerts_check_bell(w); ! alerts |= alerts_check_activity(w); ! alerts |= alerts_check_silence(w); return (alerts); } *************** *** 105,111 **** struct winlink *wl; RB_FOREACH(wl, winlinks, &s->windows) ! alerts_check_all(s, wl); } static int --- 84,90 ---- struct winlink *wl; RB_FOREACH(wl, winlinks, &s->windows) ! alerts_check_all(wl->window); } static int *************** *** 163,168 **** --- 142,153 ---- 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)) { log_debug("alerts check queued (by @%u)", w->id); event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL); *************** *** 171,280 **** } static int ! alerts_check_bell(struct session *s, struct winlink *wl) { struct client *c; - struct window *w = wl->window; int action, visual; ! 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); ! visual = options_get_number(s->options, "visual-bell"); ! TAILQ_FOREACH(c, &clients, entry) { ! if (c->session != s || c->flags & CLIENT_CONTROL) continue; ! if (!visual) { ! 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; } - 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); } static int ! alerts_check_activity(struct session *s, struct winlink *wl) { ! struct client *c; ! struct window *w = wl->window; ! if (s->curw->window == w) ! w->flags &= ~WINDOW_ACTIVITY; ! ! if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY) return (0); - if (s->curw == wl) - return (0); - if (!options_get_number(w->options, "monitor-activity")) return (0); ! if (options_get_number(s->options, "bell-on-alert")) ! alerts_ring_bell(s); ! wl->flags |= WINLINK_ACTIVITY; ! if (options_get_number(s->options, "visual-activity")) { ! TAILQ_FOREACH(c, &clients, entry) { ! if (c->session != s) ! continue; ! status_message_set(c, "Activity in window %d", wl->idx); } } return (WINDOW_ACTIVITY); } static int ! alerts_check_silence(struct session *s, struct winlink *wl) { ! struct client *c; ! struct window *w = wl->window; ! if (s->curw->window == w) ! w->flags &= ~WINDOW_SILENCE; ! ! if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE) return (0); ! if (s->curw == wl) return (0); ! if (options_get_number(w->options, "monitor-silence") == 0) ! return (0); ! if (options_get_number(s->options, "bell-on-alert")) ! alerts_ring_bell(s); ! wl->flags |= WINLINK_SILENCE; ! ! if (options_get_number(s->options, "visual-silence")) { ! TAILQ_FOREACH(c, &clients, entry) { ! if (c->session != s) ! continue; ! status_message_set(c, "Silence in window %d", wl->idx); } } return (WINDOW_SILENCE); } static void --- 156,310 ---- } static int ! alerts_check_bell(struct window *w) { + struct window *ws; + struct winlink *wl; + struct session *s; struct client *c; int action, visual; ! if (~w->flags & WINDOW_BELL) return (0); ! TAILQ_FOREACH(wl, &w->winlinks, wentry) ! wl->session->flags &= ~SESSION_ALERTED; ! TAILQ_FOREACH(wl, &w->winlinks, wentry) { ! if (wl->flags & WINLINK_BELL) 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); + } } } return (WINDOW_BELL); } static int ! alerts_check_activity(struct window *w) { ! struct winlink *wl; ! struct session *s; ! if (~w->flags & WINDOW_ACTIVITY) return (0); if (!options_get_number(w->options, "monitor-activity")) return (0); ! TAILQ_FOREACH(wl, &w->winlinks, wentry) ! wl->session->flags &= ~SESSION_ALERTED; ! TAILQ_FOREACH(wl, &w->winlinks, wentry) { ! if (wl->flags & WINLINK_ACTIVITY) ! continue; ! s = wl->session; ! 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); } static int ! alerts_check_silence(struct window *w) { ! struct winlink *wl; ! struct session *s; ! if (~w->flags & WINDOW_SILENCE) return (0); ! if (!options_get_number(w->options, "monitor-silence")) return (0); ! TAILQ_FOREACH(wl, &w->winlinks, wentry) ! wl->session->flags &= ~SESSION_ALERTED; ! TAILQ_FOREACH(wl, &w->winlinks, wentry) { ! if (wl->flags & WINLINK_SILENCE) ! continue; ! s = wl->session; ! if (s->curw != wl) { ! wl->flags |= WINLINK_SILENCE; ! notify_winlink("alert-silence", 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-silence")) + alerts_set_message(s, "Silence in window %d", wl->idx); } 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