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