Annotation of src/usr.bin/tmux/server-window.c, Revision 1.10
1.10 ! nicm 1: /* $OpenBSD: server-window.c,v 1.9 2009/11/04 22:43:11 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2009 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:
1.5 nicm 21: #include <event.h>
1.1 nicm 22: #include <unistd.h>
23:
24: #include "tmux.h"
25:
1.3 nicm 26: int server_window_backoff(struct window_pane *);
1.1 nicm 27: int server_window_check_bell(struct session *, struct window *);
28: int server_window_check_activity(struct session *, struct window *);
29: int server_window_check_content(
30: struct session *, struct window *, struct window_pane *);
31: void server_window_check_alive(struct window *);
1.2 nicm 32:
1.3 nicm 33: /* Check if this window should suspend reading. */
34: int
35: server_window_backoff(struct window_pane *wp)
36: {
37: struct client *c;
38: u_int i;
39:
40: if (!window_pane_visible(wp))
41: return (0);
42:
43: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
44: c = ARRAY_ITEM(&clients, i);
45: if (c == NULL || c->session == NULL)
1.4 nicm 46: continue;
47: if ((c->flags & (CLIENT_SUSPENDED|CLIENT_DEAD)) != 0)
1.3 nicm 48: continue;
49: if (c->session->curw->window != wp->window)
50: continue;
1.7 nicm 51:
52: if (EVBUFFER_LENGTH(c->tty.event->output) > BACKOFF_THRESHOLD)
1.3 nicm 53: return (1);
54: }
55: return (0);
1.2 nicm 56: }
1.1 nicm 57:
58: /* Window functions that need to happen every loop. */
59: void
60: server_window_loop(void)
61: {
62: struct window *w;
63: struct window_pane *wp;
64: struct session *s;
65: u_int i, j;
66:
67: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
68: w = ARRAY_ITEM(&windows, i);
69: if (w == NULL)
70: continue;
1.9 nicm 71:
72: TAILQ_FOREACH(wp, &w->panes, entry) {
73: if (server_window_backoff(wp))
74: bufferevent_disable(wp->event, EV_READ);
75: else
76: bufferevent_enable(wp->event, EV_READ);
77: }
1.1 nicm 78:
79: for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
80: s = ARRAY_ITEM(&sessions, j);
81: if (s == NULL || !session_has(s, w))
82: continue;
83:
84: if (server_window_check_bell(s, w) ||
85: server_window_check_activity(s, w))
86: server_status_session(s);
87: TAILQ_FOREACH(wp, &w->panes, entry)
88: server_window_check_content(s, w, wp);
89: }
90: w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT);
91:
92: server_window_check_alive(w);
93: }
94: }
95:
96: /* Check for bell in window. */
97: int
98: server_window_check_bell(struct session *s, struct window *w)
99: {
100: struct client *c;
101: u_int i;
102: int action, visual;
103:
104: if (!(w->flags & WINDOW_BELL))
105: return (0);
106:
107: if (session_alert_has_window(s, w, WINDOW_BELL))
108: return (0);
109: session_alert_add(s, w, WINDOW_BELL);
110:
111: action = options_get_number(&s->options, "bell-action");
112: switch (action) {
113: case BELL_ANY:
114: if (s->flags & SESSION_UNATTACHED)
115: break;
116: visual = options_get_number(&s->options, "visual-bell");
117: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
118: c = ARRAY_ITEM(&clients, i);
119: if (c == NULL || c->session != s)
120: continue;
121: if (!visual) {
122: tty_putcode(&c->tty, TTYC_BEL);
123: continue;
124: }
125: if (c->session->curw->window == w) {
126: status_message_set(c, "Bell in current window");
127: continue;
128: }
129: status_message_set(c, "Bell in window %u",
130: winlink_find_by_window(&s->windows, w)->idx);
131: }
132: break;
133: case BELL_CURRENT:
134: if (s->flags & SESSION_UNATTACHED)
135: break;
136: visual = options_get_number(&s->options, "visual-bell");
137: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
138: c = ARRAY_ITEM(&clients, i);
139: if (c == NULL || c->session != s)
140: continue;
141: if (c->session->curw->window != w)
142: continue;
143: if (!visual) {
144: tty_putcode(&c->tty, TTYC_BEL);
145: continue;
146: }
147: status_message_set(c, "Bell in current window");
148: }
149: break;
150: }
151:
152: return (1);
153: }
154:
155: /* Check for activity in window. */
156: int
157: server_window_check_activity(struct session *s, struct window *w)
158: {
159: struct client *c;
160: u_int i;
161:
162: if (!(w->flags & WINDOW_ACTIVITY))
163: return (0);
164: if (s->curw->window == w)
165: return (0);
166:
167: if (!options_get_number(&w->options, "monitor-activity"))
168: return (0);
169:
170: if (session_alert_has_window(s, w, WINDOW_ACTIVITY))
171: return (0);
172: session_alert_add(s, w, WINDOW_ACTIVITY);
173:
174: if (s->flags & SESSION_UNATTACHED)
175: return (0);
176: if (options_get_number(&s->options, "visual-activity")) {
177: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
178: c = ARRAY_ITEM(&clients, i);
179: if (c == NULL || c->session != s)
180: continue;
181: status_message_set(c, "Activity in window %u",
182: winlink_find_by_window(&s->windows, w)->idx);
183: }
184: }
185:
186: return (1);
187: }
188:
189: /* Check for content change in window. */
190: int
191: server_window_check_content(
192: struct session *s, struct window *w, struct window_pane *wp)
193: {
194: struct client *c;
195: u_int i;
196: char *found, *ptr;
197:
198: if (!(w->flags & WINDOW_ACTIVITY)) /* activity for new content */
199: return (0);
200: if (s->curw->window == w)
201: return (0);
202:
203: ptr = options_get_string(&w->options, "monitor-content");
204: if (ptr == NULL || *ptr == '\0')
205: return (0);
206:
207: if (session_alert_has_window(s, w, WINDOW_CONTENT))
208: return (0);
209:
210: if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
211: return (0);
212: xfree(found);
213:
214: session_alert_add(s, w, WINDOW_CONTENT);
215: if (s->flags & SESSION_UNATTACHED)
216: return (0);
217: if (options_get_number(&s->options, "visual-content")) {
218: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
219: c = ARRAY_ITEM(&clients, i);
220: if (c == NULL || c->session != s)
221: continue;
222: status_message_set(c, "Content in window %u",
223: winlink_find_by_window(&s->windows, w)->idx);
224: }
225: }
226:
227: return (1);
228: }
229:
230: /* Check if window still exists. */
231: void
232: server_window_check_alive(struct window *w)
233: {
234: struct window_pane *wp, *wq;
235: struct options *oo = &w->options;
236: struct session *s;
237: struct winlink *wl;
238: u_int i;
239: int destroyed;
240:
241: destroyed = 1;
242:
243: wp = TAILQ_FIRST(&w->panes);
244: while (wp != NULL) {
245: wq = TAILQ_NEXT(wp, entry);
246: /*
247: * If the pane has died and the remain-on-exit flag is not set,
248: * remove the pane; otherwise, if the flag is set, don't allow
249: * the window to be destroyed (or it'll close when the last
250: * pane dies).
251: */
252: if (wp->fd == -1 && !options_get_number(oo, "remain-on-exit")) {
253: layout_close_pane(wp);
254: window_remove_pane(w, wp);
255: server_redraw_window(w);
256: } else
257: destroyed = 0;
258: wp = wq;
259: }
260:
261: if (!destroyed)
262: return;
263:
264: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
265: s = ARRAY_ITEM(&sessions, i);
266: if (s == NULL)
267: continue;
268: if (!session_has(s, w))
269: continue;
270:
271: restart:
272: /* Detach window and either redraw or kill clients. */
273: RB_FOREACH(wl, winlinks, &s->windows) {
274: if (wl->window != w)
275: continue;
276: if (session_detach(s, wl)) {
277: server_destroy_session_group(s);
278: break;
279: }
280: server_redraw_session(s);
281: server_status_session_group(s);
282: goto restart;
283: }
284: }
285:
286: recalculate_sizes();
287: }