Annotation of src/usr.bin/tmux/notify.c, Revision 1.15
1.15 ! nicm 1: /* $OpenBSD: notify.c,v 1.14 2016/10/16 19:04:05 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:
1.9 nicm 56: static void
1.15 ! nicm 57: notify_hook(struct cmdq_item *item, struct notify_entry *ne)
1.11 nicm 58: {
59: const char *name;
60: struct cmd_find_state fs;
61: struct hook *hook;
1.14 nicm 62: struct cmdq_item *new_item, *loop;
1.11 nicm 63:
64: name = notify_hooks[ne->type];
65: if (name == NULL)
66: return;
67:
68: cmd_find_clear_state(&fs, NULL, 0);
69: if (ne->session != NULL && ne->window != NULL)
70: cmd_find_from_session_window(&fs, ne->session, ne->window);
71: else if (ne->window != NULL)
72: cmd_find_from_window(&fs, ne->window);
73: else if (ne->session != NULL)
74: cmd_find_from_session(&fs, ne->session);
1.15 ! nicm 75: else
! 76: cmd_find_current(&fs, item, CMD_FIND_QUIET);
1.11 nicm 77: if (cmd_find_empty_state(&fs) || !cmd_find_valid_state(&fs))
78: return;
79:
80: hook = hooks_find(fs.s->hooks, name);
81: if (hook == NULL)
82: return;
83: log_debug("notify hook %s", name);
84:
1.14 nicm 85: new_item = cmdq_get_command(hook->cmdlist, &fs, NULL, CMDQ_NOHOOKS);
1.11 nicm 86:
1.14 nicm 87: for (loop = new_item; loop != NULL; loop = loop->next)
1.13 nicm 88: loop->hook = xstrdup(name);
1.11 nicm 89:
1.15 ! nicm 90: cmdq_insert_after(item, new_item);
! 91: }
! 92:
! 93: static enum cmd_retval
! 94: notify_callback(struct cmdq_item *item, void *data)
! 95: {
! 96: struct notify_entry *ne = data;
! 97:
! 98: switch (ne->type) {
! 99: case NOTIFY_WINDOW_LAYOUT_CHANGED:
! 100: control_notify_window_layout_changed(ne->window);
! 101: break;
! 102: case NOTIFY_WINDOW_UNLINKED:
! 103: control_notify_window_unlinked(ne->session, ne->window);
! 104: break;
! 105: case NOTIFY_WINDOW_LINKED:
! 106: control_notify_window_linked(ne->session, ne->window);
! 107: break;
! 108: case NOTIFY_WINDOW_RENAMED:
! 109: control_notify_window_renamed(ne->window);
! 110: break;
! 111: case NOTIFY_ATTACHED_SESSION_CHANGED:
! 112: control_notify_attached_session_changed(ne->client);
! 113: break;
! 114: case NOTIFY_SESSION_RENAMED:
! 115: control_notify_session_renamed(ne->session);
! 116: break;
! 117: case NOTIFY_SESSION_CREATED:
! 118: control_notify_session_created(ne->session);
! 119: break;
! 120: case NOTIFY_SESSION_CLOSED:
! 121: control_notify_session_closed(ne->session);
! 122: break;
! 123: }
! 124: notify_hook(item, ne);
! 125:
! 126: if (ne->client != NULL)
! 127: server_client_unref(ne->client);
! 128: if (ne->session != NULL)
! 129: session_unref(ne->session);
! 130: if (ne->window != NULL)
! 131: window_remove_ref(ne->window);
! 132: free(ne);
! 133:
! 134: return (CMD_RETURN_NORMAL);
1.11 nicm 135: }
136:
137: static void
1.2 nicm 138: notify_add(enum notify_type type, struct client *c, struct session *s,
139: struct window *w)
140: {
141: struct notify_entry *ne;
1.15 ! nicm 142: struct cmdq_item *new_item;
1.2 nicm 143:
144: ne = xcalloc(1, sizeof *ne);
145: ne->type = type;
146: ne->client = c;
147: ne->session = s;
148: ne->window = w;
149:
150: if (c != NULL)
151: c->references++;
152: if (s != NULL)
153: s->references++;
154: if (w != NULL)
155: w->references++;
156:
1.15 ! nicm 157: new_item = cmdq_get_callback(notify_callback, ne);
! 158: cmdq_append(NULL, new_item);
1.5 nicm 159: }
160:
161: void
162: notify_input(struct window_pane *wp, struct evbuffer *input)
163: {
164: struct client *c;
165:
1.6 nicm 166: TAILQ_FOREACH(c, &clients, entry) {
167: if (c->flags & CLIENT_CONTROL)
1.5 nicm 168: control_notify_input(c, wp, input);
1.2 nicm 169: }
170: }
171:
1.1 nicm 172: void
1.2 nicm 173: notify_window_layout_changed(struct window *w)
1.1 nicm 174: {
1.2 nicm 175: notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w);
1.1 nicm 176: }
177:
178: void
1.2 nicm 179: notify_window_unlinked(struct session *s, struct window *w)
1.1 nicm 180: {
1.2 nicm 181: notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w);
1.1 nicm 182: }
183:
184: void
1.2 nicm 185: notify_window_linked(struct session *s, struct window *w)
1.1 nicm 186: {
1.2 nicm 187: notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w);
1.1 nicm 188: }
189:
190: void
1.2 nicm 191: notify_window_renamed(struct window *w)
1.1 nicm 192: {
1.2 nicm 193: notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w);
1.1 nicm 194: }
195:
196: void
1.2 nicm 197: notify_attached_session_changed(struct client *c)
1.1 nicm 198: {
1.2 nicm 199: notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL);
1.1 nicm 200: }
201:
202: void
1.2 nicm 203: notify_session_renamed(struct session *s)
1.1 nicm 204: {
1.2 nicm 205: notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL);
1.1 nicm 206: }
207:
208: void
1.2 nicm 209: notify_session_created(struct session *s)
1.1 nicm 210: {
1.2 nicm 211: notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL);
1.1 nicm 212: }
213:
214: void
1.2 nicm 215: notify_session_closed(struct session *s)
1.1 nicm 216: {
1.2 nicm 217: notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL);
1.1 nicm 218: }