i3
main.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  * main.c: Initialization, main loop
8  *
9  */
10 #include "all.h"
11 
12 #include <ev.h>
13 #include <fcntl.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/un.h>
17 #include <sys/time.h>
18 #include <sys/resource.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <libgen.h>
22 #include "shmlog.h"
23 
24 #include "sd-daemon.h"
25 
26 /* The original value of RLIMIT_CORE when i3 was started. We need to restore
27  * this before starting any other process, since we set RLIMIT_CORE to
28  * RLIM_INFINITY for i3 debugging versions. */
29 struct rlimit original_rlimit_core;
30 
33 
34 /* We keep the xcb_check watcher around to be able to enable and disable it
35  * temporarily for drag_pointer(). */
36 static struct ev_check *xcb_check;
37 
38 extern Con *focused;
39 
40 char **start_argv;
41 
42 xcb_connection_t *conn;
43 /* The screen (0 when you are using DISPLAY=:0) of the connection 'conn' */
45 
46 /* Display handle for libstartup-notification */
47 SnDisplay *sndisplay;
48 
49 /* The last timestamp we got from X11 (timestamps are included in some events
50  * and are used for some things, like determining a unique ID in startup
51  * notification). */
52 xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
53 
54 xcb_screen_t *root_screen;
55 xcb_window_t root;
56 
57 /* Color depth, visual id and colormap to use when creating windows and
58  * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
59  * otherwise the root window’s default (usually 24 bit TrueColor). */
60 uint8_t root_depth;
61 xcb_visualtype_t *visual_type;
62 xcb_colormap_t colormap;
63 
64 struct ev_loop *main_loop;
65 
66 xcb_key_symbols_t *keysyms;
67 
68 /* Default shmlog size if not set by user. */
69 const int default_shmlog_size = 25 * 1024 * 1024;
70 
71 /* The list of key bindings */
72 struct bindings_head *bindings;
73 
74 /* The list of exec-lines */
75 struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
76 
77 /* The list of exec_always lines */
79 
80 /* The list of assignments */
81 struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
82 
83 /* The list of workspace assignments (which workspace should end up on which
84  * output) */
86 
87 /* We hope that those are supported and set them to true */
88 bool xcursor_supported = true;
89 bool xkb_supported = true;
90 
91 /*
92  * This callback is only a dummy, see xcb_prepare_cb and xcb_check_cb.
93  * See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop
94  *
95  */
96 static void xcb_got_event(EV_P_ struct ev_io *w, int revents) {
97  /* empty, because xcb_prepare_cb and xcb_check_cb are used */
98 }
99 
100 /*
101  * Flush before blocking (and waiting for new events)
102  *
103  */
104 static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
105  xcb_flush(conn);
106 }
107 
108 /*
109  * Instead of polling the X connection socket we leave this to
110  * xcb_poll_for_event() which knows better than we can ever know.
111  *
112  */
113 static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
114  xcb_generic_event_t *event;
115 
116  while ((event = xcb_poll_for_event(conn)) != NULL) {
117  if (event->response_type == 0) {
118  if (event_is_ignored(event->sequence, 0))
119  DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
120  else {
121  xcb_generic_error_t *error = (xcb_generic_error_t *)event;
122  DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
123  error->sequence, error->error_code);
124  }
125  free(event);
126  continue;
127  }
128 
129  /* Strip off the highest bit (set if the event is generated) */
130  int type = (event->response_type & 0x7F);
131 
132  handle_event(type, event);
133 
134  free(event);
135  }
136 }
137 
138 /*
139  * Enable or disable the main X11 event handling function.
140  * This is used by drag_pointer() which has its own, modal event handler, which
141  * takes precedence over the normal event handler.
142  *
143  */
144 void main_set_x11_cb(bool enable) {
145  DLOG("Setting main X11 callback to enabled=%d\n", enable);
146  if (enable) {
147  ev_check_start(main_loop, xcb_check);
148  /* Trigger the watcher explicitly to handle all remaining X11 events.
149  * drag_pointer()’s event handler exits in the middle of the loop. */
150  ev_feed_event(main_loop, xcb_check, 0);
151  } else {
152  ev_check_stop(main_loop, xcb_check);
153  }
154 }
155 
156 /*
157  * Exit handler which destroys the main_loop. Will trigger cleanup handlers.
158  *
159  */
160 static void i3_exit(void) {
161 /* We need ev >= 4 for the following code. Since it is not *that* important (it
162  * only makes sure that there are no i3-nagbar instances left behind) we still
163  * support old systems with libev 3. */
164 #if EV_VERSION_MAJOR >= 4
165  ev_loop_destroy(main_loop);
166 #endif
167 
168  if (*shmlogname != '\0') {
169  fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
170  fflush(stderr);
171  shm_unlink(shmlogname);
172  }
173 }
174 
175 /*
176  * (One-shot) Handler for all signals with default action "Term", see signal(7)
177  *
178  * Unlinks the SHM log and re-raises the signal.
179  *
180  */
181 static void handle_signal(int sig, siginfo_t *info, void *data) {
182  if (*shmlogname != '\0') {
183  shm_unlink(shmlogname);
184  }
185  raise(sig);
186 }
187 
188 int main(int argc, char *argv[]) {
189  /* Keep a symbol pointing to the I3_VERSION string constant so that we have
190  * it in gdb backtraces. */
191  static const char *_i3_version __attribute__((used)) = I3_VERSION;
192  char *override_configpath = NULL;
193  bool autostart = true;
194  char *layout_path = NULL;
195  bool delete_layout_path = false;
196  bool force_xinerama = false;
197  char *fake_outputs = NULL;
198  bool disable_signalhandler = false;
199  bool only_check_config = false;
200  static struct option long_options[] = {
201  {"no-autostart", no_argument, 0, 'a'},
202  {"config", required_argument, 0, 'c'},
203  {"version", no_argument, 0, 'v'},
204  {"moreversion", no_argument, 0, 'm'},
205  {"more-version", no_argument, 0, 'm'},
206  {"more_version", no_argument, 0, 'm'},
207  {"help", no_argument, 0, 'h'},
208  {"layout", required_argument, 0, 'L'},
209  {"restart", required_argument, 0, 0},
210  {"force-xinerama", no_argument, 0, 0},
211  {"force_xinerama", no_argument, 0, 0},
212  {"disable-signalhandler", no_argument, 0, 0},
213  {"shmlog-size", required_argument, 0, 0},
214  {"shmlog_size", required_argument, 0, 0},
215  {"get-socketpath", no_argument, 0, 0},
216  {"get_socketpath", no_argument, 0, 0},
217  {"fake_outputs", required_argument, 0, 0},
218  {"fake-outputs", required_argument, 0, 0},
219  {"force-old-config-parser-v4.4-only", no_argument, 0, 0},
220  {0, 0, 0, 0}};
221  int option_index = 0, opt;
222 
223  setlocale(LC_ALL, "");
224 
225  /* Get the RLIMIT_CORE limit at startup time to restore this before
226  * starting processes. */
227  getrlimit(RLIMIT_CORE, &original_rlimit_core);
228 
229  /* Disable output buffering to make redirects in .xsession actually useful for debugging */
230  if (!isatty(fileno(stdout)))
231  setbuf(stdout, NULL);
232 
233  srand(time(NULL));
234 
235  /* Init logging *before* initializing debug_build to guarantee early
236  * (file) logging. */
237  init_logging();
238 
239  /* On release builds, disable SHM logging by default. */
240  shmlog_size = (is_debug_build() || strstr(argv[0], "i3-with-shmlog") != NULL ? default_shmlog_size : 0);
241 
242  start_argv = argv;
243 
244  while ((opt = getopt_long(argc, argv, "c:CvmaL:hld:V", long_options, &option_index)) != -1) {
245  switch (opt) {
246  case 'a':
247  LOG("Autostart disabled using -a\n");
248  autostart = false;
249  break;
250  case 'L':
251  FREE(layout_path);
252  layout_path = sstrdup(optarg);
253  delete_layout_path = false;
254  break;
255  case 'c':
256  FREE(override_configpath);
257  override_configpath = sstrdup(optarg);
258  break;
259  case 'C':
260  LOG("Checking configuration file only (-C)\n");
261  only_check_config = true;
262  break;
263  case 'v':
264  printf("i3 version %s © 2009 Michael Stapelberg and contributors\n", i3_version);
265  exit(EXIT_SUCCESS);
266  break;
267  case 'm':
268  printf("Binary i3 version: %s © 2009 Michael Stapelberg and contributors\n", i3_version);
270  exit(EXIT_SUCCESS);
271  break;
272  case 'V':
273  set_verbosity(true);
274  break;
275  case 'd':
276  LOG("Enabling debug logging\n");
277  set_debug_logging(true);
278  break;
279  case 'l':
280  /* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */
281  break;
282  case 0:
283  if (strcmp(long_options[option_index].name, "force-xinerama") == 0 ||
284  strcmp(long_options[option_index].name, "force_xinerama") == 0) {
285  force_xinerama = true;
286  ELOG("Using Xinerama instead of RandR. This option should be "
287  "avoided at all cost because it does not refresh the list "
288  "of screens, so you cannot configure displays at runtime. "
289  "Please check if your driver really does not support RandR "
290  "and disable this option as soon as you can.\n");
291  break;
292  } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) {
293  disable_signalhandler = true;
294  break;
295  } else if (strcmp(long_options[option_index].name, "get-socketpath") == 0 ||
296  strcmp(long_options[option_index].name, "get_socketpath") == 0) {
297  char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
298  if (socket_path) {
299  printf("%s\n", socket_path);
300  exit(EXIT_SUCCESS);
301  }
302 
303  exit(EXIT_FAILURE);
304  } else if (strcmp(long_options[option_index].name, "shmlog-size") == 0 ||
305  strcmp(long_options[option_index].name, "shmlog_size") == 0) {
306  shmlog_size = atoi(optarg);
307  /* Re-initialize logging immediately to get as many
308  * logmessages as possible into the SHM log. */
309  init_logging();
310  LOG("Limiting SHM log size to %d bytes\n", shmlog_size);
311  break;
312  } else if (strcmp(long_options[option_index].name, "restart") == 0) {
313  FREE(layout_path);
314  layout_path = sstrdup(optarg);
315  delete_layout_path = true;
316  break;
317  } else if (strcmp(long_options[option_index].name, "fake-outputs") == 0 ||
318  strcmp(long_options[option_index].name, "fake_outputs") == 0) {
319  LOG("Initializing fake outputs: %s\n", optarg);
320  fake_outputs = sstrdup(optarg);
321  break;
322  } else if (strcmp(long_options[option_index].name, "force-old-config-parser-v4.4-only") == 0) {
323  ELOG("You are passing --force-old-config-parser-v4.4-only, but that flag was removed by now.\n");
324  break;
325  }
326  /* fall-through */
327  default:
328  fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
329  fprintf(stderr, "\n");
330  fprintf(stderr, "\t-a disable autostart ('exec' lines in config)\n");
331  fprintf(stderr, "\t-c <file> use the provided configfile instead\n");
332  fprintf(stderr, "\t-C validate configuration file and exit\n");
333  fprintf(stderr, "\t-d all enable debug output\n");
334  fprintf(stderr, "\t-L <file> path to the serialized layout during restarts\n");
335  fprintf(stderr, "\t-v display version and exit\n");
336  fprintf(stderr, "\t-V enable verbose mode\n");
337  fprintf(stderr, "\n");
338  fprintf(stderr, "\t--force-xinerama\n"
339  "\tUse Xinerama instead of RandR.\n"
340  "\tThis option should only be used if you are stuck with the\n"
341  "\told nVidia closed source driver (older than 302.17), which does\n"
342  "\tnot support RandR.\n");
343  fprintf(stderr, "\n");
344  fprintf(stderr, "\t--get-socketpath\n"
345  "\tRetrieve the i3 IPC socket path from X11, print it, then exit.\n");
346  fprintf(stderr, "\n");
347  fprintf(stderr, "\t--shmlog-size <limit>\n"
348  "\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
349  "\tto 0 disables SHM logging entirely.\n"
350  "\tThe default is %d bytes.\n",
351  shmlog_size);
352  fprintf(stderr, "\n");
353  fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
354  "to send to a currently running i3 (like i3-msg). This allows you to\n"
355  "use nice and logical commands, such as:\n"
356  "\n"
357  "\ti3 border none\n"
358  "\ti3 floating toggle\n"
359  "\ti3 kill window\n"
360  "\n");
361  exit(EXIT_FAILURE);
362  }
363  }
364 
365  if (only_check_config) {
366  exit(parse_configuration(override_configpath, false) ? 0 : 1);
367  }
368 
369  /* If the user passes more arguments, we act like i3-msg would: Just send
370  * the arguments as an IPC message to i3. This allows for nice semantic
371  * commands such as 'i3 border none'. */
372  if (optind < argc) {
373  /* We enable verbose mode so that the user knows what’s going on.
374  * This should make it easier to find mistakes when the user passes
375  * arguments by mistake. */
376  set_verbosity(true);
377 
378  LOG("Additional arguments passed. Sending them as a command to i3.\n");
379  char *payload = NULL;
380  while (optind < argc) {
381  if (!payload) {
382  payload = sstrdup(argv[optind]);
383  } else {
384  char *both;
385  sasprintf(&both, "%s %s", payload, argv[optind]);
386  free(payload);
387  payload = both;
388  }
389  optind++;
390  }
391  DLOG("Command is: %s (%zd bytes)\n", payload, strlen(payload));
392  char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
393  if (!socket_path) {
394  ELOG("Could not get i3 IPC socket path\n");
395  return 1;
396  }
397 
398  int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
399  if (sockfd == -1)
400  err(EXIT_FAILURE, "Could not create socket");
401 
402  struct sockaddr_un addr;
403  memset(&addr, 0, sizeof(struct sockaddr_un));
404  addr.sun_family = AF_LOCAL;
405  strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
406  FREE(socket_path);
407  if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
408  err(EXIT_FAILURE, "Could not connect to i3");
409 
410  if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
411  (uint8_t *)payload) == -1)
412  err(EXIT_FAILURE, "IPC: write()");
413  FREE(payload);
414 
415  uint32_t reply_length;
416  uint32_t reply_type;
417  uint8_t *reply;
418  int ret;
419  if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
420  if (ret == -1)
421  err(EXIT_FAILURE, "IPC: read()");
422  return 1;
423  }
424  if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND)
425  errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND);
426  printf("%.*s\n", reply_length, reply);
427  FREE(reply);
428  return 0;
429  }
430 
431  /* Enable logging to handle the case when the user did not specify --shmlog-size */
432  init_logging();
433 
434  /* Try to enable core dumps by default when running a debug build */
435  if (is_debug_build()) {
436  struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
437  setrlimit(RLIMIT_CORE, &limit);
438 
439  /* The following code is helpful, but not required. We thus don’t pay
440  * much attention to error handling, non-linux or other edge cases. */
441  LOG("CORE DUMPS: You are running a development version of i3, so coredumps were automatically enabled (ulimit -c unlimited).\n");
442  size_t cwd_size = 1024;
443  char *cwd = smalloc(cwd_size);
444  char *cwd_ret;
445  while ((cwd_ret = getcwd(cwd, cwd_size)) == NULL && errno == ERANGE) {
446  cwd_size = cwd_size * 2;
447  cwd = srealloc(cwd, cwd_size);
448  }
449  if (cwd_ret != NULL)
450  LOG("CORE DUMPS: Your current working directory is \"%s\".\n", cwd);
451  int patternfd;
452  if ((patternfd = open("/proc/sys/kernel/core_pattern", O_RDONLY)) >= 0) {
453  memset(cwd, '\0', cwd_size);
454  if (read(patternfd, cwd, cwd_size) > 0)
455  /* a trailing newline is included in cwd */
456  LOG("CORE DUMPS: Your core_pattern is: %s", cwd);
457  close(patternfd);
458  }
459  free(cwd);
460  }
461 
462  LOG("i3 %s starting\n", i3_version);
463 
464  conn = xcb_connect(NULL, &conn_screen);
465  if (xcb_connection_has_error(conn))
466  errx(EXIT_FAILURE, "Cannot open display\n");
467 
468  sndisplay = sn_xcb_display_new(conn, NULL, NULL);
469 
470  /* Initialize the libev event loop. This needs to be done before loading
471  * the config file because the parser will install an ev_child watcher
472  * for the nagbar when config errors are found. */
473  main_loop = EV_DEFAULT;
474  if (main_loop == NULL)
475  die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
476 
477  root_screen = xcb_aux_get_screen(conn, conn_screen);
478  root = root_screen->root;
479 
480 /* Place requests for the atoms we need as soon as possible */
481 #define xmacro(atom) \
482  xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
483 #include "atoms.xmacro"
484 #undef xmacro
485 
486  root_depth = root_screen->root_depth;
487  colormap = root_screen->default_colormap;
488  visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32);
489  if (visual_type != NULL) {
490  root_depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id);
491  colormap = xcb_generate_id(conn);
492 
493  xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(conn,
494  XCB_COLORMAP_ALLOC_NONE,
495  colormap,
496  root,
497  visual_type->visual_id);
498 
499  xcb_generic_error_t *error = xcb_request_check(conn, cm_cookie);
500  if (error != NULL) {
501  ELOG("Could not create colormap. Error code: %d\n", error->error_code);
502  exit(EXIT_FAILURE);
503  }
504  } else {
506  }
507 
508  init_dpi();
509 
510  DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id);
511  DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d\n",
512  root_screen->height_in_pixels, root_screen->height_in_millimeters);
513  DLOG("One logical pixel corresponds to %d physical pixels on this display.\n", logical_px(1));
514 
515  xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
516  xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
517 
518 /* Setup NetWM atoms */
519 #define xmacro(name) \
520  do { \
521  xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
522  if (!reply) { \
523  ELOG("Could not get atom " #name "\n"); \
524  exit(-1); \
525  } \
526  A_##name = reply->atom; \
527  free(reply); \
528  } while (0);
529 #include "atoms.xmacro"
530 #undef xmacro
531 
532  load_configuration(conn, override_configpath, false);
533 
534  if (config.ipc_socket_path == NULL) {
535  /* Fall back to a file name in /tmp/ based on the PID */
536  if ((config.ipc_socket_path = getenv("I3SOCK")) == NULL)
538  else
540  }
541 
542  xcb_void_cookie_t cookie;
543  cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
544  xcb_generic_error_t *error = xcb_request_check(conn, cookie);
545  if (error != NULL) {
546  ELOG("Another window manager seems to be running (X error %d)\n", error->error_code);
547  return 1;
548  }
549 
550  xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
551  if (greply == NULL) {
552  ELOG("Could not get geometry of the root window, exiting\n");
553  return 1;
554  }
555  DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
556 
558 
559  /* Set a cursor for the root window (otherwise the root window will show no
560  cursor until the first client is launched). */
561  if (xcursor_supported)
563  else
565 
566  const xcb_query_extension_reply_t *extreply;
567  extreply = xcb_get_extension_data(conn, &xcb_xkb_id);
568  xkb_supported = extreply->present;
569  if (!extreply->present) {
570  DLOG("xkb is not present on this server\n");
571  } else {
572  DLOG("initializing xcb-xkb\n");
573  xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
574  xcb_xkb_select_events(conn,
575  XCB_XKB_ID_USE_CORE_KBD,
576  XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
577  0,
578  XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
579  0xff,
580  0xff,
581  NULL);
582 
583  /* Setting both, XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE and
584  * XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED, will lead to the
585  * X server sending us the full XKB state in KeyPress and KeyRelease:
586  * https://sources.debian.net/src/xorg-server/2:1.17.2-1.1/xkb/xkbEvents.c/?hl=927#L927
587  */
588  xcb_xkb_per_client_flags_reply_t *pcf_reply;
589  /* The last three parameters are unset because they are only relevant
590  * when using a feature called “automatic reset of boolean controls”:
591  * http://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Automatic_Reset_of_Boolean_Controls
592  * */
593  pcf_reply = xcb_xkb_per_client_flags_reply(
594  conn,
595  xcb_xkb_per_client_flags(
596  conn,
597  XCB_XKB_ID_USE_CORE_KBD,
598  XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
599  XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
600  0 /* uint32_t ctrlsToChange */,
601  0 /* uint32_t autoCtrls */,
602  0 /* uint32_t autoCtrlsValues */),
603  NULL);
604  if (pcf_reply == NULL ||
605  !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE)) {
606  ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE\n");
607  }
608  if (pcf_reply == NULL ||
609  !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED)) {
610  ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED\n");
611  }
612  free(pcf_reply);
613  xkb_base = extreply->first_event;
614  }
615 
616  restore_connect();
617 
619 
621 
622  keysyms = xcb_key_symbols_alloc(conn);
623 
625 
626  if (!load_keymap())
627  die("Could not load keymap\n");
628 
631 
632  bool needs_tree_init = true;
633  if (layout_path != NULL) {
634  LOG("Trying to restore the layout from \"%s\".\n", layout_path);
635  needs_tree_init = !tree_restore(layout_path, greply);
636  if (delete_layout_path) {
637  unlink(layout_path);
638  const char *dir = dirname(layout_path);
639  /* possibly fails with ENOTEMPTY if there are files (or
640  * sockets) left. */
641  rmdir(dir);
642  }
643  }
644  if (needs_tree_init)
645  tree_init(greply);
646 
647  free(greply);
648 
649  /* Setup fake outputs for testing */
650  if (fake_outputs == NULL && config.fake_outputs != NULL)
651  fake_outputs = config.fake_outputs;
652 
653  if (fake_outputs != NULL) {
654  fake_outputs_init(fake_outputs);
655  FREE(fake_outputs);
656  config.fake_outputs = NULL;
657  } else if (force_xinerama || config.force_xinerama) {
658  /* Force Xinerama (for drivers which don't support RandR yet, esp. the
659  * nVidia binary graphics driver), when specified either in the config
660  * file or on command-line */
661  xinerama_init();
662  } else {
663  DLOG("Checking for XRandR...\n");
665  }
666 
667  /* We need to force disabling outputs which have been loaded from the
668  * layout file but are no longer active. This can happen if the output has
669  * been disabled in the short time between writing the restart layout file
670  * and restarting i3. See #2326. */
671  if (layout_path != NULL && randr_base > -1) {
672  Con *con;
673  TAILQ_FOREACH(con, &(croot->nodes_head), nodes) {
674  Output *output;
675  TAILQ_FOREACH(output, &outputs, outputs) {
676  if (output->active || strcmp(con->name, output->name) != 0)
677  continue;
678 
679  /* This will correctly correlate the output with its content
680  * container. We need to make the connection to properly
681  * disable the output. */
682  if (output->con == NULL) {
683  output_init_con(output);
684  output->changed = false;
685  }
686 
687  output->to_be_disabled = true;
688  randr_disable_output(output);
689  }
690  }
691  }
692  FREE(layout_path);
693 
695 
696  xcb_query_pointer_reply_t *pointerreply;
697  Output *output = NULL;
698  if (!(pointerreply = xcb_query_pointer_reply(conn, pointercookie, NULL))) {
699  ELOG("Could not query pointer position, using first screen\n");
700  } else {
701  DLOG("Pointer at %d, %d\n", pointerreply->root_x, pointerreply->root_y);
702  output = get_output_containing(pointerreply->root_x, pointerreply->root_y);
703  if (!output) {
704  ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n",
705  pointerreply->root_x, pointerreply->root_y);
706  output = get_first_output();
707  }
708 
710  free(pointerreply);
711  }
712 
713  tree_render();
714 
715  /* Create the UNIX domain socket for IPC */
716  int ipc_socket = ipc_create_socket(config.ipc_socket_path);
717  if (ipc_socket == -1) {
718  ELOG("Could not create the IPC socket, IPC disabled\n");
719  } else {
720  struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
721  ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
722  ev_io_start(main_loop, ipc_io);
723  }
724 
725  /* Also handle the UNIX domain sockets passed via socket activation. The
726  * parameter 1 means "remove the environment variables", we don’t want to
727  * pass these to child processes. */
729  if (listen_fds < 0)
730  ELOG("socket activation: Error in sd_listen_fds\n");
731  else if (listen_fds == 0)
732  DLOG("socket activation: no sockets passed\n");
733  else {
734  int flags;
735  for (int fd = SD_LISTEN_FDS_START;
737  fd++) {
738  DLOG("socket activation: also listening on fd %d\n", fd);
739 
740  /* sd_listen_fds() enables FD_CLOEXEC by default.
741  * However, we need to keep the file descriptors open for in-place
742  * restarting, therefore we explicitly disable FD_CLOEXEC. */
743  if ((flags = fcntl(fd, F_GETFD)) < 0 ||
744  fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) < 0) {
745  ELOG("Could not disable FD_CLOEXEC on fd %d\n", fd);
746  }
747 
748  struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
749  ev_io_init(ipc_io, ipc_new_client, fd, EV_READ);
750  ev_io_start(main_loop, ipc_io);
751  }
752  }
753 
754  /* Set up i3 specific atoms like I3_SOCKET_PATH and I3_CONFIG_PATH */
755  x_set_i3_atoms();
757 
758  /* Set the ewmh desktop properties. */
763 
764  struct ev_io *xcb_watcher = scalloc(1, sizeof(struct ev_io));
765  xcb_check = scalloc(1, sizeof(struct ev_check));
766  struct ev_prepare *xcb_prepare = scalloc(1, sizeof(struct ev_prepare));
767 
768  ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
769  ev_io_start(main_loop, xcb_watcher);
770 
771  ev_check_init(xcb_check, xcb_check_cb);
772  ev_check_start(main_loop, xcb_check);
773 
774  ev_prepare_init(xcb_prepare, xcb_prepare_cb);
775  ev_prepare_start(main_loop, xcb_prepare);
776 
777  xcb_flush(conn);
778 
779  /* What follows is a fugly consequence of X11 protocol race conditions like
780  * the following: In an i3 in-place restart, i3 will reparent all windows
781  * to the root window, then exec() itself. In the new process, it calls
782  * manage_existing_windows. However, in case any application sent a
783  * generated UnmapNotify message to the WM (as GIMP does), this message
784  * will be handled by i3 *after* managing the window, thus i3 thinks the
785  * window just closed itself. In reality, the message was sent in the time
786  * period where i3 wasn’t running yet.
787  *
788  * To prevent this, we grab the server (disables processing of any other
789  * connections), then discard all pending events (since we didn’t do
790  * anything, there cannot be any meaningful responses), then ungrab the
791  * server. */
792  xcb_grab_server(conn);
793  {
794  xcb_aux_sync(conn);
795  xcb_generic_event_t *event;
796  while ((event = xcb_poll_for_event(conn)) != NULL) {
797  if (event->response_type == 0) {
798  free(event);
799  continue;
800  }
801 
802  /* Strip off the highest bit (set if the event is generated) */
803  int type = (event->response_type & 0x7F);
804 
805  /* We still need to handle MapRequests which are sent in the
806  * timespan starting from when we register as a window manager and
807  * this piece of code which drops events. */
808  if (type == XCB_MAP_REQUEST)
809  handle_event(type, event);
810 
811  free(event);
812  }
814  }
815  xcb_ungrab_server(conn);
816 
817  if (autostart) {
818  LOG("This is not an in-place restart, copying root window contents to a pixmap\n");
819  xcb_screen_t *root = xcb_aux_get_screen(conn, conn_screen);
820  uint16_t width = root->width_in_pixels;
821  uint16_t height = root->height_in_pixels;
822  xcb_pixmap_t pixmap = xcb_generate_id(conn);
823  xcb_gcontext_t gc = xcb_generate_id(conn);
824 
825  xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
826 
827  xcb_create_gc(conn, gc, root->root,
828  XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
829  (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
830 
831  xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
832  xcb_change_window_attributes(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
833  xcb_flush(conn);
834  xcb_free_gc(conn, gc);
835  xcb_free_pixmap(conn, pixmap);
836  }
837 
838 #if defined(__OpenBSD__)
839  if (pledge("stdio rpath wpath cpath proc exec unix", NULL) == -1)
840  err(EXIT_FAILURE, "pledge");
841 #endif
842 
843  struct sigaction action;
844 
845  action.sa_sigaction = handle_signal;
846  action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
847  sigemptyset(&action.sa_mask);
848 
849  if (!disable_signalhandler)
851  else {
852  /* Catch all signals with default action "Core", see signal(7) */
853  if (sigaction(SIGQUIT, &action, NULL) == -1 ||
854  sigaction(SIGILL, &action, NULL) == -1 ||
855  sigaction(SIGABRT, &action, NULL) == -1 ||
856  sigaction(SIGFPE, &action, NULL) == -1 ||
857  sigaction(SIGSEGV, &action, NULL) == -1)
858  ELOG("Could not setup signal handler.\n");
859  }
860 
861  /* Catch all signals with default action "Term", see signal(7) */
862  if (sigaction(SIGHUP, &action, NULL) == -1 ||
863  sigaction(SIGINT, &action, NULL) == -1 ||
864  sigaction(SIGALRM, &action, NULL) == -1 ||
865  sigaction(SIGUSR1, &action, NULL) == -1 ||
866  sigaction(SIGUSR2, &action, NULL) == -1)
867  ELOG("Could not setup signal handler.\n");
868 
869  /* Ignore SIGPIPE to survive errors when an IPC client disconnects
870  * while we are sending them a message */
871  signal(SIGPIPE, SIG_IGN);
872 
873  /* Autostarting exec-lines */
874  if (autostart) {
875  while (!TAILQ_EMPTY(&autostarts)) {
876  struct Autostart *exec = TAILQ_FIRST(&autostarts);
877 
878  LOG("auto-starting %s\n", exec->command);
880 
881  FREE(exec->command);
883  FREE(exec);
884  }
885  }
886 
887  /* Autostarting exec_always-lines */
888  while (!TAILQ_EMPTY(&autostarts_always)) {
889  struct Autostart *exec_always = TAILQ_FIRST(&autostarts_always);
890 
891  LOG("auto-starting (always!) %s\n", exec_always->command);
892  start_application(exec_always->command, exec_always->no_startup_id);
893 
894  FREE(exec_always->command);
896  FREE(exec_always);
897  }
898 
899  /* Start i3bar processes for all configured bars */
900  Barconfig *barconfig;
901  TAILQ_FOREACH(barconfig, &barconfigs, configs) {
902  char *command = NULL;
903  sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
904  barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
905  barconfig->id, current_socketpath);
906  LOG("Starting bar process: %s\n", command);
907  start_application(command, true);
908  free(command);
909  }
910 
911  /* Make sure to destroy the event loop to invoke the cleeanup callbacks
912  * when calling exit() */
913  atexit(i3_exit);
914 
915  ev_loop(main_loop, 0);
916 }
void property_handlers_init(void)
Sets the appropriate atoms for the property handlers after the atoms were received from X11...
Definition: handlers.c:1319
int ipc_send_message(int sockfd, const uint32_t message_size, const uint32_t message_type, const uint8_t *payload)
Formats a message (payload) of the given size and type and sends it to i3 via the given socket file d...
#define XCB_NUM_LOCK
Definition: xcb.h:29
#define FREE(pointer)
Definition: util.h:50
void tree_init(xcb_get_geometry_reply_t *geometry)
Initializes the tree by creating the root node, adding all RandR outputs to the tree (that means rand...
Definition: tree.c:116
void ewmh_update_current_desktop(void)
Updates _NET_CURRENT_DESKTOP with the current desktop number.
Definition: ewmh.c:21
void ewmh_update_desktop_names(void)
Updates _NET_DESKTOP_NAMES: "The names of all virtual desktops.
Definition: ewmh.c:53
char * get_process_filename(const char *prefix)
Returns the name of a temporary file with the specified prefix.
xcb_visualtype_t * visual_type
Definition: main.c:61
void * srealloc(void *ptr, size_t size)
Safe-wrapper around realloc which exits if realloc returns NULL (meaning that there is no more memory...
#define ELOG(fmt,...)
Definition: libi3.h:89
struct assignments_head assignments
Definition: main.c:81
int conn_screen
Definition: main.c:44
xcb_screen_t * root_screen
Definition: main.c:54
struct outputs_head outputs
Definition: randr.c:26
void set_debug_logging(const bool _debug_logging)
Set debug logging.
Definition: log.c:209
struct autostarts_head autostarts
Definition: main.c:75
void xcursor_load_cursors(void)
Definition: xcursor.c:28
struct barconfig_head barconfigs
Definition: config.c:18
static struct ev_check * xcb_check
Definition: main.c:36
void xcb_set_root_cursor(int cursor)
Set the cursor of the root window to the given cursor id.
Definition: xcb.c:222
struct Con * croot
Definition: tree.c:12
xcb_key_symbols_t * keysyms
Definition: main.c:66
char * current_socketpath
Definition: ipc.c:23
Output * get_first_output(void)
Returns the first output which is active.
Definition: randr.c:64
bool force_xinerama
By default, use the RandR API for multi-monitor setups.
struct bindings_head * bindings
Definition: main.c:72
void main_set_x11_cb(bool enable)
Enable or disable the main X11 event handling function.
Definition: main.c:144
struct autostarts_always_head autostarts_always
Definition: main.c:78
void restore_connect(void)
Opens a separate connection to X11 for placeholder windows when restoring layouts.
void con_focus(Con *con)
Sets input focus to the given container.
Definition: con.c:197
An Output is a physical output on your graphics driver.
Definition: data.h:344
char * root_atom_contents(const char *atomname, xcb_connection_t *provided_conn, int screen)
Try to get the contents of the given atom (for example I3_SOCKET_PATH) from the X11 root window and r...
xcb_window_t root
Definition: main.c:55
int sd_listen_fds(int unset_environment)
Definition: sd-daemon.c:47
char * id
Automatically generated ID for this bar config.
struct rlimit original_rlimit_core
The original value of RLIMIT_CORE when i3 was started.
Definition: main.c:29
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...
void randr_disable_output(Output *output)
Disables the output and moves its content.
Definition: randr.c:774
static void handle_signal(int sig, siginfo_t *info, void *data)
Definition: main.c:181
Con * output_get_content(Con *output)
Returns the output container below the given output container.
Definition: output.c:16
#define LOG(fmt,...)
Definition: libi3.h:84
char * i3bar_command
Command that should be run to execute i3bar, give a full path if i3bar is not in your $PATH...
const int default_shmlog_size
Definition: main.c:69
char * shmlogname
Definition: log.c:46
bool only_check_config
void grab_all_keys(xcb_connection_t *conn)
Grab the bound keys (tell X to send us keypress events for those keycodes)
Definition: bindings.c:144
struct ws_assignments_head ws_assignments
Definition: main.c:85
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
SnDisplay * sndisplay
Definition: main.c:47
uint32_t width
Definition: data.h:129
void ewmh_update_number_of_desktops(void)
Updates _NET_NUMBER_OF_DESKTOPS which we interpret as the number of noninternal workspaces.
Definition: ewmh.c:32
Holds the status bar configuration (i3bar).
xcb_connection_t * conn
XCB connection and root screen.
Definition: main.c:42
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
xcb_visualtype_t * get_visualtype(xcb_screen_t *screen)
Returns the visual type associated with the given screen.
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
int randr_base
Definition: handlers.c:20
int xkb_base
Definition: handlers.c:21
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...
bool changed
Internal flags, necessary for querying RandR screens (happens in two stages)
Definition: data.h:354
#define TAILQ_FIRST(head)
Definition: queue.h:336
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:490
bool active
Whether the output is currently active (has a CRTC attached with a valid mode)
Definition: data.h:350
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...
xcb_colormap_t colormap
Definition: main.c:62
void randr_init(int *event_base)
We have just established a connection to the X server and need the initial XRandR information to setu...
Definition: randr.c:865
char * name
Definition: data.h:604
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:402
Holds a command specified by either an:
Definition: data.h:327
void scratchpad_fix_resolution(void)
When starting i3 initially (and after each change to the connected outputs), this function fixes the ...
Definition: scratchpad.c:246
int shmlog_size
Definition: log.c:49
uint32_t aio_get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols)
All-in-one function which returns the modifier mask (XCB_MOD_MASK_*) for the given keysymbol...
void output_init_con(Output *output)
Initializes a CT_OUTPUT Con (searches existing ones from inplace restart before) to use for the given...
Definition: randr.c:279
void manage_existing_windows(xcb_window_t root)
Go through all existing windows (if the window manager is restarted) and manage them.
Definition: manage.c:20
void load_configuration(xcb_connection_t *conn, const char *override_configpath, bool reload)
Reads the configuration from ~/.i3/config or /etc/i3/config if not found.
Definition: config.c:71
void ewmh_update_workarea(void)
i3 currently does not support _NET_WORKAREA, because it does not correspond to i3’s concept of works...
Definition: ewmh.c:237
unsigned int xcb_numlock_mask
Definition: xcb.c:12
struct reservedpx __attribute__
void handle_event(int type, xcb_generic_event_t *event)
Takes an xcb_generic_event_t and calls the appropriate handler, based on the event type...
Definition: handlers.c:1367
Con * con
Pointer to the Con which represents this output.
Definition: data.h:362
xcb_timestamp_t last_timestamp
The last timestamp we got from X11 (timestamps are included in some events and are used for some thin...
Definition: main.c:52
bool xcursor_supported
Definition: main.c:88
void display_running_version(void)
Connects to i3 to find out the currently running version.
void start_application(const char *command, bool no_startup_id)
Starts the given application by passing it through a shell.
Definition: startup.c:132
char * command
Command, like in command mode.
Definition: data.h:329
bool load_keymap(void)
Loads the XKB keymap from the X11 server and feeds it to xkbcommon.
Definition: bindings.c:898
bool is_debug_build() __attribute__((const))
Returns true if this version of i3 is a debug build (anything which is not a release version)...
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:1144
bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry)
Loads tree from ~/.i3/_restart.json (used for in-place restarts).
Definition: tree.c:66
Con * con_descend_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
Definition: con.c:1366
uint32_t height
Definition: data.h:130
static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents)
Definition: main.c:104
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
static void xcb_got_event(EV_P_ struct ev_io *w, int revents)
Definition: main.c:96
void init_logging(void)
Initializes logging by creating an error logfile in /tmp (or XDG_RUNTIME_DIR, see get_process_filenam...
Definition: log.c:85
bool no_startup_id
no_startup_id flag for start_application().
Definition: data.h:332
void ewmh_setup_hints(void)
Set up the EWMH hints on the root window.
Definition: ewmh.c:291
const char * i3_version
Git commit identifier, from version.c.
Definition: version.c:13
A &#39;Con&#39; represents everything from the X11 root window down to a single X11 window.
Definition: data.h:558
void translate_keysyms(void)
Translates keysymbols to keycodes for all bindings which use keysyms.
Definition: bindings.c:432
#define DLOG(fmt,...)
Definition: libi3.h:94
void fake_outputs_init(const char *output_spec)
Creates outputs according to the given specification.
Definition: fake_outputs.c:35
bool xkb_supported
Definition: main.c:89
uint8_t root_depth
Definition: main.c:60
void xcursor_set_root_cursor(int cursor_id)
Sets the cursor of the root window to the &#39;pointer&#39; cursor.
Definition: xcursor.c:57
char ** start_argv
Definition: main.c:40
char * ipc_socket_path
Definition: configuration.h:97
Output * get_output_containing(unsigned int x, unsigned int y)
Returns the active (!) output which contains the coordinates x, y or NULL if there is no output which...
Definition: randr.c:94
#define ROOT_EVENT_MASK
Definition: xcb.h:49
char * name
Name of the output.
Definition: data.h:359
bool parse_configuration(const char *override_configpath, bool use_nagbar)
Finds the configuration file to use (either the one specified by override_configpath), the user’s one or the system default) and calls parse_file().
Definition: config.c:47
void init_dpi(void)
Initialize the DPI setting.
void set_verbosity(bool _verbose)
Set verbosity of i3.
Definition: log.c:193
bool event_is_ignored(const int sequence, const int response_type)
Checks if the given sequence is ignored and returns true if so.
Definition: handlers.c:51
int logical_px(const int logical)
Convert a logical amount of pixels (e.g.
bool to_be_disabled
Definition: data.h:355
#define TAILQ_EMPTY(head)
Definition: queue.h:344
Config config
Definition: config.c:16
#define SD_LISTEN_FDS_START
Definition: sd-daemon.h:102
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:1178
static void xcb_check_cb(EV_P_ ev_check *w, int revents)
Definition: main.c:113
void setup_signal_handler(void)
Setup signal handlers to safely handle SIGSEGV and SIGFPE.
Definition: sighandler.c:315
int main(int argc, char *argv[])
Definition: main.c:188
void x_set_i3_atoms(void)
Sets up i3 specific atoms (I3_SOCKET_PATH and I3_CONFIG_PATH)
Definition: x.c:1227
static void i3_exit(void)
Definition: main.c:160
void ewmh_update_desktop_viewport(void)
Updates _NET_DESKTOP_VIEWPORT, which is an array of pairs of cardinals that define the top left corne...
Definition: ewmh.c:91
void xinerama_init(void)
We have just established a connection to the X server and need the initial Xinerama information to se...
Definition: xinerama.c:106
int listen_fds
The number of file descriptors passed via socket activation.
Definition: main.c:32
char * fake_outputs
Overwrites output detection (for testing), see src/fake_outputs.c.
struct ev_loop * main_loop
Definition: main.c:64
static xcb_pixmap_t pixmap
Definition: sighandler.c:26
#define die(...)
Definition: util.h:19
Con * focused
Definition: tree.c:13