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