]> git.sur5r.net Git - i3/i3/commitdiff
Make i3bar get its config from i3 via IPC
authorMichael Stapelberg <michael@stapelberg.de>
Wed, 19 Oct 2011 21:58:19 +0000 (22:58 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Wed, 19 Oct 2011 21:58:19 +0000 (22:58 +0100)
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.

i3bar/include/config.h
i3bar/include/xcb.h
i3bar/src/config.c [new file with mode: 0644]
i3bar/src/ipc.c
i3bar/src/main.c
i3bar/src/xcb.c

index b3473917dc0fc625f03de43785a38d9b6b69661c..19b246dcface3ebd96ffa77926ca52b32c22ba02 100644 (file)
@@ -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
index c1b7cc14e3575bd98051ddd3040b89af16fd90aa..51da5d3ec7697dc64fcf3c28ee5790bcffe70fe4 100644 (file)
@@ -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 (file)
index 0000000..23c5e12
--- /dev/null
@@ -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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <i3/ipc.h>
+#include <yajl/yajl_parse.h>
+#include <yajl/yajl_version.h>
+
+#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
+}
+
index e31de333b33bbde8486d51c95a2f98c862c2370d..5969e5d68523d57952a636275aaf73176ea241a5 100644 (file)
@@ -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);
index bfccb8edd93c4ec7a4e9fce50d00ecb05c442ef9..ea48994172ef0c8e9bb76a448010ffe6adafbccf 100644 (file)
@@ -19,6 +19,7 @@
 #include <glob.h>
 
 #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 <sock_path>\tConnect to i3 via <sock_path>\n");
-    printf("-c <command>\tExecute <command> to get stdin\n");
-    printf("-m\t\tHide the bars, when mod4 is not pressed.\n");
-    printf("-d[<pos>]\tEnable dockmode. <pos> 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 <font>\tUse X-Core-Font <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() */
index 4bbc8da728764d1e3c6a5c0c7f0b215b95739acb..471209c7c98d3d3a75890eb594a5d38d063e0c14 100644 (file)
@@ -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;
 }
 
 /*