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