control-notify.c revision 1.5
1/* $OpenBSD: control-notify.c,v 1.5 2013/03/25 11:38:43 nicm Exp $ */ 2 3/* 4 * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net> 5 * Copyright (c) 2012 George Nachman <tmux@georgester.com> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 16 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 17 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/types.h> 21 22#include "tmux.h" 23 24#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \ 25 ((c) != NULL && ((c)->flags & CLIENT_CONTROL)) 26 27void 28control_notify_input(struct client *c, struct window_pane *wp, 29 struct evbuffer *input) 30{ 31 u_char *buf; 32 size_t len; 33 struct evbuffer *message; 34 u_int i; 35 36 if (c->session == NULL) 37 return; 38 39 buf = EVBUFFER_DATA(input); 40 len = EVBUFFER_LENGTH(input); 41 42 /* 43 * Only write input if the window pane is linked to a window belonging 44 * to the client's session. 45 */ 46 if (winlink_find_by_window(&c->session->windows, wp->window) != NULL) { 47 message = evbuffer_new(); 48 evbuffer_add_printf(message, "%%output %u ", wp->id); 49 for (i = 0; i < len; i++) 50 evbuffer_add_printf(message, "%02hhx", buf[i]); 51 control_write_buffer(c, message); 52 evbuffer_free(message); 53 } 54} 55 56void 57control_notify_window_layout_changed(struct window *w) 58{ 59 struct client *c; 60 struct session *s; 61 struct format_tree *ft; 62 struct winlink *wl; 63 u_int i; 64 const char *template; 65 66 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 67 c = ARRAY_ITEM(&clients, i); 68 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 69 continue; 70 s = c->session; 71 72 if (winlink_find_by_window_id(&s->windows, w->id) == NULL) 73 continue; 74 75 /* 76 * When the last pane in a window is closed it won't have a 77 * layout root and we don't need to inform the client about the 78 * layout change because the whole window will go away soon. 79 */ 80 if (w->layout_root == NULL) 81 continue; 82 template = "%layout-change #{window_id} #{window_layout}"; 83 84 ft = format_create(); 85 wl = winlink_find_by_window(&s->windows, w); 86 if (wl != NULL) { 87 format_winlink(ft, c->session, wl); 88 control_write(c, "%s", format_expand(ft, template)); 89 } 90 format_free(ft); 91 } 92} 93 94void 95control_notify_window_unlinked(unused struct session *s, struct window *w) 96{ 97 struct client *c; 98 struct session *cs; 99 u_int i; 100 101 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 102 c = ARRAY_ITEM(&clients, i); 103 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 104 continue; 105 cs = c->session; 106 107 control_write(c, "%%window-close %u", w->id); 108 } 109} 110 111void 112control_notify_window_linked(unused struct session *s, struct window *w) 113{ 114 struct client *c; 115 struct session *cs; 116 u_int i; 117 118 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 119 c = ARRAY_ITEM(&clients, i); 120 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 121 continue; 122 cs = c->session; 123 124 if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) 125 control_write(c, "%%window-add %u", w->id); 126 else 127 control_write(c, "%%unlinked-window-add %u", w->id); 128 } 129} 130 131void 132control_notify_window_renamed(struct window *w) 133{ 134 struct client *c; 135 struct session *s; 136 u_int i; 137 138 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 139 c = ARRAY_ITEM(&clients, i); 140 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 141 continue; 142 s = c->session; 143 144 control_write(c, "%%window-renamed %u %s", w->id, w->name); 145 } 146} 147 148void 149control_notify_attached_session_changed(struct client *c) 150{ 151 struct session *s; 152 153 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 154 return; 155 s = c->session; 156 157 control_write(c, "%%session-changed %u %s", s->id, s->name); 158} 159 160void 161control_notify_session_renamed(struct session *s) 162{ 163 struct client *c; 164 u_int i; 165 166 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 167 c = ARRAY_ITEM(&clients, i); 168 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session != s) 169 continue; 170 171 control_write(c, "%%session-renamed %s", s->name); 172 } 173} 174 175void 176control_notify_session_created(unused struct session *s) 177{ 178 struct client *c; 179 u_int i; 180 181 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 182 c = ARRAY_ITEM(&clients, i); 183 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 184 continue; 185 186 control_write(c, "%%sessions-changed"); 187 } 188} 189 190void 191control_notify_session_close(unused struct session *s) 192{ 193 struct client *c; 194 u_int i; 195 196 for (i = 0; i < ARRAY_LENGTH(&clients); i++) { 197 c = ARRAY_ITEM(&clients, i); 198 if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) 199 continue; 200 201 control_write(c, "%%sessions-changed"); 202 } 203} 204