From 1daa395a77bf3a3f8e8467518b479fc16e060784 Mon Sep 17 00:00:00 2001 From: Axel Wagner Date: Fri, 6 Aug 2010 03:32:05 +0200 Subject: [PATCH] Added Unicode-Support --- i3bar/include/common.h | 1 + i3bar/include/outputs.h | 1 + i3bar/include/ucs2_to_utf8.h | 1 + i3bar/include/workspaces.h | 4 + i3bar/include/xcb.h | 4 +- i3bar/src/child.c | 67 ++++++++------- i3bar/src/ipc.c | 8 +- i3bar/src/main.c | 58 ++++++++++++- i3bar/src/outputs.c | 48 +++++++---- i3bar/src/ucs2_to_utf8.c | 103 +++++++++++++++++++++++ i3bar/src/workspaces.c | 50 +++++++----- i3bar/src/xcb.c | 154 ++++++++++++++++++++--------------- 12 files changed, 355 insertions(+), 144 deletions(-) create mode 100644 i3bar/include/ucs2_to_utf8.h create mode 100644 i3bar/src/ucs2_to_utf8.c diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 3feab698..b77ac8ea 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -22,5 +22,6 @@ struct rect_t { #include "util.h" #include "workspaces.h" #include "xcb.h" +#include "ucs2_to_utf8.h" #endif diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index b00a93b4..64fa8563 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -11,6 +11,7 @@ SLIST_HEAD(outputs_head, i3_output); struct outputs_head *outputs; void parse_outputs_json(char* json); +void init_outputs(); void free_outputs(); i3_output* get_output_by_name(char* name); diff --git a/i3bar/include/ucs2_to_utf8.h b/i3bar/include/ucs2_to_utf8.h new file mode 100644 index 00000000..2fb3862a --- /dev/null +++ b/i3bar/include/ucs2_to_utf8.h @@ -0,0 +1 @@ +char *convert_utf8_to_ucs2(char *input, int *real_strlen); diff --git a/i3bar/include/workspaces.h b/i3bar/include/workspaces.h index ae3c1303..e32e7c21 100644 --- a/i3bar/include/workspaces.h +++ b/i3bar/include/workspaces.h @@ -1,6 +1,8 @@ #ifndef WORKSPACES_H_ #define WORKSPACES_H_ +#include + #include "common.h" typedef struct i3_ws i3_ws; @@ -13,6 +15,8 @@ void free_workspaces(); struct i3_ws { int num; char *name; + xcb_char2b_t *ucs2_name; + int name_glyphs; int name_width; bool visible; bool focused; diff --git a/i3bar/include/xcb.h b/i3bar/include/xcb.h index a75b7154..7bc76e62 100644 --- a/i3bar/include/xcb.h +++ b/i3bar/include/xcb.h @@ -7,8 +7,8 @@ void init_xcb(); void clean_xcb(); void get_atoms(); void destroy_windows(); -void create_windows(); +void reconfig_windows(); void draw_bars(); -int get_string_width(char *string); +int get_string_width(xcb_char2b_t *string, int glyph_len); #endif diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 5fe9ca8c..362a56d4 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -81,7 +81,7 @@ void child_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { strip_dzen_formats(buffer); FREE(statusline); statusline = buffer; - printf("%s", buffer); + printf("%s\n", buffer); draw_bars(); } @@ -91,45 +91,52 @@ void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) { } void start_child(char *command) { - int fd[2]; - pipe(fd); - child_pid = fork(); - switch (child_pid) { - case -1: - printf("ERROR: Couldn't fork()"); - exit(EXIT_FAILURE); - case 0: - close(fd[0]); + child_pid = 0; + if (command != NULL) { + int fd[2]; + pipe(fd); + child_pid = fork(); + switch (child_pid) { + case -1: + printf("ERROR: Couldn't fork()"); + exit(EXIT_FAILURE); + case 0: + close(fd[0]); + + dup2(fd[1], STDOUT_FILENO); - dup2(fd[1], STDOUT_FILENO); + static const char *shell = NULL; - static const char *shell = NULL; + if ((shell = getenv("SHELL")) == NULL) + shell = "/bin/sh"; - if ((shell = getenv("SHELL")) == NULL) - shell = "/bin/sh"; + execl(shell, shell, "-c", command, (char*) NULL); + return; + default: + close(fd[1]); - execl(shell, shell, "-c", command, (char*) NULL); - break; - default: - close(fd[1]); + dup2(fd[0], STDIN_FILENO); + + break; + } + } - dup2(fd[0], STDIN_FILENO); - fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); - child_io = malloc(sizeof(ev_io)); - ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ); - ev_io_start(main_loop, child_io); + child_io = malloc(sizeof(ev_io)); + ev_io_init(child_io, &child_io_cb, STDIN_FILENO, EV_READ); + ev_io_start(main_loop, child_io); - /* We must cleanup, if the child unexpectedly terminates */ - child_sig = malloc(sizeof(ev_io)); - ev_child_init(child_sig, &child_sig_cb, child_pid, 0); - ev_child_start(main_loop, child_sig); + /* We must cleanup, if the child unexpectedly terminates */ + child_sig = malloc(sizeof(ev_io)); + ev_child_init(child_sig, &child_sig_cb, child_pid, 0); + ev_child_start(main_loop, child_sig); - break; - } } void kill_child() { - kill(child_pid, SIGQUIT); + if (child_pid != 0) { + kill(child_pid, SIGQUIT); + } cleanup(); } diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index 4b17a4bc..271cd339 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -47,12 +47,10 @@ void got_subscribe_reply(char *reply) { } void got_output_reply(char *reply) { - printf("Got Outputs-Data!\nDestroying Windows...\n"); - destroy_windows(); - printf("Parsing JSON...\n"); + printf("Parsing Outputs-JSON...\n"); parse_outputs_json(reply); - printf("Creating_Windows...\n"); - create_windows(); + printf("Reconfiguring Windows...\n"); + reconfig_windows(); } handler_t reply_handlers[] = { diff --git a/i3bar/src/main.c b/i3bar/src/main.c index 6ce7a38a..62f4974e 100644 --- a/i3bar/src/main.c +++ b/i3bar/src/main.c @@ -5,21 +5,73 @@ #include #include #include +#include #include "common.h" +char *i3_default_sock_path = "/home/mero/.i3/ipc.sock"; + int main(int argc, char **argv) { + int opt; + int option_index = 0; + char *socket_path = NULL; + char *command = NULL; + char *fontname = NULL; + + static struct option long_opt[] = { + { "socket", required_argument, 0, 's' }, + { "command", required_argument, 0, 'c' }, + { "font", required_argument, 0, 'f' }, + { "help", no_argument, 0, 'h' }, + { NULL, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "s:c:f:h", long_opt, &option_index)) != -1) { + switch (opt) { + case 's': + socket_path = malloc(strlen(optarg)); + strcpy(socket_path, optarg); + break; + case 'c': + command = malloc(strlen(optarg)); + strcpy(command, optarg); + break; + case 'f': + fontname = malloc(strlen(optarg)); + strcpy(socket_path, optarg); + break; + default: + printf("Usage: %s [-s socket_path] [-c command] [-f font] [-h]\n", argv[0]); + printf("-s : Connect to i3 via \n"); + printf("-c : Execute to get sdtin\n"); + printf("-f : Use X-Core-Font for display\n"); + printf("-h: Display this help-message and exit\n"); + exit(EXIT_SUCCESS); + break; + } + } + + if (fontname == NULL) { + fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1"; + } + + if (socket_path == NULL) { + printf("No Socket Path Specified, default to %s\n", i3_default_sock_path); + socket_path = i3_default_sock_path; + } + main_loop = ev_default_loop(0); - init_xcb(); - init_connection("/home/mero/.i3/ipc.sock"); + init_xcb(fontname); + init_outputs(); + init_connection(socket_path); subscribe_events(); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_OUTPUTS, NULL); i3_send_msg(I3_IPC_MESSAGE_TYPE_GET_WORKSPACES, NULL); - start_child("i3status"); + start_child(command); ev_loop(main_loop, 0); diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index dc61cb47..96f7d55f 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -11,6 +11,7 @@ struct outputs_json_params { i3_output *outputs_walk; char *cur_key; char *json; + bool init; }; static int outputs_null_cb(void *params_) { @@ -82,9 +83,11 @@ static int outputs_string_cb(void *params_, const unsigned char *val, unsigned i return 0; } - params->outputs_walk->name = malloc(sizeof(const unsigned char) * (len + 1)); - strncpy(params->outputs_walk->name, (const char*) val, len); - params->outputs_walk->name[len] = '\0'; + char *name = malloc(sizeof(const unsigned char) * (len + 1)); + strncpy(name, (const char*) val, len); + name[len] = '\0'; + + params->outputs_walk->name = name; FREE(params->cur_key); @@ -105,9 +108,7 @@ static int outputs_start_map_cb(void *params_) { new_output->workspaces = malloc(sizeof(struct ws_head)); TAILQ_INIT(new_output->workspaces); - SLIST_INSERT_HEAD(params->outputs, new_output, slist); - - params->outputs_walk = SLIST_FIRST(params->outputs); + params->outputs_walk = new_output; return 1; } @@ -115,6 +116,20 @@ static int outputs_start_map_cb(void *params_) { return 1; } +static int outputs_end_map_cb(void *params_) { + struct outputs_json_params *params = (struct outputs_json_params*) params_; + + i3_output *target = get_output_by_name(params->outputs_walk->name); + + if (target == NULL) { + SLIST_INSERT_HEAD(outputs, params->outputs_walk, slist); + } else { + target->ws = params->outputs_walk->ws; + target->rect = params->outputs_walk->rect; + } + return 1; +} + static int outputs_map_key_cb(void *params_, const unsigned char *keyVal, unsigned int keyLen) { struct outputs_json_params *params = (struct outputs_json_params*) params_; FREE(params->cur_key); @@ -135,18 +150,18 @@ yajl_callbacks outputs_callbacks = { &outputs_string_cb, &outputs_start_map_cb, &outputs_map_key_cb, - NULL, + &outputs_end_map_cb, NULL, NULL }; +void init_outputs() { + outputs = malloc(sizeof(struct outputs_head)); + SLIST_INIT(outputs); +} + void parse_outputs_json(char *json) { - /* FIXME: Fasciliate stream-processing, i.e. allow starting to interpret - * JSON in chunks */ struct outputs_json_params params; - printf(json); - params.outputs = malloc(sizeof(struct outputs_head)); - SLIST_INIT(params.outputs); params.outputs_walk = NULL; params.cur_key = NULL; @@ -173,16 +188,13 @@ void parse_outputs_json(char *json) { } yajl_free(handle); - - if (outputs != NULL) { - FREE_SLIST(outputs, i3_output); - } - - outputs = params.outputs; } i3_output *get_output_by_name(char *name) { i3_output *walk; + if (name == NULL) { + return NULL; + } SLIST_FOREACH(walk, outputs, slist) { if (!strcmp(walk->name, name)) { break; diff --git a/i3bar/src/ucs2_to_utf8.c b/i3bar/src/ucs2_to_utf8.c new file mode 100644 index 00000000..8c79c3f9 --- /dev/null +++ b/i3bar/src/ucs2_to_utf8.c @@ -0,0 +1,103 @@ +/* + * vim:ts=8:expandtab + * + * i3 - an improved dynamic tiling window manager + * + * © 2009 Michael Stapelberg and contributors + * + * See file LICENSE for license information. + * + */ +#include +#include +#include +#include +#include + +static iconv_t conversion_descriptor = 0; +static iconv_t conversion_descriptor2 = 0; + +/* + * Returns the input string, but converted from UCS-2 to UTF-8. Memory will be + * allocated, thus the caller has to free the output. + * + */ +char *convert_ucs_to_utf8(char *input) { + size_t input_size = 2; + /* UTF-8 may consume up to 4 byte */ + int buffer_size = 8; + + char *buffer = calloc(buffer_size, 1); + if (buffer == NULL) + err(EXIT_FAILURE, "malloc() failed\n"); + size_t output_size = buffer_size; + /* We need to use an additional pointer, because iconv() modifies it */ + char *output = buffer; + + /* We convert the input into UCS-2 big endian */ + if (conversion_descriptor == 0) { + conversion_descriptor = iconv_open("UTF-8", "UCS-2BE"); + if (conversion_descriptor == 0) { + fprintf(stderr, "error opening the conversion context\n"); + exit(1); + } + } + + /* Get the conversion descriptor back to original state */ + iconv(conversion_descriptor, NULL, NULL, NULL, NULL); + + /* Convert our text */ + int rc = iconv(conversion_descriptor, (void*)&input, &input_size, &output, &output_size); + if (rc == (size_t)-1) { + perror("Converting to UCS-2 failed"); + return NULL; + } + + return buffer; +} + +/* + * Converts the given string to UCS-2 big endian for use with + * xcb_image_text_16(). The amount of real glyphs is stored in real_strlen, + * a buffer containing the UCS-2 encoded string (16 bit per glyph) is + * returned. It has to be freed when done. + * + */ +char *convert_utf8_to_ucs2(char *input, int *real_strlen) { + size_t input_size = strlen(input) + 1; + /* UCS-2 consumes exactly two bytes for each glyph */ + int buffer_size = input_size * 2; + + char *buffer = malloc(buffer_size); + if (buffer == NULL) + err(EXIT_FAILURE, "malloc() failed\n"); + size_t output_size = buffer_size; + /* We need to use an additional pointer, because iconv() modifies it */ + char *output = buffer; + + /* We convert the input into UCS-2 big endian */ + if (conversion_descriptor2 == 0) { + conversion_descriptor2 = iconv_open("UCS-2BE", "UTF-8"); + if (conversion_descriptor2 == 0) { + fprintf(stderr, "error opening the conversion context\n"); + exit(1); + } + } + + /* Get the conversion descriptor back to original state */ + iconv(conversion_descriptor2, NULL, NULL, NULL, NULL); + + /* Convert our text */ + int rc = iconv(conversion_descriptor2, (void*)&input, &input_size, &output, &output_size); + if (rc == (size_t)-1) { + perror("Converting to UCS-2 failed"); + if (real_strlen != NULL) + *real_strlen = 0; + return NULL; + } + + if (real_strlen != NULL) + *real_strlen = ((buffer_size - output_size) / 2) - 1; + + return buffer; +} diff --git a/i3bar/src/workspaces.c b/i3bar/src/workspaces.c index abc3a572..f4df0444 100644 --- a/i3bar/src/workspaces.c +++ b/i3bar/src/workspaces.c @@ -94,32 +94,38 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne char *output_name; if (!strcmp(params->cur_key, "name")) { - params->workspaces_walk->name = malloc(sizeof(const unsigned char) * (len + 1)); - strncpy(params->workspaces_walk->name, (const char*) val, len); - params->workspaces_walk->name[len] = '\0'; - - params->workspaces_walk->name_width = get_string_width(params->workspaces_walk->name); - - printf("Got Workspace %s, name_width: %d\n", - params->workspaces_walk->name, - params->workspaces_walk->name_width); - FREE(params->cur_key); - - return 1; + params->workspaces_walk->name = malloc(sizeof(const unsigned char) * (len + 1)); + strncpy(params->workspaces_walk->name, (const char*) val, len); + params->workspaces_walk->name[len] = '\0'; + + int ucs2_len; + xcb_char2b_t *ucs2_name = (xcb_char2b_t*) convert_utf8_to_ucs2(params->workspaces_walk->name, &ucs2_len); + params->workspaces_walk->ucs2_name = ucs2_name; + params->workspaces_walk->name_glyphs = ucs2_len; + params->workspaces_walk->name_width = get_string_width(params->workspaces_walk->ucs2_name, + params->workspaces_walk->name_glyphs); + + printf("Got Workspace %s, name_width: %d, glyphs: %d\n", + params->workspaces_walk->name, + params->workspaces_walk->name_width, + params->workspaces_walk->name_glyphs); + FREE(params->cur_key); + + return 1; } if (!strcmp(params->cur_key, "output")) { - output_name = malloc(sizeof(const unsigned char) * (len + 1)); - strncpy(output_name, (const char*) val, len); - output_name[len] = '\0'; - params->workspaces_walk->output = get_output_by_name(output_name); + output_name = malloc(sizeof(const unsigned char) * (len + 1)); + strncpy(output_name, (const char*) val, len); + output_name[len] = '\0'; + params->workspaces_walk->output = get_output_by_name(output_name); - TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces, - params->workspaces_walk, - tailq); + TAILQ_INSERT_TAIL(params->workspaces_walk->output->workspaces, + params->workspaces_walk, + tailq); - free(output_name); - return 1; + FREE(output_name); + return 1; } return 0; @@ -128,7 +134,7 @@ static int workspaces_string_cb(void *params_, const unsigned char *val, unsigne static int workspaces_start_map_cb(void *params_) { struct workspaces_json_params *params = (struct workspaces_json_params*) params_; - i3_ws *new_workspace = NULL; + i3_ws *new_workspace = NULL; if (params->cur_key == NULL) { new_workspace = malloc(sizeof(i3_ws)); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 154af575..dc227355 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -26,6 +28,8 @@ ev_prepare *xcb_prep; ev_check *xcb_chk; ev_io *xcb_io; +xcb_event_handlers_t xcb_event_handlers; + uint32_t get_colorpixel(const char *s) { char strings[3][3] = { { s[0], s[1], '\0'} , { s[2], s[3], '\0'} , @@ -128,14 +132,14 @@ void xcb_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) { * Prepare- and Check-Watchers */ } -int get_string_width(char *string) { +int get_string_width(xcb_char2b_t *string, int glyph_len) { xcb_query_text_extents_cookie_t cookie; xcb_query_text_extents_reply_t *reply; xcb_generic_error_t *error; int width; - cookie = xcb_query_text_extents(xcb_connection, xcb_font, strlen(string), (xcb_char2b_t*) string); - if ((reply= xcb_query_text_extents_reply(xcb_connection, cookie, &error)) == NULL) { + cookie = xcb_query_text_extents(xcb_connection, xcb_font, glyph_len, string); + if ((reply = xcb_query_text_extents_reply(xcb_connection, cookie, &error)) == NULL) { printf("ERROR: Could not get text extents!"); return 7; } @@ -145,7 +149,7 @@ int get_string_width(char *string) { return width; } -void init_xcb() { +void init_xcb(char *fontname) { /* FIXME: xcb_connect leaks Memory */ xcb_connection = xcb_connect(NULL, NULL); if (xcb_connection_has_error(xcb_connection)) { @@ -162,7 +166,6 @@ void init_xcb() { xcb_root = xcb_screens->root; xcb_font = xcb_generate_id(xcb_connection); - char *fontname = "-misc-fixed-medium-r-semicondensed--12-110-75-75-c-60-iso10646-1"; xcb_open_font(xcb_connection, xcb_font, strlen(fontname), @@ -219,67 +222,80 @@ void get_atoms() { printf("Got Atoms\n"); } -void destroy_windows() { - i3_output *walk; - if (outputs == NULL) { +void destroy_window(i3_output *output) { + if (output == NULL) { return; } - SLIST_FOREACH(walk, outputs, slist) { - if (walk->bar == XCB_NONE) { - continue; - } - xcb_destroy_window(xcb_connection, walk->bar); - walk->bar = XCB_NONE; + if (output->bar == XCB_NONE) { + return; } + xcb_destroy_window(xcb_connection, output->bar); + output->bar = XCB_NONE; } -void create_windows() { +void reconfig_windows() { uint32_t mask; - uint32_t values[2]; + uint32_t values[4]; i3_output *walk; SLIST_FOREACH(walk, outputs, slist) { if (!walk->active) { + destroy_window(walk); continue; } - printf("Creating Window for output %s\n", walk->name); - - walk->bar = xcb_generate_id(xcb_connection); - mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; - values[0] = xcb_screens->black_pixel; - values[1] = XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_BUTTON_PRESS; - xcb_create_window(xcb_connection, - xcb_screens->root_depth, + if (walk->bar == XCB_NONE) { + printf("Creating Window for output %s\n", walk->name); + + walk->bar = xcb_generate_id(xcb_connection); + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = xcb_screens->black_pixel; + values[1] = XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_BUTTON_PRESS; + xcb_create_window(xcb_connection, + xcb_screens->root_depth, + walk->bar, + xcb_root, + walk->rect.x, walk->rect.y, + walk->rect.w, font_height + 6, + 1, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + xcb_screens->root_visual, + mask, + values); + + xcb_change_property(xcb_connection, + XCB_PROP_MODE_REPLACE, + walk->bar, + atoms[_NET_WM_WINDOW_TYPE], + atoms[ATOM], + 32, + 1, + (unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]); + + walk->bargc = xcb_generate_id(xcb_connection); + mask = XCB_GC_FONT; + values[0] = xcb_font; + xcb_create_gc(xcb_connection, + walk->bargc, walk->bar, - xcb_root, - walk->rect.x, walk->rect.y, - walk->rect.w, font_height + 6, - 1, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - xcb_screens->root_visual, mask, values); - xcb_change_property(xcb_connection, - XCB_PROP_MODE_REPLACE, - walk->bar, - atoms[_NET_WM_WINDOW_TYPE], - atoms[ATOM], - 32, - 1, - (unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]); - - walk->bargc = xcb_generate_id(xcb_connection); - mask = XCB_GC_FONT; - values[0] = xcb_font; - xcb_create_gc(xcb_connection, - walk->bargc, - walk->bar, - mask, - values); - - xcb_map_window(xcb_connection, walk->bar); + xcb_map_window(xcb_connection, walk->bar); + } else { + mask = XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT; + values[0] = walk->rect.x; + values[1] = walk->rect.y; + values[2] = walk->rect.w; + values[3] = walk->rect.h; + xcb_configure_window(xcb_connection, + walk->bar, + mask, + values); + } } xcb_flush(xcb_connection); } @@ -294,7 +310,7 @@ void draw_bars() { continue; } if (outputs_walk->bar == XCB_NONE) { - create_windows(); + reconfig_windows(); } uint32_t color = get_colorpixel("000000"); xcb_change_gc(xcb_connection, @@ -319,13 +335,23 @@ void draw_bars() { XCB_GC_FOREGROUND, &color); - xcb_image_text_8(xcb_connection, - strlen(statusline), - outputs_walk->bar, - outputs_walk->bargc, - outputs_walk->rect.w - get_string_width(statusline) - 4, - font_height + 1, - statusline); + int glyph_count; + xcb_char2b_t *text = (xcb_char2b_t*) convert_utf8_to_ucs2(statusline, &glyph_count); + + xcb_void_cookie_t cookie; + cookie = xcb_image_text_16(xcb_connection, + glyph_count, + outputs_walk->bar, + outputs_walk->bargc, + outputs_walk->rect.w - get_string_width(text, glyph_count) - 4, + font_height + 1, + (xcb_char2b_t*) text); + + xcb_generic_error_t *err = xcb_request_check(xcb_connection, cookie); + + if (err != NULL) { + printf("XCB-Error: %d\n", err->error_code); + } } i3_ws *ws_walk; TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { @@ -357,12 +383,12 @@ void draw_bars() { outputs_walk->bargc, XCB_GC_FOREGROUND, &color); - xcb_image_text_8(xcb_connection, - strlen(ws_walk->name), - outputs_walk->bar, - outputs_walk->bargc, - i + 5, font_height + 1, - ws_walk->name); + xcb_image_text_16(xcb_connection, + ws_walk->name_glyphs, + outputs_walk->bar, + outputs_walk->bargc, + i + 5, font_height + 1, + ws_walk->ucs2_name); i += 10 + ws_walk->name_width; } -- 2.39.5