tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

window-client.c
Go to the documentation of this file.
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/time.h>
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 
26 #include "tmux.h"
27 
28 static struct screen *window_client_init(struct window_mode_entry *,
29  struct cmd_find_state *, struct args *);
30 static void window_client_free(struct window_mode_entry *);
31 static void window_client_resize(struct window_mode_entry *, u_int,
32  u_int);
33 static void window_client_update(struct window_mode_entry *);
34 static void window_client_key(struct window_mode_entry *,
35  struct client *, struct session *,
36  struct winlink *, key_code, struct mouse_event *);
37 
38 #define WINDOW_CLIENT_DEFAULT_COMMAND "detach-client -t '%%'"
39 
40 #define WINDOW_CLIENT_DEFAULT_FORMAT \
41  "#{t/p:client_activity}: session #{session_name}"
42 
43 #define WINDOW_CLIENT_DEFAULT_KEY_FORMAT \
44  "#{?#{e|<:#{line},10}," \
45  "#{line}" \
46  "," \
47  "#{?#{e|<:#{line},36}," \
48  "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \
49  "," \
50  "" \
51  "}" \
52  "}"
53 
54 static const struct menu_item window_client_menu_items[] = {
55  { "Detach", 'd', NULL },
56  { "Detach Tagged", 'D', NULL },
57  { "", KEYC_NONE, NULL },
58  { "Tag", 't', NULL },
59  { "Tag All", '\024', NULL },
60  { "Tag None", 'T', NULL },
61  { "", KEYC_NONE, NULL },
62  { "Cancel", 'q', NULL },
63 
64  { NULL, KEYC_NONE, NULL }
65 };
66 
67 const struct window_mode window_client_mode = {
68  .name = "client-mode",
69  .default_format = WINDOW_CLIENT_DEFAULT_FORMAT,
70 
71  .init = window_client_init,
72  .free = window_client_free,
73  .resize = window_client_resize,
74  .update = window_client_update,
75  .key = window_client_key,
76 };
77 
83 };
84 static const char *window_client_sort_list[] = {
85  "name",
86  "size",
87  "creation",
88  "activity"
89 };
91 
93  struct client *c;
94 };
95 
97  struct window_pane *wp;
98 
100  char *format;
101  char *key_format;
102  char *command;
103 
105  u_int item_size;
106 };
107 
108 static struct window_client_itemdata *
110 {
111  struct window_client_itemdata *item;
112 
113  data->item_list = xreallocarray(data->item_list, data->item_size + 1,
114  sizeof *data->item_list);
115  item = data->item_list[data->item_size++] = xcalloc(1, sizeof *item);
116  return (item);
117 }
118 
119 static void
121 {
122  server_client_unref(item->c);
123  free(item);
124 }
125 
126 static int
127 window_client_cmp(const void *a0, const void *b0)
128 {
129  const struct window_client_itemdata *const *a = a0;
130  const struct window_client_itemdata *const *b = b0;
131  const struct window_client_itemdata *itema = *a;
132  const struct window_client_itemdata *itemb = *b;
133  struct client *ca = itema->c;
134  struct client *cb = itemb->c;
135  int result = 0;
136 
137  switch (window_client_sort->field) {
139  result = ca->tty.sx - cb->tty.sx;
140  if (result == 0)
141  result = ca->tty.sy - cb->tty.sy;
142  break;
144  if (timercmp(&ca->creation_time, &cb->creation_time, >))
145  result = -1;
146  else if (timercmp(&ca->creation_time, &cb->creation_time, <))
147  result = 1;
148  break;
150  if (timercmp(&ca->activity_time, &cb->activity_time, >))
151  result = -1;
152  else if (timercmp(&ca->activity_time, &cb->activity_time, <))
153  result = 1;
154  break;
155  }
156 
157  /* Use WINDOW_CLIENT_BY_NAME as default order and tie breaker. */
158  if (result == 0)
159  result = strcmp(ca->name, cb->name);
160 
162  result = -result;
163  return (result);
164 }
165 
166 static void
167 window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
168  __unused uint64_t *tag, const char *filter)
169 {
170  struct window_client_modedata *data = modedata;
171  struct window_client_itemdata *item;
172  u_int i;
173  struct client *c;
174  char *text, *cp;
175 
176  for (i = 0; i < data->item_size; i++)
178  free(data->item_list);
179  data->item_list = NULL;
180  data->item_size = 0;
181 
182  TAILQ_FOREACH(c, &clients, entry) {
183  if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
184  continue;
185 
186  item = window_client_add_item(data);
187  item->c = c;
188 
189  c->references++;
190  }
191 
192  window_client_sort = sort_crit;
193  qsort(data->item_list, data->item_size, sizeof *data->item_list,
195 
196  for (i = 0; i < data->item_size; i++) {
197  item = data->item_list[i];
198  c = item->c;
199 
200  if (filter != NULL) {
201  cp = format_single(NULL, filter, c, NULL, NULL, NULL);
202  if (!format_true(cp)) {
203  free(cp);
204  continue;
205  }
206  free(cp);
207  }
208 
209  text = format_single(NULL, data->format, c, NULL, NULL, NULL);
210  mode_tree_add(data->data, NULL, item, (uint64_t)c, c->name,
211  text, -1);
212  free(text);
213  }
214 }
215 
216 static void
217 window_client_draw(__unused void *modedata, void *itemdata,
218  struct screen_write_ctx *ctx, u_int sx, u_int sy)
219 {
220  struct window_client_itemdata *item = itemdata;
221  struct client *c = item->c;
222  struct screen *s = ctx->s;
223  struct window_pane *wp;
224  u_int cx = s->cx, cy = s->cy, lines, at;
225 
226  if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
227  return;
228  wp = c->session->curw->window->active;
229 
230  lines = status_line_size(c);
231  if (lines >= sy)
232  lines = 0;
233  if (status_at_line(c) == 0)
234  at = lines;
235  else
236  at = 0;
237 
238  screen_write_cursormove(ctx, cx, cy + at, 0);
239  screen_write_preview(ctx, &wp->base, sx, sy - 2 - lines);
240 
241  if (at != 0)
242  screen_write_cursormove(ctx, cx, cy + 2, 0);
243  else
244  screen_write_cursormove(ctx, cx, cy + sy - 1 - lines, 0);
245  screen_write_hline(ctx, sx, 0, 0);
246 
247  if (at != 0)
248  screen_write_cursormove(ctx, cx, cy, 0);
249  else
250  screen_write_cursormove(ctx, cx, cy + sy - lines, 0);
251  screen_write_fast_copy(ctx, &c->status.screen, 0, 0, sx, lines);
252 }
253 
254 static void
255 window_client_menu(void *modedata, struct client *c, key_code key)
256 {
257  struct window_client_modedata *data = modedata;
258  struct window_pane *wp = data->wp;
259  struct window_mode_entry *wme;
260 
261  wme = TAILQ_FIRST(&wp->modes);
262  if (wme == NULL || wme->data != modedata)
263  return;
264  window_client_key(wme, c, NULL, NULL, key, NULL);
265 }
266 
267 static key_code
268 window_client_get_key(void *modedata, void *itemdata, u_int line)
269 {
270  struct window_client_modedata *data = modedata;
271  struct window_client_itemdata *item = itemdata;
272  struct format_tree *ft;
273  char *expanded;
274  key_code key;
275 
276  ft = format_create(NULL, NULL, FORMAT_NONE, 0);
277  format_defaults(ft, item->c, NULL, 0, NULL);
278  format_add(ft, "line", "%u", line);
279 
280  expanded = format_expand(ft, data->key_format);
281  key = key_string_lookup_string(expanded);
282  free(expanded);
283  format_free(ft);
284  return key;
285 }
286 
287 static struct screen *
289  __unused struct cmd_find_state *fs, struct args *args)
290 {
291  struct window_pane *wp = wme->wp;
293  struct screen *s;
294 
295  wme->data = data = xcalloc(1, sizeof *data);
296  data->wp = wp;
297 
298  if (args == NULL || !args_has(args, 'F'))
300  else
301  data->format = xstrdup(args_get(args, 'F'));
302  if (args == NULL || !args_has(args, 'K'))
304  else
305  data->key_format = xstrdup(args_get(args, 'K'));
306  if (args == NULL || args->argc == 0)
308  else
309  data->command = xstrdup(args->argv[0]);
310 
315  mode_tree_zoom(data->data, args);
316 
317  mode_tree_build(data->data);
318  mode_tree_draw(data->data);
319 
320  return (s);
321 }
322 
323 static void
325 {
326  struct window_client_modedata *data = wme->data;
327  u_int i;
328 
329  if (data == NULL)
330  return;
331 
332  mode_tree_free(data->data);
333 
334  for (i = 0; i < data->item_size; i++)
335  window_client_free_item(data->item_list[i]);
336  free(data->item_list);
337 
338  free(data->format);
339  free(data->key_format);
340  free(data->command);
341 
342  free(data);
343 }
344 
345 static void
346 window_client_resize(struct window_mode_entry *wme, u_int sx, u_int sy)
347 {
348  struct window_client_modedata *data = wme->data;
349 
350  mode_tree_resize(data->data, sx, sy);
351 }
352 
353 static void
355 {
356  struct window_client_modedata *data = wme->data;
357 
358  mode_tree_build(data->data);
359  mode_tree_draw(data->data);
360  data->wp->flags |= PANE_REDRAW;
361 }
362 
363 static void
364 window_client_do_detach(void *modedata, void *itemdata,
365  __unused struct client *c, key_code key)
366 {
367  struct window_client_modedata *data = modedata;
368  struct window_client_itemdata *item = itemdata;
369 
370  if (item == mode_tree_get_current(data->data))
371  mode_tree_down(data->data, 0);
372  if (key == 'd' || key == 'D')
374  else if (key == 'x' || key == 'X')
376  else if (key == 'z' || key == 'Z')
377  server_client_suspend(item->c);
378 }
379 
380 static void
382  __unused struct session *s, __unused struct winlink *wl, key_code key,
383  struct mouse_event *m)
384 {
385  struct window_pane *wp = wme->wp;
386  struct window_client_modedata *data = wme->data;
387  struct mode_tree_data *mtd = data->data;
388  struct window_client_itemdata *item;
389  int finished;
390 
391  finished = mode_tree_key(mtd, c, &key, m, NULL, NULL);
392  switch (key) {
393  case 'd':
394  case 'x':
395  case 'z':
396  item = mode_tree_get_current(mtd);
397  window_client_do_detach(data, item, c, key);
398  mode_tree_build(mtd);
399  break;
400  case 'D':
401  case 'X':
402  case 'Z':
404  mode_tree_build(mtd);
405  break;
406  case '\r':
407  item = mode_tree_get_current(mtd);
408  mode_tree_run_command(c, NULL, data->command, item->c->ttyname);
409  finished = 1;
410  break;
411  }
412  if (finished || server_client_how_many() == 0)
414  else {
415  mode_tree_draw(mtd);
416  wp->flags |= PANE_REDRAW;
417  }
418 }
int args_has(struct args *args, u_char flag)
Definition: arguments.c:259
const char * args_get(struct args *args, u_char flag)
Definition: arguments.c:295
#define __unused
Definition: compat.h:60
#define timercmp(tvp, uvp, cmp)
Definition: compat.h:230
void format_defaults(struct format_tree *ft, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp)
Definition: format.c:4684
char * format_single(struct cmdq_item *item, const char *fmt, struct client *c, struct session *s, struct winlink *wl, struct window_pane *wp)
Definition: format.c:4621
void format_add(struct format_tree *ft, const char *key, const char *fmt,...)
Definition: format.c:3126
struct format_tree * format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
Definition: format.c:3042
char * format_expand(struct format_tree *ft, const char *fmt)
Definition: format.c:4609
void format_free(struct format_tree *ft)
Definition: format.c:3066
int format_true(const char *s)
Definition: format.c:3471
key_code key_string_lookup_string(const char *string)
Definition: key-string.c:165
key_code key
Definition: key-string.c:32
void mode_tree_down(struct mode_tree_data *mtd, int wrap)
Definition: mode-tree.c:260
void mode_tree_build(struct mode_tree_data *mtd)
Definition: mode-tree.c:477
void mode_tree_free(struct mode_tree_data *mtd)
Definition: mode-tree.c:521
struct mode_tree_data * mode_tree_start(struct window_pane *wp, struct args *args, mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb, mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, mode_tree_height_cb heightcb, mode_tree_key_cb keycb, void *modedata, const struct menu_item *menu, const char **sort_list, u_int sort_size, struct screen **s)
Definition: mode-tree.c:389
void mode_tree_zoom(struct mode_tree_data *mtd, struct args *args)
Definition: mode-tree.c:443
struct mode_tree_item * mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent, void *itemdata, uint64_t tag, const char *name, const char *text, int expanded)
Definition: mode-tree.c:553
void mode_tree_run_command(struct client *c, struct cmd_find_state *fs, const char *template, const char *name)
Definition: mode-tree.c:1193
int mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, struct mouse_event *m, u_int *xp, u_int *yp)
Definition: mode-tree.c:977
void * mode_tree_get_current(struct mode_tree_data *mtd)
Definition: mode-tree.c:275
void mode_tree_each_tagged(struct mode_tree_data *mtd, mode_tree_each_cb cb, struct client *c, key_code key, int current)
Definition: mode-tree.c:367
void mode_tree_resize(struct mode_tree_data *mtd, u_int sx, u_int sy)
Definition: mode-tree.c:540
void mode_tree_draw(struct mode_tree_data *mtd)
Definition: mode-tree.c:616
#define nitems(_a)
void screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px, u_int py, u_int nx, u_int ny)
Definition: screen-write.c:548
void screen_write_hline(struct screen_write_ctx *ctx, u_int nx, int left, int right)
Definition: screen-write.c:579
void screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py, int origin)
void screen_write_preview(struct screen_write_ctx *ctx, struct screen *src, u_int nx, u_int ny)
Definition: screen-write.c:712
void server_client_unref(struct client *c)
void server_client_suspend(struct client *c)
u_int server_client_how_many(void)
Definition: server-client.c:68
void server_client_detach(struct client *c, enum msgtype msgtype)
struct clients clients
Definition: server.c:42
int status_at_line(struct client *c)
Definition: status.c:210
u_int status_line_size(struct client *c)
Definition: status.c:223
Definition: tmux.h:1435
int argc
Definition: tmux.h:1437
char ** argv
Definition: tmux.h:1438
Definition: tmux.h:1608
struct tty tty
Definition: tmux.h:1640
char * ttyname
Definition: tmux.h:1639
int references
Definition: tmux.h:1746
struct timeval creation_time
Definition: tmux.h:1624
struct status_line status
Definition: tmux.h:1652
struct timeval activity_time
Definition: tmux.h:1625
const char * name
Definition: tmux.h:1609
struct session * session
Definition: tmux.h:1743
uint64_t flags
Definition: tmux.h:1703
struct cmdq_item * item
Definition: format.c:139
struct window_pane * wp
Definition: mode-tree.c:36
struct screen * s
Definition: tmux.h:851
Definition: tmux.h:816
u_int cy
Definition: tmux.h:824
u_int cx
Definition: tmux.h:823
Definition: tmux.h:1179
struct winlink * curw
Definition: tmux.h:1192
struct screen screen
Definition: tmux.h:1559
u_int sx
Definition: tmux.h:1308
u_int sy
Definition: tmux.h:1309
struct client * c
Definition: window-client.c:93
struct mode_tree_data * data
Definition: window-client.c:99
struct window_client_itemdata ** item_list
struct window_pane * wp
Definition: window-client.c:97
Definition: tmux.h:927
void * data
Definition: tmux.h:932
struct window_pane * wp
Definition: tmux.h:928
const char * name
Definition: tmux.h:906
int flags
Definition: tmux.h:977
struct screen base
Definition: tmux.h:1021
u_int sy
Definition: tmux.h:969
u_int sx
Definition: tmux.h:968
struct window_pane * active
Definition: tmux.h:1054
@ MSG_DETACH
Definition: tmux.h:523
@ MSG_DETACHKILL
Definition: tmux.h:524
unsigned long long key_code
Definition: tmux.h:177
#define KEYC_NONE
Definition: tmux.h:113
#define FORMAT_NONE
Definition: tmux.h:1973
#define CLIENT_UNATTACHEDFLAGS
Definition: tmux.h:1695
#define PANE_REDRAW
Definition: tmux.h:978
void window_pane_reset_mode(struct window_pane *)
Definition: window.c:1105
static struct window_client_itemdata * window_client_add_item(struct window_client_modedata *data)
#define WINDOW_CLIENT_DEFAULT_KEY_FORMAT
Definition: window-client.c:43
static void window_client_menu(void *modedata, struct client *c, key_code key)
static void window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit, uint64_t *tag, const char *filter)
static void window_client_do_detach(void *modedata, void *itemdata, struct client *c, key_code key)
static struct screen * window_client_init(struct window_mode_entry *, struct cmd_find_state *, struct args *)
static const struct menu_item window_client_menu_items[]
Definition: window-client.c:54
#define WINDOW_CLIENT_DEFAULT_FORMAT
Definition: window-client.c:40
static int window_client_cmp(const void *a0, const void *b0)
static key_code window_client_get_key(void *modedata, void *itemdata, u_int line)
static void window_client_free_item(struct window_client_itemdata *item)
#define WINDOW_CLIENT_DEFAULT_COMMAND
Definition: window-client.c:38
const struct window_mode window_client_mode
Definition: window-client.c:67
window_client_sort_type
Definition: window-client.c:78
@ WINDOW_CLIENT_BY_SIZE
Definition: window-client.c:80
@ WINDOW_CLIENT_BY_ACTIVITY_TIME
Definition: window-client.c:82
@ WINDOW_CLIENT_BY_NAME
Definition: window-client.c:79
@ WINDOW_CLIENT_BY_CREATION_TIME
Definition: window-client.c:81
static void window_client_free(struct window_mode_entry *)
static struct mode_tree_sort_criteria * window_client_sort
Definition: window-client.c:90
static void window_client_update(struct window_mode_entry *)
static const char * window_client_sort_list[]
Definition: window-client.c:84
static void window_client_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx, u_int sx, u_int sy)
static void window_client_key(struct window_mode_entry *, struct client *, struct session *, struct winlink *, key_code, struct mouse_event *)
static void window_client_resize(struct window_mode_entry *, u_int, u_int)
void * xreallocarray(void *ptr, size_t nmemb, size_t size)
Definition: xmalloc.c:61
void * xcalloc(size_t nmemb, size_t size)
Definition: xmalloc.c:41
char * xstrdup(const char *str)
Definition: xmalloc.c:89