mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	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).
This commit is contained in:
		
							
								
								
									
										248
									
								
								alerts.c
									
									
									
									
									
								
							
							
						
						
									
										248
									
								
								alerts.c
									
									
									
									
									
								
							@@ -19,6 +19,7 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <event.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
	struct window	*w, *w1;
 | 
			
		||||
	int		 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;
 | 
			
		||||
	TAILQ_FOREACH_SAFE(w, &alerts_list, alerts_entry, w1) {
 | 
			
		||||
		alerts = alerts_check_all(w);
 | 
			
		||||
		log_debug("@%u alerts check, alerts %#x", w->id, alerts);
 | 
			
		||||
 | 
			
		||||
				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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		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))
 | 
			
		||||
		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)
 | 
			
		||||
	if (~w->flags & WINDOW_BELL)
 | 
			
		||||
		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);
 | 
			
		||||
	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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		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;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
 | 
			
		||||
	if (s->curw->window == w)
 | 
			
		||||
		w->flags &= ~WINDOW_ACTIVITY;
 | 
			
		||||
 | 
			
		||||
	if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
 | 
			
		||||
	if (~w->flags & WINDOW_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;
 | 
			
		||||
	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;
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
 | 
			
		||||
	if (s->curw->window == w)
 | 
			
		||||
		w->flags &= ~WINDOW_SILENCE;
 | 
			
		||||
 | 
			
		||||
	if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
 | 
			
		||||
	if (~w->flags & WINDOW_SILENCE)
 | 
			
		||||
		return (0);
 | 
			
		||||
	if (s->curw == wl)
 | 
			
		||||
	if (!options_get_number(w->options, "monitor-silence"))
 | 
			
		||||
		return (0);
 | 
			
		||||
 | 
			
		||||
	if (options_get_number(w->options, "monitor-silence") == 0)
 | 
			
		||||
		return (0);
 | 
			
		||||
	TAILQ_FOREACH(wl, &w->winlinks, wentry)
 | 
			
		||||
		wl->session->flags &= ~SESSION_ALERTED;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -853,6 +853,7 @@ server_client_loop(void)
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct window		*w;
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	int			 focus;
 | 
			
		||||
 | 
			
		||||
	TAILQ_FOREACH(c, &clients, entry) {
 | 
			
		||||
		server_client_check_exit(c);
 | 
			
		||||
@@ -866,11 +867,13 @@ server_client_loop(void)
 | 
			
		||||
	 * Any windows will have been redrawn as part of clients, so clear
 | 
			
		||||
	 * their flags now. Also check pane focus and resize.
 | 
			
		||||
	 */
 | 
			
		||||
	focus = options_get_number(global_options, "focus-events");
 | 
			
		||||
	RB_FOREACH(w, windows, &windows) {
 | 
			
		||||
		w->flags &= ~WINDOW_REDRAW;
 | 
			
		||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
			
		||||
			if (wp->fd != -1) {
 | 
			
		||||
				server_client_check_focus(wp);
 | 
			
		||||
				if (focus)
 | 
			
		||||
					server_client_check_focus(wp);
 | 
			
		||||
				server_client_check_resize(wp);
 | 
			
		||||
			}
 | 
			
		||||
			wp->flags &= ~PANE_REDRAW;
 | 
			
		||||
@@ -937,10 +940,6 @@ server_client_check_focus(struct window_pane *wp)
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	int		 push;
 | 
			
		||||
 | 
			
		||||
	/* Are focus events off? */
 | 
			
		||||
	if (!options_get_number(global_options, "focus-events"))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Do we need to push the focus state? */
 | 
			
		||||
	push = wp->flags & PANE_FOCUSPUSH;
 | 
			
		||||
	wp->flags &= ~PANE_FOCUSPUSH;
 | 
			
		||||
 
 | 
			
		||||
@@ -337,6 +337,7 @@ session_new(struct session *s, const char *name, int argc, char **argv,
 | 
			
		||||
		xasprintf(cause, "index in use: %d", idx);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	}
 | 
			
		||||
	wl->session = s;
 | 
			
		||||
 | 
			
		||||
	env = environ_create();
 | 
			
		||||
	environ_copy(global_environ, env);
 | 
			
		||||
@@ -373,6 +374,7 @@ session_attach(struct session *s, struct window *w, int idx, char **cause)
 | 
			
		||||
		xasprintf(cause, "index in use: %d", idx);
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	}
 | 
			
		||||
	wl->session = s;
 | 
			
		||||
	winlink_set_window(wl, w);
 | 
			
		||||
	notify_session_window("window-linked", s, w);
 | 
			
		||||
 | 
			
		||||
@@ -409,8 +411,8 @@ session_has(struct session *s, struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	struct winlink	*wl;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(wl, winlinks, &s->windows) {
 | 
			
		||||
		if (wl->window == w)
 | 
			
		||||
	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
 | 
			
		||||
		if (wl->session == s)
 | 
			
		||||
			return (1);
 | 
			
		||||
	}
 | 
			
		||||
	return (0);
 | 
			
		||||
@@ -679,6 +681,7 @@ session_group_synchronize1(struct session *target, struct session *s)
 | 
			
		||||
	/* Link all the windows from the target. */
 | 
			
		||||
	RB_FOREACH(wl, winlinks, ww) {
 | 
			
		||||
		wl2 = winlink_add(&s->windows, wl->idx);
 | 
			
		||||
		wl2->session = s;
 | 
			
		||||
		winlink_set_window(wl2, wl->window);
 | 
			
		||||
		notify_session_window("window-linked", s, wl2->window);
 | 
			
		||||
		wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
 | 
			
		||||
@@ -729,6 +732,7 @@ session_renumber_windows(struct session *s)
 | 
			
		||||
	/* Go through the winlinks and assign new indexes. */
 | 
			
		||||
	RB_FOREACH(wl, winlinks, &old_wins) {
 | 
			
		||||
		wl_new = winlink_add(&s->windows, new_idx);
 | 
			
		||||
		wl_new->session = s;
 | 
			
		||||
		winlink_set_window(wl_new, wl->window);
 | 
			
		||||
		wl_new->flags |= wl->flags & WINLINK_ALERTFLAGS;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							@@ -889,12 +889,16 @@ struct window {
 | 
			
		||||
#define WINDOW_STYLECHANGED 0x8000
 | 
			
		||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
 | 
			
		||||
 | 
			
		||||
	int		 alerts_queued;
 | 
			
		||||
	TAILQ_ENTRY(window) alerts_entry;
 | 
			
		||||
 | 
			
		||||
	struct options	*options;
 | 
			
		||||
 | 
			
		||||
	struct grid_cell style;
 | 
			
		||||
	struct grid_cell active_style;
 | 
			
		||||
 | 
			
		||||
	u_int		 references;
 | 
			
		||||
	TAILQ_HEAD(, winlink) winlinks;
 | 
			
		||||
 | 
			
		||||
	RB_ENTRY(window) entry;
 | 
			
		||||
};
 | 
			
		||||
@@ -903,6 +907,7 @@ RB_HEAD(windows, window);
 | 
			
		||||
/* Entry on local window list. */
 | 
			
		||||
struct winlink {
 | 
			
		||||
	int		 idx;
 | 
			
		||||
	struct session	*session;
 | 
			
		||||
	struct window	*window;
 | 
			
		||||
 | 
			
		||||
	size_t		 status_width;
 | 
			
		||||
@@ -916,6 +921,7 @@ struct winlink {
 | 
			
		||||
#define WINLINK_ALERTFLAGS (WINLINK_BELL|WINLINK_ACTIVITY|WINLINK_SILENCE)
 | 
			
		||||
 | 
			
		||||
	RB_ENTRY(winlink) entry;
 | 
			
		||||
	TAILQ_ENTRY(winlink) wentry;
 | 
			
		||||
	TAILQ_ENTRY(winlink) sentry;
 | 
			
		||||
};
 | 
			
		||||
RB_HEAD(winlinks, winlink);
 | 
			
		||||
@@ -990,6 +996,7 @@ struct session {
 | 
			
		||||
 | 
			
		||||
#define SESSION_UNATTACHED 0x1	/* not attached to any clients */
 | 
			
		||||
#define SESSION_PASTING 0x2
 | 
			
		||||
#define SESSION_ALERTED 0x4
 | 
			
		||||
	int		 flags;
 | 
			
		||||
 | 
			
		||||
	u_int		 attached;
 | 
			
		||||
@@ -2069,7 +2076,6 @@ struct window	*window_create(u_int, u_int);
 | 
			
		||||
struct window	*window_create_spawn(const char *, int, char **, const char *,
 | 
			
		||||
		     const char *, const char *, struct environ *,
 | 
			
		||||
		     struct termios *, u_int, u_int, u_int, char **);
 | 
			
		||||
void		 window_destroy(struct window *);
 | 
			
		||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
 | 
			
		||||
struct window_pane *window_find_string(struct window *, const char *);
 | 
			
		||||
int		 window_has_pane(struct window *, struct window_pane *);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								window.c
									
									
									
									
									
								
							@@ -60,6 +60,8 @@ static u_int	next_window_pane_id;
 | 
			
		||||
static u_int	next_window_id;
 | 
			
		||||
static u_int	next_active_point;
 | 
			
		||||
 | 
			
		||||
static void	window_destroy(struct window *);
 | 
			
		||||
 | 
			
		||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
 | 
			
		||||
		    u_int);
 | 
			
		||||
static void	window_pane_destroy(struct window_pane *);
 | 
			
		||||
@@ -184,6 +186,11 @@ winlink_add(struct winlinks *wwl, int idx)
 | 
			
		||||
void
 | 
			
		||||
winlink_set_window(struct winlink *wl, struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	if (wl->window != NULL) {
 | 
			
		||||
		TAILQ_REMOVE(&wl->window->winlinks, wl, wentry);
 | 
			
		||||
		window_remove_ref(w);
 | 
			
		||||
	}
 | 
			
		||||
	TAILQ_INSERT_TAIL(&w->winlinks, wl, wentry);
 | 
			
		||||
	wl->window = w;
 | 
			
		||||
	w->references++;
 | 
			
		||||
}
 | 
			
		||||
@@ -193,12 +200,14 @@ winlink_remove(struct winlinks *wwl, struct winlink *wl)
 | 
			
		||||
{
 | 
			
		||||
	struct window	*w = wl->window;
 | 
			
		||||
 | 
			
		||||
	if (w != NULL) {
 | 
			
		||||
		TAILQ_REMOVE(&w->winlinks, wl, wentry);
 | 
			
		||||
		window_remove_ref(w);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	RB_REMOVE(winlinks, wwl, wl);
 | 
			
		||||
	free(wl->status_text);
 | 
			
		||||
	free(wl);
 | 
			
		||||
 | 
			
		||||
	if (w != NULL)
 | 
			
		||||
		window_remove_ref(w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct winlink *
 | 
			
		||||
@@ -313,6 +322,7 @@ window_create(u_int sx, u_int sy)
 | 
			
		||||
	w->options = options_create(global_w_options);
 | 
			
		||||
 | 
			
		||||
	w->references = 0;
 | 
			
		||||
	TAILQ_INIT(&w->winlinks);
 | 
			
		||||
 | 
			
		||||
	w->id = next_window_id++;
 | 
			
		||||
	RB_INSERT(windows, &windows, w);
 | 
			
		||||
@@ -350,9 +360,12 @@ window_create_spawn(const char *name, int argc, char **argv, const char *path,
 | 
			
		||||
	return (w);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
static void
 | 
			
		||||
window_destroy(struct window *w)
 | 
			
		||||
{
 | 
			
		||||
	if (!TAILQ_EMPTY(&w->winlinks))
 | 
			
		||||
		fatalx("window destroyed with winlinks");
 | 
			
		||||
 | 
			
		||||
	RB_REMOVE(windows, &windows, w);
 | 
			
		||||
 | 
			
		||||
	if (w->layout_root != NULL)
 | 
			
		||||
@@ -1421,19 +1434,13 @@ window_pane_find_right(struct window_pane *wp)
 | 
			
		||||
void
 | 
			
		||||
winlink_clear_flags(struct winlink *wl)
 | 
			
		||||
{
 | 
			
		||||
	struct session	*s;
 | 
			
		||||
	struct winlink	*wl_loop;
 | 
			
		||||
	struct winlink	*loop;
 | 
			
		||||
 | 
			
		||||
	RB_FOREACH(s, sessions, &sessions) {
 | 
			
		||||
		RB_FOREACH(wl_loop, winlinks, &s->windows) {
 | 
			
		||||
			if (wl_loop->window != wl->window)
 | 
			
		||||
				continue;
 | 
			
		||||
			if ((wl_loop->flags & WINLINK_ALERTFLAGS) == 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			wl_loop->flags &= ~WINLINK_ALERTFLAGS;
 | 
			
		||||
			wl_loop->window->flags &= ~WINDOW_ALERTFLAGS;
 | 
			
		||||
			server_status_session(s);
 | 
			
		||||
	wl->window->flags &= ~WINDOW_ALERTFLAGS;
 | 
			
		||||
	TAILQ_FOREACH(loop, &wl->window->winlinks, wentry) {
 | 
			
		||||
		if ((loop->flags & WINLINK_ALERTFLAGS) != 0) {
 | 
			
		||||
			loop->flags &= ~WINLINK_ALERTFLAGS;
 | 
			
		||||
			server_status_session(loop->session);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user