1 /* $OpenBSD$ */ 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 server_client_unref(ne->client); 124 if (ne->session != NULL) 125 session_unref(ne->session); 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 139 /* 140 * notify_input() is not queued and only does anything when 141 * notifications are enabled. 142 */ 143 if (!notify_enabled) 144 return; 145 146 TAILQ_FOREACH(c, &clients, entry) { 147 if (c->flags & CLIENT_CONTROL) 148 control_notify_input(c, wp, input); 149 } 150 } 151 152 void 153 notify_window_layout_changed(struct window *w) 154 { 155 notify_add(NOTIFY_WINDOW_LAYOUT_CHANGED, NULL, NULL, w); 156 notify_drain(); 157 } 158 159 void 160 notify_window_unlinked(struct session *s, struct window *w) 161 { 162 notify_add(NOTIFY_WINDOW_UNLINKED, NULL, s, w); 163 notify_drain(); 164 } 165 166 void 167 notify_window_linked(struct session *s, struct window *w) 168 { 169 notify_add(NOTIFY_WINDOW_LINKED, NULL, s, w); 170 notify_drain(); 171 } 172 173 void 174 notify_window_renamed(struct window *w) 175 { 176 notify_add(NOTIFY_WINDOW_RENAMED, NULL, NULL, w); 177 notify_drain(); 178 } 179 180 void 181 notify_attached_session_changed(struct client *c) 182 { 183 notify_add(NOTIFY_ATTACHED_SESSION_CHANGED, c, NULL, NULL); 184 notify_drain(); 185 } 186 187 void 188 notify_session_renamed(struct session *s) 189 { 190 notify_add(NOTIFY_SESSION_RENAMED, NULL, s, NULL); 191 notify_drain(); 192 } 193 194 void 195 notify_session_created(struct session *s) 196 { 197 notify_add(NOTIFY_SESSION_CREATED, NULL, s, NULL); 198 notify_drain(); 199 } 200 201 void 202 notify_session_closed(struct session *s) 203 { 204 notify_add(NOTIFY_SESSION_CLOSED, NULL, s, NULL); 205 notify_drain(); 206 } 207