Coverage Report

Created: 2026-04-27 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tmux/control-notify.c
Line
Count
Source
1
/* $OpenBSD$ */
2
3
/*
4
 * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
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 <stdlib.h>
23
24
#include "tmux.h"
25
26
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
27
0
  ((c) != NULL && ((c)->flags & CLIENT_CONTROL) && \
28
0
   (c)->control_state != NULL)
29
30
void
31
control_notify_pane_mode_changed(int pane)
32
0
{
33
0
  struct client *c;
34
35
0
  TAILQ_FOREACH(c, &clients, entry) {
36
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
37
0
      continue;
38
39
0
    control_write(c, "%%pane-mode-changed %%%u", pane);
40
0
  }
41
0
}
42
43
void
44
control_notify_window_layout_changed(struct window *w)
45
0
{
46
0
  struct client *c;
47
0
  struct session  *s;
48
0
  struct winlink  *wl;
49
0
  const char  *template;
50
0
  char    *cp;
51
52
0
  template = "%layout-change #{window_id} #{window_layout} "
53
0
      "#{window_visible_layout} #{window_raw_flags}";
54
55
  /*
56
   * When the last pane in a window is closed it won't have a layout root
57
   * and we don't need to inform the client about the layout change
58
   * because the whole window will go away soon.
59
   */
60
0
  wl = TAILQ_FIRST(&w->winlinks);
61
0
  if (wl == NULL || w->layout_root == NULL)
62
0
    return;
63
0
  cp = format_single(NULL, template, NULL, NULL, wl, NULL);
64
65
0
  TAILQ_FOREACH(c, &clients, entry) {
66
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
67
0
      continue;
68
0
    s = c->session;
69
0
    if (winlink_find_by_window_id(&s->windows, w->id) != NULL)
70
0
      control_write(c, "%s", cp);
71
0
  }
72
0
  free(cp);
73
0
}
74
75
void
76
control_notify_window_pane_changed(struct window *w)
77
0
{
78
0
  struct client *c;
79
80
0
  TAILQ_FOREACH(c, &clients, entry) {
81
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
82
0
      continue;
83
84
0
    control_write(c, "%%window-pane-changed @%u %%%u", w->id,
85
0
        w->active->id);
86
0
  }
87
0
}
88
89
void
90
control_notify_window_unlinked(__unused struct session *s, struct window *w)
91
0
{
92
0
  struct client *c;
93
0
  struct session  *cs;
94
95
0
  TAILQ_FOREACH(c, &clients, entry) {
96
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
97
0
      continue;
98
0
    cs = c->session;
99
100
0
    if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
101
0
      control_write(c, "%%window-close @%u", w->id);
102
0
    else
103
0
      control_write(c, "%%unlinked-window-close @%u", w->id);
104
0
  }
105
0
}
106
107
void
108
control_notify_window_linked(__unused struct session *s, struct window *w)
109
0
{
110
0
  struct client *c;
111
0
  struct session  *cs;
112
113
0
  TAILQ_FOREACH(c, &clients, entry) {
114
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
115
0
      continue;
116
0
    cs = c->session;
117
118
0
    if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
119
0
      control_write(c, "%%window-add @%u", w->id);
120
0
    else
121
0
      control_write(c, "%%unlinked-window-add @%u", w->id);
122
0
  }
123
0
}
124
125
void
126
control_notify_window_renamed(struct window *w)
127
1.55k
{
128
1.55k
  struct client *c;
129
1.55k
  struct session  *cs;
130
131
1.55k
  TAILQ_FOREACH(c, &clients, entry) {
132
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
133
0
      continue;
134
0
    cs = c->session;
135
136
0
    if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
137
0
      control_write(c, "%%window-renamed @%u %s", w->id,
138
0
          w->name);
139
0
    } else {
140
0
      control_write(c, "%%unlinked-window-renamed @%u %s",
141
0
          w->id, w->name);
142
0
    }
143
0
  }
144
1.55k
}
145
146
void
147
control_notify_client_session_changed(struct client *cc)
148
0
{
149
0
  struct client *c;
150
0
  struct session  *s;
151
152
0
  if (cc->session == NULL)
153
0
    return;
154
0
  s = cc->session;
155
156
0
  TAILQ_FOREACH(c, &clients, entry) {
157
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
158
0
      continue;
159
160
0
    if (cc == c) {
161
0
      control_write(c, "%%session-changed $%u %s", s->id,
162
0
          s->name);
163
0
    } else {
164
0
      control_write(c, "%%client-session-changed %s $%u %s",
165
0
          cc->name, s->id, s->name);
166
0
    }
167
0
  }
168
0
}
169
170
void
171
control_notify_client_detached(struct client *cc)
172
0
{
173
0
  struct client *c;
174
175
0
  TAILQ_FOREACH(c, &clients, entry) {
176
0
    if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
177
0
      control_write(c, "%%client-detached %s", cc->name);
178
0
  }
179
0
}
180
181
void
182
control_notify_session_renamed(struct session *s)
183
0
{
184
0
  struct client *c;
185
186
0
  TAILQ_FOREACH(c, &clients, entry) {
187
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
188
0
      continue;
189
190
0
    control_write(c, "%%session-renamed $%u %s", s->id, s->name);
191
0
  }
192
0
}
193
194
void
195
control_notify_session_created(__unused struct session *s)
196
0
{
197
0
  struct client *c;
198
199
0
  TAILQ_FOREACH(c, &clients, entry) {
200
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
201
0
      continue;
202
203
0
    control_write(c, "%%sessions-changed");
204
0
  }
205
0
}
206
207
void
208
control_notify_session_closed(__unused struct session *s)
209
0
{
210
0
  struct client *c;
211
212
0
  TAILQ_FOREACH(c, &clients, entry) {
213
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
214
0
      continue;
215
216
0
    control_write(c, "%%sessions-changed");
217
0
  }
218
0
}
219
220
void
221
control_notify_session_window_changed(struct session *s)
222
0
{
223
0
  struct client *c;
224
225
0
  TAILQ_FOREACH(c, &clients, entry) {
226
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
227
0
      continue;
228
229
0
    control_write(c, "%%session-window-changed $%u @%u", s->id,
230
0
        s->curw->window->id);
231
0
  }
232
0
}
233
234
void
235
control_notify_paste_buffer_changed(const char *name)
236
958
{
237
958
  struct client *c;
238
239
958
  TAILQ_FOREACH(c, &clients, entry) {
240
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
241
0
      continue;
242
243
0
    control_write(c, "%%paste-buffer-changed %s", name);
244
0
  }
245
958
}
246
247
void
248
control_notify_paste_buffer_deleted(const char *name)
249
908
{
250
908
  struct client *c;
251
252
908
  TAILQ_FOREACH(c, &clients, entry) {
253
0
    if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
254
0
      continue;
255
256
0
    control_write(c, "%%paste-buffer-deleted %s", name);
257
0
  }
258
908
}