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_prepare watcher around to be able to enable and disable it
39 * temporarily for drag_pointer(). */
40 static struct ev_prepare *xcb_prepare;
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;
95 bool force_xinerama = false;
98 * This callback is only a dummy, see xcb_prepare_cb.
99 * See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop
102 static void xcb_got_event(EV_P_ struct ev_io *w, int revents) {
103 /* empty, because xcb_prepare_cb are used */
107 * Called just before the event loop sleeps. Ensures xcb’s incoming and outgoing
108 * queues are empty so that any activity will trigger another event loop
109 * iteration, and hence another xcb_prepare_cb invocation.
112 static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
113 /* Process all queued (and possibly new) events before the event loop
115 xcb_generic_event_t *event;
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);
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);
130 /* Strip off the highest bit (set if the event is generated) */
131 int type = (event->response_type & 0x7F);
133 handle_event(type, event);
138 /* Flush all queued events to X11. */
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_prepare_start(main_loop, xcb_prepare);
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_prepare, 0);
156 ev_prepare_stop(main_loop, xcb_prepare);
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 disable_randr15 = false;
201 char *fake_outputs = NULL;
202 bool disable_signalhandler = false;
203 bool only_check_config = false;
204 static struct option long_options[] = {
205 {"no-autostart", no_argument, 0, 'a'},
206 {"config", required_argument, 0, 'c'},
207 {"version", no_argument, 0, 'v'},
208 {"moreversion", no_argument, 0, 'm'},
209 {"more-version", no_argument, 0, 'm'},
210 {"more_version", no_argument, 0, 'm'},
211 {"help", no_argument, 0, 'h'},
212 {"layout", required_argument, 0, 'L'},
213 {"restart", required_argument, 0, 0},
214 {"force-xinerama", no_argument, 0, 0},
215 {"force_xinerama", no_argument, 0, 0},
216 {"disable-randr15", no_argument, 0, 0},
217 {"disable_randr15", no_argument, 0, 0},
218 {"disable-signalhandler", no_argument, 0, 0},
219 {"shmlog-size", required_argument, 0, 0},
220 {"shmlog_size", required_argument, 0, 0},
221 {"get-socketpath", no_argument, 0, 0},
222 {"get_socketpath", no_argument, 0, 0},
223 {"fake_outputs", required_argument, 0, 0},
224 {"fake-outputs", required_argument, 0, 0},
225 {"force-old-config-parser-v4.4-only", no_argument, 0, 0},
227 int option_index = 0, opt;
229 setlocale(LC_ALL, "");
231 /* Get the RLIMIT_CORE limit at startup time to restore this before
232 * starting processes. */
233 getrlimit(RLIMIT_CORE, &original_rlimit_core);
235 /* Disable output buffering to make redirects in .xsession actually useful for debugging */
236 if (!isatty(fileno(stdout)))
237 setbuf(stdout, NULL);
241 /* Init logging *before* initializing debug_build to guarantee early
245 /* On release builds, disable SHM logging by default. */
246 shmlog_size = (is_debug_build() || strstr(argv[0], "i3-with-shmlog") != NULL ? default_shmlog_size : 0);
250 while ((opt = getopt_long(argc, argv, "c:CvmaL:hld:V", long_options, &option_index)) != -1) {
253 LOG("Autostart disabled using -a\n");
258 layout_path = sstrdup(optarg);
259 delete_layout_path = false;
262 FREE(override_configpath);
263 override_configpath = sstrdup(optarg);
266 LOG("Checking configuration file only (-C)\n");
267 only_check_config = true;
270 printf("i3 version %s © 2009 Michael Stapelberg and contributors\n", i3_version);
274 printf("Binary i3 version: %s © 2009 Michael Stapelberg and contributors\n", i3_version);
275 display_running_version();
282 LOG("Enabling debug logging\n");
283 set_debug_logging(true);
286 /* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */
289 if (strcmp(long_options[option_index].name, "force-xinerama") == 0 ||
290 strcmp(long_options[option_index].name, "force_xinerama") == 0) {
291 force_xinerama = true;
292 ELOG("Using Xinerama instead of RandR. This option should be "
293 "avoided at all cost because it does not refresh the list "
294 "of screens, so you cannot configure displays at runtime. "
295 "Please check if your driver really does not support RandR "
296 "and disable this option as soon as you can.\n");
298 } else if (strcmp(long_options[option_index].name, "disable-randr15") == 0 ||
299 strcmp(long_options[option_index].name, "disable_randr15") == 0) {
300 disable_randr15 = true;
302 } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) {
303 disable_signalhandler = true;
305 } else if (strcmp(long_options[option_index].name, "get-socketpath") == 0 ||
306 strcmp(long_options[option_index].name, "get_socketpath") == 0) {
307 char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
309 printf("%s\n", socket_path);
314 } else if (strcmp(long_options[option_index].name, "shmlog-size") == 0 ||
315 strcmp(long_options[option_index].name, "shmlog_size") == 0) {
316 shmlog_size = atoi(optarg);
317 /* Re-initialize logging immediately to get as many
318 * logmessages as possible into the SHM log. */
320 LOG("Limiting SHM log size to %d bytes\n", shmlog_size);
322 } else if (strcmp(long_options[option_index].name, "restart") == 0) {
324 layout_path = sstrdup(optarg);
325 delete_layout_path = true;
327 } else if (strcmp(long_options[option_index].name, "fake-outputs") == 0 ||
328 strcmp(long_options[option_index].name, "fake_outputs") == 0) {
329 LOG("Initializing fake outputs: %s\n", optarg);
330 fake_outputs = sstrdup(optarg);
332 } else if (strcmp(long_options[option_index].name, "force-old-config-parser-v4.4-only") == 0) {
333 ELOG("You are passing --force-old-config-parser-v4.4-only, but that flag was removed by now.\n");
338 fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
339 fprintf(stderr, "\n");
340 fprintf(stderr, "\t-a disable autostart ('exec' lines in config)\n");
341 fprintf(stderr, "\t-c <file> use the provided configfile instead\n");
342 fprintf(stderr, "\t-C validate configuration file and exit\n");
343 fprintf(stderr, "\t-d all enable debug output\n");
344 fprintf(stderr, "\t-L <file> path to the serialized layout during restarts\n");
345 fprintf(stderr, "\t-v display version and exit\n");
346 fprintf(stderr, "\t-V enable verbose mode\n");
347 fprintf(stderr, "\n");
348 fprintf(stderr, "\t--force-xinerama\n"
349 "\tUse Xinerama instead of RandR.\n"
350 "\tThis option should only be used if you are stuck with the\n"
351 "\told nVidia closed source driver (older than 302.17), which does\n"
352 "\tnot support RandR.\n");
353 fprintf(stderr, "\n");
354 fprintf(stderr, "\t--get-socketpath\n"
355 "\tRetrieve the i3 IPC socket path from X11, print it, then exit.\n");
356 fprintf(stderr, "\n");
357 fprintf(stderr, "\t--shmlog-size <limit>\n"
358 "\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
359 "\tto 0 disables SHM logging entirely.\n"
360 "\tThe default is %d bytes.\n",
362 fprintf(stderr, "\n");
363 fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
364 "to send to a currently running i3 (like i3-msg). This allows you to\n"
365 "use nice and logical commands, such as:\n"
368 "\ti3 floating toggle\n"
375 if (only_check_config) {
376 exit(parse_configuration(override_configpath, false) ? 0 : 1);
379 /* If the user passes more arguments, we act like i3-msg would: Just send
380 * the arguments as an IPC message to i3. This allows for nice semantic
381 * commands such as 'i3 border none'. */
383 /* We enable verbose mode so that the user knows what’s going on.
384 * This should make it easier to find mistakes when the user passes
385 * arguments by mistake. */
388 LOG("Additional arguments passed. Sending them as a command to i3.\n");
389 char *payload = NULL;
390 while (optind < argc) {
392 payload = sstrdup(argv[optind]);
395 sasprintf(&both, "%s %s", payload, argv[optind]);
401 DLOG("Command is: %s (%zd bytes)\n", payload, strlen(payload));
402 char *socket_path = root_atom_contents("I3_SOCKET_PATH", NULL, 0);
404 ELOG("Could not get i3 IPC socket path\n");
408 int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
410 err(EXIT_FAILURE, "Could not create socket");
412 struct sockaddr_un addr;
413 memset(&addr, 0, sizeof(struct sockaddr_un));
414 addr.sun_family = AF_LOCAL;
415 strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
417 if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
418 err(EXIT_FAILURE, "Could not connect to i3");
420 if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_RUN_COMMAND,
421 (uint8_t *)payload) == -1)
422 err(EXIT_FAILURE, "IPC: write()");
425 uint32_t reply_length;
429 if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
431 err(EXIT_FAILURE, "IPC: read()");
434 if (reply_type != I3_IPC_REPLY_TYPE_COMMAND)
435 errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_REPLY_TYPE_COMMAND);
436 printf("%.*s\n", reply_length, reply);
441 /* Enable logging to handle the case when the user did not specify --shmlog-size */
444 /* Try to enable core dumps by default when running a debug build */
445 if (is_debug_build()) {
446 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
447 setrlimit(RLIMIT_CORE, &limit);
449 /* The following code is helpful, but not required. We thus don’t pay
450 * much attention to error handling, non-linux or other edge cases. */
451 LOG("CORE DUMPS: You are running a development version of i3, so coredumps were automatically enabled (ulimit -c unlimited).\n");
452 size_t cwd_size = 1024;
453 char *cwd = smalloc(cwd_size);
455 while ((cwd_ret = getcwd(cwd, cwd_size)) == NULL && errno == ERANGE) {
456 cwd_size = cwd_size * 2;
457 cwd = srealloc(cwd, cwd_size);
460 LOG("CORE DUMPS: Your current working directory is \"%s\".\n", cwd);
462 if ((patternfd = open("/proc/sys/kernel/core_pattern", O_RDONLY)) >= 0) {
463 memset(cwd, '\0', cwd_size);
464 if (read(patternfd, cwd, cwd_size) > 0)
465 /* a trailing newline is included in cwd */
466 LOG("CORE DUMPS: Your core_pattern is: %s", cwd);
472 LOG("i3 %s starting\n", i3_version);
474 conn = xcb_connect(NULL, &conn_screen);
475 if (xcb_connection_has_error(conn))
476 errx(EXIT_FAILURE, "Cannot open display\n");
478 sndisplay = sn_xcb_display_new(conn, NULL, NULL);
480 /* Initialize the libev event loop. This needs to be done before loading
481 * the config file because the parser will install an ev_child watcher
482 * for the nagbar when config errors are found. */
483 main_loop = EV_DEFAULT;
484 if (main_loop == NULL)
485 die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
487 root_screen = xcb_aux_get_screen(conn, conn_screen);
488 root = root_screen->root;
490 /* Place requests for the atoms we need as soon as possible */
491 #define xmacro(atom) \
492 xcb_intern_atom_cookie_t atom##_cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
493 #include "atoms.xmacro"
496 root_depth = root_screen->root_depth;
497 colormap = root_screen->default_colormap;
498 visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32);
499 if (visual_type != NULL) {
500 root_depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id);
501 colormap = xcb_generate_id(conn);
503 xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(conn,
504 XCB_COLORMAP_ALLOC_NONE,
507 visual_type->visual_id);
509 xcb_generic_error_t *error = xcb_request_check(conn, cm_cookie);
511 ELOG("Could not create colormap. Error code: %d\n", error->error_code);
515 visual_type = get_visualtype(root_screen);
520 DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id);
521 DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d\n",
522 root_screen->height_in_pixels, root_screen->height_in_millimeters);
523 DLOG("One logical pixel corresponds to %d physical pixels on this display.\n", logical_px(1));
525 xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
526 xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
528 /* Setup NetWM atoms */
529 #define xmacro(name) \
531 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name##_cookie, NULL); \
533 ELOG("Could not get atom " #name "\n"); \
536 A_##name = reply->atom; \
539 #include "atoms.xmacro"
542 load_configuration(conn, override_configpath, false);
544 if (config.ipc_socket_path == NULL) {
545 /* Fall back to a file name in /tmp/ based on the PID */
546 if ((config.ipc_socket_path = getenv("I3SOCK")) == NULL)
547 config.ipc_socket_path = get_process_filename("ipc-socket");
549 config.ipc_socket_path = sstrdup(config.ipc_socket_path);
552 if (config.force_xinerama) {
553 force_xinerama = true;
556 xcb_void_cookie_t cookie;
557 cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK});
558 xcb_generic_error_t *error = xcb_request_check(conn, cookie);
560 ELOG("Another window manager seems to be running (X error %d)\n", error->error_code);
561 #ifdef I3_ASAN_ENABLED
562 __lsan_do_leak_check();
567 xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
568 if (greply == NULL) {
569 ELOG("Could not get geometry of the root window, exiting\n");
572 DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
574 xcursor_load_cursors();
576 /* Set a cursor for the root window (otherwise the root window will show no
577 cursor until the first client is launched). */
578 if (xcursor_supported)
579 xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
581 xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
583 const xcb_query_extension_reply_t *extreply;
584 extreply = xcb_get_extension_data(conn, &xcb_xkb_id);
585 xkb_supported = extreply->present;
586 if (!extreply->present) {
587 DLOG("xkb is not present on this server\n");
589 DLOG("initializing xcb-xkb\n");
590 xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
591 xcb_xkb_select_events(conn,
592 XCB_XKB_ID_USE_CORE_KBD,
593 XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
595 XCB_XKB_EVENT_TYPE_STATE_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY,
600 /* Setting both, XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE and
601 * XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED, will lead to the
602 * X server sending us the full XKB state in KeyPress and KeyRelease:
603 * https://sources.debian.net/src/xorg-server/2:1.17.2-1.1/xkb/xkbEvents.c/?hl=927#L927
605 xcb_xkb_per_client_flags_reply_t *pcf_reply;
606 /* The last three parameters are unset because they are only relevant
607 * when using a feature called “automatic reset of boolean controls”:
608 * https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Automatic_Reset_of_Boolean_Controls
610 pcf_reply = xcb_xkb_per_client_flags_reply(
612 xcb_xkb_per_client_flags(
614 XCB_XKB_ID_USE_CORE_KBD,
615 XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
616 XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE | XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED,
617 0 /* uint32_t ctrlsToChange */,
618 0 /* uint32_t autoCtrls */,
619 0 /* uint32_t autoCtrlsValues */),
621 if (pcf_reply == NULL ||
622 !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE)) {
623 ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_GRABS_USE_XKB_STATE\n");
625 if (pcf_reply == NULL ||
626 !(pcf_reply->value & XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED)) {
627 ELOG("Could not set XCB_XKB_PER_CLIENT_FLAG_LOOKUP_STATE_WHEN_GRABBED\n");
630 xkb_base = extreply->first_event;
635 property_handlers_init();
639 keysyms = xcb_key_symbols_alloc(conn);
641 xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
644 die("Could not load keymap\n");
649 bool needs_tree_init = true;
650 if (layout_path != NULL) {
651 LOG("Trying to restore the layout from \"%s\".\n", layout_path);
652 needs_tree_init = !tree_restore(layout_path, greply);
653 if (delete_layout_path) {
655 const char *dir = dirname(layout_path);
656 /* possibly fails with ENOTEMPTY if there are files (or
666 /* Setup fake outputs for testing */
667 if (fake_outputs == NULL && config.fake_outputs != NULL)
668 fake_outputs = config.fake_outputs;
670 if (fake_outputs != NULL) {
671 fake_outputs_init(fake_outputs);
673 config.fake_outputs = NULL;
674 } else if (force_xinerama) {
675 /* Force Xinerama (for drivers which don't support RandR yet, esp. the
676 * nVidia binary graphics driver), when specified either in the config
677 * file or on command-line */
680 DLOG("Checking for XRandR...\n");
681 randr_init(&randr_base, disable_randr15 || config.disable_randr15);
684 /* We need to force disabling outputs which have been loaded from the
685 * layout file but are no longer active. This can happen if the output has
686 * been disabled in the short time between writing the restart layout file
687 * and restarting i3. See #2326. */
688 if (layout_path != NULL && randr_base > -1) {
690 TAILQ_FOREACH(con, &(croot->nodes_head), nodes) {
692 TAILQ_FOREACH(output, &outputs, outputs) {
693 if (output->active || strcmp(con->name, output_primary_name(output)) != 0)
696 /* This will correctly correlate the output with its content
697 * container. We need to make the connection to properly
698 * disable the output. */
699 if (output->con == NULL) {
700 output_init_con(output);
701 output->changed = false;
704 output->to_be_disabled = true;
705 randr_disable_output(output);
711 scratchpad_fix_resolution();
713 xcb_query_pointer_reply_t *pointerreply;
714 Output *output = NULL;
715 if (!(pointerreply = xcb_query_pointer_reply(conn, pointercookie, NULL))) {
716 ELOG("Could not query pointer position, using first screen\n");
718 DLOG("Pointer at %d, %d\n", pointerreply->root_x, pointerreply->root_y);
719 output = get_output_containing(pointerreply->root_x, pointerreply->root_y);
721 ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n",
722 pointerreply->root_x, pointerreply->root_y);
723 output = get_first_output();
726 con_focus(con_descend_focused(output_get_content(output->con)));
732 /* Create the UNIX domain socket for IPC */
733 int ipc_socket = ipc_create_socket(config.ipc_socket_path);
734 if (ipc_socket == -1) {
735 ELOG("Could not create the IPC socket, IPC disabled\n");
737 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
738 ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
739 ev_io_start(main_loop, ipc_io);
742 /* Also handle the UNIX domain sockets passed via socket activation. The
743 * parameter 1 means "remove the environment variables", we don’t want to
744 * pass these to child processes. */
745 listen_fds = sd_listen_fds(0);
747 ELOG("socket activation: Error in sd_listen_fds\n");
748 else if (listen_fds == 0)
749 DLOG("socket activation: no sockets passed\n");
752 for (int fd = SD_LISTEN_FDS_START;
753 fd < (SD_LISTEN_FDS_START + listen_fds);
755 DLOG("socket activation: also listening on fd %d\n", fd);
757 /* sd_listen_fds() enables FD_CLOEXEC by default.
758 * However, we need to keep the file descriptors open for in-place
759 * restarting, therefore we explicitly disable FD_CLOEXEC. */
760 if ((flags = fcntl(fd, F_GETFD)) < 0 ||
761 fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) < 0) {
762 ELOG("Could not disable FD_CLOEXEC on fd %d\n", fd);
765 struct ev_io *ipc_io = scalloc(1, sizeof(struct ev_io));
766 ev_io_init(ipc_io, ipc_new_client, fd, EV_READ);
767 ev_io_start(main_loop, ipc_io);
771 /* Set up i3 specific atoms like I3_SOCKET_PATH and I3_CONFIG_PATH */
773 ewmh_update_workarea();
775 /* Set the ewmh desktop properties. */
776 ewmh_update_current_desktop();
777 ewmh_update_number_of_desktops();
778 ewmh_update_desktop_names();
779 ewmh_update_desktop_viewport();
781 struct ev_io *xcb_watcher = scalloc(1, sizeof(struct ev_io));
782 xcb_prepare = scalloc(1, sizeof(struct ev_prepare));
784 ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
785 ev_io_start(main_loop, xcb_watcher);
787 ev_prepare_init(xcb_prepare, xcb_prepare_cb);
788 ev_prepare_start(main_loop, xcb_prepare);
792 /* What follows is a fugly consequence of X11 protocol race conditions like
793 * the following: In an i3 in-place restart, i3 will reparent all windows
794 * to the root window, then exec() itself. In the new process, it calls
795 * manage_existing_windows. However, in case any application sent a
796 * generated UnmapNotify message to the WM (as GIMP does), this message
797 * will be handled by i3 *after* managing the window, thus i3 thinks the
798 * window just closed itself. In reality, the message was sent in the time
799 * period where i3 wasn’t running yet.
801 * To prevent this, we grab the server (disables processing of any other
802 * connections), then discard all pending events (since we didn’t do
803 * anything, there cannot be any meaningful responses), then ungrab the
805 xcb_grab_server(conn);
808 xcb_generic_event_t *event;
809 while ((event = xcb_poll_for_event(conn)) != NULL) {
810 if (event->response_type == 0) {
815 /* Strip off the highest bit (set if the event is generated) */
816 int type = (event->response_type & 0x7F);
818 /* We still need to handle MapRequests which are sent in the
819 * timespan starting from when we register as a window manager and
820 * this piece of code which drops events. */
821 if (type == XCB_MAP_REQUEST)
822 handle_event(type, event);
826 manage_existing_windows(root);
828 xcb_ungrab_server(conn);
831 LOG("This is not an in-place restart, copying root window contents to a pixmap\n");
832 xcb_screen_t *root = xcb_aux_get_screen(conn, conn_screen);
833 uint16_t width = root->width_in_pixels;
834 uint16_t height = root->height_in_pixels;
835 xcb_pixmap_t pixmap = xcb_generate_id(conn);
836 xcb_gcontext_t gc = xcb_generate_id(conn);
838 xcb_create_pixmap(conn, root->root_depth, pixmap, root->root, width, height);
840 xcb_create_gc(conn, gc, root->root,
841 XCB_GC_FUNCTION | XCB_GC_PLANE_MASK | XCB_GC_FILL_STYLE | XCB_GC_SUBWINDOW_MODE,
842 (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS});
844 xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height);
845 xcb_change_window_attributes(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap});
847 xcb_free_gc(conn, gc);
848 xcb_free_pixmap(conn, pixmap);
851 #if defined(__OpenBSD__)
852 if (pledge("stdio rpath wpath cpath proc exec unix", NULL) == -1)
853 err(EXIT_FAILURE, "pledge");
856 struct sigaction action;
858 action.sa_sigaction = handle_signal;
859 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
860 sigemptyset(&action.sa_mask);
862 if (!disable_signalhandler)
863 setup_signal_handler();
865 /* Catch all signals with default action "Core", see signal(7) */
866 if (sigaction(SIGQUIT, &action, NULL) == -1 ||
867 sigaction(SIGILL, &action, NULL) == -1 ||
868 sigaction(SIGABRT, &action, NULL) == -1 ||
869 sigaction(SIGFPE, &action, NULL) == -1 ||
870 sigaction(SIGSEGV, &action, NULL) == -1)
871 ELOG("Could not setup signal handler.\n");
874 /* Catch all signals with default action "Term", see signal(7) */
875 if (sigaction(SIGHUP, &action, NULL) == -1 ||
876 sigaction(SIGINT, &action, NULL) == -1 ||
877 sigaction(SIGALRM, &action, NULL) == -1 ||
878 sigaction(SIGUSR1, &action, NULL) == -1 ||
879 sigaction(SIGUSR2, &action, NULL) == -1)
880 ELOG("Could not setup signal handler.\n");
882 /* Ignore SIGPIPE to survive errors when an IPC client disconnects
883 * while we are sending them a message */
884 signal(SIGPIPE, SIG_IGN);
886 /* Autostarting exec-lines */
888 while (!TAILQ_EMPTY(&autostarts)) {
889 struct Autostart *exec = TAILQ_FIRST(&autostarts);
891 LOG("auto-starting %s\n", exec->command);
892 start_application(exec->command, exec->no_startup_id);
895 TAILQ_REMOVE(&autostarts, exec, autostarts);
900 /* Autostarting exec_always-lines */
901 while (!TAILQ_EMPTY(&autostarts_always)) {
902 struct Autostart *exec_always = TAILQ_FIRST(&autostarts_always);
904 LOG("auto-starting (always!) %s\n", exec_always->command);
905 start_application(exec_always->command, exec_always->no_startup_id);
907 FREE(exec_always->command);
908 TAILQ_REMOVE(&autostarts_always, exec_always, autostarts_always);
912 /* Start i3bar processes for all configured bars */
913 Barconfig *barconfig;
914 TAILQ_FOREACH(barconfig, &barconfigs, configs) {
915 char *command = NULL;
916 sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
917 barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
918 barconfig->id, current_socketpath);
919 LOG("Starting bar process: %s\n", command);
920 start_application(command, true);
924 /* Make sure to destroy the event loop to invoke the cleanup callbacks
925 * when calling exit() */
928 ev_loop(main_loop, 0);