]> git.sur5r.net Git - i3/i3/commitdiff
Added Unicode-Support
authorAxel Wagner <mail@merovius.de>
Fri, 6 Aug 2010 01:32:05 +0000 (03:32 +0200)
committerAxel Wagner <mail@merovius.de>
Fri, 6 Aug 2010 01:32:05 +0000 (03:32 +0200)
12 files changed:
i3bar/include/common.h
i3bar/include/outputs.h
i3bar/include/ucs2_to_utf8.h [new file with mode: 0644]
i3bar/include/workspaces.h
i3bar/include/xcb.h
i3bar/src/child.c
i3bar/src/ipc.c
i3bar/src/main.c
i3bar/src/outputs.c
i3bar/src/ucs2_to_utf8.c [new file with mode: 0644]
i3bar/src/workspaces.c
i3bar/src/xcb.c

index 3feab6982ebea90ca9c4df28e5d72a553e749475..b77ac8ea94c99d629741529405d11513661c56e1 100644 (file)
@@ -22,5 +22,6 @@ struct rect_t {
 #include "util.h"
 #include "workspaces.h"
 #include "xcb.h"
+#include "ucs2_to_utf8.h"
 
 #endif
index b00a93b4c100c53fbc235ffc98b86f8c7985f5ed..64fa8563ce49c9537ed626eb34914afd09458d53 100644 (file)
@@ -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 (file)
index 0000000..2fb3862
--- /dev/null
@@ -0,0 +1 @@
+char *convert_utf8_to_ucs2(char *input, int *real_strlen);
index ae3c130337b1b25e0ff0d069c97ca2264ecd0944..e32e7c21a4521f4de98d943d20c7c179267e9861 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef WORKSPACES_H_
 #define WORKSPACES_H_
 
+#include <xcb/xproto.h>
+
 #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;
index a75b715408fa831a1b15d25d4dca0977a9e16a09..7bc76e6267ddeb7a8e045b6c8cb8385af6fc60cc 100644 (file)
@@ -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
index 5fe9ca8c6f2f9486880ea8dc29fd1b06f10fa645..362a56d464bde42e9863edc2c6dac3a9594cdf09 100644 (file)
@@ -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();
 }
index 4b17a4bcad6901ba915f37017b87bd45e546990e..271cd3398f7fd6ca9de6cc9d1772be22e2cab018 100644 (file)
@@ -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[] = {
index 6ce7a38ae5e14e6dd4f0fa8d3b9aa5133e6549b1..62f4974ecf9807fae537318209de24708a398e47 100644 (file)
@@ -5,21 +5,73 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <ev.h>
+#include <getopt.h>
 
 #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 <socket_path>: Connect to i3 via <socket_path>\n");
+                printf("-c <command>: Execute <command> to get sdtin\n");
+                printf("-f <font>: Use X-Core-Font <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);
 
index dc61cb47117d0445769702b4464fd051e2eca777..96f7d55fdaeb956854d8c5a24f650bb53d82868c 100644 (file)
@@ -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 (file)
index 0000000..8c79c3f
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <iconv.h>
+
+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;
+}
index abc3a572530a6e5613183fbaf6659e42bd1895ff..f4df044420357ae8005b57e6e9ea3396dfe17678 100644 (file)
@@ -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));
index 154af575d6df5fab995094a7f01e1983f5bc9497..dc227355a3c3b187c7076b6a76f81b6c80299f99 100644 (file)
@@ -1,4 +1,6 @@
 #include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#include <xcb/xcb_event.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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;
         }