i3
ipc.c
Go to the documentation of this file.
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * ipc.c: UNIX domain socket IPC (initialization, client handling, protocol).
8  *
9  */
10 #include "all.h"
11 
12 #include "yajl_utils.h"
13 
14 #include <stdint.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17 #include <fcntl.h>
18 #include <libgen.h>
19 #include <ev.h>
20 #include <yajl/yajl_gen.h>
21 #include <yajl/yajl_parse.h>
22 
23 char *current_socketpath = NULL;
24 
25 TAILQ_HEAD(ipc_client_head, ipc_client)
27 
28 /*
29  * Puts the given socket file descriptor into non-blocking mode or dies if
30  * setting O_NONBLOCK failed. Non-blocking sockets are a good idea for our
31  * IPC model because we should by no means block the window manager.
32  *
33  */
34 static void set_nonblock(int sockfd) {
35  int flags = fcntl(sockfd, F_GETFL, 0);
36  if (flags & O_NONBLOCK) {
37  return;
38  }
39  flags |= O_NONBLOCK;
40  if (fcntl(sockfd, F_SETFL, flags) < 0)
41  err(-1, "Could not set O_NONBLOCK");
42 }
43 
44 static void ipc_client_timeout(EV_P_ ev_timer *w, int revents);
45 static void ipc_socket_writeable_cb(EV_P_ struct ev_io *w, int revents);
46 
47 static ev_tstamp kill_timeout = 10.0;
48 
49 void ipc_set_kill_timeout(ev_tstamp new) {
50  kill_timeout = new;
51 }
52 
53 /*
54  * Try to write the contents of the pending buffer to the client's subscription
55  * socket. Will set, reset or clear the timeout and io write callbacks depending
56  * on the result of the write operation.
57  *
58  */
59 static void ipc_push_pending(ipc_client *client) {
60  const ssize_t result = writeall_nonblock(client->fd, client->buffer, client->buffer_size);
61  if (result < 0) {
62  return;
63  }
64 
65  if ((size_t)result == client->buffer_size) {
66  /* Everything was written successfully: clear the timer and stop the io
67  * callback. */
68  FREE(client->buffer);
69  client->buffer_size = 0;
70  if (client->timeout) {
71  ev_timer_stop(main_loop, client->timeout);
72  FREE(client->timeout);
73  }
74  ev_io_stop(main_loop, client->write_callback);
75  return;
76  }
77 
78  /* Otherwise, make sure that the io callback is enabled and create a new
79  * timer if needed. */
80  ev_io_start(main_loop, client->write_callback);
81 
82  if (!client->timeout) {
83  struct ev_timer *timeout = scalloc(1, sizeof(struct ev_timer));
84  ev_timer_init(timeout, ipc_client_timeout, kill_timeout, 0.);
85  timeout->data = client;
86  client->timeout = timeout;
87  ev_set_priority(timeout, EV_MINPRI);
88  ev_timer_start(main_loop, client->timeout);
89  } else if (result > 0) {
90  /* Keep the old timeout when nothing is written. Otherwise, we would
91  * keep a dead connection by continuously renewing its timeouts. */
92  ev_timer_stop(main_loop, client->timeout);
93  ev_timer_set(client->timeout, kill_timeout, 0.0);
94  ev_timer_start(main_loop, client->timeout);
95  }
96  if (result == 0) {
97  return;
98  }
99 
100  /* Shift the buffer to the left and reduce the allocated space. */
101  client->buffer_size -= (size_t)result;
102  memmove(client->buffer, client->buffer + result, client->buffer_size);
103  client->buffer = srealloc(client->buffer, client->buffer_size);
104 }
105 
106 /*
107  * Given a message and a message type, create the corresponding header, merge it
108  * with the message and append it to the given client's output buffer. Also,
109  * send the message if the client's buffer was empty.
110  *
111  */
112 static void ipc_send_client_message(ipc_client *client, size_t size, const uint32_t message_type, const uint8_t *payload) {
113  const i3_ipc_header_t header = {
114  .magic = {'i', '3', '-', 'i', 'p', 'c'},
115  .size = size,
116  .type = message_type};
117  const size_t header_size = sizeof(i3_ipc_header_t);
118  const size_t message_size = header_size + size;
119 
120  const bool push_now = (client->buffer_size == 0);
121  client->buffer = srealloc(client->buffer, client->buffer_size + message_size);
122  memcpy(client->buffer + client->buffer_size, ((void *)&header), header_size);
123  memcpy(client->buffer + client->buffer_size + header_size, payload, size);
124  client->buffer_size += message_size;
125 
126  if (push_now) {
127  ipc_push_pending(client);
128  }
129 }
130 
131 static void free_ipc_client(ipc_client *client, int exempt_fd) {
132  if (client->fd != exempt_fd) {
133  DLOG("Disconnecting client on fd %d\n", client->fd);
134  close(client->fd);
135  }
136 
137  ev_io_stop(main_loop, client->read_callback);
138  FREE(client->read_callback);
139  ev_io_stop(main_loop, client->write_callback);
140  FREE(client->write_callback);
141  if (client->timeout) {
142  ev_timer_stop(main_loop, client->timeout);
143  FREE(client->timeout);
144  }
145 
146  free(client->buffer);
147 
148  for (int i = 0; i < client->num_events; i++) {
149  free(client->events[i]);
150  }
151  free(client->events);
152  TAILQ_REMOVE(&all_clients, client, clients);
153  free(client);
154 }
155 
156 /*
157  * Sends the specified event to all IPC clients which are currently connected
158  * and subscribed to this kind of event.
159  *
160  */
161 void ipc_send_event(const char *event, uint32_t message_type, const char *payload) {
162  ipc_client *current;
163  TAILQ_FOREACH(current, &all_clients, clients) {
164  for (int i = 0; i < current->num_events; i++) {
165  if (strcasecmp(current->events[i], event) == 0) {
166  ipc_send_client_message(current, strlen(payload), message_type, (uint8_t *)payload);
167  break;
168  }
169  }
170  }
171 }
172 
173 /*
174  * For shutdown events, we send the reason for the shutdown.
175  */
177  yajl_gen gen = ygenalloc();
178  y(map_open);
179 
180  ystr("change");
181 
182  if (reason == SHUTDOWN_REASON_RESTART) {
183  ystr("restart");
184  } else if (reason == SHUTDOWN_REASON_EXIT) {
185  ystr("exit");
186  }
187 
188  y(map_close);
189 
190  const unsigned char *payload;
191  ylength length;
192 
193  y(get_buf, &payload, &length);
194  ipc_send_event("shutdown", I3_IPC_EVENT_SHUTDOWN, (const char *)payload);
195 
196  y(free);
197 }
198 
199 /*
200  * Calls shutdown() on each socket and closes it. This function is to be called
201  * when exiting or restarting only!
202  *
203  * exempt_fd is never closed. Set to -1 to close all fds.
204  *
205  */
206 void ipc_shutdown(shutdown_reason_t reason, int exempt_fd) {
207  ipc_send_shutdown_event(reason);
208 
209  ipc_client *current;
210  while (!TAILQ_EMPTY(&all_clients)) {
211  current = TAILQ_FIRST(&all_clients);
212  if (current->fd != exempt_fd) {
213  shutdown(current->fd, SHUT_RDWR);
214  }
215  free_ipc_client(current, exempt_fd);
216  }
217 }
218 
219 /*
220  * Executes the command and returns whether it could be successfully parsed
221  * or not (at the moment, always returns true).
222  *
223  */
224 IPC_HANDLER(run_command) {
225  /* To get a properly terminated buffer, we copy
226  * message_size bytes out of the buffer */
227  char *command = sstrndup((const char *)message, message_size);
228  LOG("IPC: received: *%s*\n", command);
229  yajl_gen gen = yajl_gen_alloc(NULL);
230 
231  CommandResult *result = parse_command(command, gen, client);
232  free(command);
233 
234  if (result->needs_tree_render)
235  tree_render();
236 
237  command_result_free(result);
238 
239  const unsigned char *reply;
240  ylength length;
241  yajl_gen_get_buf(gen, &reply, &length);
242 
243  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_COMMAND,
244  (const uint8_t *)reply);
245 
246  yajl_gen_free(gen);
247 }
248 
249 static void dump_rect(yajl_gen gen, const char *name, Rect r) {
250  ystr(name);
251  y(map_open);
252  ystr("x");
253  y(integer, r.x);
254  ystr("y");
255  y(integer, r.y);
256  ystr("width");
257  y(integer, r.width);
258  ystr("height");
259  y(integer, r.height);
260  y(map_close);
261 }
262 
263 static void dump_event_state_mask(yajl_gen gen, Binding *bind) {
264  y(array_open);
265  for (int i = 0; i < 20; i++) {
266  if (bind->event_state_mask & (1 << i)) {
267  switch (1 << i) {
268  case XCB_KEY_BUT_MASK_SHIFT:
269  ystr("shift");
270  break;
271  case XCB_KEY_BUT_MASK_LOCK:
272  ystr("lock");
273  break;
274  case XCB_KEY_BUT_MASK_CONTROL:
275  ystr("ctrl");
276  break;
277  case XCB_KEY_BUT_MASK_MOD_1:
278  ystr("Mod1");
279  break;
280  case XCB_KEY_BUT_MASK_MOD_2:
281  ystr("Mod2");
282  break;
283  case XCB_KEY_BUT_MASK_MOD_3:
284  ystr("Mod3");
285  break;
286  case XCB_KEY_BUT_MASK_MOD_4:
287  ystr("Mod4");
288  break;
289  case XCB_KEY_BUT_MASK_MOD_5:
290  ystr("Mod5");
291  break;
292  case XCB_KEY_BUT_MASK_BUTTON_1:
293  ystr("Button1");
294  break;
295  case XCB_KEY_BUT_MASK_BUTTON_2:
296  ystr("Button2");
297  break;
298  case XCB_KEY_BUT_MASK_BUTTON_3:
299  ystr("Button3");
300  break;
301  case XCB_KEY_BUT_MASK_BUTTON_4:
302  ystr("Button4");
303  break;
304  case XCB_KEY_BUT_MASK_BUTTON_5:
305  ystr("Button5");
306  break;
307  case (I3_XKB_GROUP_MASK_1 << 16):
308  ystr("Group1");
309  break;
310  case (I3_XKB_GROUP_MASK_2 << 16):
311  ystr("Group2");
312  break;
313  case (I3_XKB_GROUP_MASK_3 << 16):
314  ystr("Group3");
315  break;
316  case (I3_XKB_GROUP_MASK_4 << 16):
317  ystr("Group4");
318  break;
319  }
320  }
321  }
322  y(array_close);
323 }
324 
325 static void dump_binding(yajl_gen gen, Binding *bind) {
326  y(map_open);
327  ystr("input_code");
328  y(integer, bind->keycode);
329 
330  ystr("input_type");
331  ystr((const char *)(bind->input_type == B_KEYBOARD ? "keyboard" : "mouse"));
332 
333  ystr("symbol");
334  if (bind->symbol == NULL)
335  y(null);
336  else
337  ystr(bind->symbol);
338 
339  ystr("command");
340  ystr(bind->command);
341 
342  // This key is only provided for compatibility, new programs should use
343  // event_state_mask instead.
344  ystr("mods");
345  dump_event_state_mask(gen, bind);
346 
347  ystr("event_state_mask");
348  dump_event_state_mask(gen, bind);
349 
350  y(map_close);
351 }
352 
353 void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
354  y(map_open);
355  ystr("id");
356  y(integer, (uintptr_t)con);
357 
358  ystr("type");
359  switch (con->type) {
360  case CT_ROOT:
361  ystr("root");
362  break;
363  case CT_OUTPUT:
364  ystr("output");
365  break;
366  case CT_CON:
367  ystr("con");
368  break;
369  case CT_FLOATING_CON:
370  ystr("floating_con");
371  break;
372  case CT_WORKSPACE:
373  ystr("workspace");
374  break;
375  case CT_DOCKAREA:
376  ystr("dockarea");
377  break;
378  }
379 
380  /* provided for backwards compatibility only. */
381  ystr("orientation");
382  if (!con_is_split(con))
383  ystr("none");
384  else {
385  if (con_orientation(con) == HORIZ)
386  ystr("horizontal");
387  else
388  ystr("vertical");
389  }
390 
391  ystr("scratchpad_state");
392  switch (con->scratchpad_state) {
393  case SCRATCHPAD_NONE:
394  ystr("none");
395  break;
396  case SCRATCHPAD_FRESH:
397  ystr("fresh");
398  break;
399  case SCRATCHPAD_CHANGED:
400  ystr("changed");
401  break;
402  }
403 
404  ystr("percent");
405  if (con->percent == 0.0)
406  y(null);
407  else
408  y(double, con->percent);
409 
410  ystr("urgent");
411  y(bool, con->urgent);
412 
413  if (!TAILQ_EMPTY(&(con->marks_head))) {
414  ystr("marks");
415  y(array_open);
416 
417  mark_t *mark;
418  TAILQ_FOREACH(mark, &(con->marks_head), marks) {
419  ystr(mark->name);
420  }
421 
422  y(array_close);
423  }
424 
425  ystr("focused");
426  y(bool, (con == focused));
427 
428  if (con->type != CT_ROOT && con->type != CT_OUTPUT) {
429  ystr("output");
430  ystr(con_get_output(con)->name);
431  }
432 
433  ystr("layout");
434  switch (con->layout) {
435  case L_DEFAULT:
436  DLOG("About to dump layout=default, this is a bug in the code.\n");
437  assert(false);
438  break;
439  case L_SPLITV:
440  ystr("splitv");
441  break;
442  case L_SPLITH:
443  ystr("splith");
444  break;
445  case L_STACKED:
446  ystr("stacked");
447  break;
448  case L_TABBED:
449  ystr("tabbed");
450  break;
451  case L_DOCKAREA:
452  ystr("dockarea");
453  break;
454  case L_OUTPUT:
455  ystr("output");
456  break;
457  }
458 
459  ystr("workspace_layout");
460  switch (con->workspace_layout) {
461  case L_DEFAULT:
462  ystr("default");
463  break;
464  case L_STACKED:
465  ystr("stacked");
466  break;
467  case L_TABBED:
468  ystr("tabbed");
469  break;
470  default:
471  DLOG("About to dump workspace_layout=%d (none of default/stacked/tabbed), this is a bug.\n", con->workspace_layout);
472  assert(false);
473  break;
474  }
475 
476  ystr("last_split_layout");
477  switch (con->layout) {
478  case L_SPLITV:
479  ystr("splitv");
480  break;
481  default:
482  ystr("splith");
483  break;
484  }
485 
486  ystr("border");
487  switch (con->border_style) {
488  case BS_NORMAL:
489  ystr("normal");
490  break;
491  case BS_NONE:
492  ystr("none");
493  break;
494  case BS_PIXEL:
495  ystr("pixel");
496  break;
497  }
498 
499  ystr("current_border_width");
500  y(integer, con->current_border_width);
501 
502  dump_rect(gen, "rect", con->rect);
503  dump_rect(gen, "deco_rect", con->deco_rect);
504  dump_rect(gen, "window_rect", con->window_rect);
505  dump_rect(gen, "geometry", con->geometry);
506 
507  ystr("name");
508  if (con->window && con->window->name)
509  ystr(i3string_as_utf8(con->window->name));
510  else if (con->name != NULL)
511  ystr(con->name);
512  else
513  y(null);
514 
515  if (con->title_format != NULL) {
516  ystr("title_format");
517  ystr(con->title_format);
518  }
519 
520  if (con->type == CT_WORKSPACE) {
521  ystr("num");
522  y(integer, con->num);
523  }
524 
525  ystr("window");
526  if (con->window)
527  y(integer, con->window->id);
528  else
529  y(null);
530 
531  if (con->window && !inplace_restart) {
532  /* Window properties are useless to preserve when restarting because
533  * they will be queried again anyway. However, for i3-save-tree(1),
534  * they are very useful and save i3-save-tree dealing with X11. */
535  ystr("window_properties");
536  y(map_open);
537 
538 #define DUMP_PROPERTY(key, prop_name) \
539  do { \
540  if (con->window->prop_name != NULL) { \
541  ystr(key); \
542  ystr(con->window->prop_name); \
543  } \
544  } while (0)
545 
546  DUMP_PROPERTY("class", class_class);
547  DUMP_PROPERTY("instance", class_instance);
548  DUMP_PROPERTY("window_role", role);
549 
550  if (con->window->name != NULL) {
551  ystr("title");
552  ystr(i3string_as_utf8(con->window->name));
553  }
554 
555  ystr("transient_for");
556  if (con->window->transient_for == XCB_NONE)
557  y(null);
558  else
559  y(integer, con->window->transient_for);
560 
561  y(map_close);
562  }
563 
564  ystr("nodes");
565  y(array_open);
566  Con *node;
567  if (con->type != CT_DOCKAREA || !inplace_restart) {
568  TAILQ_FOREACH(node, &(con->nodes_head), nodes) {
569  dump_node(gen, node, inplace_restart);
570  }
571  }
572  y(array_close);
573 
574  ystr("floating_nodes");
575  y(array_open);
576  TAILQ_FOREACH(node, &(con->floating_head), floating_windows) {
577  dump_node(gen, node, inplace_restart);
578  }
579  y(array_close);
580 
581  ystr("focus");
582  y(array_open);
583  TAILQ_FOREACH(node, &(con->focus_head), focused) {
584  y(integer, (uintptr_t)node);
585  }
586  y(array_close);
587 
588  ystr("fullscreen_mode");
589  y(integer, con->fullscreen_mode);
590 
591  ystr("sticky");
592  y(bool, con->sticky);
593 
594  ystr("floating");
595  switch (con->floating) {
596  case FLOATING_AUTO_OFF:
597  ystr("auto_off");
598  break;
599  case FLOATING_AUTO_ON:
600  ystr("auto_on");
601  break;
602  case FLOATING_USER_OFF:
603  ystr("user_off");
604  break;
605  case FLOATING_USER_ON:
606  ystr("user_on");
607  break;
608  }
609 
610  ystr("swallows");
611  y(array_open);
612  Match *match;
613  TAILQ_FOREACH(match, &(con->swallow_head), matches) {
614  /* We will generate a new restart_mode match specification after this
615  * loop, so skip this one. */
616  if (match->restart_mode)
617  continue;
618  y(map_open);
619  if (match->dock != M_DONTCHECK) {
620  ystr("dock");
621  y(integer, match->dock);
622  ystr("insert_where");
623  y(integer, match->insert_where);
624  }
625 
626 #define DUMP_REGEX(re_name) \
627  do { \
628  if (match->re_name != NULL) { \
629  ystr(#re_name); \
630  ystr(match->re_name->pattern); \
631  } \
632  } while (0)
633 
634  DUMP_REGEX(class);
635  DUMP_REGEX(instance);
636  DUMP_REGEX(window_role);
637  DUMP_REGEX(title);
638 
639 #undef DUMP_REGEX
640  y(map_close);
641  }
642 
643  if (inplace_restart) {
644  if (con->window != NULL) {
645  y(map_open);
646  ystr("id");
647  y(integer, con->window->id);
648  ystr("restart_mode");
649  y(bool, true);
650  y(map_close);
651  }
652  }
653  y(array_close);
654 
655  if (inplace_restart && con->window != NULL) {
656  ystr("depth");
657  y(integer, con->depth);
658  }
659 
660  if (inplace_restart && con->type == CT_ROOT && previous_workspace_name) {
661  ystr("previous_workspace_name");
663  }
664 
665  y(map_close);
666 }
667 
668 static void dump_bar_bindings(yajl_gen gen, Barconfig *config) {
669  if (TAILQ_EMPTY(&(config->bar_bindings)))
670  return;
671 
672  ystr("bindings");
673  y(array_open);
674 
675  struct Barbinding *current;
676  TAILQ_FOREACH(current, &(config->bar_bindings), bindings) {
677  y(map_open);
678 
679  ystr("input_code");
680  y(integer, current->input_code);
681  ystr("command");
682  ystr(current->command);
683  ystr("release");
684  y(bool, current->release == B_UPON_KEYRELEASE);
685 
686  y(map_close);
687  }
688 
689  y(array_close);
690 }
691 
692 static char *canonicalize_output_name(char *name) {
693  /* Do not canonicalize special output names. */
694  if (strcasecmp(name, "primary") == 0) {
695  return name;
696  }
697  Output *output = get_output_by_name(name, false);
698  return output ? output_primary_name(output) : name;
699 }
700 
701 static void dump_bar_config(yajl_gen gen, Barconfig *config) {
702  y(map_open);
703 
704  ystr("id");
705  ystr(config->id);
706 
707  if (config->num_outputs > 0) {
708  ystr("outputs");
709  y(array_open);
710  for (int c = 0; c < config->num_outputs; c++) {
711  /* Convert monitor names (RandR ≥ 1.5) or output names
712  * (RandR < 1.5) into monitor names. This way, existing
713  * configs which use output names transparently keep
714  * working. */
715  ystr(canonicalize_output_name(config->outputs[c]));
716  }
717  y(array_close);
718  }
719 
720  if (!TAILQ_EMPTY(&(config->tray_outputs))) {
721  ystr("tray_outputs");
722  y(array_open);
723 
724  struct tray_output_t *tray_output;
725  TAILQ_FOREACH(tray_output, &(config->tray_outputs), tray_outputs) {
726  ystr(canonicalize_output_name(tray_output->output));
727  }
728 
729  y(array_close);
730  }
731 
732 #define YSTR_IF_SET(name) \
733  do { \
734  if (config->name) { \
735  ystr(#name); \
736  ystr(config->name); \
737  } \
738  } while (0)
739 
740  ystr("tray_padding");
741  y(integer, config->tray_padding);
742 
743  YSTR_IF_SET(socket_path);
744 
745  ystr("mode");
746  switch (config->mode) {
747  case M_HIDE:
748  ystr("hide");
749  break;
750  case M_INVISIBLE:
751  ystr("invisible");
752  break;
753  case M_DOCK:
754  default:
755  ystr("dock");
756  break;
757  }
758 
759  ystr("hidden_state");
760  switch (config->hidden_state) {
761  case S_SHOW:
762  ystr("show");
763  break;
764  case S_HIDE:
765  default:
766  ystr("hide");
767  break;
768  }
769 
770  ystr("modifier");
771  y(integer, config->modifier);
772 
774 
775  ystr("position");
776  if (config->position == P_BOTTOM)
777  ystr("bottom");
778  else
779  ystr("top");
780 
781  YSTR_IF_SET(status_command);
782  YSTR_IF_SET(font);
783 
784  if (config->separator_symbol) {
785  ystr("separator_symbol");
786  ystr(config->separator_symbol);
787  }
788 
789  ystr("workspace_buttons");
790  y(bool, !config->hide_workspace_buttons);
791 
792  ystr("strip_workspace_numbers");
793  y(bool, config->strip_workspace_numbers);
794 
795  ystr("strip_workspace_name");
796  y(bool, config->strip_workspace_name);
797 
798  ystr("binding_mode_indicator");
799  y(bool, !config->hide_binding_mode_indicator);
800 
801  ystr("verbose");
802  y(bool, config->verbose);
803 
804 #undef YSTR_IF_SET
805 #define YSTR_IF_SET(name) \
806  do { \
807  if (config->colors.name) { \
808  ystr(#name); \
809  ystr(config->colors.name); \
810  } \
811  } while (0)
812 
813  ystr("colors");
814  y(map_open);
815  YSTR_IF_SET(background);
816  YSTR_IF_SET(statusline);
817  YSTR_IF_SET(separator);
818  YSTR_IF_SET(focused_background);
819  YSTR_IF_SET(focused_statusline);
820  YSTR_IF_SET(focused_separator);
821  YSTR_IF_SET(focused_workspace_border);
822  YSTR_IF_SET(focused_workspace_bg);
823  YSTR_IF_SET(focused_workspace_text);
824  YSTR_IF_SET(active_workspace_border);
825  YSTR_IF_SET(active_workspace_bg);
826  YSTR_IF_SET(active_workspace_text);
827  YSTR_IF_SET(inactive_workspace_border);
828  YSTR_IF_SET(inactive_workspace_bg);
829  YSTR_IF_SET(inactive_workspace_text);
830  YSTR_IF_SET(urgent_workspace_border);
831  YSTR_IF_SET(urgent_workspace_bg);
832  YSTR_IF_SET(urgent_workspace_text);
833  YSTR_IF_SET(binding_mode_border);
834  YSTR_IF_SET(binding_mode_bg);
835  YSTR_IF_SET(binding_mode_text);
836  y(map_close);
837 
838  y(map_close);
839 #undef YSTR_IF_SET
840 }
841 
842 IPC_HANDLER(tree) {
843  setlocale(LC_NUMERIC, "C");
844  yajl_gen gen = ygenalloc();
845  dump_node(gen, croot, false);
846  setlocale(LC_NUMERIC, "");
847 
848  const unsigned char *payload;
849  ylength length;
850  y(get_buf, &payload, &length);
851 
852  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_TREE, payload);
853  y(free);
854 }
855 
856 /*
857  * Formats the reply message for a GET_WORKSPACES request and sends it to the
858  * client
859  *
860  */
861 IPC_HANDLER(get_workspaces) {
862  yajl_gen gen = ygenalloc();
863  y(array_open);
864 
865  Con *focused_ws = con_get_workspace(focused);
866 
867  Con *output;
868  TAILQ_FOREACH(output, &(croot->nodes_head), nodes) {
869  if (con_is_internal(output))
870  continue;
871  Con *ws;
872  TAILQ_FOREACH(ws, &(output_get_content(output)->nodes_head), nodes) {
873  assert(ws->type == CT_WORKSPACE);
874  y(map_open);
875 
876  ystr("num");
877  y(integer, ws->num);
878 
879  ystr("name");
880  ystr(ws->name);
881 
882  ystr("visible");
883  y(bool, workspace_is_visible(ws));
884 
885  ystr("focused");
886  y(bool, ws == focused_ws);
887 
888  ystr("rect");
889  y(map_open);
890  ystr("x");
891  y(integer, ws->rect.x);
892  ystr("y");
893  y(integer, ws->rect.y);
894  ystr("width");
895  y(integer, ws->rect.width);
896  ystr("height");
897  y(integer, ws->rect.height);
898  y(map_close);
899 
900  ystr("output");
901  ystr(output->name);
902 
903  ystr("urgent");
904  y(bool, ws->urgent);
905 
906  y(map_close);
907  }
908  }
909 
910  y(array_close);
911 
912  const unsigned char *payload;
913  ylength length;
914  y(get_buf, &payload, &length);
915 
916  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_WORKSPACES, payload);
917  y(free);
918 }
919 
920 /*
921  * Formats the reply message for a GET_OUTPUTS request and sends it to the
922  * client
923  *
924  */
925 IPC_HANDLER(get_outputs) {
926  yajl_gen gen = ygenalloc();
927  y(array_open);
928 
929  Output *output;
931  y(map_open);
932 
933  ystr("name");
935 
936  ystr("active");
937  y(bool, output->active);
938 
939  ystr("primary");
940  y(bool, output->primary);
941 
942  ystr("rect");
943  y(map_open);
944  ystr("x");
945  y(integer, output->rect.x);
946  ystr("y");
947  y(integer, output->rect.y);
948  ystr("width");
949  y(integer, output->rect.width);
950  ystr("height");
951  y(integer, output->rect.height);
952  y(map_close);
953 
954  ystr("current_workspace");
955  Con *ws = NULL;
956  if (output->con && (ws = con_get_fullscreen_con(output->con, CF_OUTPUT)))
957  ystr(ws->name);
958  else
959  y(null);
960 
961  y(map_close);
962  }
963 
964  y(array_close);
965 
966  const unsigned char *payload;
967  ylength length;
968  y(get_buf, &payload, &length);
969 
970  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_OUTPUTS, payload);
971  y(free);
972 }
973 
974 /*
975  * Formats the reply message for a GET_MARKS request and sends it to the
976  * client
977  *
978  */
979 IPC_HANDLER(get_marks) {
980  yajl_gen gen = ygenalloc();
981  y(array_open);
982 
983  Con *con;
985  mark_t *mark;
986  TAILQ_FOREACH(mark, &(con->marks_head), marks) {
987  ystr(mark->name);
988  }
989  }
990 
991  y(array_close);
992 
993  const unsigned char *payload;
994  ylength length;
995  y(get_buf, &payload, &length);
996 
997  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_MARKS, payload);
998  y(free);
999 }
1000 
1001 /*
1002  * Returns the version of i3
1003  *
1004  */
1005 IPC_HANDLER(get_version) {
1006  yajl_gen gen = ygenalloc();
1007  y(map_open);
1008 
1009  ystr("major");
1010  y(integer, MAJOR_VERSION);
1011 
1012  ystr("minor");
1013  y(integer, MINOR_VERSION);
1014 
1015  ystr("patch");
1016  y(integer, PATCH_VERSION);
1017 
1018  ystr("human_readable");
1019  ystr(i3_version);
1020 
1021  ystr("loaded_config_file_name");
1023 
1024  y(map_close);
1025 
1026  const unsigned char *payload;
1027  ylength length;
1028  y(get_buf, &payload, &length);
1029 
1030  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_VERSION, payload);
1031  y(free);
1032 }
1033 
1034 /*
1035  * Formats the reply message for a GET_BAR_CONFIG request and sends it to the
1036  * client.
1037  *
1038  */
1039 IPC_HANDLER(get_bar_config) {
1040  yajl_gen gen = ygenalloc();
1041 
1042  /* If no ID was passed, we return a JSON array with all IDs */
1043  if (message_size == 0) {
1044  y(array_open);
1045  Barconfig *current;
1046  TAILQ_FOREACH(current, &barconfigs, configs) {
1047  ystr(current->id);
1048  }
1049  y(array_close);
1050 
1051  const unsigned char *payload;
1052  ylength length;
1053  y(get_buf, &payload, &length);
1054 
1055  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_BAR_CONFIG, payload);
1056  y(free);
1057  return;
1058  }
1059 
1060  /* To get a properly terminated buffer, we copy
1061  * message_size bytes out of the buffer */
1062  char *bar_id = NULL;
1063  sasprintf(&bar_id, "%.*s", message_size, message);
1064  LOG("IPC: looking for config for bar ID \"%s\"\n", bar_id);
1065  Barconfig *current, *config = NULL;
1066  TAILQ_FOREACH(current, &barconfigs, configs) {
1067  if (strcmp(current->id, bar_id) != 0)
1068  continue;
1069 
1070  config = current;
1071  break;
1072  }
1073  free(bar_id);
1074 
1075  if (!config) {
1076  /* If we did not find a config for the given ID, the reply will contain
1077  * a null 'id' field. */
1078  y(map_open);
1079 
1080  ystr("id");
1081  y(null);
1082 
1083  y(map_close);
1084  } else {
1085  dump_bar_config(gen, config);
1086  }
1087 
1088  const unsigned char *payload;
1089  ylength length;
1090  y(get_buf, &payload, &length);
1091 
1092  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_BAR_CONFIG, payload);
1093  y(free);
1094 }
1095 
1096 /*
1097  * Returns a list of configured binding modes
1098  *
1099  */
1100 IPC_HANDLER(get_binding_modes) {
1101  yajl_gen gen = ygenalloc();
1102 
1103  y(array_open);
1104  struct Mode *mode;
1105  SLIST_FOREACH(mode, &modes, modes) {
1106  ystr(mode->name);
1107  }
1108  y(array_close);
1109 
1110  const unsigned char *payload;
1111  ylength length;
1112  y(get_buf, &payload, &length);
1113 
1114  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_BINDING_MODES, payload);
1115  y(free);
1116 }
1117 
1118 /*
1119  * Callback for the YAJL parser (will be called when a string is parsed).
1120  *
1121  */
1122 static int add_subscription(void *extra, const unsigned char *s,
1123  ylength len) {
1124  ipc_client *client = extra;
1125 
1126  DLOG("should add subscription to extra %p, sub %.*s\n", client, (int)len, s);
1127  int event = client->num_events;
1128 
1129  client->num_events++;
1130  client->events = srealloc(client->events, client->num_events * sizeof(char *));
1131  /* We copy the string because it is not null-terminated and strndup()
1132  * is missing on some BSD systems */
1133  client->events[event] = scalloc(len + 1, 1);
1134  memcpy(client->events[event], s, len);
1135 
1136  DLOG("client is now subscribed to:\n");
1137  for (int i = 0; i < client->num_events; i++) {
1138  DLOG("event %s\n", client->events[i]);
1139  }
1140  DLOG("(done)\n");
1141 
1142  return 1;
1143 }
1144 
1145 /*
1146  * Subscribes this connection to the event types which were given as a JSON
1147  * serialized array in the payload field of the message.
1148  *
1149  */
1150 IPC_HANDLER(subscribe) {
1151  yajl_handle p;
1152  yajl_status stat;
1153 
1154  /* Setup the JSON parser */
1155  static yajl_callbacks callbacks = {
1156  .yajl_string = add_subscription,
1157  };
1158 
1159  p = yalloc(&callbacks, (void *)client);
1160  stat = yajl_parse(p, (const unsigned char *)message, message_size);
1161  if (stat != yajl_status_ok) {
1162  unsigned char *err;
1163  err = yajl_get_error(p, true, (const unsigned char *)message,
1164  message_size);
1165  ELOG("YAJL parse error: %s\n", err);
1166  yajl_free_error(p, err);
1167 
1168  const char *reply = "{\"success\":false}";
1169  ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t *)reply);
1170  yajl_free(p);
1171  return;
1172  }
1173  yajl_free(p);
1174  const char *reply = "{\"success\":true}";
1175  ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SUBSCRIBE, (const uint8_t *)reply);
1176 
1177  if (client->first_tick_sent) {
1178  return;
1179  }
1180 
1181  bool is_tick = false;
1182  for (int i = 0; i < client->num_events; i++) {
1183  if (strcmp(client->events[i], "tick") == 0) {
1184  is_tick = true;
1185  break;
1186  }
1187  }
1188  if (!is_tick) {
1189  return;
1190  }
1191 
1192  client->first_tick_sent = true;
1193  const char *payload = "{\"first\":true,\"payload\":\"\"}";
1194  ipc_send_client_message(client, strlen(payload), I3_IPC_EVENT_TICK, (const uint8_t *)payload);
1195 }
1196 
1197 /*
1198  * Returns the raw last loaded i3 configuration file contents.
1199  */
1200 IPC_HANDLER(get_config) {
1201  yajl_gen gen = ygenalloc();
1202 
1203  y(map_open);
1204 
1205  ystr("config");
1207 
1208  y(map_close);
1209 
1210  const unsigned char *payload;
1211  ylength length;
1212  y(get_buf, &payload, &length);
1213 
1214  ipc_send_client_message(client, length, I3_IPC_REPLY_TYPE_CONFIG, payload);
1215  y(free);
1216 }
1217 
1218 /*
1219  * Sends the tick event from the message payload to subscribers. Establishes a
1220  * synchronization point in event-related tests.
1221  */
1222 IPC_HANDLER(send_tick) {
1223  yajl_gen gen = ygenalloc();
1224 
1225  y(map_open);
1226 
1227  ystr("first");
1228  y(bool, false);
1229 
1230  ystr("payload");
1231  yajl_gen_string(gen, (unsigned char *)message, message_size);
1232 
1233  y(map_close);
1234 
1235  const unsigned char *payload;
1236  ylength length;
1237  y(get_buf, &payload, &length);
1238 
1239  ipc_send_event("tick", I3_IPC_EVENT_TICK, (const char *)payload);
1240  y(free);
1241 
1242  const char *reply = "{\"success\":true}";
1243  ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_TICK, (const uint8_t *)reply);
1244  DLOG("Sent tick event\n");
1245 }
1246 
1247 struct sync_state {
1248  char *last_key;
1249  uint32_t rnd;
1250  xcb_window_t window;
1251 };
1252 
1253 static int _sync_json_key(void *extra, const unsigned char *val, size_t len) {
1254  struct sync_state *state = extra;
1255  FREE(state->last_key);
1256  state->last_key = scalloc(len + 1, 1);
1257  memcpy(state->last_key, val, len);
1258  return 1;
1259 }
1260 
1261 static int _sync_json_int(void *extra, long long val) {
1262  struct sync_state *state = extra;
1263  if (strcasecmp(state->last_key, "rnd") == 0) {
1264  state->rnd = val;
1265  } else if (strcasecmp(state->last_key, "window") == 0) {
1266  state->window = (xcb_window_t)val;
1267  }
1268  return 1;
1269 }
1270 
1272  yajl_handle p;
1273  yajl_status stat;
1274 
1275  /* Setup the JSON parser */
1276  static yajl_callbacks callbacks = {
1277  .yajl_map_key = _sync_json_key,
1278  .yajl_integer = _sync_json_int,
1279  };
1280 
1281  struct sync_state state;
1282  memset(&state, '\0', sizeof(struct sync_state));
1283  p = yalloc(&callbacks, (void *)&state);
1284  stat = yajl_parse(p, (const unsigned char *)message, message_size);
1285  FREE(state.last_key);
1286  if (stat != yajl_status_ok) {
1287  unsigned char *err;
1288  err = yajl_get_error(p, true, (const unsigned char *)message,
1289  message_size);
1290  ELOG("YAJL parse error: %s\n", err);
1291  yajl_free_error(p, err);
1292 
1293  const char *reply = "{\"success\":false}";
1294  ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SYNC, (const uint8_t *)reply);
1295  yajl_free(p);
1296  return;
1297  }
1298  yajl_free(p);
1299 
1300  DLOG("received IPC sync request (rnd = %d, window = 0x%08x)\n", state.rnd, state.window);
1301  sync_respond(state.window, state.rnd);
1302  const char *reply = "{\"success\":true}";
1303  ipc_send_client_message(client, strlen(reply), I3_IPC_REPLY_TYPE_SYNC, (const uint8_t *)reply);
1304 }
1305 
1306 /* The index of each callback function corresponds to the numeric
1307  * value of the message type (see include/i3/ipc.h) */
1309  handle_run_command,
1310  handle_get_workspaces,
1311  handle_subscribe,
1312  handle_get_outputs,
1313  handle_tree,
1314  handle_get_marks,
1315  handle_get_bar_config,
1316  handle_get_version,
1317  handle_get_binding_modes,
1318  handle_get_config,
1319  handle_send_tick,
1320  handle_sync,
1321 };
1322 
1323 /*
1324  * Handler for activity on a client connection, receives a message from a
1325  * client.
1326  *
1327  * For now, the maximum message size is 2048. I’m not sure for what the
1328  * IPC interface will be used in the future, thus I’m not implementing a
1329  * mechanism for arbitrarily long messages, as it seems like overkill
1330  * at the moment.
1331  *
1332  */
1333 static void ipc_receive_message(EV_P_ struct ev_io *w, int revents) {
1334  uint32_t message_type;
1335  uint32_t message_length;
1336  uint8_t *message = NULL;
1337  ipc_client *client = (ipc_client *)w->data;
1338  assert(client->fd == w->fd);
1339 
1340  int ret = ipc_recv_message(w->fd, &message_type, &message_length, &message);
1341  /* EOF or other error */
1342  if (ret < 0) {
1343  /* Was this a spurious read? See ev(3) */
1344  if (ret == -1 && errno == EAGAIN) {
1345  FREE(message);
1346  return;
1347  }
1348 
1349  /* If not, there was some kind of error. We don’t bother and close the
1350  * connection. Delete the client from the list of clients. */
1351  free_ipc_client(client, -1);
1352  FREE(message);
1353  return;
1354  }
1355 
1356  if (message_type >= (sizeof(handlers) / sizeof(handler_t)))
1357  DLOG("Unhandled message type: %d\n", message_type);
1358  else {
1359  handler_t h = handlers[message_type];
1360  h(client, message, 0, message_length, message_type);
1361  }
1362 
1363  FREE(message);
1364 }
1365 
1366 static void ipc_client_timeout(EV_P_ ev_timer *w, int revents) {
1367  /* No need to be polite and check for writeability, the other callback would
1368  * have been called by now. */
1369  ipc_client *client = (ipc_client *)w->data;
1370 
1371  char *cmdline = NULL;
1372 #if defined(__linux__) && defined(SO_PEERCRED)
1373  struct ucred peercred;
1374  socklen_t so_len = sizeof(peercred);
1375  if (getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0) {
1376  goto end;
1377  }
1378  char *exepath;
1379  sasprintf(&exepath, "/proc/%d/cmdline", peercred.pid);
1380 
1381  int fd = open(exepath, O_RDONLY);
1382  free(exepath);
1383  if (fd == -1) {
1384  goto end;
1385  }
1386  char buf[512] = {'\0'}; /* cut off cmdline for the error message. */
1387  const ssize_t n = read(fd, buf, sizeof(buf));
1388  close(fd);
1389  if (n < 0) {
1390  goto end;
1391  }
1392  for (char *walk = buf; walk < buf + n - 1; walk++) {
1393  if (*walk == '\0') {
1394  *walk = ' ';
1395  }
1396  }
1397  cmdline = buf;
1398 
1399  if (cmdline) {
1400  ELOG("client %p with pid %d and cmdline '%s' on fd %d timed out, killing\n", client, peercred.pid, cmdline, client->fd);
1401  }
1402 
1403 end:
1404 #endif
1405  if (!cmdline) {
1406  ELOG("client %p on fd %d timed out, killing\n", client, client->fd);
1407  }
1408 
1409  free_ipc_client(client, -1);
1410 }
1411 
1412 static void ipc_socket_writeable_cb(EV_P_ ev_io *w, int revents) {
1413  DLOG("fd %d writeable\n", w->fd);
1414  ipc_client *client = (ipc_client *)w->data;
1415 
1416  /* If this callback is called then there should be a corresponding active
1417  * timer. */
1418  assert(client->timeout != NULL);
1419  ipc_push_pending(client);
1420 }
1421 
1422 /*
1423  * Handler for activity on the listening socket, meaning that a new client
1424  * has just connected and we should accept() him. Sets up the event handler
1425  * for activity on the new connection and inserts the file descriptor into
1426  * the list of clients.
1427  *
1428  */
1429 void ipc_new_client(EV_P_ struct ev_io *w, int revents) {
1430  struct sockaddr_un peer;
1431  socklen_t len = sizeof(struct sockaddr_un);
1432  int fd;
1433  if ((fd = accept(w->fd, (struct sockaddr *)&peer, &len)) < 0) {
1434  if (errno != EINTR) {
1435  perror("accept()");
1436  }
1437  return;
1438  }
1439 
1440  /* Close this file descriptor on exec() */
1441  (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
1442 
1443  ipc_new_client_on_fd(EV_A_ fd);
1444 }
1445 
1446 /*
1447  * ipc_new_client_on_fd() only sets up the event handler
1448  * for activity on the new connection and inserts the file descriptor into
1449  * the list of clients.
1450  *
1451  * This variant is useful for the inherited IPC connection when restarting.
1452  *
1453  */
1455  set_nonblock(fd);
1456 
1457  ipc_client *client = scalloc(1, sizeof(ipc_client));
1458  client->fd = fd;
1459 
1460  client->read_callback = scalloc(1, sizeof(struct ev_io));
1461  client->read_callback->data = client;
1462  ev_io_init(client->read_callback, ipc_receive_message, fd, EV_READ);
1463  ev_io_start(EV_A_ client->read_callback);
1464 
1465  client->write_callback = scalloc(1, sizeof(struct ev_io));
1466  client->write_callback->data = client;
1467  ev_io_init(client->write_callback, ipc_socket_writeable_cb, fd, EV_WRITE);
1468 
1469  DLOG("IPC: new client connected on fd %d\n", fd);
1470  TAILQ_INSERT_TAIL(&all_clients, client, clients);
1471  return client;
1472 }
1473 
1474 /*
1475  * Creates the UNIX domain socket at the given path, sets it to non-blocking
1476  * mode, bind()s and listen()s on it.
1477  *
1478  */
1479 int ipc_create_socket(const char *filename) {
1480  int sockfd;
1481 
1483 
1484  char *resolved = resolve_tilde(filename);
1485  DLOG("Creating IPC-socket at %s\n", resolved);
1486  char *copy = sstrdup(resolved);
1487  const char *dir = dirname(copy);
1488  if (!path_exists(dir))
1489  mkdirp(dir, DEFAULT_DIR_MODE);
1490  free(copy);
1491 
1492  /* Unlink the unix domain socket before */
1493  unlink(resolved);
1494 
1495  if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
1496  perror("socket()");
1497  free(resolved);
1498  return -1;
1499  }
1500 
1501  (void)fcntl(sockfd, F_SETFD, FD_CLOEXEC);
1502 
1503  struct sockaddr_un addr;
1504  memset(&addr, 0, sizeof(struct sockaddr_un));
1505  addr.sun_family = AF_LOCAL;
1506  strncpy(addr.sun_path, resolved, sizeof(addr.sun_path) - 1);
1507  if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
1508  perror("bind()");
1509  free(resolved);
1510  return -1;
1511  }
1512 
1513  set_nonblock(sockfd);
1514 
1515  if (listen(sockfd, 5) < 0) {
1516  perror("listen()");
1517  free(resolved);
1518  return -1;
1519  }
1520 
1521  current_socketpath = resolved;
1522  return sockfd;
1523 }
1524 
1525 /*
1526  * Generates a json workspace event. Returns a dynamically allocated yajl
1527  * generator. Free with yajl_gen_free().
1528  */
1529 yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old) {
1530  setlocale(LC_NUMERIC, "C");
1531  yajl_gen gen = ygenalloc();
1532 
1533  y(map_open);
1534 
1535  ystr("change");
1536  ystr(change);
1537 
1538  ystr("current");
1539  if (current == NULL)
1540  y(null);
1541  else
1542  dump_node(gen, current, false);
1543 
1544  ystr("old");
1545  if (old == NULL)
1546  y(null);
1547  else
1548  dump_node(gen, old, false);
1549 
1550  y(map_close);
1551 
1552  setlocale(LC_NUMERIC, "");
1553 
1554  return gen;
1555 }
1556 
1557 /*
1558  * For the workspace events we send, along with the usual "change" field, also
1559  * the workspace container in "current". For focus events, we send the
1560  * previously focused workspace in "old".
1561  */
1562 void ipc_send_workspace_event(const char *change, Con *current, Con *old) {
1563  yajl_gen gen = ipc_marshal_workspace_event(change, current, old);
1564 
1565  const unsigned char *payload;
1566  ylength length;
1567  y(get_buf, &payload, &length);
1568 
1569  ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, (const char *)payload);
1570 
1571  y(free);
1572 }
1573 
1574 /*
1575  * For the window events we send, along the usual "change" field,
1576  * also the window container, in "container".
1577  */
1578 void ipc_send_window_event(const char *property, Con *con) {
1579  DLOG("Issue IPC window %s event (con = %p, window = 0x%08x)\n",
1580  property, con, (con->window ? con->window->id : XCB_WINDOW_NONE));
1581 
1582  setlocale(LC_NUMERIC, "C");
1583  yajl_gen gen = ygenalloc();
1584 
1585  y(map_open);
1586 
1587  ystr("change");
1588  ystr(property);
1589 
1590  ystr("container");
1591  dump_node(gen, con, false);
1592 
1593  y(map_close);
1594 
1595  const unsigned char *payload;
1596  ylength length;
1597  y(get_buf, &payload, &length);
1598 
1599  ipc_send_event("window", I3_IPC_EVENT_WINDOW, (const char *)payload);
1600  y(free);
1601  setlocale(LC_NUMERIC, "");
1602 }
1603 
1604 /*
1605  * For the barconfig update events, we send the serialized barconfig.
1606  */
1608  DLOG("Issue barconfig_update event for id = %s\n", barconfig->id);
1609  setlocale(LC_NUMERIC, "C");
1610  yajl_gen gen = ygenalloc();
1611 
1612  dump_bar_config(gen, barconfig);
1613 
1614  const unsigned char *payload;
1615  ylength length;
1616  y(get_buf, &payload, &length);
1617 
1618  ipc_send_event("barconfig_update", I3_IPC_EVENT_BARCONFIG_UPDATE, (const char *)payload);
1619  y(free);
1620  setlocale(LC_NUMERIC, "");
1621 }
1622 
1623 /*
1624  * For the binding events, we send the serialized binding struct.
1625  */
1626 void ipc_send_binding_event(const char *event_type, Binding *bind) {
1627  DLOG("Issue IPC binding %s event (sym = %s, code = %d)\n", event_type, bind->symbol, bind->keycode);
1628 
1629  setlocale(LC_NUMERIC, "C");
1630 
1631  yajl_gen gen = ygenalloc();
1632 
1633  y(map_open);
1634 
1635  ystr("change");
1636  ystr(event_type);
1637 
1638  ystr("binding");
1639  dump_binding(gen, bind);
1640 
1641  y(map_close);
1642 
1643  const unsigned char *payload;
1644  ylength length;
1645  y(get_buf, &payload, &length);
1646 
1647  ipc_send_event("binding", I3_IPC_EVENT_BINDING, (const char *)payload);
1648 
1649  y(free);
1650  setlocale(LC_NUMERIC, "");
1651 }
1652 
1653 /*
1654  * Sends a restart reply to the IPC client on the specified fd.
1655  */
1657  DLOG("ipc_confirm_restart(fd %d)\n", client->fd);
1658  static const char *reply = "[{\"success\":true}]";
1660  client, strlen(reply), I3_IPC_REPLY_TYPE_COMMAND,
1661  (const uint8_t *)reply);
1662  ipc_push_pending(client);
1663 }
char ** events
Definition: ipc.h:32
int num
the workspace number, if this Con is of type CT_WORKSPACE and the workspace is not a named workspace ...
Definition: data.h:643
#define FREE(pointer)
Definition: util.h:47
char * sstrndup(const char *str, size_t size)
Safe-wrapper around strndup which exits if strndup returns NULL (meaning that there is no more memory...
struct outputs_head outputs
Definition: randr.c:21
Defines a mouse command to be executed instead of the default behavior when clicking on the non-statu...
uint32_t height
Definition: data.h:161
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:114
bool restart_mode
Definition: data.h:551
void * srealloc(void *ptr, size_t size)
Safe-wrapper around realloc which exits if realloc returns NULL (meaning that there is no more memory...
handler_t handlers[12]
Definition: ipc.c:1308
#define YSTR_IF_SET(name)
static void ipc_socket_writeable_cb(EV_P_ struct ev_io *w, int revents)
char * current_socketpath
Definition: ipc.c:23
int input_code
The button to be used (e.g., 1 for "button1").
static int _sync_json_int(void *extra, long long val)
Definition: ipc.c:1261
IPC_HANDLER(run_command)
Definition: ipc.c:224
struct barconfig_head barconfigs
Definition: config.c:19
char * id
Automatically generated ID for this bar config.
CommandResult * parse_command(const char *input, yajl_gen gen, ipc_client *client)
Parses and executes the given command.
input_type_t input_type
Definition: data.h:285
struct Con * croot
Definition: tree.c:12
#define DLOG(fmt,...)
Definition: libi3.h:104
#define TAILQ_HEAD(name, type)
Definition: queue.h:318
struct ev_io * write_callback
Definition: ipc.h:39
static void dump_bar_config(yajl_gen gen, Barconfig *config)
Definition: ipc.c:701
bool release
If true, the command will be executed after the button is released.
#define TAILQ_EMPTY(head)
Definition: queue.h:344
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
int mkdirp(const char *path, mode_t mode)
Emulates mkdir -p (creates any missing folders)
void ipc_send_binding_event(const char *event_type, Binding *bind)
For the binding events, we send the serialized binding struct.
Definition: ipc.c:1626
bool workspace_is_visible(Con *ws)
Returns true if the workspace is currently visible.
Definition: workspace.c:299
static void dump_event_state_mask(yajl_gen gen, Binding *bind)
Definition: ipc.c:263
static void dump_bar_bindings(yajl_gen gen, Barconfig *config)
Definition: ipc.c:668
Definition: data.h:60
bool path_exists(const char *path)
Checks if the given path exists by calling stat().
Definition: util.c:178
static void ipc_receive_message(EV_P_ struct ev_io *w, int revents)
Definition: ipc.c:1333
char * current_config
Definition: config.c:16
struct bindings_head * bindings
Definition: main.c:74
void ipc_send_window_event(const char *property, Con *con)
For the window events we send, along the usual "change" field, also the window container, in "container".
Definition: ipc.c:1578
enum Con::@20 type
int ipc_recv_message(int sockfd, uint32_t *message_type, uint32_t *reply_length, uint8_t **reply)
Reads a message from the given socket file descriptor and stores its length (reply_length) as well as...
struct modes_head modes
Definition: config.c:18
#define yalloc(callbacks, client)
Definition: yajl_utils.h:23
Stores a rectangle, for example the size of a window, the child window etc.
Definition: data.h:157
uint32_t size
Definition: shmlog.h:36
uint32_t x
Definition: data.h:158
enum Match::@15 dock
char * symbol
Symbol the user specified in configfile, if any.
Definition: data.h:325
Output * get_output_by_name(const char *name, const bool require_active)
Returns the output with the given name or NULL.
Definition: randr.c:47
void ipc_send_barconfig_update_event(Barconfig *barconfig)
For the barconfig update events, we send the serialized barconfig.
Definition: ipc.c:1607
void ipc_confirm_restart(ipc_client *client)
Sends a restart reply to the IPC client on the specified fd.
Definition: ipc.c:1656
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:402
nodes_head
Definition: data.h:694
static void set_nonblock(int sockfd)
Definition: ipc.c:34
struct Rect rect
Definition: data.h:649
static void free_ipc_client(ipc_client *client, int exempt_fd)
Definition: ipc.c:131
A &#39;Con&#39; represents everything from the X11 root window down to a single X11 window.
Definition: data.h:613
#define TAILQ_FIRST(head)
Definition: queue.h:336
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
int fd
Definition: ipc.h:28
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
Definition: con.c:418
Con * con_get_output(Con *con)
Gets the output container (first container with CT_OUTPUT in hierarchy) this node is on...
Definition: con.c:404
static int add_subscription(void *extra, const unsigned char *s, ylength len)
Definition: ipc.c:1122
static cmdp_state state
void command_result_free(CommandResult *result)
Frees a CommandResult.
orientation_t con_orientation(Con *con)
Returns the orientation of the given container (for stacked containers, vertical orientation is used ...
Definition: con.c:1418
void tree_render(void)
Renders the tree, that is rendering all outputs using render_con() and pushing the changes to X11 usi...
Definition: tree.c:449
char * name
Definition: data.h:659
uint8_t * buffer
Definition: ipc.h:41
uint32_t y
Definition: data.h:159
#define DUMP_PROPERTY(key, prop_name)
char * current_configpath
Definition: config.c:15
size_t buffer_size
Definition: ipc.h:42
struct pending_marks * marks
static void dump_binding(yajl_gen gen, Binding *bind)
Definition: ipc.c:325
#define DUMP_REGEX(re_name)
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
bool con_is_split(Con *con)
Returns true if a container should be considered split.
Definition: con.c:326
Definition: data.h:62
Definition: data.h:98
bool con_is_internal(Con *con)
Returns true if the container is internal, such as __i3_scratch.
Definition: con.c:532
void ipc_shutdown(shutdown_reason_t reason, int exempt_fd)
Calls shutdown() on each socket and closes it.
Definition: ipc.c:206
char * command
The command which is to be executed for this button.
#define LOG(fmt,...)
Definition: libi3.h:94
Con * output_get_content(Con *output)
Returns the output container below the given output container.
Definition: output.c:16
uint32_t width
Definition: data.h:160
void ipc_set_kill_timeout(ev_tstamp new)
Set the maximum duration that we allow for a connection with an unwriteable socket.
Definition: ipc.c:49
bool urgent
Definition: data.h:618
static ev_tstamp kill_timeout
Definition: ipc.c:47
An Output is a physical output on your graphics driver.
Definition: data.h:375
A struct that contains useful information about the result of a command as a whole (e...
char * name
Definition: configuration.h:83
static void ipc_push_pending(ipc_client *client)
Definition: ipc.c:59
Definition: data.h:97
Definition: data.h:63
size_t ylength
Definition: yajl_utils.h:24
static void ipc_send_shutdown_event(shutdown_reason_t reason)
Definition: ipc.c:176
Holds a keybinding, consisting of a keycode combined with modifiers and the command which is executed...
Definition: data.h:282
struct Con * focused
Definition: tree.c:13
xcb_window_t window
Definition: ipc.c:1250
shutdown_reason_t
Calls to ipc_shutdown() should provide a reason for the shutdown.
Definition: ipc.h:102
struct all_cons_head all_cons
Definition: tree.c:15
struct Window * window
Definition: data.h:681
int num_events
Definition: ipc.h:31
void ipc_send_event(const char *event, uint32_t message_type, const char *payload)
Sends the specified event to all IPC clients which are currently connected and subscribed to this kin...
Definition: ipc.c:161
yajl_gen ipc_marshal_workspace_event(const char *change, Con *current, Con *old)
Generates a json workspace event.
Definition: ipc.c:1529
Definition: data.h:92
Definition: data.h:602
The configuration file can contain multiple sets of bindings.
Definition: configuration.h:82
ssize_t writeall_nonblock(int fd, const void *buf, size_t count)
Like writeall, but instead of retrying upon EAGAIN (returned when a write would block), the function stops and returns the total number of bytes written so far.
static int _sync_json_key(void *extra, const unsigned char *val, size_t len)
Definition: ipc.c:1253
const char * i3string_as_utf8(i3String *str)
Returns the UTF-8 encoded version of the i3String.
#define ygenalloc()
Definition: yajl_utils.h:22
Definition: data.h:96
void sync_respond(xcb_window_t window, uint32_t rnd)
Definition: sync.c:12
const char * i3_version
Git commit identifier, from version.c.
Definition: version.c:13
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
Definition: data.h:502
static void ipc_send_client_message(ipc_client *client, size_t size, const uint32_t message_type, const uint8_t *payload)
Definition: ipc.c:112
static void dump_rect(yajl_gen gen, const char *name, Rect r)
Definition: ipc.c:249
#define ELOG(fmt,...)
Definition: libi3.h:99
Definition: data.h:64
#define ystr(str)
Definition: commands.c:22
static char * canonicalize_output_name(char *name)
Definition: ipc.c:692
Con * con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode)
Returns the first fullscreen node below this node.
Definition: con.c:467
char * resolve_tilde(const char *path)
This function resolves ~ in pathnames.
struct ev_io * read_callback
Definition: ipc.h:38
struct ev_timer * timeout
Definition: ipc.h:40
Definition: data.h:94
char * previous_workspace_name
Stores a copy of the name of the last used workspace for the workspace back-and-forth switching...
Definition: workspace.c:19
struct ev_loop * main_loop
Definition: main.c:66
Definition: ipc.h:27
Definition: data.h:93
ipc_client * ipc_new_client_on_fd(EV_P_ int fd)
ipc_new_client_on_fd() only sets up the event handler for activity on the new connection and inserts ...
Definition: ipc.c:1454
all_clients
Definition: ipc.c:26
void(* handler_t)(ipc_client *, uint8_t *, int, uint32_t, uint32_t)
Definition: ipc.h:58
void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart)
Definition: ipc.c:353
Config config
Definition: config.c:17
void ipc_new_client(EV_P_ struct ev_io *w, int revents)
Handler for activity on the listening socket, meaning that a new client has just connected and we sho...
Definition: ipc.c:1429
uint32_t y
Definition: data.h:128
void ipc_send_workspace_event(const char *change, Con *current, Con *old)
For the workspace events we send, along with the usual "change" field, also the workspace container i...
Definition: ipc.c:1562
char * command
Command, like in command mode.
Definition: data.h:334
int ipc_create_socket(const char *filename)
Creates the UNIX domain socket at the given path, sets it to non-blocking mode, bind()s and listen()s...
Definition: ipc.c:1479
static void ipc_client_timeout(EV_P_ ev_timer *w, int revents)
Definition: ipc.c:1366
char * output_primary_name(Output *output)
Retrieves the primary name of an output.
Definition: output.c:51
char * last_key
Definition: ipc.c:1248
xcb_window_t id
Definition: data.h:411
marks_head
Definition: data.h:671
Holds the status bar configuration (i3bar).
uint32_t rnd
Definition: ipc.c:1249
#define DEFAULT_DIR_MODE
Definition: libi3.h:25
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:376
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
static i3_shmlog_header * header
Definition: log.c:55
enum Match::@17 insert_where
i3_event_state_mask_t event_state_mask
Bitmask which is applied against event->state for KeyPress and KeyRelease events to determine whether...
Definition: data.h:320
char * name
Definition: data.h:603
uint32_t keycode
Keycode to bind.
Definition: data.h:315