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