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