i3
src/main.c
Go to the documentation of this file.
00001 /*
00002  * vim:ts=4:sw=4:expandtab
00003  *
00004  * i3 - an improved dynamic tiling window manager
00005  * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
00006  *
00007  * main.c: Initialization, main loop
00008  *
00009  */
00010 #include <ev.h>
00011 #include <fcntl.h>
00012 #include <sys/types.h>
00013 #include <sys/socket.h>
00014 #include <sys/un.h>
00015 #include <sys/time.h>
00016 #include <sys/resource.h>
00017 #include <sys/mman.h>
00018 #include <sys/stat.h>
00019 #include "all.h"
00020 
00021 #include "sd-daemon.h"
00022 
00023 /* The original value of RLIMIT_CORE when i3 was started. We need to restore
00024  * this before starting any other process, since we set RLIMIT_CORE to
00025  * RLIM_INFINITY for i3 debugging versions. */
00026 struct rlimit original_rlimit_core;
00027 
00028 /* Whether this version of i3 is a debug build or a release build. */
00029 bool debug_build = false;
00030 
00032 int listen_fds;
00033 
00034 static int xkb_event_base;
00035 
00036 int xkb_current_group;
00037 
00038 extern Con *focused;
00039 
00040 char **start_argv;
00041 
00042 xcb_connection_t *conn;
00043 /* The screen (0 when you are using DISPLAY=:0) of the connection 'conn' */
00044 int conn_screen;
00045 
00046 /* Display handle for libstartup-notification */
00047 SnDisplay *sndisplay;
00048 
00049 /* The last timestamp we got from X11 (timestamps are included in some events
00050  * and are used for some things, like determining a unique ID in startup
00051  * notification). */
00052 xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
00053 
00054 xcb_screen_t *root_screen;
00055 xcb_window_t root;
00056 
00057 /* Color depth, visual id and colormap to use when creating windows and
00058  * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
00059  * otherwise the root window’s default (usually 24 bit TrueColor). */
00060 uint8_t root_depth;
00061 xcb_visualid_t visual_id;
00062 xcb_colormap_t colormap;
00063 
00064 struct ev_loop *main_loop;
00065 
00066 xcb_key_symbols_t *keysyms;
00067 
00068 /* Those are our connections to X11 for use with libXcursor and XKB */
00069 Display *xlibdpy, *xkbdpy;
00070 
00071 /* The list of key bindings */
00072 struct bindings_head *bindings;
00073 
00074 /* The list of exec-lines */
00075 struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
00076 
00077 /* The list of exec_always lines */
00078 struct autostarts_always_head autostarts_always = TAILQ_HEAD_INITIALIZER(autostarts_always);
00079 
00080 /* The list of assignments */
00081 struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
00082 
00083 /* The list of workspace assignments (which workspace should end up on which
00084  * output) */
00085 struct ws_assignments_head ws_assignments = TAILQ_HEAD_INITIALIZER(ws_assignments);
00086 
00087 /* We hope that those are supported and set them to true */
00088 bool xcursor_supported = true;
00089 bool xkb_supported = true;
00090 
00091 /* This will be set to true when -C is used so that functions can behave
00092  * slightly differently. We don’t want i3-nagbar to be started when validating
00093  * the config, for example. */
00094 bool only_check_config = false;
00095 
00096 /*
00097  * This callback is only a dummy, see xcb_prepare_cb and xcb_check_cb.
00098  * See also man libev(3): "ev_prepare" and "ev_check" - customise your event loop
00099  *
00100  */
00101 static void xcb_got_event(EV_P_ struct ev_io *w, int revents) {
00102     /* empty, because xcb_prepare_cb and xcb_check_cb are used */
00103 }
00104 
00105 /*
00106  * Flush before blocking (and waiting for new events)
00107  *
00108  */
00109 static void xcb_prepare_cb(EV_P_ ev_prepare *w, int revents) {
00110     xcb_flush(conn);
00111 }
00112 
00113 /*
00114  * Instead of polling the X connection socket we leave this to
00115  * xcb_poll_for_event() which knows better than we can ever know.
00116  *
00117  */
00118 static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
00119     xcb_generic_event_t *event;
00120 
00121     while ((event = xcb_poll_for_event(conn)) != NULL) {
00122         if (event->response_type == 0) {
00123             if (event_is_ignored(event->sequence, 0))
00124                 DLOG("Expected X11 Error received for sequence %x\n", event->sequence);
00125             else {
00126                 xcb_generic_error_t *error = (xcb_generic_error_t*)event;
00127                 ELOG("X11 Error received! sequence 0x%x, error_code = %d\n",
00128                      error->sequence, error->error_code);
00129             }
00130             free(event);
00131             continue;
00132         }
00133 
00134         /* Strip off the highest bit (set if the event is generated) */
00135         int type = (event->response_type & 0x7F);
00136 
00137         handle_event(type, event);
00138 
00139         free(event);
00140     }
00141 }
00142 
00143 
00144 /*
00145  * When using xmodmap to change the keyboard mapping, this event
00146  * is only sent via XKB. Therefore, we need this special handler.
00147  *
00148  */
00149 static void xkb_got_event(EV_P_ struct ev_io *w, int revents) {
00150     DLOG("Handling XKB event\n");
00151     XkbEvent ev;
00152 
00153     /* When using xmodmap, every change (!) gets an own event.
00154      * Therefore, we just read all events and only handle the
00155      * mapping_notify once. */
00156     bool mapping_changed = false;
00157     while (XPending(xkbdpy)) {
00158         XNextEvent(xkbdpy, (XEvent*)&ev);
00159         /* While we should never receive a non-XKB event,
00160          * better do sanity checking */
00161         if (ev.type != xkb_event_base)
00162             continue;
00163 
00164         if (ev.any.xkb_type == XkbMapNotify) {
00165             mapping_changed = true;
00166             continue;
00167         }
00168 
00169         if (ev.any.xkb_type != XkbStateNotify) {
00170             ELOG("Unknown XKB event received (type %d)\n", ev.any.xkb_type);
00171             continue;
00172         }
00173 
00174         /* See The XKB Extension: Library Specification, section 14.1 */
00175         /* We check if the current group (each group contains
00176          * two levels) has been changed. Mode_switch activates
00177          * group XkbGroup2Index */
00178         if (xkb_current_group == ev.state.group)
00179             continue;
00180 
00181         xkb_current_group = ev.state.group;
00182 
00183         if (ev.state.group == XkbGroup2Index) {
00184             DLOG("Mode_switch enabled\n");
00185             grab_all_keys(conn, true);
00186         }
00187 
00188         if (ev.state.group == XkbGroup1Index) {
00189             DLOG("Mode_switch disabled\n");
00190             ungrab_all_keys(conn);
00191             grab_all_keys(conn, false);
00192         }
00193     }
00194 
00195     if (!mapping_changed)
00196         return;
00197 
00198     DLOG("Keyboard mapping changed, updating keybindings\n");
00199     xcb_key_symbols_free(keysyms);
00200     keysyms = xcb_key_symbols_alloc(conn);
00201 
00202     xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
00203 
00204     ungrab_all_keys(conn);
00205     DLOG("Re-grabbing...\n");
00206     translate_keysyms();
00207     grab_all_keys(conn, (xkb_current_group == XkbGroup2Index));
00208     DLOG("Done\n");
00209 }
00210 
00211 /*
00212  * Exit handler which destroys the main_loop. Will trigger cleanup handlers.
00213  *
00214  */
00215 static void i3_exit(void) {
00216 /* We need ev >= 4 for the following code. Since it is not *that* important (it
00217  * only makes sure that there are no i3-nagbar instances left behind) we still
00218  * support old systems with libev 3. */
00219 #if EV_VERSION_MAJOR >= 4
00220     ev_loop_destroy(main_loop);
00221 #endif
00222 
00223     if (*shmlogname != '\0') {
00224         fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
00225         fflush(stderr);
00226         shm_unlink(shmlogname);
00227     }
00228 }
00229 
00230 /*
00231  * (One-shot) Handler for all signals with default action "Term", see signal(7)
00232  *
00233  * Unlinks the SHM log and re-raises the signal.
00234  *
00235  */
00236 static void handle_signal(int sig, siginfo_t *info, void *data) {
00237     fprintf(stderr, "Received signal %d, terminating\n", sig);
00238     if (*shmlogname != '\0') {
00239         fprintf(stderr, "Closing SHM log \"%s\"\n", shmlogname);
00240         shm_unlink(shmlogname);
00241     }
00242     fflush(stderr);
00243     raise(sig);
00244 }
00245 
00246 int main(int argc, char *argv[]) {
00247     /* Keep a symbol pointing to the I3_VERSION string constant so that we have
00248      * it in gdb backtraces. */
00249     const char *i3_version = I3_VERSION;
00250     char *override_configpath = NULL;
00251     bool autostart = true;
00252     char *layout_path = NULL;
00253     bool delete_layout_path = false;
00254     bool force_xinerama = false;
00255     char *fake_outputs = NULL;
00256     bool disable_signalhandler = false;
00257     static struct option long_options[] = {
00258         {"no-autostart", no_argument, 0, 'a'},
00259         {"config", required_argument, 0, 'c'},
00260         {"version", no_argument, 0, 'v'},
00261         {"help", no_argument, 0, 'h'},
00262         {"layout", required_argument, 0, 'L'},
00263         {"restart", required_argument, 0, 0},
00264         {"force-xinerama", no_argument, 0, 0},
00265         {"force_xinerama", no_argument, 0, 0},
00266         {"disable-signalhandler", no_argument, 0, 0},
00267         {"shmlog-size", required_argument, 0, 0},
00268         {"shmlog_size", required_argument, 0, 0},
00269         {"get-socketpath", no_argument, 0, 0},
00270         {"get_socketpath", no_argument, 0, 0},
00271         {"fake_outputs", required_argument, 0, 0},
00272         {"fake-outputs", required_argument, 0, 0},
00273         {0, 0, 0, 0}
00274     };
00275     int option_index = 0, opt;
00276     xcb_void_cookie_t colormap_cookie;
00277 
00278     setlocale(LC_ALL, "");
00279 
00280     /* Get the RLIMIT_CORE limit at startup time to restore this before
00281      * starting processes. */
00282     getrlimit(RLIMIT_CORE, &original_rlimit_core);
00283 
00284     /* Disable output buffering to make redirects in .xsession actually useful for debugging */
00285     if (!isatty(fileno(stdout)))
00286         setbuf(stdout, NULL);
00287 
00288     srand(time(NULL));
00289 
00290     /* Init logging *before* initializing debug_build to guarantee early
00291      * (file) logging. */
00292     init_logging();
00293 
00294     /* i3_version contains either something like this:
00295      *     "4.0.2 (2011-11-11, branch "release")".
00296      * or: "4.0.2-123-gCOFFEEBABE (2011-11-11, branch "next")".
00297      *
00298      * So we check for the offset of the first opening round bracket to
00299      * determine whether this is a git version or a release version. */
00300     debug_build = ((strchr(i3_version, '(') - i3_version) > 10);
00301 
00302     /* On non-release builds, disable SHM logging by default. */
00303     shmlog_size = (debug_build ? 25 * 1024 * 1024 : 0);
00304 
00305     start_argv = argv;
00306 
00307     while ((opt = getopt_long(argc, argv, "c:CvaL:hld:V", long_options, &option_index)) != -1) {
00308         switch (opt) {
00309             case 'a':
00310                 LOG("Autostart disabled using -a\n");
00311                 autostart = false;
00312                 break;
00313             case 'L':
00314                 FREE(layout_path);
00315                 layout_path = sstrdup(optarg);
00316                 delete_layout_path = false;
00317                 break;
00318             case 'c':
00319                 FREE(override_configpath);
00320                 override_configpath = sstrdup(optarg);
00321                 break;
00322             case 'C':
00323                 LOG("Checking configuration file only (-C)\n");
00324                 only_check_config = true;
00325                 break;
00326             case 'v':
00327                 printf("i3 version " I3_VERSION " © 2009-2012 Michael Stapelberg and contributors\n");
00328                 exit(EXIT_SUCCESS);
00329             case 'V':
00330                 set_verbosity(true);
00331                 break;
00332             case 'd':
00333                 LOG("Enabling debug loglevel %s\n", optarg);
00334                 add_loglevel(optarg);
00335                 break;
00336             case 'l':
00337                 /* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */
00338                 break;
00339             case 0:
00340                 if (strcmp(long_options[option_index].name, "force-xinerama") == 0 ||
00341                     strcmp(long_options[option_index].name, "force_xinerama") == 0) {
00342                     force_xinerama = true;
00343                     ELOG("Using Xinerama instead of RandR. This option should be "
00344                          "avoided at all cost because it does not refresh the list "
00345                          "of screens, so you cannot configure displays at runtime. "
00346                          "Please check if your driver really does not support RandR "
00347                          "and disable this option as soon as you can.\n");
00348                     break;
00349                 } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) {
00350                     disable_signalhandler = true;
00351                     break;
00352                 } else if (strcmp(long_options[option_index].name, "get-socketpath") == 0 ||
00353                            strcmp(long_options[option_index].name, "get_socketpath") == 0) {
00354                     char *socket_path = root_atom_contents("I3_SOCKET_PATH");
00355                     if (socket_path) {
00356                         printf("%s\n", socket_path);
00357                         return 0;
00358                     }
00359 
00360                     return 1;
00361                 } else if (strcmp(long_options[option_index].name, "shmlog-size") == 0 ||
00362                            strcmp(long_options[option_index].name, "shmlog_size") == 0) {
00363                     shmlog_size = atoi(optarg);
00364                     /* Re-initialize logging immediately to get as many
00365                      * logmessages as possible into the SHM log. */
00366                     init_logging();
00367                     LOG("Limiting SHM log size to %d bytes\n", shmlog_size);
00368                     break;
00369                 } else if (strcmp(long_options[option_index].name, "restart") == 0) {
00370                     FREE(layout_path);
00371                     layout_path = sstrdup(optarg);
00372                     delete_layout_path = true;
00373                     break;
00374                 } else if (strcmp(long_options[option_index].name, "fake-outputs") == 0 ||
00375                            strcmp(long_options[option_index].name, "fake_outputs") == 0) {
00376                     LOG("Initializing fake outputs: %s\n", optarg);
00377                     fake_outputs = sstrdup(optarg);
00378                     break;
00379                 }
00380                 /* fall-through */
00381             default:
00382                 fprintf(stderr, "Usage: %s [-c configfile] [-d loglevel] [-a] [-v] [-V] [-C]\n", argv[0]);
00383                 fprintf(stderr, "\n");
00384                 fprintf(stderr, "\t-a          disable autostart ('exec' lines in config)\n");
00385                 fprintf(stderr, "\t-c <file>   use the provided configfile instead\n");
00386                 fprintf(stderr, "\t-C          validate configuration file and exit\n");
00387                 fprintf(stderr, "\t-d <level>  enable debug output with the specified loglevel\n");
00388                 fprintf(stderr, "\t-L <file>   path to the serialized layout during restarts\n");
00389                 fprintf(stderr, "\t-v          display version and exit\n");
00390                 fprintf(stderr, "\t-V          enable verbose mode\n");
00391                 fprintf(stderr, "\n");
00392                 fprintf(stderr, "\t--force-xinerama\n"
00393                                 "\tUse Xinerama instead of RandR.\n"
00394                                 "\tThis option should only be used if you are stuck with the\n"
00395                                 "\tnvidia closed source driver which does not support RandR.\n");
00396                 fprintf(stderr, "\n");
00397                 fprintf(stderr, "\t--get-socketpath\n"
00398                                 "\tRetrieve the i3 IPC socket path from X11, print it, then exit.\n");
00399                 fprintf(stderr, "\n");
00400                 fprintf(stderr, "\t--shmlog-size <limit>\n"
00401                                 "\tLimits the size of the i3 SHM log to <limit> bytes. Setting this\n"
00402                                 "\tto 0 disables SHM logging entirely.\n"
00403                                 "\tThe default is %d bytes.\n", shmlog_size);
00404                 fprintf(stderr, "\n");
00405                 fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
00406                                 "to send to a currently running i3 (like i3-msg). This allows you to\n"
00407                                 "use nice and logical commands, such as:\n"
00408                                 "\n"
00409                                 "\ti3 border none\n"
00410                                 "\ti3 floating toggle\n"
00411                                 "\ti3 kill window\n"
00412                                 "\n");
00413                 exit(EXIT_FAILURE);
00414         }
00415     }
00416 
00417     /* If the user passes more arguments, we act like i3-msg would: Just send
00418      * the arguments as an IPC message to i3. This allows for nice semantic
00419      * commands such as 'i3 border none'. */
00420     if (optind < argc) {
00421         /* We enable verbose mode so that the user knows what’s going on.
00422          * This should make it easier to find mistakes when the user passes
00423          * arguments by mistake. */
00424         set_verbosity(true);
00425 
00426         LOG("Additional arguments passed. Sending them as a command to i3.\n");
00427         char *payload = NULL;
00428         while (optind < argc) {
00429             if (!payload) {
00430                 payload = sstrdup(argv[optind]);
00431             } else {
00432                 char *both;
00433                 sasprintf(&both, "%s %s", payload, argv[optind]);
00434                 free(payload);
00435                 payload = both;
00436             }
00437             optind++;
00438         }
00439         LOG("Command is: %s (%d bytes)\n", payload, strlen(payload));
00440         char *socket_path = root_atom_contents("I3_SOCKET_PATH");
00441         if (!socket_path) {
00442             ELOG("Could not get i3 IPC socket path\n");
00443             return 1;
00444         }
00445 
00446         int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
00447         if (sockfd == -1)
00448             err(EXIT_FAILURE, "Could not create socket");
00449 
00450         struct sockaddr_un addr;
00451         memset(&addr, 0, sizeof(struct sockaddr_un));
00452         addr.sun_family = AF_LOCAL;
00453         strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
00454         if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
00455             err(EXIT_FAILURE, "Could not connect to i3");
00456 
00457         if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND,
00458                              (uint8_t*)payload) == -1)
00459             err(EXIT_FAILURE, "IPC: write()");
00460 
00461         uint32_t reply_length;
00462         uint8_t *reply;
00463         int ret;
00464         if ((ret = ipc_recv_message(sockfd, I3_IPC_MESSAGE_TYPE_COMMAND,
00465                                     &reply_length, &reply)) != 0) {
00466             if (ret == -1)
00467                 err(EXIT_FAILURE, "IPC: read()");
00468             return 1;
00469         }
00470         printf("%.*s\n", reply_length, reply);
00471         return 0;
00472     }
00473 
00474     /* Enable logging to handle the case when the user did not specify --shmlog-size */
00475     init_logging();
00476 
00477     /* Try to enable core dumps by default when running a debug build */
00478     if (debug_build) {
00479         struct rlimit limit = { RLIM_INFINITY, RLIM_INFINITY };
00480         setrlimit(RLIMIT_CORE, &limit);
00481 
00482         /* The following code is helpful, but not required. We thus don’t pay
00483          * much attention to error handling, non-linux or other edge cases. */
00484         char cwd[PATH_MAX];
00485         LOG("CORE DUMPS: You are running a development version of i3, so coredumps were automatically enabled (ulimit -c unlimited).\n");
00486         if (getcwd(cwd, sizeof(cwd)) != NULL)
00487             LOG("CORE DUMPS: Your current working directory is \"%s\".\n", cwd);
00488         int patternfd;
00489         if ((patternfd = open("/proc/sys/kernel/core_pattern", O_RDONLY)) >= 0) {
00490             memset(cwd, '\0', sizeof(cwd));
00491             if (read(patternfd, cwd, sizeof(cwd)) > 0)
00492                 /* a trailing newline is included in cwd */
00493                 LOG("CORE DUMPS: Your core_pattern is: %s", cwd);
00494             close(patternfd);
00495         }
00496     }
00497 
00498     LOG("i3 (tree) version " I3_VERSION " starting\n");
00499 
00500     conn = xcb_connect(NULL, &conn_screen);
00501     if (xcb_connection_has_error(conn))
00502         errx(EXIT_FAILURE, "Cannot open display\n");
00503 
00504     sndisplay = sn_xcb_display_new(conn, NULL, NULL);
00505 
00506     /* Initialize the libev event loop. This needs to be done before loading
00507      * the config file because the parser will install an ev_child watcher
00508      * for the nagbar when config errors are found. */
00509     main_loop = EV_DEFAULT;
00510     if (main_loop == NULL)
00511             die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
00512 
00513     root_screen = xcb_aux_get_screen(conn, conn_screen);
00514     root = root_screen->root;
00515 
00516     /* By default, we use the same depth and visual as the root window, which
00517      * usually is TrueColor (24 bit depth) and the corresponding visual.
00518      * However, we also check if a 32 bit depth and visual are available (for
00519      * transparency) and use it if so. */
00520     root_depth = root_screen->root_depth;
00521     visual_id = root_screen->root_visual;
00522     colormap = root_screen->default_colormap;
00523 
00524     DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id);
00525 
00526     xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
00527     xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
00528 
00529     load_configuration(conn, override_configpath, false);
00530     if (only_check_config) {
00531         LOG("Done checking configuration file. Exiting.\n");
00532         exit(0);
00533     }
00534 
00535     if (config.ipc_socket_path == NULL) {
00536         /* Fall back to a file name in /tmp/ based on the PID */
00537         if ((config.ipc_socket_path = getenv("I3SOCK")) == NULL)
00538             config.ipc_socket_path = get_process_filename("ipc-socket");
00539         else
00540             config.ipc_socket_path = sstrdup(config.ipc_socket_path);
00541     }
00542 
00543     uint32_t mask = XCB_CW_EVENT_MASK;
00544     uint32_t values[] = { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT |
00545                           XCB_EVENT_MASK_STRUCTURE_NOTIFY |         /* when the user adds a screen (e.g. video
00546                                                                            projector), the root window gets a
00547                                                                            ConfigureNotify */
00548                           XCB_EVENT_MASK_POINTER_MOTION |
00549                           XCB_EVENT_MASK_PROPERTY_CHANGE |
00550                           XCB_EVENT_MASK_ENTER_WINDOW };
00551     xcb_void_cookie_t cookie;
00552     cookie = xcb_change_window_attributes_checked(conn, root, mask, values);
00553     check_error(conn, cookie, "Another window manager seems to be running");
00554 
00555     /* By now we already checked for replies once, so let’s see if colormap
00556      * creation worked (if requested). */
00557     if (colormap != root_screen->default_colormap) {
00558         xcb_generic_error_t *error = xcb_request_check(conn, colormap_cookie);
00559         if (error != NULL) {
00560             ELOG("Could not create ColorMap for 32 bit visual, falling back to X11 default.\n");
00561             root_depth = root_screen->root_depth;
00562             visual_id = root_screen->root_visual;
00563             colormap = root_screen->default_colormap;
00564             DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id);
00565             free(error);
00566         }
00567     }
00568 
00569     xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
00570     if (greply == NULL) {
00571         ELOG("Could not get geometry of the root window, exiting\n");
00572         return 1;
00573     }
00574     DLOG("root geometry reply: (%d, %d) %d x %d\n", greply->x, greply->y, greply->width, greply->height);
00575 
00576     /* Place requests for the atoms we need as soon as possible */
00577     #define xmacro(atom) \
00578         xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom);
00579     #include "atoms.xmacro"
00580     #undef xmacro
00581 
00582     /* Initialize the Xlib connection */
00583     xlibdpy = xkbdpy = XOpenDisplay(NULL);
00584 
00585     /* Try to load the X cursors and initialize the XKB extension */
00586     if (xlibdpy == NULL) {
00587         ELOG("ERROR: XOpenDisplay() failed, disabling libXcursor/XKB support\n");
00588         xcursor_supported = false;
00589         xkb_supported = false;
00590     } else if (fcntl(ConnectionNumber(xlibdpy), F_SETFD, FD_CLOEXEC) == -1) {
00591         ELOG("Could not set FD_CLOEXEC on xkbdpy\n");
00592         return 1;
00593     } else {
00594         xcursor_load_cursors();
00595         /*init_xkb();*/
00596     }
00597 
00598     /* Set a cursor for the root window (otherwise the root window will show no
00599        cursor until the first client is launched). */
00600     if (xcursor_supported)
00601         xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
00602     else xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
00603 
00604     if (xkb_supported) {
00605         int errBase,
00606             major = XkbMajorVersion,
00607             minor = XkbMinorVersion;
00608 
00609         if (fcntl(ConnectionNumber(xkbdpy), F_SETFD, FD_CLOEXEC) == -1) {
00610             fprintf(stderr, "Could not set FD_CLOEXEC on xkbdpy\n");
00611             return 1;
00612         }
00613 
00614         int i1;
00615         if (!XkbQueryExtension(xkbdpy,&i1,&xkb_event_base,&errBase,&major,&minor)) {
00616             fprintf(stderr, "XKB not supported by X-server\n");
00617             return 1;
00618         }
00619         /* end of ugliness */
00620 
00621         if (!XkbSelectEvents(xkbdpy, XkbUseCoreKbd,
00622                              XkbMapNotifyMask | XkbStateNotifyMask,
00623                              XkbMapNotifyMask | XkbStateNotifyMask)) {
00624             fprintf(stderr, "Could not set XKB event mask\n");
00625             return 1;
00626         }
00627     }
00628 
00629     /* Setup NetWM atoms */
00630     #define xmacro(name) \
00631         do { \
00632             xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \
00633             if (!reply) { \
00634                 ELOG("Could not get atom " #name "\n"); \
00635                 exit(-1); \
00636             } \
00637             A_ ## name = reply->atom; \
00638             free(reply); \
00639         } while (0);
00640     #include "atoms.xmacro"
00641     #undef xmacro
00642 
00643     property_handlers_init();
00644 
00645     ewmh_setup_hints();
00646 
00647     keysyms = xcb_key_symbols_alloc(conn);
00648 
00649     xcb_numlock_mask = aio_get_mod_mask_for(XCB_NUM_LOCK, keysyms);
00650 
00651     translate_keysyms();
00652     grab_all_keys(conn, false);
00653 
00654     bool needs_tree_init = true;
00655     if (layout_path) {
00656         LOG("Trying to restore the layout from %s...", layout_path);
00657         needs_tree_init = !tree_restore(layout_path, greply);
00658         if (delete_layout_path)
00659             unlink(layout_path);
00660         free(layout_path);
00661     }
00662     if (needs_tree_init)
00663         tree_init(greply);
00664 
00665     free(greply);
00666 
00667     /* Setup fake outputs for testing */
00668     if (fake_outputs == NULL && config.fake_outputs != NULL)
00669         fake_outputs = config.fake_outputs;
00670 
00671     if (fake_outputs != NULL) {
00672         fake_outputs_init(fake_outputs);
00673         FREE(fake_outputs);
00674         config.fake_outputs = NULL;
00675     } else if (force_xinerama || config.force_xinerama) {
00676         /* Force Xinerama (for drivers which don't support RandR yet, esp. the
00677          * nVidia binary graphics driver), when specified either in the config
00678          * file or on command-line */
00679         xinerama_init();
00680     } else {
00681         DLOG("Checking for XRandR...\n");
00682         randr_init(&randr_base);
00683     }
00684 
00685     xcb_query_pointer_reply_t *pointerreply;
00686     Output *output = NULL;
00687     if (!(pointerreply = xcb_query_pointer_reply(conn, pointercookie, NULL))) {
00688         ELOG("Could not query pointer position, using first screen\n");
00689         output = get_first_output();
00690     } else {
00691         DLOG("Pointer at %d, %d\n", pointerreply->root_x, pointerreply->root_y);
00692         output = get_output_containing(pointerreply->root_x, pointerreply->root_y);
00693         if (!output) {
00694             ELOG("ERROR: No screen at (%d, %d), starting on the first screen\n",
00695                  pointerreply->root_x, pointerreply->root_y);
00696             output = get_first_output();
00697         }
00698 
00699         con_focus(con_descend_focused(output_get_content(output->con)));
00700     }
00701 
00702     tree_render();
00703 
00704     /* Create the UNIX domain socket for IPC */
00705     int ipc_socket = ipc_create_socket(config.ipc_socket_path);
00706     if (ipc_socket == -1) {
00707         ELOG("Could not create the IPC socket, IPC disabled\n");
00708     } else {
00709         free(config.ipc_socket_path);
00710         struct ev_io *ipc_io = scalloc(sizeof(struct ev_io));
00711         ev_io_init(ipc_io, ipc_new_client, ipc_socket, EV_READ);
00712         ev_io_start(main_loop, ipc_io);
00713     }
00714 
00715     /* Also handle the UNIX domain sockets passed via socket activation. The
00716      * parameter 1 means "remove the environment variables", we don’t want to
00717      * pass these to child processes. */
00718     listen_fds = sd_listen_fds(0);
00719     if (listen_fds < 0)
00720         ELOG("socket activation: Error in sd_listen_fds\n");
00721     else if (listen_fds == 0)
00722         DLOG("socket activation: no sockets passed\n");
00723     else {
00724         int flags;
00725         for (int fd = SD_LISTEN_FDS_START;
00726              fd < (SD_LISTEN_FDS_START + listen_fds);
00727              fd++) {
00728             DLOG("socket activation: also listening on fd %d\n", fd);
00729 
00730             /* sd_listen_fds() enables FD_CLOEXEC by default.
00731              * However, we need to keep the file descriptors open for in-place
00732              * restarting, therefore we explicitly disable FD_CLOEXEC. */
00733             if ((flags = fcntl(fd, F_GETFD)) < 0 ||
00734                 fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) < 0) {
00735                 ELOG("Could not disable FD_CLOEXEC on fd %d\n", fd);
00736             }
00737 
00738             struct ev_io *ipc_io = scalloc(sizeof(struct ev_io));
00739             ev_io_init(ipc_io, ipc_new_client, fd, EV_READ);
00740             ev_io_start(main_loop, ipc_io);
00741         }
00742     }
00743 
00744     /* Set up i3 specific atoms like I3_SOCKET_PATH and I3_CONFIG_PATH */
00745     x_set_i3_atoms();
00746 
00747     struct ev_io *xcb_watcher = scalloc(sizeof(struct ev_io));
00748     struct ev_io *xkb = scalloc(sizeof(struct ev_io));
00749     struct ev_check *xcb_check = scalloc(sizeof(struct ev_check));
00750     struct ev_prepare *xcb_prepare = scalloc(sizeof(struct ev_prepare));
00751 
00752     ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
00753     ev_io_start(main_loop, xcb_watcher);
00754 
00755 
00756     if (xkb_supported) {
00757         ev_io_init(xkb, xkb_got_event, ConnectionNumber(xkbdpy), EV_READ);
00758         ev_io_start(main_loop, xkb);
00759 
00760         /* Flush the buffer so that libev can properly get new events */
00761         XFlush(xkbdpy);
00762     }
00763 
00764     ev_check_init(xcb_check, xcb_check_cb);
00765     ev_check_start(main_loop, xcb_check);
00766 
00767     ev_prepare_init(xcb_prepare, xcb_prepare_cb);
00768     ev_prepare_start(main_loop, xcb_prepare);
00769 
00770     xcb_flush(conn);
00771 
00772     manage_existing_windows(root);
00773 
00774     struct sigaction action;
00775 
00776     action.sa_sigaction = handle_signal;
00777     action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
00778     sigemptyset(&action.sa_mask);
00779 
00780     if (!disable_signalhandler)
00781         setup_signal_handler();
00782     else {
00783         /* Catch all signals with default action "Core", see signal(7) */
00784         if (sigaction(SIGQUIT, &action, NULL) == -1 ||
00785             sigaction(SIGILL, &action, NULL) == -1 ||
00786             sigaction(SIGABRT, &action, NULL) == -1 ||
00787             sigaction(SIGFPE, &action, NULL) == -1 ||
00788             sigaction(SIGSEGV, &action, NULL) == -1)
00789             ELOG("Could not setup signal handler");
00790     }
00791 
00792     /* Catch all signals with default action "Term", see signal(7) */
00793     if (sigaction(SIGHUP, &action, NULL) == -1 ||
00794         sigaction(SIGINT, &action, NULL) == -1 ||
00795         sigaction(SIGALRM, &action, NULL) == -1 ||
00796         sigaction(SIGUSR1, &action, NULL) == -1 ||
00797         sigaction(SIGUSR2, &action, NULL) == -1)
00798         ELOG("Could not setup signal handler");
00799 
00800     /* Ignore SIGPIPE to survive errors when an IPC client disconnects
00801      * while we are sending him a message */
00802     signal(SIGPIPE, SIG_IGN);
00803 
00804     /* Autostarting exec-lines */
00805     if (autostart) {
00806         struct Autostart *exec;
00807         TAILQ_FOREACH(exec, &autostarts, autostarts) {
00808             LOG("auto-starting %s\n", exec->command);
00809             start_application(exec->command, exec->no_startup_id);
00810         }
00811     }
00812 
00813     /* Autostarting exec_always-lines */
00814     struct Autostart *exec_always;
00815     TAILQ_FOREACH(exec_always, &autostarts_always, autostarts_always) {
00816         LOG("auto-starting (always!) %s\n", exec_always->command);
00817         start_application(exec_always->command, exec_always->no_startup_id);
00818     }
00819 
00820     /* Start i3bar processes for all configured bars */
00821     Barconfig *barconfig;
00822     TAILQ_FOREACH(barconfig, &barconfigs, configs) {
00823         char *command = NULL;
00824         sasprintf(&command, "%s --bar_id=%s --socket=\"%s\"",
00825                 barconfig->i3bar_command ? barconfig->i3bar_command : "i3bar",
00826                 barconfig->id, current_socketpath);
00827         LOG("Starting bar process: %s\n", command);
00828         start_application(command, true);
00829         free(command);
00830     }
00831 
00832     /* Make sure to destroy the event loop to invoke the cleeanup callbacks
00833      * when calling exit() */
00834     atexit(i3_exit);
00835 
00836     ev_loop(main_loop, 0);
00837 }