xref: /openbsd-src/usr.bin/tmux/control-notify.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /* $OpenBSD: control-notify.c,v 1.1 2012/09/03 09:32:38 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 
27 void
28 control_notify_window_layout_changed(struct window *w)
29 {
30 	struct client		*c;
31 	struct session		*s;
32 	struct format_tree	*ft;
33 	struct winlink		*wl;
34 	u_int			 i;
35 	const char		*template;
36 
37 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
38 		c = ARRAY_ITEM(&clients, i);
39 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
40 			continue;
41 		s = c->session;
42 
43 		if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
44 			continue;
45 
46 		/*
47 		 * When the last pane in a window is closed it won't have a
48 		 * layout root and we don't need to inform the client about the
49 		 * layout change because the whole window will go away soon.
50 		 */
51 		if (w->layout_root == NULL)
52 			continue;
53 		template = "%layout-change #{window_id} #{window_layout}";
54 
55 		ft = format_create();
56 		wl = winlink_find_by_window(&s->windows, w);
57 		if (wl != NULL) {
58 			format_winlink(ft, c->session, wl);
59 			control_write(c, "%s", format_expand(ft, template));
60 		}
61 		format_free(ft);
62 	}
63 }
64 
65 void
66 control_notify_window_unlinked(unused struct session *s, struct window *w)
67 {
68 	struct client	*c;
69 	struct session	*cs;
70 	u_int		 i;
71 
72 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
73 		c = ARRAY_ITEM(&clients, i);
74 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
75 			continue;
76 		cs = c->session;
77 
78 		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
79 			control_write(c, "%%window-close %u", w->id);
80 		else
81 			control_write(c, "%%unlinked-window-close %u", w->id);
82 	}
83 }
84 
85 void
86 control_notify_window_linked(unused struct session *s, struct window *w)
87 {
88 	struct client	*c;
89 	struct session	*cs;
90 	u_int		 i;
91 
92 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
93 		c = ARRAY_ITEM(&clients, i);
94 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
95 			continue;
96 		cs = c->session;
97 
98 		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
99 			control_write(c, "%%window-add %u", w->id);
100 		else
101 			control_write(c, "%%unlinked-window-add %u", w->id);
102 	}
103 }
104 
105 void
106 control_notify_window_renamed(struct window *w)
107 {
108 	struct client	*c;
109 	struct session	*s;
110 	u_int		 i;
111 
112 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
113 		c = ARRAY_ITEM(&clients, i);
114 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
115 			continue;
116 		s = c->session;
117 
118 		if (winlink_find_by_window_id(&s->windows, w->id) != NULL) {
119 			control_write(c, "%%window-renamed %u %s",
120 			    w->id, w->name);
121 		} else {
122 			control_write(c, "%%unlinked-window-renamed %u %s",
123 			    w->id, w->name);
124 		}
125 	}
126 }
127 
128 void
129 control_notify_attached_session_changed(struct client *c)
130 {
131 	struct session	*s;
132 
133 	if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
134 		return;
135 	s = c->session;
136 
137 	control_write(c, "%%session-changed %d %s", s->idx, s->name);
138 }
139 
140 void
141 control_notify_session_renamed(struct session *s)
142 {
143 	struct client	*c;
144 	u_int		 i;
145 
146 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
147 		c = ARRAY_ITEM(&clients, i);
148 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session != s)
149 			continue;
150 
151 		control_write(c, "%%session-renamed %s", s->name);
152 	}
153 }
154 
155 void
156 control_notify_session_created(unused struct session *s)
157 {
158 	struct client	*c;
159 	u_int		 i;
160 
161 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
162 		c = ARRAY_ITEM(&clients, i);
163 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
164 			continue;
165 
166 		control_write(c, "%%sessions-changed");
167 	}
168 }
169 
170 void
171 control_notify_session_close(unused struct session *s)
172 {
173 	struct client	*c;
174 	u_int		 i;
175 
176 	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
177 		c = ARRAY_ITEM(&clients, i);
178 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
179 			continue;
180 
181 		control_write(c, "%%sessions-changed");
182 	}
183 }
184