xref: /netbsd-src/external/bsd/tmux/dist/control-notify.c (revision c23f9150cad51fdd442fa1806fac769ae26a1fdd)
1928fc495Schristos /* $OpenBSD$ */
2928fc495Schristos 
3928fc495Schristos /*
4ed4e6cd4Schristos  * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
5928fc495Schristos  * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6928fc495Schristos  *
7928fc495Schristos  * Permission to use, copy, modify, and distribute this software for any
8928fc495Schristos  * purpose with or without fee is hereby granted, provided that the above
9928fc495Schristos  * copyright notice and this permission notice appear in all copies.
10928fc495Schristos  *
11928fc495Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12928fc495Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13928fc495Schristos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14928fc495Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15928fc495Schristos  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16928fc495Schristos  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17928fc495Schristos  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18928fc495Schristos  */
19928fc495Schristos 
20928fc495Schristos #include <sys/types.h>
21928fc495Schristos 
22ed4e6cd4Schristos #include <stdlib.h>
23ed4e6cd4Schristos 
24928fc495Schristos #include "tmux.h"
25928fc495Schristos 
26928fc495Schristos #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
27928fc495Schristos 	((c) != NULL && ((c)->flags & CLIENT_CONTROL))
28928fc495Schristos 
29928fc495Schristos void
control_notify_pane_mode_changed(int pane)30c9ad075bSchristos control_notify_pane_mode_changed(int pane)
31c9ad075bSchristos {
32c9ad075bSchristos 	struct client	*c;
33c9ad075bSchristos 
34c9ad075bSchristos 	TAILQ_FOREACH(c, &clients, entry) {
35c9ad075bSchristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
36c9ad075bSchristos 			continue;
37c9ad075bSchristos 
38c9ad075bSchristos 		control_write(c, "%%pane-mode-changed %%%u", pane);
39c9ad075bSchristos 	}
40c9ad075bSchristos }
41c9ad075bSchristos 
42c9ad075bSchristos void
control_notify_window_layout_changed(struct window * w)43928fc495Schristos control_notify_window_layout_changed(struct window *w)
44928fc495Schristos {
45928fc495Schristos 	struct client	*c;
46928fc495Schristos 	struct session	*s;
47928fc495Schristos 	struct winlink	*wl;
48928fc495Schristos 	const char	*template;
494e179ddaSchristos 	char		*cp;
50ed4e6cd4Schristos 
51ed4e6cd4Schristos 	template = "%layout-change #{window_id} #{window_layout} "
529fb66d81Schristos 	    "#{window_visible_layout} #{window_raw_flags}";
53928fc495Schristos 
545494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
55928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
56928fc495Schristos 			continue;
57928fc495Schristos 		s = c->session;
58928fc495Schristos 
59928fc495Schristos 		if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
60928fc495Schristos 			continue;
61928fc495Schristos 
62928fc495Schristos 		/*
63928fc495Schristos 		 * When the last pane in a window is closed it won't have a
64928fc495Schristos 		 * layout root and we don't need to inform the client about the
65928fc495Schristos 		 * layout change because the whole window will go away soon.
66928fc495Schristos 		 */
67928fc495Schristos 		if (w->layout_root == NULL)
68928fc495Schristos 			continue;
69928fc495Schristos 
70928fc495Schristos 		wl = winlink_find_by_window(&s->windows, w);
71928fc495Schristos 		if (wl != NULL) {
724e179ddaSchristos 			cp = format_single(NULL, template, c, NULL, wl, NULL);
734e179ddaSchristos 			control_write(c, "%s", cp);
744e179ddaSchristos 			free(cp);
75928fc495Schristos 		}
76928fc495Schristos 	}
77928fc495Schristos }
78928fc495Schristos 
79928fc495Schristos void
control_notify_window_pane_changed(struct window * w)80c9ad075bSchristos control_notify_window_pane_changed(struct window *w)
81c9ad075bSchristos {
82c9ad075bSchristos 	struct client	*c;
83c9ad075bSchristos 
84c9ad075bSchristos 	TAILQ_FOREACH(c, &clients, entry) {
85c9ad075bSchristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
86c9ad075bSchristos 			continue;
87c9ad075bSchristos 
88c9ad075bSchristos 		control_write(c, "%%window-pane-changed @%u %%%u", w->id,
89c9ad075bSchristos 		    w->active->id);
90c9ad075bSchristos 	}
91c9ad075bSchristos }
92c9ad075bSchristos 
93c9ad075bSchristos void
control_notify_window_unlinked(__unused struct session * s,struct window * w)94ed4e6cd4Schristos control_notify_window_unlinked(__unused struct session *s, struct window *w)
95928fc495Schristos {
96928fc495Schristos 	struct client	*c;
975494e770Schristos 	struct session	*cs;
98928fc495Schristos 
995494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
100928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
101928fc495Schristos 			continue;
1025494e770Schristos 		cs = c->session;
103928fc495Schristos 
1045494e770Schristos 		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
105928fc495Schristos 			control_write(c, "%%window-close @%u", w->id);
1065494e770Schristos 		else
1075494e770Schristos 			control_write(c, "%%unlinked-window-close @%u", w->id);
108928fc495Schristos 	}
109928fc495Schristos }
110928fc495Schristos 
111928fc495Schristos void
control_notify_window_linked(__unused struct session * s,struct window * w)112ed4e6cd4Schristos control_notify_window_linked(__unused struct session *s, struct window *w)
113928fc495Schristos {
114928fc495Schristos 	struct client	*c;
115928fc495Schristos 	struct session	*cs;
116928fc495Schristos 
1175494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
118928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
119928fc495Schristos 			continue;
120928fc495Schristos 		cs = c->session;
121928fc495Schristos 
122928fc495Schristos 		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
123928fc495Schristos 			control_write(c, "%%window-add @%u", w->id);
124928fc495Schristos 		else
125928fc495Schristos 			control_write(c, "%%unlinked-window-add @%u", w->id);
126928fc495Schristos 	}
127928fc495Schristos }
128928fc495Schristos 
129928fc495Schristos void
control_notify_window_renamed(struct window * w)130928fc495Schristos control_notify_window_renamed(struct window *w)
131928fc495Schristos {
132928fc495Schristos 	struct client	*c;
1335494e770Schristos 	struct session	*cs;
134928fc495Schristos 
1355494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
136928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
137928fc495Schristos 			continue;
1385494e770Schristos 		cs = c->session;
139928fc495Schristos 
1405494e770Schristos 		if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
1415494e770Schristos 			control_write(c, "%%window-renamed @%u %s", w->id,
1425494e770Schristos 			    w->name);
1435494e770Schristos 		} else {
1445494e770Schristos 			control_write(c, "%%unlinked-window-renamed @%u %s",
1455494e770Schristos 			    w->id, w->name);
1465494e770Schristos 		}
147928fc495Schristos 	}
148928fc495Schristos }
149928fc495Schristos 
150928fc495Schristos void
control_notify_client_session_changed(struct client * cc)151c9ad075bSchristos control_notify_client_session_changed(struct client *cc)
152928fc495Schristos {
153c9ad075bSchristos 	struct client	*c;
154928fc495Schristos 	struct session	*s;
155928fc495Schristos 
156c9ad075bSchristos 	if (cc->session == NULL)
157928fc495Schristos 		return;
158c9ad075bSchristos 	s = cc->session;
159928fc495Schristos 
160c9ad075bSchristos 	TAILQ_FOREACH(c, &clients, entry) {
161c9ad075bSchristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
162c9ad075bSchristos 			continue;
163c9ad075bSchristos 
164c9ad075bSchristos 		if (cc == c) {
165c9ad075bSchristos 			control_write(c, "%%session-changed $%u %s", s->id,
166c9ad075bSchristos 			    s->name);
167c9ad075bSchristos 		} else {
168c9ad075bSchristos 			control_write(c, "%%client-session-changed %s $%u %s",
169c9ad075bSchristos 			    cc->name, s->id, s->name);
170c9ad075bSchristos 		}
171c9ad075bSchristos 	}
172928fc495Schristos }
173928fc495Schristos 
174928fc495Schristos void
control_notify_client_detached(struct client * cc)1759fb66d81Schristos control_notify_client_detached(struct client *cc)
1769fb66d81Schristos {
1779fb66d81Schristos 	struct client	*c;
1789fb66d81Schristos 
1799fb66d81Schristos 	TAILQ_FOREACH(c, &clients, entry) {
1809fb66d81Schristos 		if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
1819fb66d81Schristos 			control_write(c, "%%client-detached %s", cc->name);
1829fb66d81Schristos 	}
1839fb66d81Schristos }
1849fb66d81Schristos 
1859fb66d81Schristos void
control_notify_session_renamed(struct session * s)186928fc495Schristos control_notify_session_renamed(struct session *s)
187928fc495Schristos {
188928fc495Schristos 	struct client	*c;
189928fc495Schristos 
1905494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
191928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
192928fc495Schristos 			continue;
193928fc495Schristos 
194928fc495Schristos 		control_write(c, "%%session-renamed $%u %s", s->id, s->name);
195928fc495Schristos 	}
196928fc495Schristos }
197928fc495Schristos 
198928fc495Schristos void
control_notify_session_created(__unused struct session * s)199ed4e6cd4Schristos control_notify_session_created(__unused struct session *s)
200928fc495Schristos {
201928fc495Schristos 	struct client	*c;
202928fc495Schristos 
2035494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
204928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
205928fc495Schristos 			continue;
206928fc495Schristos 
207928fc495Schristos 		control_write(c, "%%sessions-changed");
208928fc495Schristos 	}
209928fc495Schristos }
210928fc495Schristos 
211928fc495Schristos void
control_notify_session_closed(__unused struct session * s)2124e179ddaSchristos control_notify_session_closed(__unused struct session *s)
213928fc495Schristos {
214928fc495Schristos 	struct client	*c;
215928fc495Schristos 
2165494e770Schristos 	TAILQ_FOREACH(c, &clients, entry) {
217928fc495Schristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
218928fc495Schristos 			continue;
219928fc495Schristos 
220928fc495Schristos 		control_write(c, "%%sessions-changed");
221928fc495Schristos 	}
222928fc495Schristos }
223c9ad075bSchristos 
224c9ad075bSchristos void
control_notify_session_window_changed(struct session * s)225c9ad075bSchristos control_notify_session_window_changed(struct session *s)
226c9ad075bSchristos {
227c9ad075bSchristos 	struct client	*c;
228c9ad075bSchristos 
229c9ad075bSchristos 	TAILQ_FOREACH(c, &clients, entry) {
230c9ad075bSchristos 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
231c9ad075bSchristos 			continue;
232c9ad075bSchristos 
233c9ad075bSchristos 		control_write(c, "%%session-window-changed $%u @%u", s->id,
234c9ad075bSchristos 		    s->curw->window->id);
235c9ad075bSchristos 	}
236c9ad075bSchristos }
237*c23f9150Swiz 
238*c23f9150Swiz void
control_notify_paste_buffer_changed(const char * name)239*c23f9150Swiz control_notify_paste_buffer_changed(const char *name)
240*c23f9150Swiz {
241*c23f9150Swiz 	struct client	*c;
242*c23f9150Swiz 
243*c23f9150Swiz 	TAILQ_FOREACH(c, &clients, entry) {
244*c23f9150Swiz 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
245*c23f9150Swiz 			continue;
246*c23f9150Swiz 
247*c23f9150Swiz 		control_write(c, "%%paste-buffer-changed %s", name);
248*c23f9150Swiz 	}
249*c23f9150Swiz }
250*c23f9150Swiz 
251*c23f9150Swiz void
control_notify_paste_buffer_deleted(const char * name)252*c23f9150Swiz control_notify_paste_buffer_deleted(const char *name)
253*c23f9150Swiz {
254*c23f9150Swiz 	struct client	*c;
255*c23f9150Swiz 
256*c23f9150Swiz 	TAILQ_FOREACH(c, &clients, entry) {
257*c23f9150Swiz 		if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
258*c23f9150Swiz 			continue;
259*c23f9150Swiz 
260*c23f9150Swiz 		control_write(c, "%%paste-buffer-deleted %s", name);
261*c23f9150Swiz 	}
262*c23f9150Swiz }
263