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