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.
This commit is contained in:
Michael Stapelberg 2011-10-19 22:58:19 +01:00
parent 15bface10d
commit a5be27cb79
6 changed files with 388 additions and 240 deletions

View 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

View 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

214
i3bar/src/config.c Normal file
View File

@ -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
}

View 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);

View 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() */

View 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;
}
/*