Annotation of src/usr.bin/tmux/control-notify.c, Revision 1.14
1.14 ! nicm 1: /* $OpenBSD: control-notify.c,v 1.13 2015/11/18 14:27:44 nicm Exp $ */
1.1 nicm 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:
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
63: control_notify_window_layout_changed(struct window *w)
64: {
65: struct client *c;
66: struct session *s;
67: struct format_tree *ft;
68: struct winlink *wl;
69: const char *template;
1.12 nicm 70: char *expanded;
71:
72: template = "%layout-change #{window_id} #{window_layout} "
73: "#{window_visible_layout} #{window_flags}";
1.1 nicm 74:
1.11 nicm 75: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 76: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
77: continue;
78: s = c->session;
79:
80: if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
81: continue;
82:
83: /*
84: * When the last pane in a window is closed it won't have a
85: * layout root and we don't need to inform the client about the
86: * layout change because the whole window will go away soon.
87: */
88: if (w->layout_root == NULL)
89: continue;
90:
1.14 ! nicm 91: ft = format_create(0);
1.1 nicm 92: wl = winlink_find_by_window(&s->windows, w);
93: if (wl != NULL) {
1.10 nicm 94: format_defaults(ft, c, NULL, wl, NULL);
1.12 nicm 95: expanded = format_expand(ft, template);
96: control_write(c, "%s", expanded);
97: free(expanded);
1.1 nicm 98: }
99: format_free(ft);
100: }
101: }
102:
103: void
1.13 nicm 104: control_notify_window_unlinked(__unused struct session *s, struct window *w)
1.1 nicm 105: {
106: struct client *c;
1.9 nicm 107: struct session *cs;
1.1 nicm 108:
1.11 nicm 109: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 110: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
111: continue;
1.9 nicm 112: cs = c->session;
1.1 nicm 113:
1.9 nicm 114: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
115: control_write(c, "%%window-close @%u", w->id);
116: else
117: control_write(c, "%%unlinked-window-close @%u", w->id);
1.1 nicm 118: }
119: }
120:
121: void
1.13 nicm 122: control_notify_window_linked(__unused struct session *s, struct window *w)
1.1 nicm 123: {
124: struct client *c;
125: struct session *cs;
126:
1.11 nicm 127: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 128: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
129: continue;
130: cs = c->session;
131:
132: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
1.7 nicm 133: control_write(c, "%%window-add @%u", w->id);
1.1 nicm 134: else
1.7 nicm 135: control_write(c, "%%unlinked-window-add @%u", w->id);
1.1 nicm 136: }
137: }
138:
139: void
140: control_notify_window_renamed(struct window *w)
141: {
142: struct client *c;
1.9 nicm 143: struct session *cs;
1.1 nicm 144:
1.11 nicm 145: TAILQ_FOREACH(c, &clients, entry) {
1.1 nicm 146: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
147: continue;
1.9 nicm 148: cs = c->session;
1.1 nicm 149:
1.9 nicm 150: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
151: control_write(c, "%%window-renamed @%u %s", w->id,
152: w->name);
153: } else {
154: control_write(c, "%%unlinked-window-renamed @%u %s",
155: w->id, w->name);
156: }
1.1 nicm 157: }
158: }
159:
160: void
161: control_notify_attached_session_changed(struct client *c)
162: {
163: struct session *s;
164:
165: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
166: return;
167: s = c->session;
168:
1.7 nicm 169: control_write(c, "%%session-changed $%u %s", s->id, s->name);
1.1 nicm 170: }
171:
172: void
173: control_notify_session_renamed(struct session *s)
174: {
175: struct client *c;
176:
1.11 nicm 177: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 178: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 179: continue;
180:
1.7 nicm 181: control_write(c, "%%session-renamed $%u %s", s->id, s->name);
1.1 nicm 182: }
183: }
184:
185: void
1.13 nicm 186: control_notify_session_created(__unused struct session *s)
1.1 nicm 187: {
188: struct client *c;
189:
1.11 nicm 190: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 191: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 192: continue;
193:
194: control_write(c, "%%sessions-changed");
195: }
196: }
197:
198: void
1.13 nicm 199: control_notify_session_close(__unused struct session *s)
1.1 nicm 200: {
201: struct client *c;
202:
1.11 nicm 203: TAILQ_FOREACH(c, &clients, entry) {
1.7 nicm 204: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 205: continue;
206:
207: control_write(c, "%%sessions-changed");
208: }
209: }