1 /* Id */ 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 19 #include <sys/types.h> 20 21 #include <stdlib.h> 22 23 #include "tmux.h" 24 25 enum notify_type { 26 NOTIFY_WINDOW_LAYOUT_CHANGED, 27 NOTIFY_WINDOW_UNLINKED, 28 NOTIFY_WINDOW_LINKED, 29 NOTIFY_WINDOW_RENAMED, 30 NOTIFY_ATTACHED_SESSION_CHANGED, 31 NOTIFY_SESSION_RENAMED, 32 NOTIFY_SESSION_CREATED, 33 NOTIFY_SESSION_CLOSED 34 }; 35 36 struct notify_entry { 37 enum notify_type type; 38 39 struct client *client; 40 struct session *session; 41 struct window *window; 42 43 TAILQ_ENTRY(notify_entry) entry; 44 }; 45 TAILQ_HEAD(, notify_entry) notify_queue = TAILQ_HEAD_INITIALIZER(notify_queue); 46 int notify_enabled = 1; 47 48 void notify_drain(void); 49 void notify_add(enum notify_type, struct client *, struct session *, 50 struct window *); 51 52 void 53 notify_enable(void) 54 { 55 notify_enabled = 1; 56 notify_drain(); 57 } 58 59 void 60 notify_disable(void) 61 { 62 notify_enabled = 0; 63 } 64 65 void 66 notify_add(enum notify_type type, struct client *c, struct session *s, 67 struct window *w) 68 { 69 struct notify_entry *ne; 70 71 ne = xcalloc(1, sizeof *ne); 72 ne->type = type; 73 ne->client = c; 74 ne->session = s; 75 ne->window = w; 76 TAILQ_INSERT_TAIL(¬ify_queue, ne, entry); 77 78 if (c != NULL) 79 c->references++; 80 if (s != NULL) 81 s->references++; 82 if (w != NULL) 83 w->references++; 84 } 85 86 void 87 notify_drain(void) 88 { 89 struct notify_entry *ne, *ne1; 90 91 if (!notify_enabled) 92 return; 93 94 TAILQ_FOREACH_SAFE(ne, ¬ify_queue, entry, ne1) { 95 switch (ne->type) { 96 case NOTIFY_WINDOW_LAYOUT_CHANGED: 97 control_notify_window_layout_changed(ne->window); 98 break; 99 case NOTIFY_WINDOW_UNLINKED: 100 control_notify_window_unlinked(ne->session, ne->window); 101 break; 102 case NOTIFY_WINDOW_LINKED: 103 control_notify_window_linked(ne->session, ne->window); 104 break; 105 case NOTIFY_WINDOW_RENAMED: 106 control_notify_window_renamed(ne->window); 107 break; 108 case NOTIFY_ATTACHED_SESSION_CHANGED: 109 control_notify_attached_session_changed(ne->client); 110 break; 111 case NOTIFY_SESSION_RENAMED: 112 control_notify_session_renamed(ne->session); 113 break; 114 case NOTIFY_SESSION_CREATED: 115 control_notify_session_created(ne->session); 116 break; 117 case NOTIFY_SESSION_CLOSED: 118 control_notify_session_close(ne->session); 119 break; 120 } 121 122 if (ne->client != NULL) 123 ne->client->references--; 124 if (ne->session != NULL) 125 ne->session->references--; 126 if (ne->window != NULL) 127 window_remove_ref(ne->window); 128 129 TAILQ_REMOVE(¬ify_queue, ne, entry); 130 free(ne); 131 } 132 } 133 134 void 135 notify_input(struct window_pane *wp, struct evbuffer *input) 136 { 137 struct client *c; 138 u_int i; 139 140 /* 141 * notify_input() is not queued and only does anything when 142 * notifications are enabled. 143 */ 144 if (!notify_enabled) 145 return; 146 147 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 148 c = ARRAY_ITEM(&clients, i); 149 if (c != NULL && (c->flags & CLIENT_CONTROL)) 150 control_notify_input(c, wp, input); 151 } 152 } 153 154 void 155 notify_window_layout_changed(struct window *w) 156 { 157 notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w); 158 notify_drain(); 159 } 160 161 void 162 notify_window_unlinked(struct session *s, struct window *w) 163 { 164 notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w); 165 notify_drain(); 166 } 167 168 void 169 notify_window_linked(struct session *s, struct window *w) 170 { 171 notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w); 172 notify_drain(); 173 } 174 175 void 176 notify_window_renamed(struct window *w) 177 { 178 notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w); 179 notify_drain(); 180 } 181 182 void 183 notify_attached_session_changed(struct client *c) 184 { 185 notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL); 186 notify_drain(); 187 } 188 189 void 190 notify_session_renamed(struct session *s) 191 { 192 notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL); 193 notify_drain(); 194 } 195 196 void 197 notify_session_created(struct session *s) 198 { 199 notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL); 200 notify_drain(); 201 } 202 203 void 204 notify_session_closed(struct session *s) 205 { 206 notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL); 207 notify_drain(); 208 } 209