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