1*99acee14Snicm /* $OpenBSD: control-notify.c,v 1.31 2022/10/28 13:00:02 nicm Exp $ */
2d5dd2023Snicm
3d5dd2023Snicm /*
498ca8272Snicm * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
5d5dd2023Snicm * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6d5dd2023Snicm *
7d5dd2023Snicm * Permission to use, copy, modify, and distribute this software for any
8d5dd2023Snicm * purpose with or without fee is hereby granted, provided that the above
9d5dd2023Snicm * copyright notice and this permission notice appear in all copies.
10d5dd2023Snicm *
11d5dd2023Snicm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12d5dd2023Snicm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13d5dd2023Snicm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14d5dd2023Snicm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15d5dd2023Snicm * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16d5dd2023Snicm * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17d5dd2023Snicm * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18d5dd2023Snicm */
19d5dd2023Snicm
20d5dd2023Snicm #include <sys/types.h>
21d5dd2023Snicm
2278f99b37Snicm #include <stdlib.h>
2378f99b37Snicm
24d5dd2023Snicm #include "tmux.h"
25d5dd2023Snicm
26d5dd2023Snicm #define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
27d5dd2023Snicm ((c) != NULL && ((c)->flags & CLIENT_CONTROL))
28d5dd2023Snicm
29d5dd2023Snicm void
control_notify_pane_mode_changed(int pane)303c14ce20Snicm control_notify_pane_mode_changed(int pane)
313c14ce20Snicm {
323c14ce20Snicm struct client *c;
333c14ce20Snicm
343c14ce20Snicm TAILQ_FOREACH(c, &clients, entry) {
353c14ce20Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
363c14ce20Snicm continue;
373c14ce20Snicm
383c14ce20Snicm control_write(c, "%%pane-mode-changed %%%u", pane);
393c14ce20Snicm }
403c14ce20Snicm }
413c14ce20Snicm
423c14ce20Snicm void
control_notify_window_layout_changed(struct window * w)43d5dd2023Snicm control_notify_window_layout_changed(struct window *w)
44d5dd2023Snicm {
45d5dd2023Snicm struct client *c;
46d5dd2023Snicm struct session *s;
47d5dd2023Snicm struct winlink *wl;
48d5dd2023Snicm const char *template;
49e35be1bbSnicm char *cp;
5078f99b37Snicm
5178f99b37Snicm template = "%layout-change #{window_id} #{window_layout} "
52b1a38154Snicm "#{window_visible_layout} #{window_raw_flags}";
53d5dd2023Snicm
5482873134Snicm TAILQ_FOREACH(c, &clients, entry) {
55d5dd2023Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
56d5dd2023Snicm continue;
57d5dd2023Snicm s = c->session;
58d5dd2023Snicm
59d5dd2023Snicm if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
60d5dd2023Snicm continue;
61d5dd2023Snicm
62d5dd2023Snicm /*
63d5dd2023Snicm * When the last pane in a window is closed it won't have a
64d5dd2023Snicm * layout root and we don't need to inform the client about the
65d5dd2023Snicm * layout change because the whole window will go away soon.
66d5dd2023Snicm */
67d5dd2023Snicm if (w->layout_root == NULL)
68d5dd2023Snicm continue;
69d5dd2023Snicm
70d5dd2023Snicm wl = winlink_find_by_window(&s->windows, w);
71d5dd2023Snicm if (wl != NULL) {
72e35be1bbSnicm cp = format_single(NULL, template, c, NULL, wl, NULL);
73e35be1bbSnicm control_write(c, "%s", cp);
74e35be1bbSnicm free(cp);
75d5dd2023Snicm }
76d5dd2023Snicm }
77d5dd2023Snicm }
78d5dd2023Snicm
79d5dd2023Snicm void
control_notify_window_pane_changed(struct window * w)803c14ce20Snicm control_notify_window_pane_changed(struct window *w)
813c14ce20Snicm {
823c14ce20Snicm struct client *c;
833c14ce20Snicm
843c14ce20Snicm TAILQ_FOREACH(c, &clients, entry) {
853c14ce20Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
863c14ce20Snicm continue;
873c14ce20Snicm
883c14ce20Snicm control_write(c, "%%window-pane-changed @%u %%%u", w->id,
893c14ce20Snicm w->active->id);
903c14ce20Snicm }
913c14ce20Snicm }
923c14ce20Snicm
933c14ce20Snicm void
control_notify_window_unlinked(__unused struct session * s,struct window * w)94d0e2e7f1Snicm control_notify_window_unlinked(__unused struct session *s, struct window *w)
95d5dd2023Snicm {
96d5dd2023Snicm struct client *c;
973e8f9303Snicm struct session *cs;
98d5dd2023Snicm
9982873134Snicm TAILQ_FOREACH(c, &clients, entry) {
100d5dd2023Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
101d5dd2023Snicm continue;
1023e8f9303Snicm cs = c->session;
103d5dd2023Snicm
1043e8f9303Snicm if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
1059eac9144Snicm control_write(c, "%%window-close @%u", w->id);
1063e8f9303Snicm else
1073e8f9303Snicm control_write(c, "%%unlinked-window-close @%u", w->id);
108d5dd2023Snicm }
109d5dd2023Snicm }
110d5dd2023Snicm
111d5dd2023Snicm void
control_notify_window_linked(__unused struct session * s,struct window * w)112d0e2e7f1Snicm control_notify_window_linked(__unused struct session *s, struct window *w)
113d5dd2023Snicm {
114d5dd2023Snicm struct client *c;
115d5dd2023Snicm struct session *cs;
116d5dd2023Snicm
11782873134Snicm TAILQ_FOREACH(c, &clients, entry) {
118d5dd2023Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
119d5dd2023Snicm continue;
120d5dd2023Snicm cs = c->session;
121d5dd2023Snicm
122d5dd2023Snicm if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
1239eac9144Snicm control_write(c, "%%window-add @%u", w->id);
124d5dd2023Snicm else
1259eac9144Snicm control_write(c, "%%unlinked-window-add @%u", w->id);
126d5dd2023Snicm }
127d5dd2023Snicm }
128d5dd2023Snicm
129d5dd2023Snicm void
control_notify_window_renamed(struct window * w)130d5dd2023Snicm control_notify_window_renamed(struct window *w)
131d5dd2023Snicm {
132d5dd2023Snicm struct client *c;
1333e8f9303Snicm struct session *cs;
134d5dd2023Snicm
13582873134Snicm TAILQ_FOREACH(c, &clients, entry) {
136d5dd2023Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
137d5dd2023Snicm continue;
1383e8f9303Snicm cs = c->session;
139d5dd2023Snicm
1403e8f9303Snicm if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
1413e8f9303Snicm control_write(c, "%%window-renamed @%u %s", w->id,
1423e8f9303Snicm w->name);
1433e8f9303Snicm } else {
1443e8f9303Snicm control_write(c, "%%unlinked-window-renamed @%u %s",
1453e8f9303Snicm w->id, w->name);
1463e8f9303Snicm }
147d5dd2023Snicm }
148d5dd2023Snicm }
149d5dd2023Snicm
150d5dd2023Snicm void
control_notify_client_session_changed(struct client * cc)1513c14ce20Snicm control_notify_client_session_changed(struct client *cc)
152d5dd2023Snicm {
1533c14ce20Snicm struct client *c;
154d5dd2023Snicm struct session *s;
155d5dd2023Snicm
1563c14ce20Snicm if (cc->session == NULL)
157d5dd2023Snicm return;
1583c14ce20Snicm s = cc->session;
159d5dd2023Snicm
1603c14ce20Snicm TAILQ_FOREACH(c, &clients, entry) {
1613c14ce20Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
1623c14ce20Snicm continue;
1633c14ce20Snicm
1643c14ce20Snicm if (cc == c) {
1653c14ce20Snicm control_write(c, "%%session-changed $%u %s", s->id,
1663c14ce20Snicm s->name);
1673c14ce20Snicm } else {
1683c14ce20Snicm control_write(c, "%%client-session-changed %s $%u %s",
1693c14ce20Snicm cc->name, s->id, s->name);
1703c14ce20Snicm }
1713c14ce20Snicm }
172d5dd2023Snicm }
173d5dd2023Snicm
174d5dd2023Snicm void
control_notify_client_detached(struct client * cc)1752b1e50bbSnicm control_notify_client_detached(struct client *cc)
1762b1e50bbSnicm {
1772b1e50bbSnicm struct client *c;
1782b1e50bbSnicm
1792b1e50bbSnicm TAILQ_FOREACH(c, &clients, entry) {
1802b1e50bbSnicm if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
1812b1e50bbSnicm control_write(c, "%%client-detached %s", cc->name);
1822b1e50bbSnicm }
1832b1e50bbSnicm }
1842b1e50bbSnicm
1852b1e50bbSnicm void
control_notify_session_renamed(struct session * s)186d5dd2023Snicm control_notify_session_renamed(struct session *s)
187d5dd2023Snicm {
188d5dd2023Snicm struct client *c;
189d5dd2023Snicm
19082873134Snicm TAILQ_FOREACH(c, &clients, entry) {
1919eac9144Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
192d5dd2023Snicm continue;
193d5dd2023Snicm
1949eac9144Snicm control_write(c, "%%session-renamed $%u %s", s->id, s->name);
195d5dd2023Snicm }
196d5dd2023Snicm }
197d5dd2023Snicm
198d5dd2023Snicm void
control_notify_session_created(__unused struct session * s)199d0e2e7f1Snicm control_notify_session_created(__unused struct session *s)
200d5dd2023Snicm {
201d5dd2023Snicm struct client *c;
202d5dd2023Snicm
20382873134Snicm TAILQ_FOREACH(c, &clients, entry) {
2049eac9144Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
205d5dd2023Snicm continue;
206d5dd2023Snicm
207d5dd2023Snicm control_write(c, "%%sessions-changed");
208d5dd2023Snicm }
209d5dd2023Snicm }
210d5dd2023Snicm
211d5dd2023Snicm void
control_notify_session_closed(__unused struct session * s)21283f26c8fSnicm control_notify_session_closed(__unused struct session *s)
213d5dd2023Snicm {
214d5dd2023Snicm struct client *c;
215d5dd2023Snicm
21682873134Snicm TAILQ_FOREACH(c, &clients, entry) {
2179eac9144Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
218d5dd2023Snicm continue;
219d5dd2023Snicm
220d5dd2023Snicm control_write(c, "%%sessions-changed");
221d5dd2023Snicm }
222d5dd2023Snicm }
2233c14ce20Snicm
2243c14ce20Snicm void
control_notify_session_window_changed(struct session * s)2253c14ce20Snicm control_notify_session_window_changed(struct session *s)
2263c14ce20Snicm {
2273c14ce20Snicm struct client *c;
2283c14ce20Snicm
2293c14ce20Snicm TAILQ_FOREACH(c, &clients, entry) {
2303c14ce20Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
2313c14ce20Snicm continue;
2323c14ce20Snicm
2333c14ce20Snicm control_write(c, "%%session-window-changed $%u @%u", s->id,
2343c14ce20Snicm s->curw->window->id);
2353c14ce20Snicm }
2363c14ce20Snicm }
237d79e52f9Snicm
238d79e52f9Snicm void
control_notify_paste_buffer_changed(const char * name)239d79e52f9Snicm control_notify_paste_buffer_changed(const char *name)
240d79e52f9Snicm {
241d79e52f9Snicm struct client *c;
242d79e52f9Snicm
243d79e52f9Snicm TAILQ_FOREACH(c, &clients, entry) {
244d79e52f9Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
245d79e52f9Snicm continue;
246d79e52f9Snicm
247*99acee14Snicm control_write(c, "%%paste-buffer-changed %s", name);
248*99acee14Snicm }
249*99acee14Snicm }
250*99acee14Snicm
251*99acee14Snicm void
control_notify_paste_buffer_deleted(const char * name)252*99acee14Snicm control_notify_paste_buffer_deleted(const char *name)
253*99acee14Snicm {
254*99acee14Snicm struct client *c;
255*99acee14Snicm
256*99acee14Snicm TAILQ_FOREACH(c, &clients, entry) {
257*99acee14Snicm if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
258*99acee14Snicm continue;
259*99acee14Snicm
260*99acee14Snicm control_write(c, "%%paste-buffer-deleted %s", name);
261d79e52f9Snicm }
262d79e52f9Snicm }
263