X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fmain.c;h=0d1457fdc1e18ca443fe652292f7343c9948b91f;hb=aa0b1f599f25cfe858ebbc7fa80d459bcdb2ae02;hp=59c0014639bacf0ca19450e772219ffe197b157f;hpb=f2209a873c47d651c2e87b4ee4ebf203e99fa6ab;p=i3%2Fi3 diff --git a/src/main.c b/src/main.c index 59c00146..0d1457fd 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,3 @@ -#undef I3__FILE__ -#define I3__FILE__ "main.c" /* * vim:ts=4:sw=4:expandtab * @@ -9,6 +7,8 @@ * main.c: Initialization, main loop * */ +#include "all.h" + #include #include #include @@ -19,9 +19,12 @@ #include #include #include -#include "all.h" #include "shmlog.h" +#ifdef I3_ASAN_ENABLED +#include +#endif + #include "sd-daemon.h" /* The original value of RLIMIT_CORE when i3 was started. We need to restore @@ -59,7 +62,7 @@ xcb_window_t root; * pixmaps. Will use 32 bit depth and an appropriate visual, if available, * otherwise the root window’s default (usually 24 bit TrueColor). */ uint8_t root_depth; -xcb_visualid_t visual_id; +xcb_visualtype_t *visual_type; xcb_colormap_t colormap; struct ev_loop *main_loop; @@ -189,12 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, void *data) { int main(int argc, char *argv[]) { /* Keep a symbol pointing to the I3_VERSION string constant so that we have * it in gdb backtraces. */ - const char *_i3_version __attribute__((unused)) = i3_version; + static const char *_i3_version __attribute__((used)) = I3_VERSION; char *override_configpath = NULL; bool autostart = true; char *layout_path = NULL; bool delete_layout_path = false; bool force_xinerama = false; + bool disable_randr15 = false; char *fake_outputs = NULL; bool disable_signalhandler = false; bool only_check_config = false; @@ -210,6 +214,8 @@ int main(int argc, char *argv[]) { {"restart", required_argument, 0, 0}, {"force-xinerama", no_argument, 0, 0}, {"force_xinerama", no_argument, 0, 0}, + {"disable-randr15", no_argument, 0, 0}, + {"disable_randr15", no_argument, 0, 0}, {"disable-signalhandler", no_argument, 0, 0}, {"shmlog-size", required_argument, 0, 0}, {"shmlog_size", required_argument, 0, 0}, @@ -290,6 +296,10 @@ int main(int argc, char *argv[]) { "Please check if your driver really does not support RandR " "and disable this option as soon as you can.\n"); break; + } else if (strcmp(long_options[option_index].name, "disable-randr15") == 0 || + strcmp(long_options[option_index].name, "disable_randr15") == 0) { + disable_randr15 = true; + break; } else if (strcmp(long_options[option_index].name, "disable-signalhandler") == 0) { disable_signalhandler = true; break; @@ -404,12 +414,14 @@ int main(int argc, char *argv[]) { memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_LOCAL; strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + FREE(socket_path); if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) err(EXIT_FAILURE, "Could not connect to i3"); - if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_COMMAND, + if (ipc_send_message(sockfd, strlen(payload), I3_IPC_MESSAGE_TYPE_RUN_COMMAND, (uint8_t *)payload) == -1) err(EXIT_FAILURE, "IPC: write()"); + FREE(payload); uint32_t reply_length; uint32_t reply_type; @@ -420,9 +432,10 @@ int main(int argc, char *argv[]) { err(EXIT_FAILURE, "IPC: read()"); return 1; } - if (reply_type != I3_IPC_MESSAGE_TYPE_COMMAND) - errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_MESSAGE_TYPE_COMMAND); + if (reply_type != I3_IPC_REPLY_TYPE_COMMAND) + errx(EXIT_FAILURE, "IPC: received reply of type %d but expected %d (COMMAND)", reply_type, I3_IPC_REPLY_TYPE_COMMAND); printf("%.*s\n", reply_length, reply); + FREE(reply); return 0; } @@ -451,7 +464,7 @@ int main(int argc, char *argv[]) { memset(cwd, '\0', cwd_size); if (read(patternfd, cwd, cwd_size) > 0) /* a trailing newline is included in cwd */ - LOG("CORE DUMPS: Your core_pattern is: \"%s\".\n", cwd); + LOG("CORE DUMPS: Your core_pattern is: %s", cwd); close(patternfd); } free(cwd); @@ -481,18 +494,33 @@ int main(int argc, char *argv[]) { #include "atoms.xmacro" #undef xmacro - /* By default, we use the same depth and visual as the root window, which - * usually is TrueColor (24 bit depth) and the corresponding visual. - * However, we also check if a 32 bit depth and visual are available (for - * transparency) and use it if so. */ root_depth = root_screen->root_depth; - visual_id = root_screen->root_visual; colormap = root_screen->default_colormap; + visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32); + if (visual_type != NULL) { + root_depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id); + colormap = xcb_generate_id(conn); + + xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(conn, + XCB_COLORMAP_ALLOC_NONE, + colormap, + root, + visual_type->visual_id); + + xcb_generic_error_t *error = xcb_request_check(conn, cm_cookie); + if (error != NULL) { + ELOG("Could not create colormap. Error code: %d\n", error->error_code); + exit(EXIT_FAILURE); + } + } else { + visual_type = get_visualtype(root_screen); + } - DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id); - DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d, dpi = %d\n", - root_screen->height_in_pixels, root_screen->height_in_millimeters, - (int)((double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters)); + init_dpi(); + + DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id); + DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d\n", + root_screen->height_in_pixels, root_screen->height_in_millimeters); DLOG("One logical pixel corresponds to %d physical pixels on this display.\n", logical_px(1)); xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root); @@ -524,7 +552,14 @@ int main(int argc, char *argv[]) { xcb_void_cookie_t cookie; cookie = xcb_change_window_attributes_checked(conn, root, XCB_CW_EVENT_MASK, (uint32_t[]){ROOT_EVENT_MASK}); - check_error(conn, cookie, "Another window manager seems to be running"); + xcb_generic_error_t *error = xcb_request_check(conn, cookie); + if (error != NULL) { + ELOG("Another window manager seems to be running (X error %d)\n", error->error_code); +#ifdef I3_ASAN_ENABLED + __lsan_do_leak_check(); +#endif + return 1; + } xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL); if (greply == NULL) { @@ -567,7 +602,7 @@ int main(int argc, char *argv[]) { xcb_xkb_per_client_flags_reply_t *pcf_reply; /* The last three parameters are unset because they are only relevant * when using a feature called “automatic reset of boolean controls”: - * http://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Automatic_Reset_of_Boolean_Controls + * https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Automatic_Reset_of_Boolean_Controls * */ pcf_reply = xcb_xkb_per_client_flags_reply( conn, @@ -609,7 +644,7 @@ int main(int argc, char *argv[]) { grab_all_keys(conn); bool needs_tree_init = true; - if (layout_path) { + if (layout_path != NULL) { LOG("Trying to restore the layout from \"%s\".\n", layout_path); needs_tree_init = !tree_restore(layout_path, greply); if (delete_layout_path) { @@ -619,7 +654,6 @@ int main(int argc, char *argv[]) { * sockets) left. */ rmdir(dir); } - free(layout_path); } if (needs_tree_init) tree_init(greply); @@ -641,8 +675,35 @@ int main(int argc, char *argv[]) { xinerama_init(); } else { DLOG("Checking for XRandR...\n"); - randr_init(&randr_base); + randr_init(&randr_base, disable_randr15 || config.disable_randr15); + } + + /* We need to force disabling outputs which have been loaded from the + * layout file but are no longer active. This can happen if the output has + * been disabled in the short time between writing the restart layout file + * and restarting i3. See #2326. */ + if (layout_path != NULL && randr_base > -1) { + Con *con; + TAILQ_FOREACH(con, &(croot->nodes_head), nodes) { + Output *output; + TAILQ_FOREACH(output, &outputs, outputs) { + if (output->active || strcmp(con->name, output_primary_name(output)) != 0) + continue; + + /* This will correctly correlate the output with its content + * container. We need to make the connection to properly + * disable the output. */ + if (output->con == NULL) { + output_init_con(output); + output->changed = false; + } + + output->to_be_disabled = true; + randr_disable_output(output); + } + } } + FREE(layout_path); scratchpad_fix_resolution(); @@ -660,6 +721,7 @@ int main(int argc, char *argv[]) { } con_focus(con_descend_focused(output_get_content(output->con))); + free(pointerreply); } tree_render(); @@ -781,12 +843,17 @@ int main(int argc, char *argv[]) { (uint32_t[]){XCB_GX_COPY, ~0, XCB_FILL_STYLE_SOLID, XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}); xcb_copy_area(conn, root->root, pixmap, gc, 0, 0, 0, 0, width, height); - xcb_change_window_attributes_checked(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap}); + xcb_change_window_attributes(conn, root->root, XCB_CW_BACK_PIXMAP, (uint32_t[]){pixmap}); xcb_flush(conn); xcb_free_gc(conn, gc); xcb_free_pixmap(conn, pixmap); } +#if defined(__OpenBSD__) + if (pledge("stdio rpath wpath cpath proc exec unix", NULL) == -1) + err(EXIT_FAILURE, "pledge"); +#endif + struct sigaction action; action.sa_sigaction = handle_signal;