Annotation of src/usr.bin/tmux/alerts.c, Revision 1.8
1.8 ! nicm 1: /* $OpenBSD: alerts.c,v 1.7 2015/11/20 16:33:46 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
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:
25: int alerts_fired;
26:
27: void alerts_timer(int, short, void *);
28: int alerts_enabled(struct window *, int);
29: void alerts_callback(int, short, void *);
30: void alerts_reset(struct window *);
31:
1.8 ! nicm 32: int alerts_check_all(struct session *, struct winlink *);
1.1 nicm 33: int alerts_check_bell(struct session *, struct winlink *);
34: int alerts_check_activity(struct session *, struct winlink *);
35: int alerts_check_silence(struct session *, struct winlink *);
36: void alerts_ring_bell(struct session *);
37:
38: void
1.5 nicm 39: alerts_timer(__unused int fd, __unused short events, void *arg)
1.1 nicm 40: {
41: struct window *w = arg;
42:
43: log_debug("@%u alerts timer expired", w->id);
44: alerts_reset(w);
45: alerts_queue(w, WINDOW_SILENCE);
46: }
47:
48: void
1.5 nicm 49: alerts_callback(__unused int fd, __unused short events, __unused void *arg)
1.1 nicm 50: {
51: struct window *w;
52: struct session *s;
53: struct winlink *wl;
54: int flags, alerts;
55:
56: RB_FOREACH(w, windows, &windows) {
57: RB_FOREACH(s, sessions, &sessions) {
1.8 ! nicm 58: if (s->flags & SESSION_UNATTACHED)
! 59: continue;
1.1 nicm 60: RB_FOREACH(wl, winlinks, &s->windows) {
61: if (wl->window != w)
62: continue;
63: flags = w->flags;
64:
1.8 ! nicm 65: alerts = alerts_check_all(s, wl);
1.1 nicm 66:
67: log_debug("%s:%d @%u alerts check, alerts %#x, "
68: "flags %#x", s->name, wl->idx, w->id,
69: alerts, flags);
70: }
71: }
72: }
73: alerts_fired = 0;
74: }
75:
76: int
1.8 ! nicm 77: alerts_check_all(struct session *s, struct winlink *wl)
! 78: {
! 79: int alerts;
! 80:
! 81: alerts = alerts_check_bell(s, wl);
! 82: alerts |= alerts_check_activity(s, wl);
! 83: alerts |= alerts_check_silence(s, wl);
! 84: if (alerts != 0)
! 85: server_status_session(s);
! 86:
! 87: return (alerts);
! 88: }
! 89:
! 90: void
! 91: alerts_check_session(struct session *s)
! 92: {
! 93: struct winlink *wl;
! 94:
! 95: RB_FOREACH(wl, winlinks, &s->windows)
! 96: alerts_check_all(s, wl);
! 97: }
! 98:
! 99: int
1.1 nicm 100: alerts_enabled(struct window *w, int flags)
101: {
1.7 nicm 102: if (flags & WINDOW_BELL)
103: return (1);
1.1 nicm 104: if (flags & WINDOW_ACTIVITY) {
1.4 nicm 105: if (options_get_number(w->options, "monitor-activity"))
1.1 nicm 106: return (1);
107: }
108: if (flags & WINDOW_SILENCE) {
1.4 nicm 109: if (options_get_number(w->options, "monitor-silence") != 0)
1.1 nicm 110: return (1);
111: }
112: return (0);
113: }
114:
115: void
116: alerts_reset_all(void)
117: {
118: struct window *w;
119:
120: RB_FOREACH(w, windows, &windows)
121: alerts_reset(w);
122: }
123:
124: void
125: alerts_reset(struct window *w)
126: {
127: struct timeval tv;
128:
129: w->flags &= ~WINDOW_SILENCE;
130: event_del(&w->alerts_timer);
131:
132: timerclear(&tv);
1.4 nicm 133: tv.tv_sec = options_get_number(w->options, "monitor-silence");
1.1 nicm 134:
135: log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
136: if (tv.tv_sec != 0)
137: event_add(&w->alerts_timer, &tv);
138: }
139:
140: void
141: alerts_queue(struct window *w, int flags)
142: {
1.3 nicm 143: if (w->flags & WINDOW_ACTIVITY)
144: alerts_reset(w);
145:
1.1 nicm 146: if (!event_initialized(&w->alerts_timer))
147: evtimer_set(&w->alerts_timer, alerts_timer, w);
148:
1.6 nicm 149: if (!alerts_fired) {
150: w->flags |= flags;
151: log_debug("@%u alerts flags added %#x", w->id, flags);
152:
153: if (alerts_enabled(w, flags)) {
154: log_debug("alerts check queued (by @%u)", w->id);
155: event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
156: alerts_fired = 1;
157: }
1.1 nicm 158: }
159: }
160:
161: int
162: alerts_check_bell(struct session *s, struct winlink *wl)
163: {
164: struct client *c;
165: struct window *w = wl->window;
166: int action, visual;
167:
1.8 ! nicm 168: if (!(w->flags & WINDOW_BELL))
1.1 nicm 169: return (0);
1.8 ! nicm 170: if (s->curw != wl) {
1.1 nicm 171: wl->flags |= WINLINK_BELL;
1.8 ! nicm 172: w->flags &= ~WINDOW_BELL;
! 173: }
1.1 nicm 174: if (s->curw->window == w)
175: w->flags &= ~WINDOW_BELL;
176:
1.4 nicm 177: action = options_get_number(s->options, "bell-action");
1.1 nicm 178: if (action == BELL_NONE)
179: return (0);
180:
1.4 nicm 181: visual = options_get_number(s->options, "visual-bell");
1.1 nicm 182: TAILQ_FOREACH(c, &clients, entry) {
183: if (c->session != s || c->flags & CLIENT_CONTROL)
184: continue;
185: if (!visual) {
186: if ((action == BELL_CURRENT &&
187: c->session->curw->window == w) ||
188: (action == BELL_OTHER &&
189: c->session->curw->window != w) ||
190: action == BELL_ANY)
1.2 nicm 191: tty_putcode(&c->tty, TTYC_BEL);
1.1 nicm 192: continue;
193: }
194: if (action == BELL_CURRENT && c->session->curw->window == w)
195: status_message_set(c, "Bell in current window");
196: else if (action == BELL_ANY || (action == BELL_OTHER &&
197: c->session->curw->window != w))
198: status_message_set(c, "Bell in window %d", wl->idx);
199: }
200:
201: return (WINDOW_BELL);
202: }
203:
204: int
205: alerts_check_activity(struct session *s, struct winlink *wl)
206: {
207: struct client *c;
208: struct window *w = wl->window;
209:
210: if (s->curw->window == w)
211: w->flags &= ~WINDOW_ACTIVITY;
212:
213: if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
214: return (0);
1.8 ! nicm 215: if (s->curw == wl)
1.1 nicm 216: return (0);
217:
1.4 nicm 218: if (!options_get_number(w->options, "monitor-activity"))
1.1 nicm 219: return (0);
220:
1.4 nicm 221: if (options_get_number(s->options, "bell-on-alert"))
1.1 nicm 222: alerts_ring_bell(s);
223: wl->flags |= WINLINK_ACTIVITY;
224:
1.4 nicm 225: if (options_get_number(s->options, "visual-activity")) {
1.1 nicm 226: TAILQ_FOREACH(c, &clients, entry) {
227: if (c->session != s)
228: continue;
229: status_message_set(c, "Activity in window %d", wl->idx);
230: }
231: }
232:
233: return (WINDOW_ACTIVITY);
234: }
235:
236: int
237: alerts_check_silence(struct session *s, struct winlink *wl)
238: {
239: struct client *c;
240: struct window *w = wl->window;
241:
242: if (s->curw->window == w)
243: w->flags &= ~WINDOW_SILENCE;
244:
245: if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
246: return (0);
1.8 ! nicm 247: if (s->curw == wl)
1.1 nicm 248: return (0);
249:
1.4 nicm 250: if (options_get_number(w->options, "monitor-silence") == 0)
1.1 nicm 251: return (0);
252:
1.4 nicm 253: if (options_get_number(s->options, "bell-on-alert"))
1.1 nicm 254: alerts_ring_bell(s);
255: wl->flags |= WINLINK_SILENCE;
256:
1.4 nicm 257: if (options_get_number(s->options, "visual-silence")) {
1.1 nicm 258: TAILQ_FOREACH(c, &clients, entry) {
259: if (c->session != s)
260: continue;
261: status_message_set(c, "Silence in window %d", wl->idx);
262: }
263: }
264:
265: return (WINDOW_SILENCE);
266: }
267:
268: void
269: alerts_ring_bell(struct session *s)
270: {
271: struct client *c;
272:
273: TAILQ_FOREACH(c, &clients, entry) {
274: if (c->session == s && !(c->flags & CLIENT_CONTROL))
1.2 nicm 275: tty_putcode(&c->tty, TTYC_BEL);
1.1 nicm 276: }
277: }