From: Michael Stapelberg Date: Tue, 28 Jul 2009 11:55:09 +0000 (+0200) Subject: Some little fixes for bapt’s patch, use predict_text_width, support UTF8, pre-render... X-Git-Tag: 3.c~44 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e6198ad6c8474e8c1caf0ab20072a21f48029468;p=i3%2Fi3 Some little fixes for bapt’s patch, use predict_text_width, support UTF8, pre-render workspace names --- diff --git a/include/data.h b/include/data.h index eb4c2fd6..5bca3ae7 100644 --- a/include/data.h +++ b/include/data.h @@ -165,9 +165,12 @@ struct Workspace { /** Number of this workspace, starting from 0 */ int num; - /** Name of the workspave */ + /** Name of the workspace (in UCS-2) */ char *name; + /** Length of the workspace’s name (in glyphs) */ + int name_len; + /** x, y, width, height */ Rect rect; diff --git a/include/workspace.h b/include/workspace.h new file mode 100644 index 00000000..2b41a527 --- /dev/null +++ b/include/workspace.h @@ -0,0 +1,27 @@ +/* + * vim:ts=8:expandtab + * + * i3 - an improved dynamic tiling window manager + * + * © 2009 Michael Stapelberg and contributors + * + * See file LICENSE for license information. + * + */ +#include + +#include "data.h" + +#ifndef _WORKSPACE_H +#define _WORKSPACE_H + +/** + * Sets the name (or just its number) for the given workspace. This has to + * be called for every workspace as the rendering function + * (render_internal_bar) relies on workspace->name and workspace->name_len + * being ready-to-use. + * + */ +void workspace_set_name(Workspace *ws, const char *name); + +#endif diff --git a/include/xcb.h b/include/xcb.h index 694c6c6c..6ae49107 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -157,7 +157,7 @@ void cached_pixmap_prepare(xcb_connection_t *conn, struct Cached_Pixmap *pixmap) * real length (amount of glyphs) using the given font. * */ -int predict_text_width(xcb_connection_t *conn, char *font_pattern, char *text, +int predict_text_width(xcb_connection_t *conn, const char *font_pattern, char *text, int length); #endif diff --git a/src/config.c b/src/config.c index 49c10b10..fc5fa647 100644 --- a/src/config.c +++ b/src/config.c @@ -19,6 +19,7 @@ #include "config.h" #include "xcb.h" #include "table.h" +#include "workspace.h" Config config; @@ -302,28 +303,29 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, char *ws_str = sstrdup(value); char *end = strchr(ws_str, ' '); if (end == NULL) - die("Malformed name, couln't find terminating space\n"); - *end='\0'; + die("Malformed name, couln't find terminating space\n"); + *end = '\0'; /* Strip trailing whitespace */ while (strlen(value) > 0 && value[strlen(value)-1] == ' ') - value[strlen(value)-1] = '\0'; + value[strlen(value)-1] = '\0'; - int ws_num=atoi(ws_str); + int ws_num = atoi(ws_str); - if ( ws_num < 1 || ws_num > 10 ) - die("Malformed name, invalid workspace Number\n"); + if (ws_num < 1 || ws_num > 10) + die("Malformed name, invalid workspace number\n"); /* find the name */ - char *name= value; + char *name = value; name += strlen(ws_str) + 1; - /* if no name reinitialize the name to NULL for reload */ if (name == '\0') { - workspaces[ws_num - 1].name=NULL; - continue; + free(ws_str); + continue; } - workspaces[ws_num - 1].name=sstrdup(name); + + workspace_set_name(&(workspaces[ws_num - 1]), name); + free(ws_str); continue; } @@ -423,6 +425,14 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, free(v->value); free(v); } + + /* Set an empty name for every workspace which got no name */ + for (int i = 0; i < 10; i++) { + if (workspaces[i].name != NULL) + continue; + + workspace_set_name(&(workspaces[i]), NULL); + } return; } diff --git a/src/layout.c b/src/layout.c index 7bc22f1b..2dbcf71c 100644 --- a/src/layout.c +++ b/src/layout.c @@ -434,45 +434,31 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid struct Colortriple *color = (screen->current_workspace == c ? &(config.bar.focused) : &(config.bar.unfocused)); + Workspace *ws = &workspaces[c]; - char *label=NULL; - if ( workspaces[c].name != NULL ) - asprintf(&label, "%d: %s",c+1, workspaces[c].name); - else - asprintf(&label, "%d", c+1); /* Calculate the length of a string in a given font */ + int text_width = predict_text_width(conn, config.font, ws->name, ws->name_len); - xcb_query_text_extents_cookie_t extents_cookie; - xcb_query_text_extents_reply_t *extents_reply; - xcb_char2b_t *chars; - int str_width; - int i; - chars = malloc(strlen(label) * sizeof(xcb_char2b_t)); - for (i=0; iid, - strlen(label), - chars); - extents_reply = xcb_query_text_extents_reply(conn, - extents_cookie, - NULL); - free(chars); - str_width = extents_reply->overall_width; - free(extents_reply); + /* Draw the outer rect */ xcb_draw_rect(conn, screen->bar, screen->bargc, color->border, - drawn, 1, str_width + 8, height - 2); + drawn, /* x */ + 1, /* y */ + text_width + 5 + 5, /* width = text width + 5 px left + 5px right */ + height - 2 /* height = max. height - 1 px upper and 1 px bottom border */); + + /* Draw the background of this rect */ xcb_draw_rect(conn, screen->bar, screen->bargc, color->background, - drawn + 1, 2, str_width + 6, height - 4); + drawn + 1, + 2, + text_width + 4 + 4, + height - 4); xcb_change_gc_single(conn, screen->bargc, XCB_GC_FOREGROUND, color->text); xcb_change_gc_single(conn, screen->bargc, XCB_GC_BACKGROUND, color->background); - xcb_image_text_8(conn, strlen(label), screen->bar, screen->bargc, drawn + 5 /* X */, - font->height + 1 /* Y = baseline of font */, label); - drawn+=str_width+8; - free(label); + xcb_image_text_16(conn, ws->name_len, screen->bar, screen->bargc, drawn + 5 /* X */, + font->height + 1 /* Y = baseline of font */, + (xcb_char2b_t*)ws->name); + drawn += text_width + 12; } LOG("done rendering internal\n"); diff --git a/src/workspace.c b/src/workspace.c new file mode 100644 index 00000000..40a5692a --- /dev/null +++ b/src/workspace.c @@ -0,0 +1,43 @@ +/* + * vim:ts=8:expandtab + * + * i3 - an improved dynamic tiling window manager + * + * © 2009 Michael Stapelberg and contributors + * + * See file LICENSE for license information. + * + * workspace.c: Functions for modifying workspaces + * + */ +#include +#include +#include + +#include "util.h" +#include "data.h" + +/* + * Sets the name (or just its number) for the given workspace. This has to + * be called for every workspace as the rendering function + * (render_internal_bar) relies on workspace->name and workspace->name_len + * being ready-to-use. + * + */ +void workspace_set_name(Workspace *ws, const char *name) { + char *label; + int ret; + + if (name != NULL) + ret = asprintf(&label, "%d: %s", ws->num + 1, name); + else ret = asprintf(&label, "%d", ws->num + 1); + + if (ret == -1) + errx(1, "asprintf() failed"); + + FREE(ws->name); + + ws->name = convert_utf8_to_ucs2(label, &(ws->name_len)); + + free(label); +} diff --git a/src/xcb.c b/src/xcb.c index 62927961..ff0c32d0 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -341,10 +341,10 @@ static xcb_charinfo_t *get_charinfo(int col, int row, xcb_query_font_reply_t *fo * real length (amount of glyphs) using the given font. * */ -int predict_text_width(xcb_connection_t *conn, char *font_pattern, char *text, int length) { +int predict_text_width(xcb_connection_t *conn, const char *font_pattern, char *text, int length) { xcb_query_font_reply_t *font_info; xcb_charinfo_t *table; - int i, width; + int i, width = 0; i3Font *font = load_font(conn, font_pattern); font_info = xcb_query_font_reply(conn, xcb_query_font_unchecked(conn, font->id), NULL);