From: Michael Stapelberg Date: Wed, 19 Oct 2011 21:58:19 +0000 (+0100) Subject: Make i3bar get its config from i3 via IPC X-Git-Tag: 4.1~92^2~35 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a5be27cb79f63b6303b65c70a79bddf44c1017d4;p=i3%2Fi3 Make i3bar get its config from i3 via IPC In order to not duplicate configuration options and make stuff confusing, we dropped the commandline flags (except for socket_path and bar_id). This means that you *have to* specify bar_id when starting i3bar. The best way is to let i3 start i3bar, which it will do automatically for every bar {} configuration block it finds. --- diff --git a/i3bar/include/config.h b/i3bar/include/config.h index b3473917..19b246dc 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -13,10 +13,25 @@ typedef struct config_t { int hide_on_modifier; dockpos_t dockpos; int verbose; - xcb_colors_t *colors; + struct xcb_color_strings_t colors; int disable_ws; + char *bar_id; + char *command; + char *fontname; } config_t; config_t config; +/** + * Start parsing the received bar configuration json-string + * + */ +void parse_config_json(char *json); + +/** + * free()s the color strings as soon as they are not needed anymore. + * + */ +void free_colors(struct xcb_color_strings_t *colors); + #endif diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index c1b7cc14..51da5d3e 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -40,10 +40,18 @@ struct xcb_color_strings_t { typedef struct xcb_colors_t xcb_colors_t; /* - * Initialize xcb and use the specified fontname for text-rendering + * Early initialization of the connection to X11: Everything which does not + * depend on 'config'. * */ -char *init_xcb(char *fontname); +char *init_xcb_early(); + +/** + * Initialization which depends on 'config' being usable. Called after the + * configuration has arrived. + * + */ +void init_xcb_late(char *fontname); /* * Initialize the colors diff --git a/i3bar/src/config.c b/i3bar/src/config.c new file mode 100644 index 00000000..23c5e122 --- /dev/null +++ b/i3bar/src/config.c @@ -0,0 +1,214 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3bar - an xcb-based status- and ws-bar for i3 + * + * © 2010-2011 Axel Wagner and contributors + * + * See file LICENSE for license information + * + * src/outputs.c: Maintaining the output-list + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static char *cur_key; + +/* + * Parse a key. + * + * Essentially we just save it in cur_key. + * + */ +#if YAJL_MAJOR >= 2 +static int config_map_key_cb(void *params_, const unsigned char *keyVal, size_t keyLen) { +#else +static int config_map_key_cb(void *params_, const unsigned char *keyVal, unsigned keyLen) { +#endif + FREE(cur_key); + + cur_key = malloc(sizeof(unsigned char) * (keyLen + 1)); + strncpy(cur_key, (const char*) keyVal, keyLen); + cur_key[keyLen] = '\0'; + + return 1; +} + +/* + * Parse a string + * + */ +#if YAJL_MAJOR >= 2 +static int config_string_cb(void *params_, const unsigned char *val, size_t len) { +#else +static int config_string_cb(void *params_, const unsigned char *val, unsigned int len) { +#endif + /* The id is ignored, we already have it in config.bar_id */ + if (!strcmp(cur_key, "id")) + return 1; + + if (!strcmp(cur_key, "mode")) { + DLOG("mode = %.*s, len = %d\n", len, val, len); + config.hide_on_modifier = (len == 4 && !strncmp((const char*)val, "hide", strlen("hide"))); + return 1; + } + + if (!strcmp(cur_key, "position")) { + DLOG("position = %.*s\n", len, val); + config.dockpos = (len == 3 && !strncmp((const char*)val, "top", strlen("top")) ? DOCKPOS_TOP : DOCKPOS_BOT); + return 1; + } + + if (!strcmp(cur_key, "status_command")) { + /* We cannot directly start the child here, because start_child() also + * needs to be run when no command was specified (to setup stdin). + * Therefore we save the command in 'config' and access it later in + * got_bar_config() */ + DLOG("command = %.*s\n", len, val); + asprintf(&config.command, "%.*s", len, val); + return 1; + } + + if (!strcmp(cur_key, "font")) { + DLOG("font = %.*s\n", len, val); + asprintf(&config.fontname, "%.*s", len, val); + return 1; + } + + if (!strcmp(cur_key, "outputs")) { + printf("+output %.*s\n", len, val); + /* XXX: these are not implemented yet */ + return 1; + } + + if (!strcmp(cur_key, "tray_output")) { + printf("tray_output %.*s\n", len, val); + /* XXX: these are not implemented yet */ + return 1; + } + +#define COLOR(json_name, struct_name) \ + do { \ + if (!strcmp(cur_key, #json_name)) { \ + DLOG(#json_name " = " #struct_name " = %.*s\n", len, val); \ + asprintf(&(config.colors.struct_name), "%.*s", len, val); \ + return 1; \ + } \ + } while (0) + + COLOR(statusline, bar_fg); + COLOR(background, bar_bg); + COLOR(focused_workspace_text, focus_ws_fg); + COLOR(focused_workspace_bg, focus_ws_bg); + COLOR(active_workspace_text, active_ws_fg); + COLOR(active_workspace_bg, active_ws_bg); + COLOR(inactive_workspace_text, inactive_ws_fg); + COLOR(inactive_workspace_bg, inactive_ws_bg); + COLOR(urgent_workspace_text, urgent_ws_fg); + COLOR(urgent_workspace_bg, urgent_ws_bg); + + printf("got unexpected string %.*s for cur_key = %s\n", len, val, cur_key); + + return 0; +} + +/* + * Parse a boolean value + * + */ +static int config_boolean_cb(void *params_, int val) { + if (!strcmp(cur_key, "workspace_buttons")) { + DLOG("workspace_buttons = %d\n", val); + config.disable_ws = !val; + return 1; + } + + if (!strcmp(cur_key, "verbose")) { + DLOG("verbose = %d\n", val); + config.verbose = val; + return 1; + } + + return 0; +} + +/* A datastructure to pass all these callbacks to yajl */ +static yajl_callbacks outputs_callbacks = { + NULL, + &config_boolean_cb, + NULL, + NULL, + NULL, + &config_string_cb, + NULL, + &config_map_key_cb, + NULL, + NULL, + NULL +}; + +/* + * Start parsing the received bar configuration json-string + * + */ +void parse_config_json(char *json) { + yajl_handle handle; + yajl_status state; +#if YAJL_MAJOR < 2 + yajl_parser_config parse_conf = { 0, 0 }; + + handle = yajl_alloc(&outputs_callbacks, &parse_conf, NULL, NULL); +#else + handle = yajl_alloc(&outputs_callbacks, NULL, NULL); +#endif + + state = yajl_parse(handle, (const unsigned char*) json, strlen(json)); + + /* FIXME: Proper errorhandling for JSON-parsing */ + switch (state) { + case yajl_status_ok: + break; + case yajl_status_client_canceled: +#if YAJL_MAJOR < 2 + case yajl_status_insufficient_data: +#endif + case yajl_status_error: + ELOG("Could not parse config-reply!\n"); + exit(EXIT_FAILURE); + break; + } + + yajl_free(handle); +} + +/* + * free()s the color strings as soon as they are not needed anymore. + * + */ +void free_colors(struct xcb_color_strings_t *colors) { +#define FREE_COLOR(x) \ + do { \ + if (colors->x) \ + free(colors->x); \ + } while (0) + FREE_COLOR(bar_fg); + FREE_COLOR(bar_bg); + FREE_COLOR(active_ws_fg); + FREE_COLOR(active_ws_bg); + FREE_COLOR(inactive_ws_fg); + FREE_COLOR(inactive_ws_bg); + FREE_COLOR(urgent_ws_fg); + FREE_COLOR(urgent_ws_bg); + FREE_COLOR(focus_ws_fg); + FREE_COLOR(focus_ws_bg); +#undef FREE_COLOR +} + diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index e31de333..5969e5d6 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -114,12 +114,47 @@ void got_output_reply(char *reply) { reconfig_windows(); } +/* + * Called when we get the configuration for our bar instance + * + */ +void got_bar_config(char *reply) { + DLOG("Received bar config \"%s\"\n", reply); + /* We initiate the main-function by requesting infos about the outputs and + * workspaces. Everything else (creating the bars, showing the right workspace- + * buttons and more) is taken care of by the event-drivenness of the code */ + i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); + parse_config_json(reply); + + /* Now we can actually use 'config', so let's subscribe to the appropriate + * events and request the workspaces if necessary. */ + subscribe_events(); + if (!config.disable_ws) + i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); + + /* Initialize the rest of XCB */ + init_xcb_late(config.fontname); + + /* Resolve color strings to colorpixels and save them, then free the strings. */ + init_colors(&(config.colors)); + free_colors(&(config.colors)); + + /* The name of this function is actually misleading. Even if no command is + * specified, this function initiates the watchers to listen on stdin and + * react accordingly */ + start_child(config.command); + FREE(config.command); +} + /* Data-structure to easily call the reply-handlers later */ handler_t reply_handlers[] = { &got_command_reply, &got_workspace_reply, &got_subscribe_reply, &got_output_reply, + NULL, + NULL, + &got_bar_config, }; /* @@ -232,7 +267,8 @@ void got_data(struct ev_loop *loop, ev_io *watcher, int events) { type ^= 1 << 31; event_handlers[type](buffer); } else { - reply_handlers[type](buffer); + if (reply_handlers[type]) + reply_handlers[type](buffer); } FREE(header); diff --git a/i3bar/src/main.c b/i3bar/src/main.c index bfccb8ed..ea489941 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -19,6 +19,7 @@ #include #include "common.h" +#include "libi3.h" /* * Glob path, i.e. expand ~ @@ -39,61 +40,11 @@ char *expand_path(char *path) { return result; } -static void read_color(char **color) { - int len = strlen(optarg); - if (len == 6 || (len == 7 && optarg[0] == '#')) { - int offset = len - 6; - int good = 1, i; - for (i = offset; good && i < 6 + offset; ++i) { - char c = optarg[i]; - if (!(c >= 'a' && c <= 'f') - && !(c >= 'A' && c <= 'F') - && !(c >= '0' && c <= '9')) { - good = 0; - break; - } - } - if (good) { - *color = strdup(optarg + offset); - return; - } - } - - fprintf(stderr, "Bad color value \"%s\"\n", optarg); - exit(EXIT_FAILURE); -} - -static void free_colors(struct xcb_color_strings_t *colors) { -#define FREE_COLOR(x) \ - do { \ - if (colors->x) \ - free(colors->x); \ - } while (0) - FREE_COLOR(bar_fg); - FREE_COLOR(bar_bg); - FREE_COLOR(active_ws_fg); - FREE_COLOR(active_ws_bg); - FREE_COLOR(inactive_ws_fg); - FREE_COLOR(inactive_ws_bg); - FREE_COLOR(urgent_ws_fg); - FREE_COLOR(urgent_ws_bg); - FREE_COLOR(focus_ws_fg); - FREE_COLOR(focus_ws_bg); -#undef FREE_COLOR -} - void print_usage(char *elf_name) { - printf("Usage: %s [-s sock_path] [-c command] [-m|-d[pos]] [-f font] [-V] [-h]\n", elf_name); + printf("Usage: %s [-s sock_path] [-h] [-v]\n", elf_name); printf("-s \tConnect to i3 via \n"); - printf("-c \tExecute to get stdin\n"); - printf("-m\t\tHide the bars, when mod4 is not pressed.\n"); - printf("-d[]\tEnable dockmode. is \"top\" or \"bottom\". Default is bottom\n"); - printf("\t\tIf -c is specified, the childprocess is sent a SIGSTOP on hiding,\n"); - printf("\t\tand a SIGCONT on unhiding of the bars\n"); - printf("-f \tUse X-Core-Font for display\n"); - printf("-w\t\tDisable workspace-buttons\n"); - printf("-V\t\tBe (very) verbose with the debug-output\n"); printf("-h\t\tDisplay this help-message and exit\n"); + printf("-v\t\tDisplay version number and exit\n"); } /* @@ -120,107 +71,33 @@ int main(int argc, char **argv) { int opt; int option_index = 0; char *socket_path = getenv("I3SOCK"); - char *command = NULL; - char *fontname = NULL; char *i3_default_sock_path = "/tmp/i3-ipc.sock"; - struct xcb_color_strings_t colors = { NULL, }; - /* Definition of the standard-config */ - config.hide_on_modifier = 0; - config.dockpos = DOCKPOS_NONE; - config.disable_ws = 0; + /* Initialize the standard config to use 0 as default */ + memset(&config, '\0', sizeof(config_t)); static struct option long_opt[] = { { "socket", required_argument, 0, 's' }, - { "command", required_argument, 0, 'c' }, - { "hide", no_argument, 0, 'm' }, - { "dock", optional_argument, 0, 'd' }, - { "font", required_argument, 0, 'f' }, - { "nows", no_argument, 0, 'w' }, + { "bar_id", required_argument, 0, 0 }, { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'v' }, - { "verbose", no_argument, 0, 'V' }, - { "color-bar-fg", required_argument, 0, 'A' }, - { "color-bar-bg", required_argument, 0, 'B' }, - { "color-active-ws-fg", required_argument, 0, 'C' }, - { "color-active-ws-bg", required_argument, 0, 'D' }, - { "color-inactive-ws-fg", required_argument, 0, 'E' }, - { "color-inactive-ws-bg", required_argument, 0, 'F' }, - { "color-urgent-ws-bg", required_argument, 0, 'G' }, - { "color-urgent-ws-fg", required_argument, 0, 'H' }, - { "color-focus-ws-bg", required_argument, 0, 'I' }, - { "color-focus-ws-fg", required_argument, 0, 'J' }, { NULL, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "s:c:d::mf:whvVA:B:C:D:E:F:G:H:I:J:", long_opt, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "s:hv", long_opt, &option_index)) != -1) { switch (opt) { case 's': socket_path = expand_path(optarg); break; - case 'c': - command = strdup(optarg); - break; - case 'm': - config.hide_on_modifier = 1; - break; - case 'd': - config.hide_on_modifier = 0; - if (optarg == NULL) { - config.dockpos = DOCKPOS_BOT; - break; - } - if (!strcmp(optarg, "top")) { - config.dockpos = DOCKPOS_TOP; - } else if (!strcmp(optarg, "bottom")) { - config.dockpos = DOCKPOS_BOT; - } else { - print_usage(argv[0]); - exit(EXIT_FAILURE); - } - break; - case 'f': - fontname = strdup(optarg); - break; - case 'w': - config.disable_ws = 1; - break; case 'v': printf("i3bar version " I3_VERSION " © 2010-2011 Axel Wagner and contributors\n"); exit(EXIT_SUCCESS); break; - case 'V': - config.verbose = 1; - break; - case 'A': - read_color(&colors.bar_fg); - break; - case 'B': - read_color(&colors.bar_bg); - break; - case 'C': - read_color(&colors.active_ws_fg); - break; - case 'D': - read_color(&colors.active_ws_bg); - break; - case 'E': - read_color(&colors.inactive_ws_fg); - break; - case 'F': - read_color(&colors.inactive_ws_bg); - break; - case 'G': - read_color(&colors.urgent_ws_bg); - break; - case 'H': - read_color(&colors.urgent_ws_fg); - break; - case 'I': - read_color(&colors.focus_ws_bg); - break; - case 'J': - read_color(&colors.focus_ws_fg); + case 0: + if (!strcmp(long_opt[option_index].name, "bar_id")) { + FREE(config.bar_id); + config.bar_id = sstrdup(optarg); + } break; default: print_usage(argv[0]); @@ -229,26 +106,16 @@ int main(int argc, char **argv) { } } - if (fontname == NULL) { - /* This is a very restrictive default. More sensefull would be something like - * "-misc-*-*-*-*--*-*-*-*-*-*-*-*". But since that produces very ugly results - * on my machine, let's stick with this until we have a configfile */ - fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1"; - } - - if (config.dockpos != DOCKPOS_NONE) { - if (config.hide_on_modifier) { - ELOG("--dock and --hide are mutually exclusive!\n"); - exit(EXIT_FAILURE); - } - } else { - config.hide_on_modifier = 1; + if (!config.bar_id) { + /* TODO: maybe we want -f which will automatically ask i3 for the first + * configured bar (and error out if there are too many)? */ + ELOG("No bar_id passed. Please let i3 start i3bar or specify --bar_id\n"); + exit(EXIT_FAILURE); } main_loop = ev_default_loop(0); - init_colors(&colors); - char *atom_sock_path = init_xcb(fontname); + char *atom_sock_path = init_xcb_early(); if (socket_path == NULL) { socket_path = atom_sock_path; @@ -259,27 +126,12 @@ int main(int argc, char **argv) { socket_path = expand_path(i3_default_sock_path); } - free_colors(&colors); - init_outputs(); if (init_connection(socket_path)) { - /* We subscribe to the i3-events we need */ - subscribe_events(); - - /* We initiate the main-function by requesting infos about the outputs and - * workspaces. Everything else (creating the bars, showing the right workspace- - * buttons and more) is taken care of by the event-driveniness of the code */ - i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); - if (!config.disable_ws) { - i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); - } + /* Request the bar configuration. When it arrives, we fill the config array. */ + i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_BAR_CONFIG, config.bar_id); } - /* The name of this function is actually misleading. Even if no -c is specified, - * this function initiates the watchers to listen on stdin and react accordingly */ - start_child(command); - FREE(command); - /* We listen to SIGTERM/QUIT/INT and try to exit cleanly, by stopping the main-loop. * We only need those watchers on the stack, so putting them on the stack saves us * some calls to free() */ diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 4bbc8da7..471209c7 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -790,10 +790,11 @@ void xkb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { } /* - * Initialize xcb and use the specified fontname for text-rendering + * Early initialization of the connection to X11: Everything which does not + * depend on 'config'. * */ -char *init_xcb(char *fontname) { +char *init_xcb_early() { /* FIXME: xcb_connect leaks Memory */ xcb_connection = xcb_connect(NULL, &screen); if (xcb_connection_has_error(xcb_connection)) { @@ -809,66 +810,10 @@ char *init_xcb(char *fontname) { xcb_screen = xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)).data; xcb_root = xcb_screen->root; - /* We load and allocate the font */ - xcb_font = xcb_generate_id(xcb_connection); - xcb_void_cookie_t open_font_cookie; - open_font_cookie = xcb_open_font_checked(xcb_connection, - xcb_font, - strlen(fontname), - fontname); - - /* We need to save info about the font, because we need the font's height and - * information about the width of characters */ - xcb_query_font_cookie_t query_font_cookie; - query_font_cookie = xcb_query_font(xcb_connection, - xcb_font); - - /* To grab modifiers without blocking other applications from receiving key-events - * involving that modifier, we sadly have to use xkb which is not yet fully supported - * in xcb */ - if (config.hide_on_modifier) { - int xkb_major, xkb_minor, xkb_errbase, xkb_err; - xkb_major = XkbMajorVersion; - xkb_minor = XkbMinorVersion; - - xkb_dpy = XkbOpenDisplay(NULL, - &xkb_event_base, - &xkb_errbase, - &xkb_major, - &xkb_minor, - &xkb_err); - - if (xkb_dpy == NULL) { - ELOG("No XKB!\n"); - exit(EXIT_FAILURE); - } - - if (fcntl(ConnectionNumber(xkb_dpy), F_SETFD, FD_CLOEXEC) == -1) { - ELOG("Could not set FD_CLOEXEC on xkbdpy: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - - int i1; - if (!XkbQueryExtension(xkb_dpy, &i1, &xkb_event_base, &xkb_errbase, &xkb_major, &xkb_minor)) { - ELOG("XKB not supported by X-server!\n"); - exit(EXIT_FAILURE); - } - - if (!XkbSelectEvents(xkb_dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask)) { - ELOG("Could not grab Key!\n"); - exit(EXIT_FAILURE); - } - - xkb_io = malloc(sizeof(ev_io)); - ev_io_init(xkb_io, &xkb_io_cb, ConnectionNumber(xkb_dpy), EV_READ); - ev_io_start(main_loop, xkb_io); - XFlush(xkb_dpy); - } - /* We draw the statusline to a seperate pixmap, because it looks the same on all bars and * this way, we can choose to crop it */ uint32_t mask = XCB_GC_FOREGROUND; - uint32_t vals[3] = { colors.bar_bg, colors.bar_bg, xcb_font }; + uint32_t vals[] = { colors.bar_bg, colors.bar_bg }; statusline_clear = xcb_generate_id(xcb_connection); xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection, @@ -877,7 +822,7 @@ char *init_xcb(char *fontname) { mask, vals); - mask |= XCB_GC_BACKGROUND | XCB_GC_FONT; + mask |= XCB_GC_BACKGROUND; vals[0] = colors.bar_fg; statusline_ctx = xcb_generate_id(xcb_connection); xcb_void_cookie_t sl_ctx_cookie = xcb_create_gc_checked(xcb_connection, @@ -931,6 +876,92 @@ char *init_xcb(char *fontname) { } } + + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || + xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || + xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) { + exit(EXIT_FAILURE); + } + + return path; +} + +/* + * Initialization which depends on 'config' being usable. Called after the + * configuration has arrived. + * + */ +void init_xcb_late(char *fontname) { + if (fontname == NULL) { + /* This is a very restrictive default. More sensefull would be something like + * "-misc-*-*-*-*--*-*-*-*-*-*-*-*". But since that produces very ugly results + * on my machine, let's stick with this until we have a configfile */ + fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1"; + } + + /* We load and allocate the font */ + xcb_font = xcb_generate_id(xcb_connection); + xcb_void_cookie_t open_font_cookie; + open_font_cookie = xcb_open_font_checked(xcb_connection, + xcb_font, + strlen(fontname), + fontname); + + /* We need to save info about the font, because we need the font's height and + * information about the width of characters */ + xcb_query_font_cookie_t query_font_cookie; + query_font_cookie = xcb_query_font(xcb_connection, + xcb_font); + + xcb_change_gc(xcb_connection, + statusline_ctx, + XCB_GC_FONT, + (uint32_t[]){ xcb_font }); + + xcb_flush(xcb_connection); + + /* To grab modifiers without blocking other applications from receiving key-events + * involving that modifier, we sadly have to use xkb which is not yet fully supported + * in xcb */ + if (config.hide_on_modifier) { + int xkb_major, xkb_minor, xkb_errbase, xkb_err; + xkb_major = XkbMajorVersion; + xkb_minor = XkbMinorVersion; + + xkb_dpy = XkbOpenDisplay(NULL, + &xkb_event_base, + &xkb_errbase, + &xkb_major, + &xkb_minor, + &xkb_err); + + if (xkb_dpy == NULL) { + ELOG("No XKB!\n"); + exit(EXIT_FAILURE); + } + + if (fcntl(ConnectionNumber(xkb_dpy), F_SETFD, FD_CLOEXEC) == -1) { + ELOG("Could not set FD_CLOEXEC on xkbdpy: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + int i1; + if (!XkbQueryExtension(xkb_dpy, &i1, &xkb_event_base, &xkb_errbase, &xkb_major, &xkb_minor)) { + ELOG("XKB not supported by X-server!\n"); + exit(EXIT_FAILURE); + } + + if (!XkbSelectEvents(xkb_dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask)) { + ELOG("Could not grab Key!\n"); + exit(EXIT_FAILURE); + } + + xkb_io = malloc(sizeof(ev_io)); + ev_io_init(xkb_io, &xkb_io_cb, ConnectionNumber(xkb_dpy), EV_READ); + ev_io_start(main_loop, xkb_io); + XFlush(xkb_dpy); + } + /* Now we save the font-infos */ font_info = xcb_query_font_reply(xcb_connection, query_font_cookie, @@ -949,14 +980,6 @@ char *init_xcb(char *fontname) { } DLOG("Calculated Font-height: %d\n", font_height); - - if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || - xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || - xcb_request_failed(sl_ctx_cookie, "Could not allocate statusline-buffer-context")) { - exit(EXIT_FAILURE); - } - - return path; } /*