Coverage Report

Created: 2026-04-12 06:58

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