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