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