From 1c4100ce5d8f9a7edc46f80f8a20ca50c6d97f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Mon, 5 Oct 2015 12:58:05 +0200 Subject: [PATCH] Use 32-bit visuals for i3bar when possible and allow RGBA colors. This patch creates all necessary windows for i3bar with 32-bit visuals if available. It also introduces the possibility to define RGBA colors (next to RGB colors), which allows the user to set the opacity of any color. This requires running a compositor. With this patch we also start supporting _NET_SYSTEM_TRAY_VISUAL, which is necessary for the tray icons so they create the tray window with the correct depth and visual. --- i3-input/main.c | 4 +- i3-nagbar/main.c | 4 +- i3bar/include/cairo_util.h | 1 + i3bar/src/cairo_util.c | 21 +++++-- i3bar/src/xcb.c | 121 ++++++++++++++++++++++++++++--------- include/libi3.h | 4 +- libi3/font.c | 17 +++--- src/restore_layout.c | 4 +- src/sighandler.c | 2 +- src/x.c | 4 +- 10 files changed, 132 insertions(+), 50 deletions(-) diff --git a/i3-input/main.c b/i3-input/main.c index cf3884e9..4e1be78b 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -141,12 +141,12 @@ static int handle_expose(void *data, xcb_connection_t *conn, xcb_expose_event_t /* draw the prompt … */ if (prompt != NULL) { - draw_text(prompt, pixmap, pixmap_gc, logical_px(4), logical_px(4), logical_px(492)); + draw_text(prompt, pixmap, pixmap_gc, NULL, logical_px(4), logical_px(4), logical_px(492)); } /* … and the text */ if (input_position > 0) { i3String *input = i3string_from_ucs2(glyphs_ucs, input_position); - draw_text(input, pixmap, pixmap_gc, prompt_offset + logical_px(4), logical_px(4), logical_px(492)); + draw_text(input, pixmap, pixmap_gc, NULL, prompt_offset + logical_px(4), logical_px(4), logical_px(492)); i3string_free(input); } diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index d86cd69a..d6ace221 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -196,7 +196,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { /* restore font color */ set_font_colors(pixmap_gc, color_text, color_background); - draw_text(prompt, pixmap, pixmap_gc, + draw_text(prompt, pixmap, pixmap_gc, NULL, logical_px(4) + logical_px(4), logical_px(4) + logical_px(4), rect.width - logical_px(4) - logical_px(4)); @@ -264,7 +264,7 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { values[1] = color_button_background; set_font_colors(pixmap_gc, color_text, color_button_background); /* the x term seems to set left/right padding */ - draw_text(buttons[c].label, pixmap, pixmap_gc, + draw_text(buttons[c].label, pixmap, pixmap_gc, NULL, y - w - line_width + logical_px(6), logical_px(4) + logical_px(3), rect.width - y + w + line_width - logical_px(6)); diff --git a/i3bar/include/cairo_util.h b/i3bar/include/cairo_util.h index 749beec8..390e6a1c 100644 --- a/i3bar/include/cairo_util.h +++ b/i3bar/include/cairo_util.h @@ -15,6 +15,7 @@ typedef struct color_t { double red; double green; double blue; + double alpha; /* For compatibility, we also store the colorpixel for now. */ uint32_t colorpixel; diff --git a/i3bar/src/cairo_util.c b/i3bar/src/cairo_util.c index aff763c3..288969c9 100644 --- a/i3bar/src/cairo_util.c +++ b/i3bar/src/cairo_util.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include #include @@ -16,7 +17,7 @@ #include "libi3.h" xcb_connection_t *xcb_connection; -xcb_screen_t *root_screen; +xcb_visualtype_t *visual_type; /* * Initialize the cairo surface to represent the given drawable. @@ -30,7 +31,7 @@ void cairo_surface_init(surface_t *surface, xcb_drawable_t drawable, int width, if (xcb_request_failed(gc_cookie, "Could not create graphical context")) exit(EXIT_FAILURE); - surface->surface = cairo_xcb_surface_create(xcb_connection, surface->id, get_visualtype(root_screen), width, height); + surface->surface = cairo_xcb_surface_create(xcb_connection, surface->id, visual_type, width, height); surface->cr = cairo_create(surface->surface); } @@ -50,15 +51,25 @@ void cairo_surface_free(surface_t *surface) { * */ color_t cairo_hex_to_color(const char *color) { - char groups[3][3] = { + char alpha[2]; + if (strlen(color) == strlen("#rrggbbaa")) { + alpha[0] = color[7]; + alpha[1] = color[8]; + } else { + alpha[0] = alpha[1] = 'F'; + } + + char groups[4][3] = { {color[1], color[2], '\0'}, {color[3], color[4], '\0'}, - {color[5], color[6], '\0'}}; + {color[5], color[6], '\0'}, + {alpha[0], alpha[1], '\0'}}; return (color_t){ .red = strtol(groups[0], NULL, 16) / 255.0, .green = strtol(groups[1], NULL, 16) / 255.0, .blue = strtol(groups[2], NULL, 16) / 255.0, + .alpha = strtol(groups[3], NULL, 16) / 255.0, .colorpixel = get_colorpixel(color)}; } @@ -67,5 +78,5 @@ color_t cairo_hex_to_color(const char *color) { * */ void cairo_set_source_color(surface_t *surface, color_t color) { - cairo_set_source_rgb(surface->cr, color.red, color.green, color.blue); + cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha); } diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index f5d065f0..443e30ea 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -64,6 +64,10 @@ static i3Font font; /* Icon size (based on font size) */ int icon_size; +xcb_visualtype_t *visual_type; +uint8_t depth; +xcb_colormap_t colormap; + /* Overall height of the bar (based on font size) */ int bar_height; @@ -170,14 +174,17 @@ static void draw_separator(uint32_t x, struct status_block *block) { uint32_t center_x = x - sep_offset; if (config.separator_symbol == NULL) { /* Draw a classic one pixel, vertical separator. */ + cairo_save(statusline_surface.cr); + cairo_set_operator(statusline_surface.cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_color(&statusline_surface, colors.sep_fg); cairo_rectangle(statusline_surface.cr, center_x, logical_px(sep_voff_px), logical_px(1), bar_height - 2 * logical_px(sep_voff_px)); cairo_fill(statusline_surface.cr); + cairo_restore(statusline_surface.cr); } else { /* Draw a custom separator. */ uint32_t separator_x = MAX(x - block->sep_block_width, center_x - separator_symbol_width / 2); set_font_colors(statusline_surface.gc, colors.sep_fg.colorpixel, colors.bar_bg.colorpixel); - draw_text(config.separator_symbol, statusline_surface.id, statusline_surface.gc, + draw_text(config.separator_symbol, statusline_surface.id, statusline_surface.gc, visual_type, separator_x, logical_px(ws_voff_px), x - separator_x); } } @@ -239,9 +246,11 @@ void refresh_statusline(bool use_short_text) { realloc_sl_buffer(); /* Clear the statusline pixmap. */ + cairo_save(statusline_surface.cr); cairo_set_source_color(&statusline_surface, colors.bar_bg); - cairo_rectangle(statusline_surface.cr, 0, 0, MAX(root_screen->width_in_pixels, statusline_width), bar_height); - cairo_fill(statusline_surface.cr); + cairo_set_operator(statusline_surface.cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(statusline_surface.cr); + cairo_restore(statusline_surface.cr); /* Draw the text of each block. */ uint32_t x = 0; @@ -263,7 +272,8 @@ void refresh_statusline(bool use_short_text) { } set_font_colors(statusline_surface.gc, fg_color.colorpixel, colors.bar_bg.colorpixel); - draw_text(block->full_text, statusline_surface.id, statusline_surface.gc, x + block->x_offset, logical_px(ws_voff_px), block->width); + draw_text(block->full_text, statusline_surface.id, statusline_surface.gc, visual_type, + x + block->x_offset, logical_px(ws_voff_px), block->width); x += block->width + block->sep_block_width + block->x_offset + block->x_append; /* If this is not the last block, draw a separator. */ @@ -699,11 +709,15 @@ static void handle_client_message(xcb_client_message_event_t *event) { ELOG("No output found\n"); return; } - xcb_reparent_window(xcb_connection, - client, - output->bar.id, - output->rect.w - icon_size - logical_px(config.tray_padding), - logical_px(config.tray_padding)); + + xcb_void_cookie_t rcookie = xcb_reparent_window(xcb_connection, + client, + output->bar.id, + output->rect.w - icon_size - logical_px(config.tray_padding), + logical_px(config.tray_padding)); + if (xcb_request_failed(rcookie, "Could not reparent window. Maybe it is using an incorrect depth/visual?")) + return; + /* We reconfigure the window to use a reasonable size. The systray * specification explicitly says: * Tray icons may be assigned any size by the system tray, and @@ -1106,11 +1120,29 @@ char *init_xcb_early() { root_screen = xcb_aux_get_screen(xcb_connection, screen); xcb_root = root_screen->root; + depth = root_screen->root_depth; + colormap = root_screen->default_colormap; + visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32); + if (visual_type) { + depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id); + colormap = xcb_generate_id(xcb_connection); + xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(xcb_connection, + XCB_COLORMAP_ALLOC_NONE, + colormap, + xcb_root, + visual_type->visual_id); + if (xcb_request_failed(cm_cookie, "Could not allocate colormap")) { + exit(EXIT_FAILURE); + } + } else { + visual_type = get_visualtype(root_screen); + } + /* 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 */ xcb_pixmap_t statusline_id = xcb_generate_id(xcb_connection); xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection, - root_screen->root_depth, + depth, statusline_id, xcb_root, root_screen->width_in_pixels, @@ -1248,17 +1280,17 @@ void init_tray(void) { /* tray support: we need a window to own the selection */ selwin = xcb_generate_id(xcb_connection); - uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT; - uint32_t selval[] = {1}; + uint32_t selmask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP; + uint32_t selval[] = {root_screen->black_pixel, root_screen->black_pixel, 1, colormap}; xcb_create_window(xcb_connection, - root_screen->root_depth, + depth, selwin, xcb_root, -1, -1, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, - root_screen->root_visual, + visual_type->visual_id, selmask, selval); @@ -1272,6 +1304,14 @@ void init_tray(void) { 32, 1, &orientation); + xcb_change_property(xcb_connection, + XCB_PROP_MODE_REPLACE, + selwin, + atoms[_NET_SYSTEM_TRAY_VISUAL], + XCB_ATOM_VISUALID, + 32, + 1, + &visual_type->visual_id); init_tray_colors(); @@ -1473,7 +1513,7 @@ void realloc_sl_buffer(void) { xcb_pixmap_t statusline_id = xcb_generate_id(xcb_connection); xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection, - root_screen->root_depth, + depth, statusline_id, xcb_root, MAX(root_screen->width_in_pixels, statusline_width), @@ -1551,41 +1591,44 @@ void reconfig_windows(bool redraw_bars) { xcb_window_t bar_id = xcb_generate_id(xcb_connection); xcb_pixmap_t buffer_id = xcb_generate_id(xcb_connection); - mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; - /* Black background */ + mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; + values[0] = colors.bar_bg.colorpixel; + values[1] = root_screen->black_pixel; /* If hide_on_modifier is set to hide or invisible mode, i3 is not supposed to manage our bar windows */ - values[1] = (config.hide_on_modifier == M_DOCK ? 0 : 1); + values[2] = (config.hide_on_modifier == M_DOCK ? 0 : 1); /* We enable the following EventMask fields: * EXPOSURE, to get expose events (we have to re-draw then) * SUBSTRUCTURE_REDIRECT, to get ConfigureRequests when the tray * child windows use ConfigureWindow * BUTTON_PRESS, to handle clicks on the workspace buttons * */ - values[2] = XCB_EVENT_MASK_EXPOSURE | + values[3] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_BUTTON_PRESS; if (config.hide_on_modifier == M_DOCK) { /* If the bar is normally visible, catch visibility change events to suspend * the status process when the bar is obscured by full-screened windows. */ - values[2] |= XCB_EVENT_MASK_VISIBILITY_CHANGE; + values[3] |= XCB_EVENT_MASK_VISIBILITY_CHANGE; walk->visible = true; } + values[4] = colormap; + xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection, - root_screen->root_depth, + depth, bar_id, xcb_root, walk->rect.x, walk->rect.y + walk->rect.h - bar_height, walk->rect.w, bar_height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, - root_screen->root_visual, + visual_type->visual_id, mask, values); /* The double-buffer we use to render stuff off-screen */ xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection, - root_screen->root_depth, + depth, buffer_id, bar_id, walk->rect.w, @@ -1701,7 +1744,7 @@ void reconfig_windows(bool redraw_bars) { DLOG("Recreating buffer for output %s\n", walk->name); xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection, - root_screen->root_depth, + depth, walk->buffer.id, walk->bar.id, walk->rect.w, @@ -1766,10 +1809,13 @@ void draw_bars(bool unhide) { /* Oh shit, an active output without an own bar. Create it now! */ reconfig_windows(false); } + /* First things first: clear the backbuffer */ + cairo_save(outputs_walk->buffer.cr); cairo_set_source_color(&(outputs_walk->buffer), colors.bar_bg); - cairo_rectangle(outputs_walk->buffer.cr, 0, 0, outputs_walk->rect.w, bar_height); - cairo_fill(outputs_walk->buffer.cr); + cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(outputs_walk->buffer.cr); + cairo_restore(outputs_walk->buffer.cr); if (!config.disable_ws) { i3_ws *ws_walk; @@ -1798,20 +1844,27 @@ void draw_bars(bool unhide) { unhide = true; } + cairo_save(outputs_walk->buffer.cr); + cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE); + + /* Draw the border of the button. */ cairo_set_source_color(&(outputs_walk->buffer), border_color); cairo_rectangle(outputs_walk->buffer.cr, workspace_width, logical_px(1), ws_walk->name_width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1), font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1)); cairo_fill(outputs_walk->buffer.cr); + /* Draw the inside of the button. */ cairo_set_source_color(&(outputs_walk->buffer), bg_color); cairo_rectangle(outputs_walk->buffer.cr, workspace_width + logical_px(1), 2 * logical_px(1), ws_walk->name_width + 2 * logical_px(ws_hoff_px), font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1)); cairo_fill(outputs_walk->buffer.cr); + cairo_restore(outputs_walk->buffer.cr); + set_font_colors(outputs_walk->buffer.gc, fg_color.colorpixel, bg_color.colorpixel); - draw_text(ws_walk->name, outputs_walk->buffer.id, outputs_walk->buffer.gc, + draw_text(ws_walk->name, outputs_walk->buffer.id, outputs_walk->buffer.gc, visual_type, workspace_width + logical_px(ws_hoff_px) + logical_px(1), logical_px(ws_voff_px), ws_walk->name_width); @@ -1828,6 +1881,9 @@ void draw_bars(bool unhide) { color_t fg_color = colors.binding_mode_fg; color_t bg_color = colors.binding_mode_bg; + cairo_save(outputs_walk->buffer.cr); + cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_color(&(outputs_walk->buffer), colors.binding_mode_border); cairo_rectangle(outputs_walk->buffer.cr, workspace_width, logical_px(1), binding.width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1), @@ -1840,10 +1896,13 @@ void draw_bars(bool unhide) { font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1)); cairo_fill(outputs_walk->buffer.cr); + cairo_restore(outputs_walk->buffer.cr); + set_font_colors(outputs_walk->buffer.gc, fg_color.colorpixel, bg_color.colorpixel); draw_text(binding.name, outputs_walk->buffer.id, outputs_walk->buffer.gc, + visual_type, workspace_width + logical_px(ws_hoff_px) + logical_px(1), logical_px(ws_voff_px), binding.width); @@ -1876,9 +1935,12 @@ void draw_bars(bool unhide) { int x_src = (int16_t)(statusline_width - visible_statusline_width); int x_dest = (int16_t)(outputs_walk->rect.w - tray_width - logical_px(sb_hoff_px) - visible_statusline_width); + cairo_save(outputs_walk->buffer.cr); + cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(outputs_walk->buffer.cr, statusline_surface.surface, x_dest - x_src, 0); cairo_rectangle(outputs_walk->buffer.cr, x_dest, 0, (int16_t)visible_statusline_width, (int16_t)bar_height); cairo_fill(outputs_walk->buffer.cr); + cairo_restore(outputs_walk->buffer.cr); } workspace_width = 0; @@ -1906,9 +1968,14 @@ void redraw_bars(void) { if (!outputs_walk->active) { continue; } + + cairo_save(outputs_walk->bar.cr); + cairo_set_operator(outputs_walk->bar.cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(outputs_walk->bar.cr, outputs_walk->buffer.surface, 0, 0); cairo_rectangle(outputs_walk->bar.cr, 0, 0, outputs_walk->rect.w, outputs_walk->rect.h); cairo_fill(outputs_walk->bar.cr); + cairo_restore(outputs_walk->bar.cr); + xcb_flush(xcb_connection); } } diff --git a/include/libi3.h b/include/libi3.h index 9e7ef133..c1e109ef 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -402,8 +402,8 @@ bool font_is_pango(void); * Text must be specified as an i3String. * */ -void draw_text(i3String *text, xcb_drawable_t drawable, - xcb_gcontext_t gc, int x, int y, int max_width); +void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc, + xcb_visualtype_t *visual, int x, int y, int max_width); /** * ASCII version of draw_text to print static strings. diff --git a/libi3/font.c b/libi3/font.c index b8c31b73..8bdf3d60 100644 --- a/libi3/font.c +++ b/libi3/font.c @@ -102,12 +102,12 @@ static bool load_pango_font(i3Font *font, const char *desc) { * */ static void draw_text_pango(const char *text, size_t text_len, - xcb_drawable_t drawable, int x, int y, + xcb_drawable_t drawable, xcb_visualtype_t *visual, int x, int y, int max_width, bool is_markup) { /* Create the Pango layout */ /* root_visual_type is cached in load_pango_font */ cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable, - root_visual_type, x + max_width, y + savedFont->height); + visual, x + max_width, y + savedFont->height); cairo_t *cr = cairo_create(surface); PangoLayout *layout = create_layout_with_dpi(cr); gint height; @@ -391,9 +391,12 @@ static void draw_text_xcb(const xcb_char2b_t *text, size_t text_len, xcb_drawabl * Text must be specified as an i3String. * */ -void draw_text(i3String *text, xcb_drawable_t drawable, - xcb_gcontext_t gc, int x, int y, int max_width) { +void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc, + xcb_visualtype_t *visual, int x, int y, int max_width) { assert(savedFont != NULL); + if (visual == NULL) { + visual = root_visual_type; + } switch (savedFont->type) { case FONT_TYPE_NONE: @@ -407,7 +410,7 @@ void draw_text(i3String *text, xcb_drawable_t drawable, case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text), - drawable, x, y, max_width, i3string_is_markup(text)); + drawable, visual, x, y, max_width, i3string_is_markup(text)); return; #endif default: @@ -432,7 +435,7 @@ void draw_text_ascii(const char *text, xcb_drawable_t drawable, if (text_len > 255) { /* The text is too long to draw it directly to X */ i3String *str = i3string_from_utf8(text); - draw_text(str, drawable, gc, x, y, max_width); + draw_text(str, drawable, gc, NULL, x, y, max_width); i3string_free(str); } else { /* X11 coordinates for fonts start at the baseline */ @@ -446,7 +449,7 @@ void draw_text_ascii(const char *text, xcb_drawable_t drawable, case FONT_TYPE_PANGO: /* Render the text using Pango */ draw_text_pango(text, strlen(text), - drawable, x, y, max_width, false); + drawable, root_visual_type, x, y, max_width, false); return; #endif default: diff --git a/src/restore_layout.c b/src/restore_layout.c index 439d23cc..70eed523 100644 --- a/src/restore_layout.c +++ b/src/restore_layout.c @@ -161,7 +161,7 @@ static void update_placeholder_contents(placeholder_state *state) { DLOG("con %p (placeholder 0x%08x) line %d: %s\n", state->con, state->window, n, serialized); i3String *str = i3string_from_utf8(serialized); - draw_text(str, state->pixmap, state->gc, 2, (n * (config.font.height + 2)) + 2, state->rect.width - 2); + draw_text(str, state->pixmap, state->gc, NULL, 2, (n * (config.font.height + 2)) + 2, state->rect.width - 2); i3string_free(str); n++; free(serialized); @@ -172,7 +172,7 @@ static void update_placeholder_contents(placeholder_state *state) { int text_width = predict_text_width(line); int x = (state->rect.width / 2) - (text_width / 2); int y = (state->rect.height / 2) - (config.font.height / 2); - draw_text(line, state->pixmap, state->gc, x, y, text_width); + draw_text(line, state->pixmap, state->gc, NULL, x, y, text_width); i3string_free(line); xcb_flush(conn); xcb_aux_sync(conn); diff --git a/src/sighandler.c b/src/sighandler.c index ceaa4842..555f5e55 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -154,7 +154,7 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei if (i == backtrace_string_index) set_font_colors(pixmap_gc, get_colorpixel(bt_colour), get_colorpixel("#000000")); - draw_text(crash_text_i3strings[i], pixmap, pixmap_gc, + draw_text(crash_text_i3strings[i], pixmap, pixmap_gc, NULL, 8, 5 + i * font_height, width - 16); /* and reset the colour again for other lines */ diff --git a/src/x.c b/src/x.c index 9b9ba6aa..d312666b 100644 --- a/src/x.c +++ b/src/x.c @@ -552,7 +552,7 @@ void x_draw_decoration(Con *con) { FREE(formatted_mark); mark_width = predict_text_width(mark); - draw_text(mark, parent->pixmap, parent->pm_gc, + draw_text(mark, parent->pixmap, parent->pm_gc, NULL, con->deco_rect.x + con->deco_rect.width - mark_width - logical_px(2), con->deco_rect.y + text_offset_y, mark_width); @@ -561,7 +561,7 @@ void x_draw_decoration(Con *con) { i3String *title = win->title_format == NULL ? win->name : window_parse_title_format(win); draw_text(title, - parent->pixmap, parent->pm_gc, + parent->pixmap, parent->pm_gc, NULL, con->deco_rect.x + logical_px(2) + indent_px, con->deco_rect.y + text_offset_y, con->deco_rect.width - logical_px(2) - indent_px - mark_width - logical_px(2)); if (win->title_format != NULL)