#include <xcb/xcb.h>
#include <xcb/xproto.h>
#include <xcb/xcb_atom.h>
+#include <xcb/xcb_aux.h>
#ifdef XCB_COMPAT
#include "xcb_compat.h"
*
*/
void refresh_statusline() {
- size_t glyph_count;
+ struct status_block *block;
- if (statusline == NULL) {
- return;
+ uint32_t old_statusline_width = statusline_width;
+ statusline_width = 0;
+
+ /* Convert all blocks from UTF-8 to UCS-2 and predict the text width (in
+ * pixels). */
+ TAILQ_FOREACH(block, &statusline_head, blocks) {
+ block->ucs2_full_text = (xcb_char2b_t*)convert_utf8_to_ucs2(block->full_text, &(block->glyph_count_full_text));
+ block->width = predict_text_width((char*)block->ucs2_full_text, block->glyph_count_full_text, true);
+ /* If this is not the last block, add some pixels for a separator. */
+ if (TAILQ_NEXT(block, blocks) != NULL)
+ block->width += 9;
+ statusline_width += block->width;
}
- xcb_char2b_t *text = (xcb_char2b_t*)convert_utf8_to_ucs2(statusline, &glyph_count);
- uint32_t old_statusline_width = statusline_width;
- statusline_width = predict_text_width((char*)text, glyph_count, true);
/* If the statusline is bigger than our screen we need to make sure that
* the pixmap provides enough space, so re-allocate if the width grew */
if (statusline_width > xcb_screen->width_in_pixels &&
statusline_width > old_statusline_width)
realloc_sl_buffer();
+ /* Clear the statusline pixmap. */
xcb_rectangle_t rect = { 0, 0, xcb_screen->width_in_pixels, font.height };
xcb_poly_fill_rectangle(xcb_connection, statusline_pm, statusline_clear, 1, &rect);
- set_font_colors(statusline_ctx, colors.bar_fg, colors.bar_bg);
- draw_text((char*)text, glyph_count, true, statusline_pm, statusline_ctx,
- 0, 0, xcb_screen->width_in_pixels);
- FREE(text);
+ /* Draw the text of each block. */
+ uint32_t x = 0;
+ TAILQ_FOREACH(block, &statusline_head, blocks) {
+ uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg);
+ set_font_colors(statusline_ctx, colorpixel, colors.bar_bg);
+ draw_text((char*)block->ucs2_full_text, block->glyph_count_full_text,
+ true, statusline_pm, statusline_ctx, x, 0, block->width);
+ x += block->width;
+
+ if (TAILQ_NEXT(block, blocks) != NULL) {
+ /* This is not the last block, draw a separator. */
+ set_font_colors(statusline_ctx, get_colorpixel("#666666"), colors.bar_bg);
+ xcb_poly_line(xcb_connection, XCB_COORD_MODE_ORIGIN, statusline_pm,
+ statusline_ctx, 2,
+ (xcb_point_t[]){ { x - 5, 2 }, { x - 5, font.height - 2 } });
+ }
+
+ FREE(block->ucs2_full_text);
+ }
}
/*
* and set cur_ws accordingly */
TAILQ_FOREACH(cur_ws, walk->workspaces, tailq) {
DLOG("x = %d\n", x);
- if (x < cur_ws->name_width + 10) {
+ if (x >= 0 && x < cur_ws->name_width + 10) {
break;
}
- x -= cur_ws->name_width + 10;
+ x -= cur_ws->name_width + 11;
}
if (cur_ws == NULL) {
return;
break;
}
- const size_t len = strlen(cur_ws->name) + strlen("workspace \"\"") + 1;
- char buffer[len];
- snprintf(buffer, len, "workspace \"%s\"", cur_ws->name);
+ /* To properly handle workspace names with double quotes in them, we need
+ * to escape the double quotes. Unfortunately, that’s rather ugly in C: We
+ * first count the number of double quotes, then we allocate a large enough
+ * buffer, then we copy character by character. */
+ int num_quotes = 0;
+ size_t namelen = 0;
+ for (char *walk = cur_ws->name; *walk != '\0'; walk++) {
+ if (*walk == '"')
+ num_quotes++;
+ /* While we’re looping through the name anyway, we can save one
+ * strlen(). */
+ namelen++;
+ }
+
+ const size_t len = namelen + strlen("workspace \"\"") + 1;
+ char *buffer = scalloc(len+num_quotes);
+ strncpy(buffer, "workspace \"", strlen("workspace \""));
+ int inpos, outpos;
+ for (inpos = 0, outpos = strlen("workspace \"");
+ inpos < namelen;
+ inpos++, outpos++) {
+ if (cur_ws->name[inpos] == '"') {
+ buffer[outpos] = '\\';
+ outpos++;
+ }
+ buffer[outpos] = cur_ws->name[inpos];
+ }
+ buffer[outpos] = '"';
i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, buffer);
+ free(buffer);
}
/*
bool map_it = true;
int xe_version = 1;
xcb_get_property_cookie_t xembedc;
- xembedc = xcb_get_property_unchecked(xcb_connection,
- 0,
- client,
- atoms[_XEMBED_INFO],
- XCB_GET_PROPERTY_TYPE_ANY,
- 0,
- 2 * 32);
+ xcb_generic_error_t *error;
+ xembedc = xcb_get_property(xcb_connection,
+ 0,
+ client,
+ atoms[_XEMBED_INFO],
+ XCB_GET_PROPERTY_TYPE_ANY,
+ 0,
+ 2 * 32);
xcb_get_property_reply_t *xembedr = xcb_get_property_reply(xcb_connection,
xembedc,
- NULL);
+ &error);
+ if (error != NULL) {
+ ELOG("Error getting _XEMBED_INFO property: error_code %d\n",
+ error->error_code);
+ free(error);
+ return;
+ }
if (xembedr != NULL && xembedr->length != 0) {
DLOG("xembed format = %d, len = %d\n", xembedr->format, xembedr->length);
uint32_t *xembed = xcb_get_property_value(xembedr);
#define ATOM_DO(name) atom_cookies[name] = xcb_intern_atom(xcb_connection, 0, strlen(#name), #name);
#include "xcb_atoms.def"
- xcb_screen = xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)).data;
+ xcb_screen = xcb_aux_get_screen(xcb_connection, screen);
xcb_root = xcb_screen->root;
/* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
1,
&rect);
- if (statusline != NULL) {
+ if (!TAILQ_EMPTY(&statusline_head)) {
DLOG("Printing statusline!\n");
/* Luckily we already prepared a seperate pixmap containing the rendered
i3_ws *ws_walk;
TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) {
- DLOG("Drawing Button for WS %s at x = %d\n", ws_walk->name, i);
+ DLOG("Drawing Button for WS %s at x = %d, len = %d\n", ws_walk->name, i, ws_walk->name_width);
uint32_t fg_color = colors.inactive_ws_fg;
uint32_t bg_color = colors.inactive_ws_bg;
uint32_t border_color = colors.inactive_ws_border;
outputs_walk->bargc,
mask,
vals_border);
- xcb_rectangle_t rect_border = { i + 1, 0, ws_walk->name_width + 10, font.height + 4 };
+ xcb_rectangle_t rect_border = { i, 0, ws_walk->name_width + 10, font.height + 4 };
xcb_poly_fill_rectangle(xcb_connection,
outputs_walk->buffer,
outputs_walk->bargc,
outputs_walk->bargc,
mask,
vals);
- xcb_rectangle_t rect = { i + 2, 1, ws_walk->name_width + 8, font.height + 2 };
+ xcb_rectangle_t rect = { i + 1, 1, ws_walk->name_width + 8, font.height + 2 };
xcb_poly_fill_rectangle(xcb_connection,
outputs_walk->buffer,
outputs_walk->bargc,
&rect);
set_font_colors(outputs_walk->bargc, fg_color, bg_color);
draw_text((char*)ws_walk->ucs2_name, ws_walk->name_glyphs, true,
- outputs_walk->buffer, outputs_walk->bargc, i + 6, 2, ws_walk->name_width);
- i += 12 + ws_walk->name_width;
+ outputs_walk->buffer, outputs_walk->bargc, i + 5, 2, ws_walk->name_width);
+ i += 10 + ws_walk->name_width + 1;
}
i = 0;