Annotation of src/usr.bin/tmux/notify.c, Revision 1.13
1.13 ! nicm 1: /* $OpenBSD: notify.c,v 1.12 2016/10/15 00:12:58 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2012 George Nachman <tmux@georgester.com>
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:
1.2 nicm 19: #include <sys/types.h>
20: #include <sys/queue.h>
21:
22: #include <stdlib.h>
23:
1.1 nicm 24: #include "tmux.h"
25:
1.2 nicm 26: enum notify_type {
27: NOTIFY_WINDOW_LAYOUT_CHANGED,
28: NOTIFY_WINDOW_UNLINKED,
29: NOTIFY_WINDOW_LINKED,
30: NOTIFY_WINDOW_RENAMED,
31: NOTIFY_ATTACHED_SESSION_CHANGED,
32: NOTIFY_SESSION_RENAMED,
33: NOTIFY_SESSION_CREATED,
34: NOTIFY_SESSION_CLOSED
35: };
36:
1.11 nicm 37: static const char *notify_hooks[] = {
38: "window-layout-changed",
39: NULL, /* "window-unlinked", */
40: NULL, /* "window-linked", */
41: "window-renamed",
42: NULL, /* "attached-session-changed", */
43: "session-renamed",
44: NULL, /* "session-created", */
45: NULL, /* "session-closed" */
46: };
47:
1.2 nicm 48: struct notify_entry {
49: enum notify_type type;
50:
51: struct client *client;
52: struct session *session;
53: struct window *window;
54:
55: TAILQ_ENTRY(notify_entry) entry;
56: };
1.9 nicm 57: TAILQ_HEAD(notify_queue, notify_entry);
58: static struct notify_queue notify_queue = TAILQ_HEAD_INITIALIZER(notify_queue);
59:
60: static void notify_add(enum notify_type, struct client *, struct session *,
61: struct window *);
1.2 nicm 62:
1.9 nicm 63: static void
1.11 nicm 64: notify_hook(struct notify_entry *ne)
65: {
66: const char *name;
67: struct cmd_find_state fs;
68: struct hook *hook;
1.13 ! nicm 69: struct cmd_q *new_cmdq, *loop;
1.11 nicm 70:
71: name = notify_hooks[ne->type];
72: if (name == NULL)
73: return;
74:
75: cmd_find_clear_state(&fs, NULL, 0);
76: if (ne->session != NULL && ne->window != NULL)
77: cmd_find_from_session_window(&fs, ne->session, ne->window);
78: else if (ne->window != NULL)
79: cmd_find_from_window(&fs, ne->window);
80: else if (ne->session != NULL)
81: cmd_find_from_session(&fs, ne->session);
82: if (cmd_find_empty_state(&fs) || !cmd_find_valid_state(&fs))
83: return;
84:
85: hook = hooks_find(fs.s->hooks, name);
86: if (hook == NULL)
87: return;
88: log_debug("notify hook %s", name);
89:
1.13 ! nicm 90: new_cmdq = cmdq_get_command(hook->cmdlist, &fs, NULL, CMD_Q_NOHOOKS);
1.11 nicm 91:
1.13 ! nicm 92: for (loop = new_cmdq; loop != NULL; loop = loop->next)
! 93: loop->hook = xstrdup(name);
1.11 nicm 94:
1.13 ! nicm 95: cmdq_append(NULL, new_cmdq);
1.11 nicm 96: }
97:
98: static void
1.2 nicm 99: notify_add(enum notify_type type, struct client *c, struct session *s,
100: struct window *w)
101: {
102: struct notify_entry *ne;
103:
104: ne = xcalloc(1, sizeof *ne);
105: ne->type = type;
106: ne->client = c;
107: ne->session = s;
108: ne->window = w;
109: TAILQ_INSERT_TAIL(¬ify_queue, ne, entry);
110:
111: if (c != NULL)
112: c->references++;
113: if (s != NULL)
114: s->references++;
115: if (w != NULL)
116: w->references++;
117: }
118:
1.10 nicm 119: void
1.2 nicm 120: notify_drain(void)
121: {
122: struct notify_entry *ne, *ne1;
123:
124: TAILQ_FOREACH_SAFE(ne, ¬ify_queue, entry, ne1) {
125: switch (ne->type) {
126: case NOTIFY_WINDOW_LAYOUT_CHANGED:
1.4 nicm 127: control_notify_window_layout_changed(ne->window);
1.2 nicm 128: break;
129: case NOTIFY_WINDOW_UNLINKED:
1.4 nicm 130: control_notify_window_unlinked(ne->session, ne->window);
1.2 nicm 131: break;
132: case NOTIFY_WINDOW_LINKED:
1.4 nicm 133: control_notify_window_linked(ne->session, ne->window);
1.2 nicm 134: break;
135: case NOTIFY_WINDOW_RENAMED:
1.4 nicm 136: control_notify_window_renamed(ne->window);
1.2 nicm 137: break;
138: case NOTIFY_ATTACHED_SESSION_CHANGED:
1.4 nicm 139: control_notify_attached_session_changed(ne->client);
1.2 nicm 140: break;
141: case NOTIFY_SESSION_RENAMED:
1.4 nicm 142: control_notify_session_renamed(ne->session);
1.2 nicm 143: break;
144: case NOTIFY_SESSION_CREATED:
1.4 nicm 145: control_notify_session_created(ne->session);
1.2 nicm 146: break;
147: case NOTIFY_SESSION_CLOSED:
1.12 nicm 148: control_notify_session_closed(ne->session);
1.2 nicm 149: break;
150: }
1.11 nicm 151: TAILQ_REMOVE(¬ify_queue, ne, entry);
152: notify_hook(ne);
1.2 nicm 153:
154: if (ne->client != NULL)
1.7 nicm 155: server_client_unref(ne->client);
1.2 nicm 156: if (ne->session != NULL)
1.8 nicm 157: session_unref(ne->session);
1.2 nicm 158: if (ne->window != NULL)
1.3 nicm 159: window_remove_ref(ne->window);
1.2 nicm 160: free(ne);
1.5 nicm 161: }
162: }
163:
164: void
165: notify_input(struct window_pane *wp, struct evbuffer *input)
166: {
167: struct client *c;
168:
1.6 nicm 169: TAILQ_FOREACH(c, &clients, entry) {
170: if (c->flags & CLIENT_CONTROL)
1.5 nicm 171: control_notify_input(c, wp, input);
1.2 nicm 172: }
173: }
174:
1.1 nicm 175: void
1.2 nicm 176: notify_window_layout_changed(struct window *w)
1.1 nicm 177: {
1.2 nicm 178: notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w);
179: notify_drain();
1.1 nicm 180: }
181:
182: void
1.2 nicm 183: notify_window_unlinked(struct session *s, struct window *w)
1.1 nicm 184: {
1.2 nicm 185: notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w);
186: notify_drain();
1.1 nicm 187: }
188:
189: void
1.2 nicm 190: notify_window_linked(struct session *s, struct window *w)
1.1 nicm 191: {
1.2 nicm 192: notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w);
193: notify_drain();
1.1 nicm 194: }
195:
196: void
1.2 nicm 197: notify_window_renamed(struct window *w)
1.1 nicm 198: {
1.2 nicm 199: notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w);
200: notify_drain();
1.1 nicm 201: }
202:
203: void
1.2 nicm 204: notify_attached_session_changed(struct client *c)
1.1 nicm 205: {
1.2 nicm 206: notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL);
207: notify_drain();
1.1 nicm 208: }
209:
210: void
1.2 nicm 211: notify_session_renamed(struct session *s)
1.1 nicm 212: {
1.2 nicm 213: notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL);
214: notify_drain();
1.1 nicm 215: }
216:
217: void
1.2 nicm 218: notify_session_created(struct session *s)
1.1 nicm 219: {
1.2 nicm 220: notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL);
221: notify_drain();
1.1 nicm 222: }
223:
224: void
1.2 nicm 225: notify_session_closed(struct session *s)
1.1 nicm 226: {
1.2 nicm 227: notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL);
228: notify_drain();
1.1 nicm 229: }