From 3a69ff1c89ce2cb0df24ea58a4e0e167a9c10e39 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 19 Oct 2016 09:22:08 +0000 Subject: Alerts are too slow, so rather than walking all sessions and windows, add a link of winlinks to each window and a pointer to the session to each winlink. Also rewrite the alerts processing to return to the old behaviour (alert in any window sets the flag on any winlink). --- usr.bin/tmux/alerts.c | 246 ++++++++++++++++++++++++++++---------------------- 1 file changed, 138 insertions(+), 108 deletions(-) (limited to 'usr.bin/tmux/alerts.c') diff --git a/usr.bin/tmux/alerts.c b/usr.bin/tmux/alerts.c index c2bd6464f63..2cee03f47ff 100644 --- a/usr.bin/tmux/alerts.c +++ b/usr.bin/tmux/alerts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: alerts.c,v 1.13 2016/10/16 22:18:04 nicm Exp $ */ +/* $OpenBSD: alerts.c,v 1.14 2016/10/19 09:22:07 nicm Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -19,6 +19,7 @@ #include #include +#include #include "tmux.h" @@ -29,13 +30,16 @@ static int alerts_enabled(struct window *, int); 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 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,53 +53,28 @@ alerts_timer(__unused int fd, __unused short events, void *arg) 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; + struct window *w, *w1; + int alerts; - alerts = alerts_check_all(s, wl); + TAILQ_FOREACH_SAFE(w, &alerts_list, alerts_entry, w1) { + alerts = alerts_check_all(w); + log_debug("@%u alerts check, alerts %#x", w->id, alerts); - log_debug("%s:%d @%u alerts check, alerts %#x, " - "flags %#x", s->name, wl->idx, w->id, - alerts, flags); - } - } + w->alerts_queued = 0; + TAILQ_REMOVE(&alerts_list, w, alerts_entry); + window_remove_ref(w); } 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) +alerts_check_all(struct window *w) { 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); - } - + alerts = alerts_check_bell(w); + alerts |= alerts_check_activity(w); + alerts |= alerts_check_silence(w); return (alerts); } @@ -105,7 +84,7 @@ alerts_check_session(struct session *s) struct winlink *wl; RB_FOREACH(wl, winlinks, &s->windows) - alerts_check_all(s, wl); + alerts_check_all(wl->window); } static int @@ -163,6 +142,12 @@ alerts_queue(struct window *w, int 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)) { log_debug("alerts check queued (by @%u)", w->id); event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL); @@ -171,112 +156,157 @@ alerts_queue(struct window *w, int flags) } 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 window *w = wl->window; 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); + TAILQ_FOREACH(wl, &w->winlinks, wentry) + wl->session->flags &= ~SESSION_ALERTED; - visual = options_get_number(s->options, "visual-bell"); - TAILQ_FOREACH(c, &clients, entry) { - if (c->session != s || c->flags & CLIENT_CONTROL) + TAILQ_FOREACH(wl, &w->winlinks, wentry) { + if (wl->flags & WINLINK_BELL) 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); + 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); } static int -alerts_check_activity(struct session *s, struct winlink *wl) +alerts_check_activity(struct window *w) { - struct client *c; - struct window *w = wl->window; - - if (s->curw->window == w) - w->flags &= ~WINDOW_ACTIVITY; + struct winlink *wl; + struct session *s; - if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY) - return (0); - if (s->curw == wl) + if (~w->flags & WINDOW_ACTIVITY) 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; + TAILQ_FOREACH(wl, &w->winlinks, wentry) + wl->session->flags &= ~SESSION_ALERTED; - 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); + 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 session *s, struct winlink *wl) +alerts_check_silence(struct window *w) { - struct client *c; - struct window *w = wl->window; - - if (s->curw->window == w) - w->flags &= ~WINDOW_SILENCE; + struct winlink *wl; + struct session *s; - if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE) - return (0); - if (s->curw == wl) + if (~w->flags & WINDOW_SILENCE) return (0); - - if (options_get_number(w->options, "monitor-silence") == 0) + if (!options_get_number(w->options, "monitor-silence")) return (0); - if (options_get_number(s->options, "bell-on-alert")) - alerts_ring_bell(s); - wl->flags |= WINLINK_SILENCE; + TAILQ_FOREACH(wl, &w->winlinks, wentry) + wl->session->flags &= ~SESSION_ALERTED; - 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); + 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 alerts_ring_bell(struct session *s) { -- cgit v1.2.3