Annotation of src/usr.bin/tmux/control-notify.c, Revision 1.21
1.21 ! nicm 1: /* $OpenBSD: control-notify.c,v 1.20 2017/03/08 13:36:12 nicm Exp $ */
1.1 nicm 2:
3: /*
1.16 nicm 4: * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 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:
1.12 nicm 22: #include <stdlib.h>
23:
1.1 nicm 24: #include "tmux.h"
25:
26: #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
27: ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
1.2 nicm 28:
29: void
30: control_notify_input(struct client *c, struct window_pane *wp,
31: struct evbuffer *input)
32: {
33: u_char *buf;
34: size_t len;
35: struct evbuffer *message;
36: u_int i;
37:
38: if (c->session == NULL)
39: return;
40:
41: buf = EVBUFFER_DATA(input);
42: len = EVBUFFER_LENGTH(input);
43:
44: /*
45: * Only write input if the window pane is linked to a window belonging
46: * to the client's session.
47: */
48: if (winlink_find_by_window(&c->session->windows, wp->window) != NULL) {
49: message = evbuffer_new();
1.7 nicm 50: evbuffer_add_printf(message, "%%output %%%u ", wp->id);
1.6 nicm 51: for (i = 0; i < len; i++) {
52: if (buf[i] < ' ' || buf[i] == '\\')
53: evbuffer_add_printf(message, "\\%03o", buf[i]);
54: else
55: evbuffer_add_printf(message, "%c", buf[i]);
56: }
1.2 nicm 57: control_write_buffer(c, message);
58: evbuffer_free(message);
59: }
60: }
1.1 nicm 61:
62: void
1.21 ! nicm 63: control_notify_pane_mode_changed(int pane)
! 64: {
! 65: struct client *c;
! 66:
! 67: TAILQ_FOREACH(c, &clients, entry) {
! 68: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
! 69: continue;
! 70:
! 71: control_write(c, "%%pane-mode-changed %%%u", pane);
! 72: }
! 73: }
! 74:
! 75: void
1.1 nicm 76: control_notify_window_layout_changed(struct window *w)
77: {
1.21 ! nicm 78: struct client *c;
! 79: struct session *s;
! 80: struct winlink *wl;
! 81: const char *template;
! 82: char *cp;
1.12 nicm 83:
84: template = "%layout-change #{window_id} #{window_layout} "
85: "#{window_visible_layout} #{window_flags}";
1.1 nicm 86:
1.11 nicm 87: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 88: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
89: continue;
90: s = c->session;
91:
92: if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
93: continue;
94:
95: /*
96: * When the last pane in a window is closed it won't have a
97: * layout root and we don't need to inform the client about the
98: * layout change because the whole window will go away soon.
99: */
100: if (w->layout_root == NULL)
101: continue;
102:
103: wl = winlink_find_by_window(&s->windows, w);
104: if (wl != NULL) {
1.20 nicm 105: cp = format_single(NULL, template, c, NULL, wl, NULL);
106: control_write(c, "%s", cp);
107: free(cp);
1.1 nicm 108: }
109: }
110: }
111:
112: void
1.21 ! nicm 113: control_notify_window_pane_changed(struct window *w)
! 114: {
! 115: struct client *c;
! 116:
! 117: TAILQ_FOREACH(c, &clients, entry) {
! 118: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
! 119: continue;
! 120:
! 121: control_write(c, "%%window-pane-changed @%u %%%u", w->id,
! 122: w->active->id);
! 123: }
! 124: }
! 125:
! 126: void
1.13 nicm 127: control_notify_window_unlinked(__unused struct session *s, struct window *w)
1.1 nicm 128: {
129: struct client *c;
1.9 nicm 130: struct session *cs;
1.1 nicm 131:
1.11 nicm 132: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 133: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
134: continue;
1.9 nicm 135: cs = c->session;
1.1 nicm 136:
1.9 nicm 137: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
138: control_write(c, "%%window-close @%u", w->id);
139: else
140: control_write(c, "%%unlinked-window-close @%u", w->id);
1.1 nicm 141: }
142: }
143:
144: void
1.13 nicm 145: control_notify_window_linked(__unused struct session *s, struct window *w)
1.1 nicm 146: {
147: struct client *c;
148: struct session *cs;
149:
1.11 nicm 150: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 151: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
152: continue;
153: cs = c->session;
154:
155: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
1.7 nicm 156: control_write(c, "%%window-add @%u", w->id);
1.1 nicm 157: else
1.7 nicm 158: control_write(c, "%%unlinked-window-add @%u", w->id);
1.1 nicm 159: }
160: }
161:
162: void
163: control_notify_window_renamed(struct window *w)
164: {
165: struct client *c;
1.9 nicm 166: struct session *cs;
1.1 nicm 167:
1.11 nicm 168: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 169: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
170: continue;
1.9 nicm 171: cs = c->session;
1.1 nicm 172:
1.9 nicm 173: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
174: control_write(c, "%%window-renamed @%u %s", w->id,
175: w->name);
176: } else {
177: control_write(c, "%%unlinked-window-renamed @%u %s",
178: w->id, w->name);
179: }
1.1 nicm 180: }
181: }
182:
183: void
1.21 ! nicm 184: control_notify_client_session_changed(struct client *cc)
1.1 nicm 185: {
1.21 ! nicm 186: struct client *c;
1.1 nicm 187: struct session *s;
188:
1.21 ! nicm 189: if (cc->session == NULL)
1.1 nicm 190: return;
1.21 ! nicm 191: s = cc->session;
1.1 nicm 192:
1.21 ! nicm 193: TAILQ_FOREACH(c, &clients, entry) {
! 194: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
! 195: continue;
! 196:
! 197: if (cc == c) {
! 198: control_write(c, "%%session-changed $%u %s", s->id,
! 199: s->name);
! 200: } else {
! 201: control_write(c, "%%client-session-changed %s $%u %s",
! 202: cc->name, s->id, s->name);
! 203: }
! 204: }
1.1 nicm 205: }
206:
207: void
208: control_notify_session_renamed(struct session *s)
209: {
210: struct client *c;
211:
1.11 nicm 212: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 213: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 214: continue;
215:
1.7 nicm 216: control_write(c, "%%session-renamed $%u %s", s->id, s->name);
1.1 nicm 217: }
218: }
219:
220: void
1.13 nicm 221: control_notify_session_created(__unused struct session *s)
1.1 nicm 222: {
223: struct client *c;
224:
1.11 nicm 225: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 226: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 227: continue;
228:
229: control_write(c, "%%sessions-changed");
230: }
231: }
232:
233: void
1.17 nicm 234: control_notify_session_closed(__unused struct session *s)
1.1 nicm 235: {
236: struct client *c;
237:
1.11 nicm 238: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 239: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 240: continue;
241:
242: control_write(c, "%%sessions-changed");
1.21 ! nicm 243: }
! 244: }
! 245:
! 246: void
! 247: control_notify_session_window_changed(struct session *s)
! 248: {
! 249: struct client *c;
! 250:
! 251: TAILQ_FOREACH(c, &clients, entry) {
! 252: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
! 253: continue;
! 254:
! 255: control_write(c, "%%session-window-changed $%u @%u", s->id,
! 256: s->curw->window->id);
1.1 nicm 257: }
258: }