2 * vim:ts=4:sw=4:expandtab
4 * i3 - an improved dynamic tiling window manager
5 * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
7 * main.c: Initialization, main loop
14 #include <sys/types.h>
15 #include <sys/socket.h>
18 #include <sys/resource.h>
24 #ifdef I3_ASAN_ENABLED
25 #include <sanitizer/lsan_interface.h>
28 #include "sd-daemon.h"
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;
35 /** The number of file descriptors passed via socket activation. */
38 /* We keep the xcb_check watcher around to be able to enable and disable it
39 * temporarily for drag_pointer(). */
40 static struct ev_check *xcb_check;
46 xcb_connection_t *conn;
47 /* The screen (0 when you are using DISPLAY=:0) of the connection 'conn' */
50 /* Display handle for libstartup-notification */
53 /* The last timestamp we got from X11 (timestamps are included in some events
54 * and are used for some things, like determining a unique ID in startup
56 xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
58 xcb_screen_t *root_screen;
61 /* Color depth, visual id and colormap to use when creating windows and
62 * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
63 * otherwise the root window’s default (usually 24 bit TrueColor). */
65 xcb_visualtype_t *visual_type;
66 xcb_colormap_t colormap;
68 struct ev_loop *main_loop;
70 xcb_key_symbols_t *keysyms;
72 /* Default shmlog size if not set by user. */
73 const int default_shmlog_size = 25 * 1024 * 1024;
75 /* The list of key bindings */
76 struct bindings_head *bindings;
78 /* The list of exec-lines */
79 struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
81 /* The list of exec_always lines */
82 struct autostarts_always_head autostarts_always = TAILQ_HEAD_INITIALIZER(autostarts_always);
84 /* The list of assignments */
85 struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
87 /* The list of workspace assignments (which workspace should end up on which
89 struct ws_assignments_head ws_assignments = TAILQ_HEAD_INITIALIZER(ws_assignments);
91 /* We hope that those are supported and set them to true */
92 bool xcursor_supported = true;
93 bool xkb_supported = true;
96 * This callback is only a dummy, see xcb_prepare_cb and xcb_check_cb.
97 * See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop
100 static void xcb_got_event(EV_P_ struct ev_io *w, int revents) {
101 /* empty, because xcb_prepare_cb and xcb_check_cb are used */
105 * Flush before blocking (and waiting for new events)
108 static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
113 * Instead of polling the X connection socket we leave this to
114 * xcb_poll_for_event() which knows better than we can ever know.
117 static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
118 xcb_generic_event_t *event;
120 while ((event = xcb_poll_for_event(conn)) != NULL) {
121 if (event->response_type == 0) {
122 if (event_is_ignored(event->sequence, 0))
123 DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
125 xcb_generic_error_t *error = (xcb_generic_error_t *)event;
126 DLOG("X11 Error received (probably harmless)! sequence 0x%x, error_code = %d\n",
127 error->sequence, error->error_code);
133 /* Strip off the highest bit (set if the event is generated) */
134 int type = (event->response_type & 0x7F);
136 handle_event(type, event);
143 * Enable or disable the main X11 event handling function.
144 * This is used by drag_pointer() which has its own, modal event handler, which
145 * takes precedence over the normal event handler.
148 void main_set_x11_cb(bool enable) {
149 DLOG("Setting main X11 callback to enabled=%d\n", enable);
151 ev_check_start(main_loop, xcb_check);
152 /* Trigger the watcher explicitly to handle all remaining X11 events.
153 * drag_pointer()’s event handler exits in the middle of the loop. */
154 ev_feed_event(main_loop, xcb_check, 0);
156 ev_check_stop(main_loop, xcb_check);
161 * Exit handler which destroys the main_loop. Will trigger cleanup handlers.
164 static void i3_exit(void) {
165 /* We need ev >= 4 for the following code. Since it is not *that* important (it
166 * only makes sure that there are no i3-nagbar instances left behind) we still
167 * support old systems with libev 3. */
168 #if EV_VERSION_MAJOR >= 4
169 ev_loop_destroy(main_loop);
172 if (*shmlogname != '\0') {
173 fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
175 shm_unlink(shmlogname);
180 * (One-shot) Handler for all signals with default action "Term", see signal(7)
182 * Unlinks the SHM log and re-raises the signal.
185 static void handle_signal(int sig, siginfo_t *info, void *data) {
186 if (*shmlogname != '\0') {
187 shm_unlink(shmlogname);
192 int main(int argc, char *argv[]) {
193 /* Keep a symbol pointing to the I3_VERSION string constant so that we have
194 * it in gdb backtraces. */
195 static const char *_i3_version __attribute__((used)) = I3_VERSION;
196 char *override_configpath = NULL;
197 bool autostart = true;
198 char *layout_path = NULL;
199 bool delete_layout_path = false;
200 bool force_xinerama = false;
201 bool disable_randr15 = false;
202 char *fake_outputs = NULL;
203 bool disable_signalhandler = false;
204 bool only_check_config = false;
205 static struct option long_options[] = {
206 {"no-autostart", no_argument, 0, 'a'},
207 {"config", required_argument, 0, 'c'},
208 {"version", no_argument, 0, 'v'},
209 {"moreversion", no_argument, 0, 'm'},
210 {"more-version", no_argument, 0, 'm'},
211 {"more_version", no_argument, 0, 'm'},
212 {"help", no_argument, 0, 'h'},
213 {"layout", required_argument, 0, 'L'},
214 {"restart", required_argument, 0, 0},
215 {"force-xinerama", no_argument, 0, 0},
216 {"force_xinerama", no_argument, 0, 0},
217 {"disable-randr15", no_argument, 0, 0},
218 {"disable_randr15", no_argument, 0, 0},
219 {"disable-signalhandler", no_argument, 0, 0},
220 {"shmlog-size", required_argument, 0, 0},
221 {"shmlog_size", required_argument, 0, 0},
222 {"get-socketpath", no_argument, 0, 0},
223 {"get_socketpath", no_argument, 0, 0},
224 {"fake_outputs", required_argument, 0, 0},
225 {"fake-outputs", required_argument, 0, 0},
226 {"force-old-config-parser-v4.4-only", no_argument, 0, 0},
228 int option_index = 0, opt;
230 setlocale(LC_ALL, "");
232 /* Get the RLIMIT_CORE limit at startup time to restore this before
233 * starting processes. */
234 getrlimit(RLIMIT_CORE, &original_rlimit_core);
236 /* Disable output buffering to make redirects in .xsession actually useful for debugging */
237 if (!isatty(fileno(stdout)))
238 setbuf(stdout, NULL);
242 /* Init logging *before* initializing debug_build to guarantee early
246 /* On release builds, disable SHM logging by default. */
247 shmlog_size = (is_debug_build() || strstr(argv[0], "i3-with-shmlog") != NULL ? default_shmlog_size : 0);
251 while ((opt = getopt_long(argc, argv, "c:CvmaL:hld:V", long_options, &option_index)) != -1) {
254 LOG("Autostart disabled using -a\n");
259 layout_path = sstrdup(optarg);
260 delete_layout_path = false;
263 FREE(override_configpath);
264 override_configpath = sstrdup(optarg);
267 LOG("Checking configuration file only (-C)\n");
268 only_check_config = true;
271 printf("i3 version %s © 2009 Michael Stapelberg and contributors\n", i3_version);
275 printf("Binary i3 version: %s © 2009 Michael Stapelberg and contributors\n", i3_version);
276 display_running_version();
283 LOG("Enabling debug logging\n");
284 set_debug_logging(true);
287 /* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */
290 if (strcmp(long_options[option_index].name, "force-xinerama") == 0 ||
291 strcmp(long_options[option_index].name, "force_xinerama") == 0) {
292 force_xinerama = true;
293 ELOG("Using Xinerama instead of RandR. This option should be "
294 "avoided at all cost because it does not refresh the list "
295 "of screens, so you cannot configure displays at runtime. "
296 "Please check if your driver really does not support RandR "
297 "and disable this option as soon as you can.\n");
299 } else if (strcmp(long_options[option_index].name, "disable-randr15") == 0 ||
300 strcmp(long_options[option_index].name, "disable_randr15") == 0) {
301 disable_randr15 = true;
303 } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) {
304 disable_signalhandler = true;
306 } else if (strcmp(long_options[option_index].name, "get-socketpath") == 0 ||
307 strcmp(long_options[option_index].name, "get_socketpath") == 0) {
308 char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
310 printf("%s\n", socket_path);
315 } else if (strcmp(long_options[option_index].name, "shmlog-size") == 0 ||
316 strcmp(long_options[option_index].name, "shmlog_size") == 0) {
317 shmlog_size = atoi(optarg);
318 /* Re-initialize logging immediately to get as many
319 * logmessages as possible into the SHM log. */
321 LOG("Limiting SHM log size to %d bytes\n", shmlog_size);
323 } else if (strcmp(long_options[option_index].name, "restart") == 0) {
325 layout_path = sstrdup(optarg);
326 delete_layout_path = true;
328 } else if (strcmp(long_options[option_index].name, "fake-outputs") == 0 ||
329 strcmp(long_options[option_index].name, "fake_outputs") == 0) {
330 LOG("Initializing fake outputs: %s\n", optarg);
331 fake_outputs = sstrdup(optarg);
333 } else if (strcmp(long_options[option_index].name, "force-old-config-parser-v4.4-only") == 0) {
334 ELOG("You are passing --force-old-config-parser-v4.4-only, but that flag was removed by now.\n");
339 fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
340 fprintf(stderr, "\n");
341 fprintf(stderr, "\t-a disable autostart ('exec' lines in config)\n");
342 fprintf(stderr, "\t-c <file> use the provided configfile instead\n");
343 fprintf(stderr, "\t-C validate configuration file and exit\n");
344 fprintf(stderr, "\t-d all enable debug output\n");
345 fprintf(stderr, "\t-L <file> path to the serialized layout during restarts\n");
346 fprintf(stderr, "\t-v display version and exit\n");
347 fprintf(stderr, "\t-V enable verbose mode\n");
348 fprintf(stderr, "\n");
349 fprintf(stderr, "\t--force-xinerama\n"
350 "\tUse Xinerama instead of RandR.\n"
351 "\tThis option should only be used if you are stuck with the\n"
352 "\told nVidia closed source driver (older than 302.17), which does\n"
353 "\tnot support RandR.\n");
354 fprintf(stderr, "\n");
355 fprintf(stderr, "\t--get-socketpath\n"
356 "\tRetrieve the i3 IPC socket path from X11, print it, then exit.\n");
357 fprintf(stderr, "\n");
358 fprintf(stderr, "\t--shmlog-size <limit>\n"
359 "\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
360 "\tto 0 disables SHM logging entirely.\n"
361 "\tThe default is %d bytes.\n",
363 fprintf(stderr, "\n");
364 fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
365 "to send to a currently running i3 (like i3-msg). This allows you to\n"
366 "use nice and logical commands, such as:\n"
369 "\ti3 floating toggle\n"
376 if (only_check_config) {
377 exit(parse_configuration(override_configpath, false) ? 0 : 1);
380 /* If the user passes more arguments, we act like i3-msg would: Just send
381 * the arguments as an IPC message to i3. This allows for nice semantic
382 * commands such as 'i3 border none'. */
384 /* We enable verbose mode so that the user knows what’s going on.
385 * This should make it easier to find mistakes when the user passes
386 * arguments by mistake. */
389 LOG("Additional arguments passed. Sending them as a command to i3.\n");
390 char *payload = NULL;
391 while (optind < argc) {
393 payload = sstrdup(argv[optind]);
396 sasprintf(&both, "%s %s", payload, argv[optind]);
402 DLOG("Command is: %s (%zd bytes)\n", payload, strlen(payload));
403 char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
405 ELOG("Could not get i3 IPC socket path\n");
409 int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
411 err(EXIT_FAILURE, "Could not create socket");
413 struct sockaddr_un addr;
414 memset(&addr, 0, sizeof(struct sockaddr_un));
415 addr.sun_family = AF_LOCAL;
416 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
418 if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
419 err(EXIT_FAILURE, "Could not connect to i3");
421 if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
422 (uint8_t *)payload) == -1)
423 err(EXIT_FAILURE, "IPC: write()");
426 uint32_t reply_length;
430 if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
432 err(EXIT_FAILURE, "IPC: read()");
435 if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND)
436 errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND);
437 printf("%.*s\n", reply_length, reply);
442 /* Enable logging to handle the case when the user did not specify --shmlog-size */
445 /* Try to enable core dumps by default when running a debug build */
446 if (is_debug_build()) {
447 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
448 setrlimit(RLIMIT_CORE, &limit);
450 /* The following code is helpful, but not required. We thus don’t pay
451 * much attention to error handling, non-linux or other edge cases. */
452 LOG("CORE DUMPS: You are running a development version of i3, so coredumps were automatically enabled (ulimit -c unlimited).\n");
453 size_t cwd_size = 1024;
454 char *cwd = smalloc(cwd_size);
456 while ((cwd_ret = getcwd(cwd, cwd_size)) == NULL && errno == ERANGE) {
457 cwd_size = cwd_size * 2;
458 cwd = srealloc(cwd, cwd_size);
461 LOG("CORE DUMPS: Your current working directory is \"%s\".\n", cwd);
463 if ((patternfd = open("/proc/sys/kernel/core_pattern", O_RDONLY)) >= 0) {
464 memset(cwd, '\0', cwd_size);
465 if (read(patternfd, cwd, cwd_size) > 0)
466 /* a trailing newline is included in cwd */
467 LOG("CORE DUMPS: Your core_pattern is: %s", cwd);
473 LOG("i3 %s starting\n", i3_version);
475 conn = xcb_connect(NULL, &conn_screen);
476 if (xcb_connection_has_error(conn))
477 errx(EXIT_FAILURE, "Cannot open display\n");
479 sndisplay = sn_xcb_display_new(conn, NULL, NULL);
481 /* Initialize the libev event loop. This needs to be done before loading
482 * the config file because the parser will install an ev_child watcher
483 * for the nagbar when config errors are found. */
484 main_loop = EV_DEFAULT;
485 if (main_loop == NULL)
486 die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
488 root_screen = xcb_aux_get_screen(conn, conn_screen);
489 root = root_screen->root;
491 /* Place requests for the atoms we need as soon as possible */
492 #define xmacro(atom) \
493 xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
494 #include "atoms.xmacro"
497 root_depth = root_screen->root_depth;
498 colormap = root_screen->default_colormap;
499 visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32);
500 if (visual_type != NULL) {
501 root_depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id);
502 colormap = xcb_generate_id(conn);
504 xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(conn,
505 XCB_COLORMAP_ALLOC_NONE,
508 visual_type->visual_id);
510 xcb_generic_error_t *error = xcb_request_check(conn, cm_cookie);
512 ELOG("Could not create colormap. Error code: %d\n", error->error_code);
516 visual_type = get_visualtype(root_screen);
521 DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id);
522 DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d\n",
523 root_screen->height_in_pixels, root_screen->height_in_millimeters);
524 DLOG("One logical pixel corresponds to %d physical pixels on this display.\n", logical_px(1));
526 xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
527 xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
529 /* Setup NetWM atoms */
530 #define xmacro(name) \
532 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
534 ELOG("Could not get atom " #name "\n"); \
537 A_##name = reply->atom; \
540 #include "atoms.xmacro"
543 load_configuration(conn, override_configpath, false);
545 if (config.ipc_socket_path == NULL) {
546 /* Fall back to a file name in /tmp/ based on the PID */
547 if ((config.ipc_socket_path = getenv("I3SOCK")) == NULL)
548 config.ipc_socket_path = get_process_filename("ipc-socket");
550 config.ipc_socket_path = sstrdup(config.ipc_socket_path);
553 xcb_void_cookie_t cookie;
554 cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
555 xcb_generic_error_t *error = xcb_request_check(conn, cookie);
557 ELOG("Another window manager seems to be running (X error %d)\n", error->error_code);
558 #ifdef I3_ASAN_ENABLED
559 __lsan_do_leak_check();
564 xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
565 if (greply == NULL) {
566 ELOG("Could not get geometry of the root window, exiting\n");
569 DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
571 xcursor_load_cursors();
573 /* Set a cursor for the root window (otherwise the root window will show no
574 cursor until the first client is launched). */
575 if (xcursor_supported)
576 xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
578 xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
580 const xcb_query_extension_reply_t *extreply;
581 extreply = xcb_get_extension_data(conn, &xcb_xkb_id);
582 xkb_supported = extreply->present;
583 if (!extreply->present) {
584 DLOG("xkb is not present on this server\n");
586 DLOG("initializing xcb-xkb\n");
587 xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
588 xcb_xkb_select_events(conn,
589 XCB_XKB_ID_USE_CORE_KBD,
590 XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
592 XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
597 /* Setting both, XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE and
598 * XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED, will lead to the
599 * X server sending us the full XKB state in KeyPress and KeyRelease:
600 * https://sources.debian.net/src/xorg-server/2:1.17.2-1.1/xkb/xkbEvents.c/?hl=927#L927
602 xcb_xkb_per_client_flags_reply_t *pcf_reply;
603 /* The last three parameters are unset because they are only relevant
604 * when using a feature called “automatic reset of boolean controls”:
605 * http://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Automatic_Reset_of_Boolean_Controls
607 pcf_reply = xcb_xkb_per_client_flags_reply(
609 xcb_xkb_per_client_flags(
611 XCB_XKB_ID_USE_CORE_KBD,
612 XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
613 XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
614 0 /* uint32_t ctrlsToChange */,
615 0 /* uint32_t autoCtrls */,
616 0 /* uint32_t autoCtrlsValues */),
618 if (pcf_reply == NULL ||
619 !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE)) {
620 ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE\n");
622 if (pcf_reply == NULL ||
623 !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED)) {
624 ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED\n");
627 xkb_base = extreply->first_event;
632 property_handlers_init();
636 keysyms = xcb_key_symbols_alloc(conn);
638 xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
641 die("Could not load keymap\n");
646 bool needs_tree_init = true;
647 if (layout_path != NULL) {
648 LOG("Trying to restore the layout from \"%s\".\n", layout_path);
649 needs_tree_init = !tree_restore(layout_path, greply);
650 if (delete_layout_path) {
652 const char *dir = dirname(layout_path);
653 /* possibly fails with ENOTEMPTY if there are files (or
663 /* Setup fake outputs for testing */
664 if (fake_outputs == NULL && config.fake_outputs != NULL)
665 fake_outputs = config.fake_outputs;
667 if (fake_outputs != NULL) {
668 fake_outputs_init(fake_outputs);
670 config.fake_outputs = NULL;
671 } else if (force_xinerama || config.force_xinerama) {
672 /* Force Xinerama (for drivers which don't support RandR yet, esp. the
673 * nVidia binary graphics driver), when specified either in the config
674 * file or on command-line */
677 DLOG("Checking for XRandR...\n");
678 randr_init(&randr_base, disable_randr15 || config.disable_randr15);
681 /* We need to force disabling outputs which have been loaded from the
682 * layout file but are no longer active. This can happen if the output has
683 * been disabled in the short time between writing the restart layout file
684 * and restarting i3. See #2326. */
685 if (layout_path != NULL && randr_base > -1) {
687 TAILQ_FOREACH(con, &(croot->nodes_head), nodes) {
689 TAILQ_FOREACH(output, &outputs, outputs) {
690 if (output->active || strcmp(con->name, output->name) != 0)
693 /* This will correctly correlate the output with its content
694 * container. We need to make the connection to properly
695 * disable the output. */
696 if (output->con == NULL) {
697 output_init_con(output);
698 output->changed = false;
701 output->to_be_disabled = true;
702 randr_disable_output(output);
708 scratchpad_fix_resolution();
710 xcb_query_pointer_reply_t *pointerreply;
711 Output *output = NULL;
712 if (!(pointerreply = xcb_query_pointer_reply(conn, pointercookie, NULL))) {
713 ELOG("Could not query pointer position, using first screen\n");
715 DLOG("Pointer at %d, %d\n", pointerreply->root_x, pointerreply->root_y);
716 output = get_output_containing(pointerreply->root_x, pointerreply->root_y);
718 ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n",
719 pointerreply->root_x, pointerreply->root_y);
720 output = get_first_output();
723 con_focus(con_descend_focused(output_get_content(output->con)));
729 /* Create the UNIX domain socket for IPC */
730 int ipc_socket = ipc_create_socket(config.ipc_socket_path);
731 if (ipc_socket == -1) {
732 ELOG("Could not create the IPC socket, IPC disabled\n");
734 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
735 ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
736 ev_io_start(main_loop, ipc_io);
739 /* Also handle the UNIX domain sockets passed via socket activation. The
740 * parameter 1 means "remove the environment variables", we don’t want to
741 * pass these to child processes. */
742 listen_fds = sd_listen_fds(0);
744 ELOG("socket activation: Error in sd_listen_fds\n");
745 else if (listen_fds == 0)
746 DLOG("socket activation: no sockets passed\n");
749 for (int fd = SD_LISTEN_FDS_START;
750 fd < (SD_LISTEN_FDS_START + listen_fds);
752 DLOG("socket activation: also listening on fd %d\n", fd);
754 /* sd_listen_fds() enables FD_CLOEXEC by default.
755 * However, we need to keep the file descriptors open for in-place
756 * restarting, therefore we explicitly disable FD_CLOEXEC. */
757 if ((flags = fcntl(fd, F_GETFD)) < 0 ||
758 fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) < 0) {
759 ELOG("Could not disable FD_CLOEXEC on fd %d\n", fd);
762 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
763 ev_io_init(ipc_io, ipc_new_client, fd, EV_READ);
764 ev_io_start(main_loop, ipc_io);
768 /* Set up i3 specific atoms like I3_SOCKET_PATH and I3_CONFIG_PATH */
770 ewmh_update_workarea();
772 /* Set the ewmh desktop properties. */
773 ewmh_update_current_desktop();
774 ewmh_update_number_of_desktops();
775 ewmh_update_desktop_names();
776 ewmh_update_desktop_viewport();
778 struct ev_io *xcb_watcher = scalloc(1, sizeof(struct ev_io));
779 xcb_check = scalloc(1, sizeof(struct ev_check));
780 struct ev_prepare *xcb_prepare = scalloc(1, sizeof(struct ev_prepare));
782 ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
783 ev_io_start(main_loop, xcb_watcher);
785 ev_check_init(xcb_check, xcb_check_cb);
786 ev_check_start(main_loop, xcb_check);
788 ev_prepare_init(xcb_prepare, xcb_prepare_cb);
789 ev_prepare_start(main_loop, xcb_prepare);
793 /* What follows is a fugly consequence of X11 protocol race conditions like
794 * the following: In an i3 in-place restart, i3 will reparent all windows
795 * to the root window, then exec() itself. In the new process, it calls
796 * manage_existing_windows. However, in case any application sent a
797 * generated UnmapNotify message to the WM (as GIMP does), this message
798 * will be handled by i3 *after* managing the window, thus i3 thinks the
799 * window just closed itself. In reality, the message was sent in the time
800 * period where i3 wasn’t running yet.
802 * To prevent this, we grab the server (disables processing of any other
803 * connections), then discard all pending events (since we didn’t do
804 * anything, there cannot be any meaningful responses), then ungrab the
806 xcb_grab_server(conn);
809 xcb_generic_event_t *event;
810 while ((event = xcb_poll_for_event(conn)) != NULL) {
811 if (event->response_type == 0) {
816 /* Strip off the highest bit (set if the event is generated) */
817 int type = (event->response_type & 0x7F);
819 /* We still need to handle MapRequests which are sent in the
820 * timespan starting from when we register as a window manager and
821 * this piece of code which drops events. */
822 if (type == XCB_MAP_REQUEST)
823 handle_event(type, event);
827 manage_existing_windows(root);
829 xcb_ungrab_server(conn);
832 LOG("This is not an in-place restart, copying root window contents to a pixmap\n");
833 xcb_screen_t *root = xcb_aux_get_screen(conn, conn_screen);
834 uint16_t width = root->width_in_pixels;
835 uint16_t height = root->height_in_pixels;
836 xcb_pixmap_t pixmap = xcb_generate_id(conn);
837 xcb_gcontext_t gc = xcb_generate_id(conn);
839 xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
841 xcb_create_gc(conn, gc, root->root,
842 XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
843 (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
845 xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
846 xcb_change_window_attributes(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
848 xcb_free_gc(conn, gc);
849 xcb_free_pixmap(conn, pixmap);
852 #if defined(__OpenBSD__)
853 if (pledge("stdio rpath wpath cpath proc exec unix", NULL) == -1)
854 err(EXIT_FAILURE, "pledge");
857 struct sigaction action;
859 action.sa_sigaction = handle_signal;
860 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
861 sigemptyset(&action.sa_mask);
863 if (!disable_signalhandler)
864 setup_signal_handler();
866 /* Catch all signals with default action "Core", see signal(7) */
867 if (sigaction(SIGQUIT, &action, NULL) == -1 ||
868 sigaction(SIGILL, &action, NULL) == -1 ||
869 sigaction(SIGABRT, &action, NULL) == -1 ||
870 sigaction(SIGFPE, &action, NULL) == -1 ||
871 sigaction(SIGSEGV, &action, NULL) == -1)
872 ELOG("Could not setup signal handler.\n");
875 /* Catch all signals with default action "Term", see signal(7) */
876 if (sigaction(SIGHUP, &action, NULL) == -1 ||
877 sigaction(SIGINT, &action, NULL) == -1 ||
878 sigaction(SIGALRM, &action, NULL) == -1 ||
879 sigaction(SIGUSR1, &action, NULL) == -1 ||
880 sigaction(SIGUSR2, &action, NULL) == -1)
881 ELOG("Could not setup signal handler.\n");
883 /* Ignore SIGPIPE to survive errors when an IPC client disconnects
884 * while we are sending them a message */
885 signal(SIGPIPE, SIG_IGN);
887 /* Autostarting exec-lines */
889 while (!TAILQ_EMPTY(&autostarts)) {
890 struct Autostart *exec = TAILQ_FIRST(&autostarts);
892 LOG("auto-starting %s\n", exec->command);
893 start_application(exec->command, exec->no_startup_id);
896 TAILQ_REMOVE(&autostarts, exec, autostarts);
901 /* Autostarting exec_always-lines */
902 while (!TAILQ_EMPTY(&autostarts_always)) {
903 struct Autostart *exec_always = TAILQ_FIRST(&autostarts_always);
905 LOG("auto-starting (always!) %s\n", exec_always->command);
906 start_application(exec_always->command, exec_always->no_startup_id);
908 FREE(exec_always->command);
909 TAILQ_REMOVE(&autostarts_always, exec_always, autostarts_always);
913 /* Start i3bar processes for all configured bars */
914 Barconfig *barconfig;
915 TAILQ_FOREACH(barconfig, &barconfigs, configs) {
916 char *command = NULL;
917 sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
918 barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
919 barconfig->id, current_socketpath);
920 LOG("Starting bar process: %s\n", command);
921 start_application(command, true);
925 /* Make sure to destroy the event loop to invoke the cleeanup callbacks
926 * when calling exit() */
929 ev_loop(main_loop, 0);