[BACK]Return to alerts.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/alerts.c, Revision 1.13

1.13    ! nicm        1: /* $OpenBSD: alerts.c,v 1.12 2016/10/03 22:52:11 nicm Exp $ */
1.1       nicm        2:
                      3: /*
1.10      nicm        4:  * Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1       nicm        5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <event.h>
                     22:
                     23: #include "tmux.h"
                     24:
1.12      nicm       25: static int     alerts_fired;
1.1       nicm       26:
1.12      nicm       27: static void    alerts_timer(int, short, void *);
                     28: static int     alerts_enabled(struct window *, int);
                     29: static void    alerts_callback(int, short, void *);
                     30: static void    alerts_reset(struct window *);
                     31:
                     32: static void    alerts_run_hook(struct session *, struct winlink *, int);
                     33: static int     alerts_check_all(struct session *, struct winlink *);
                     34: static int     alerts_check_bell(struct session *, struct winlink *);
                     35: static int     alerts_check_activity(struct session *, struct winlink *);
                     36: static int     alerts_check_silence(struct session *, struct winlink *);
                     37: static void    alerts_ring_bell(struct session *);
1.1       nicm       38:
1.12      nicm       39: static void
1.5       nicm       40: alerts_timer(__unused int fd, __unused short events, void *arg)
1.1       nicm       41: {
                     42:        struct window   *w = arg;
                     43:
                     44:        log_debug("@%u alerts timer expired", w->id);
                     45:        alerts_reset(w);
                     46:        alerts_queue(w, WINDOW_SILENCE);
                     47: }
                     48:
1.12      nicm       49: static void
1.5       nicm       50: alerts_callback(__unused int fd, __unused short events, __unused void *arg)
1.1       nicm       51: {
                     52:        struct window   *w;
                     53:        struct session  *s;
                     54:        struct winlink  *wl;
                     55:        int              flags, alerts;
                     56:
                     57:        RB_FOREACH(w, windows, &windows) {
                     58:                RB_FOREACH(s, sessions, &sessions) {
                     59:                        RB_FOREACH(wl, winlinks, &s->windows) {
                     60:                                if (wl->window != w)
                     61:                                        continue;
                     62:                                flags = w->flags;
                     63:
1.8       nicm       64:                                alerts = alerts_check_all(s, wl);
1.1       nicm       65:
                     66:                                log_debug("%s:%d @%u alerts check, alerts %#x, "
                     67:                                    "flags %#x", s->name, wl->idx, w->id,
                     68:                                    alerts, flags);
                     69:                        }
                     70:                }
                     71:        }
                     72:        alerts_fired = 0;
                     73: }
                     74:
1.12      nicm       75: static void
1.9       nicm       76: alerts_run_hook(struct session *s, struct winlink *wl, int flags)
                     77: {
                     78:        if (flags & WINDOW_BELL)
1.13    ! nicm       79:                notify_winlink("alert-bell", s, wl);
1.9       nicm       80:        if (flags & WINDOW_SILENCE)
1.13    ! nicm       81:                notify_winlink("alert-silence", s, wl);
1.9       nicm       82:        if (flags & WINDOW_ACTIVITY)
1.13    ! nicm       83:                notify_winlink("alert-activity", s, wl);
1.9       nicm       84: }
                     85:
1.12      nicm       86: static int
1.8       nicm       87: alerts_check_all(struct session *s, struct winlink *wl)
                     88: {
                     89:        int     alerts;
                     90:
                     91:        alerts  = alerts_check_bell(s, wl);
                     92:        alerts |= alerts_check_activity(s, wl);
                     93:        alerts |= alerts_check_silence(s, wl);
1.9       nicm       94:        if (alerts != 0) {
                     95:                alerts_run_hook(s, wl, alerts);
1.8       nicm       96:                server_status_session(s);
1.9       nicm       97:        }
1.8       nicm       98:
                     99:        return (alerts);
                    100: }
                    101:
                    102: void
                    103: alerts_check_session(struct session *s)
                    104: {
                    105:        struct winlink  *wl;
                    106:
                    107:        RB_FOREACH(wl, winlinks, &s->windows)
                    108:                alerts_check_all(s, wl);
                    109: }
                    110:
1.12      nicm      111: static int
1.1       nicm      112: alerts_enabled(struct window *w, int flags)
                    113: {
1.7       nicm      114:        if (flags & WINDOW_BELL)
                    115:                return (1);
1.1       nicm      116:        if (flags & WINDOW_ACTIVITY) {
1.4       nicm      117:                if (options_get_number(w->options, "monitor-activity"))
1.1       nicm      118:                        return (1);
                    119:        }
                    120:        if (flags & WINDOW_SILENCE) {
1.4       nicm      121:                if (options_get_number(w->options, "monitor-silence") != 0)
1.1       nicm      122:                        return (1);
                    123:        }
                    124:        return (0);
                    125: }
                    126:
                    127: void
                    128: alerts_reset_all(void)
                    129: {
                    130:        struct window   *w;
                    131:
                    132:        RB_FOREACH(w, windows, &windows)
                    133:                alerts_reset(w);
                    134: }
                    135:
1.12      nicm      136: static void
1.1       nicm      137: alerts_reset(struct window *w)
                    138: {
                    139:        struct timeval  tv;
                    140:
                    141:        w->flags &= ~WINDOW_SILENCE;
                    142:        event_del(&w->alerts_timer);
                    143:
                    144:        timerclear(&tv);
1.4       nicm      145:        tv.tv_sec = options_get_number(w->options, "monitor-silence");
1.1       nicm      146:
                    147:        log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
                    148:        if (tv.tv_sec != 0)
                    149:                event_add(&w->alerts_timer, &tv);
                    150: }
                    151:
                    152: void
                    153: alerts_queue(struct window *w, int flags)
                    154: {
1.3       nicm      155:        if (w->flags & WINDOW_ACTIVITY)
                    156:                alerts_reset(w);
                    157:
1.1       nicm      158:        if (!event_initialized(&w->alerts_timer))
                    159:                evtimer_set(&w->alerts_timer, alerts_timer, w);
                    160:
1.11      nicm      161:        if ((w->flags & flags) != flags) {
1.6       nicm      162:                w->flags |= flags;
                    163:                log_debug("@%u alerts flags added %#x", w->id, flags);
1.11      nicm      164:        }
1.6       nicm      165:
1.11      nicm      166:        if (!alerts_fired && alerts_enabled(w, flags)) {
                    167:                log_debug("alerts check queued (by @%u)", w->id);
                    168:                event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
                    169:                alerts_fired = 1;
1.1       nicm      170:        }
                    171: }
                    172:
1.12      nicm      173: static int
1.1       nicm      174: alerts_check_bell(struct session *s, struct winlink *wl)
                    175: {
                    176:        struct client   *c;
                    177:        struct window   *w = wl->window;
                    178:        int              action, visual;
                    179:
1.8       nicm      180:        if (!(w->flags & WINDOW_BELL))
1.1       nicm      181:                return (0);
1.8       nicm      182:        if (s->curw != wl) {
1.1       nicm      183:                wl->flags |= WINLINK_BELL;
1.8       nicm      184:                w->flags &= ~WINDOW_BELL;
                    185:        }
1.1       nicm      186:        if (s->curw->window == w)
                    187:                w->flags &= ~WINDOW_BELL;
                    188:
1.4       nicm      189:        action = options_get_number(s->options, "bell-action");
1.1       nicm      190:        if (action == BELL_NONE)
                    191:                return (0);
                    192:
1.4       nicm      193:        visual = options_get_number(s->options, "visual-bell");
1.1       nicm      194:        TAILQ_FOREACH(c, &clients, entry) {
                    195:                if (c->session != s || c->flags & CLIENT_CONTROL)
                    196:                        continue;
                    197:                if (!visual) {
                    198:                        if ((action == BELL_CURRENT &&
                    199:                            c->session->curw->window == w) ||
                    200:                            (action == BELL_OTHER &&
                    201:                            c->session->curw->window != w) ||
                    202:                            action == BELL_ANY)
1.2       nicm      203:                                tty_putcode(&c->tty, TTYC_BEL);
1.1       nicm      204:                        continue;
                    205:                }
                    206:                if (action == BELL_CURRENT && c->session->curw->window == w)
                    207:                        status_message_set(c, "Bell in current window");
                    208:                else if (action == BELL_ANY || (action == BELL_OTHER &&
                    209:                    c->session->curw->window != w))
                    210:                        status_message_set(c, "Bell in window %d", wl->idx);
                    211:        }
                    212:
                    213:        return (WINDOW_BELL);
                    214: }
                    215:
1.12      nicm      216: static int
1.1       nicm      217: alerts_check_activity(struct session *s, struct winlink *wl)
                    218: {
                    219:        struct client   *c;
                    220:        struct window   *w = wl->window;
                    221:
                    222:        if (s->curw->window == w)
                    223:                w->flags &= ~WINDOW_ACTIVITY;
                    224:
                    225:        if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
                    226:                return (0);
1.8       nicm      227:        if (s->curw == wl)
1.1       nicm      228:                return (0);
                    229:
1.4       nicm      230:        if (!options_get_number(w->options, "monitor-activity"))
1.1       nicm      231:                return (0);
                    232:
1.4       nicm      233:        if (options_get_number(s->options, "bell-on-alert"))
1.1       nicm      234:                alerts_ring_bell(s);
                    235:        wl->flags |= WINLINK_ACTIVITY;
                    236:
1.4       nicm      237:        if (options_get_number(s->options, "visual-activity")) {
1.1       nicm      238:                TAILQ_FOREACH(c, &clients, entry) {
                    239:                        if (c->session != s)
                    240:                                continue;
                    241:                        status_message_set(c, "Activity in window %d", wl->idx);
                    242:                }
                    243:        }
                    244:
                    245:        return (WINDOW_ACTIVITY);
                    246: }
                    247:
1.12      nicm      248: static int
1.1       nicm      249: alerts_check_silence(struct session *s, struct winlink *wl)
                    250: {
                    251:        struct client   *c;
                    252:        struct window   *w = wl->window;
                    253:
                    254:        if (s->curw->window == w)
                    255:                w->flags &= ~WINDOW_SILENCE;
                    256:
                    257:        if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
                    258:                return (0);
1.8       nicm      259:        if (s->curw == wl)
1.1       nicm      260:                return (0);
                    261:
1.4       nicm      262:        if (options_get_number(w->options, "monitor-silence") == 0)
1.1       nicm      263:                return (0);
                    264:
1.4       nicm      265:        if (options_get_number(s->options, "bell-on-alert"))
1.1       nicm      266:                alerts_ring_bell(s);
                    267:        wl->flags |= WINLINK_SILENCE;
                    268:
1.4       nicm      269:        if (options_get_number(s->options, "visual-silence")) {
1.1       nicm      270:                TAILQ_FOREACH(c, &clients, entry) {
                    271:                        if (c->session != s)
                    272:                                continue;
                    273:                        status_message_set(c, "Silence in window %d", wl->idx);
                    274:                }
                    275:        }
                    276:
                    277:        return (WINDOW_SILENCE);
                    278: }
                    279:
1.12      nicm      280: static void
1.1       nicm      281: alerts_ring_bell(struct session *s)
                    282: {
                    283:        struct client   *c;
                    284:
                    285:        TAILQ_FOREACH(c, &clients, entry) {
                    286:                if (c->session == s && !(c->flags & CLIENT_CONTROL))
1.2       nicm      287:                        tty_putcode(&c->tty, TTYC_BEL);
1.1       nicm      288:        }
                    289: }