Annotation of src/usr.bin/tmux/control-notify.c, Revision 1.9
1.9 ! nicm 1: /* $OpenBSD: control-notify.c,v 1.8 2013/03/26 10:54:48 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:
22: #include "tmux.h"
23:
24: #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
25: ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
1.2 nicm 26:
27: void
28: control_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();
1.7 nicm 48: evbuffer_add_printf(message, "%%output %%%u ", wp->id);
1.6 nicm 49: for (i = 0; i < len; i++) {
50: if (buf[i] < ' ' || buf[i] == '\\')
51: evbuffer_add_printf(message, "\\%03o", buf[i]);
52: else
53: evbuffer_add_printf(message, "%c", buf[i]);
54: }
1.2 nicm 55: control_write_buffer(c, message);
56: evbuffer_free(message);
57: }
58: }
1.1 nicm 59:
60: void
61: control_notify_window_layout_changed(struct window *w)
62: {
63: struct client *c;
64: struct session *s;
65: struct format_tree *ft;
66: struct winlink *wl;
67: u_int i;
68: const char *template;
69:
70: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
71: c = ARRAY_ITEM(&clients, i);
72: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
73: continue;
74: s = c->session;
75:
76: if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
77: continue;
78:
79: /*
80: * When the last pane in a window is closed it won't have a
81: * layout root and we don't need to inform the client about the
82: * layout change because the whole window will go away soon.
83: */
84: if (w->layout_root == NULL)
85: continue;
86: template = "%layout-change #{window_id} #{window_layout}";
87:
88: ft = format_create();
89: wl = winlink_find_by_window(&s->windows, w);
90: if (wl != NULL) {
91: format_winlink(ft, c->session, wl);
92: control_write(c, "%s", format_expand(ft, template));
93: }
94: format_free(ft);
95: }
96: }
97:
98: void
99: control_notify_window_unlinked(unused struct session *s, struct window *w)
100: {
101: struct client *c;
1.9 ! nicm 102: struct session *cs;
1.1 nicm 103: u_int i;
104:
105: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
106: c = ARRAY_ITEM(&clients, i);
107: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
108: continue;
1.9 ! nicm 109: cs = c->session;
1.1 nicm 110:
1.9 ! nicm 111: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
! 112: control_write(c, "%%window-close @%u", w->id);
! 113: else
! 114: control_write(c, "%%unlinked-window-close @%u", w->id);
1.1 nicm 115: }
116: }
117:
118: void
119: control_notify_window_linked(unused struct session *s, struct window *w)
120: {
121: struct client *c;
122: struct session *cs;
123: u_int i;
124:
125: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
126: c = ARRAY_ITEM(&clients, i);
127: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
128: continue;
129: cs = c->session;
130:
131: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
1.7 nicm 132: control_write(c, "%%window-add @%u", w->id);
1.1 nicm 133: else
1.7 nicm 134: control_write(c, "%%unlinked-window-add @%u", w->id);
1.1 nicm 135: }
136: }
137:
138: void
139: control_notify_window_renamed(struct window *w)
140: {
141: struct client *c;
1.9 ! nicm 142: struct session *cs;
1.1 nicm 143: u_int i;
144:
145: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
146: c = ARRAY_ITEM(&clients, i);
147: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
148: continue;
1.9 ! nicm 149: cs = c->session;
1.1 nicm 150:
1.9 ! nicm 151: if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
! 152: control_write(c, "%%window-renamed @%u %s", w->id,
! 153: w->name);
! 154: } else {
! 155: control_write(c, "%%unlinked-window-renamed @%u %s",
! 156: w->id, w->name);
! 157: }
1.1 nicm 158: }
159: }
160:
161: void
162: control_notify_attached_session_changed(struct client *c)
163: {
164: struct session *s;
165:
166: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
167: return;
168: s = c->session;
169:
1.7 nicm 170: control_write(c, "%%session-changed $%u %s", s->id, s->name);
1.1 nicm 171: }
172:
173: void
174: control_notify_session_renamed(struct session *s)
175: {
176: struct client *c;
177: u_int i;
178:
179: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
180: c = ARRAY_ITEM(&clients, i);
1.7 nicm 181: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 182: continue;
183:
1.7 nicm 184: control_write(c, "%%session-renamed $%u %s", s->id, s->name);
1.1 nicm 185: }
186: }
187:
188: void
189: control_notify_session_created(unused struct session *s)
190: {
191: struct client *c;
192: u_int i;
193:
194: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
195: c = ARRAY_ITEM(&clients, i);
1.7 nicm 196: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 197: continue;
198:
199: control_write(c, "%%sessions-changed");
200: }
201: }
202:
203: void
204: control_notify_session_close(unused struct session *s)
205: {
206: struct client *c;
207: u_int i;
208:
209: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
210: c = ARRAY_ITEM(&clients, i);
1.7 nicm 211: if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
1.1 nicm 212: continue;
213:
214: control_write(c, "%%sessions-changed");
215: }
216: }