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