When drawing text, mark the surface as dirty.
Since libi3 currently creates its own cairo surface for drawing text, we need to mark our own surface as dirty to force cairo to invalidate its cache. Otherwise, this will result in graphical glitches such as the text not showing up at all. This wrapper can be removed in the future when libi3 is adapted to reuse the same cairo surface as we do for all other drawing operations.
This commit is contained in:
parent
a5d4c7c9ab
commit
ff0aeddede
|
@ -64,3 +64,11 @@ color_t cairo_hex_to_color(const char *color);
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cairo_set_source_color(surface_t *surface, color_t color);
|
void cairo_set_source_color(surface_t *surface, color_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the given text using libi3.
|
||||||
|
* This function also marks the surface dirty which is needed if other means of
|
||||||
|
* drawing are used. This will be the case when using XCB to draw text.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cairo_draw_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width);
|
||||||
|
|
|
@ -80,3 +80,16 @@ color_t cairo_hex_to_color(const char *color) {
|
||||||
void cairo_set_source_color(surface_t *surface, color_t color) {
|
void cairo_set_source_color(surface_t *surface, color_t color) {
|
||||||
cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
|
cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the given text using libi3.
|
||||||
|
* This function also marks the surface dirty which is needed if other means of
|
||||||
|
* drawing are used. This will be the case when using XCB to draw text.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void cairo_draw_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) {
|
||||||
|
set_font_colors(surface->gc, fg_color.colorpixel, bg_color.colorpixel);
|
||||||
|
draw_text(text, surface->id, surface->gc, visual_type, x, y, max_width);
|
||||||
|
|
||||||
|
cairo_surface_mark_dirty(surface->surface);
|
||||||
|
}
|
||||||
|
|
|
@ -179,13 +179,13 @@ static void draw_separator(uint32_t x, struct status_block *block) {
|
||||||
cairo_set_source_color(&statusline_surface, colors.sep_fg);
|
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_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_fill(statusline_surface.cr);
|
||||||
|
cairo_surface_flush(statusline_surface.surface);
|
||||||
cairo_restore(statusline_surface.cr);
|
cairo_restore(statusline_surface.cr);
|
||||||
} else {
|
} else {
|
||||||
/* Draw a custom separator. */
|
/* Draw a custom separator. */
|
||||||
uint32_t separator_x = MAX(x - block->sep_block_width, center_x - separator_symbol_width / 2);
|
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);
|
cairo_draw_text(config.separator_symbol, &statusline_surface, colors.sep_fg, colors.bar_bg,
|
||||||
draw_text(config.separator_symbol, statusline_surface.id, statusline_surface.gc, visual_type,
|
separator_x, logical_px(ws_voff_px), x - separator_x);
|
||||||
separator_x, logical_px(ws_voff_px), x - separator_x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,6 +250,7 @@ void refresh_statusline(bool use_short_text) {
|
||||||
cairo_set_source_color(&statusline_surface, colors.bar_bg);
|
cairo_set_source_color(&statusline_surface, colors.bar_bg);
|
||||||
cairo_set_operator(statusline_surface.cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator(statusline_surface.cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_paint(statusline_surface.cr);
|
cairo_paint(statusline_surface.cr);
|
||||||
|
cairo_surface_flush(statusline_surface.surface);
|
||||||
cairo_restore(statusline_surface.cr);
|
cairo_restore(statusline_surface.cr);
|
||||||
|
|
||||||
/* Draw the text of each block. */
|
/* Draw the text of each block. */
|
||||||
|
@ -267,13 +268,13 @@ void refresh_statusline(bool use_short_text) {
|
||||||
cairo_set_source_color(&statusline_surface, colors.urgent_ws_bg);
|
cairo_set_source_color(&statusline_surface, colors.urgent_ws_bg);
|
||||||
cairo_rectangle(statusline_surface.cr, x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2));
|
cairo_rectangle(statusline_surface.cr, x - logical_px(2), logical_px(1), block->width + logical_px(4), bar_height - logical_px(2));
|
||||||
cairo_fill(statusline_surface.cr);
|
cairo_fill(statusline_surface.cr);
|
||||||
|
cairo_surface_flush(statusline_surface.surface);
|
||||||
} else {
|
} else {
|
||||||
fg_color = (block->color ? cairo_hex_to_color(block->color) : colors.bar_fg);
|
fg_color = (block->color ? cairo_hex_to_color(block->color) : colors.bar_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_font_colors(statusline_surface.gc, fg_color.colorpixel, colors.bar_bg.colorpixel);
|
cairo_draw_text(block->full_text, &statusline_surface, fg_color, colors.bar_bg,
|
||||||
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->x_offset, logical_px(ws_voff_px), block->width);
|
|
||||||
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
|
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
|
||||||
|
|
||||||
/* If this is not the last block, draw a separator. */
|
/* If this is not the last block, draw a separator. */
|
||||||
|
@ -1815,6 +1816,7 @@ void draw_bars(bool unhide) {
|
||||||
cairo_set_source_color(&(outputs_walk->buffer), colors.bar_bg);
|
cairo_set_source_color(&(outputs_walk->buffer), colors.bar_bg);
|
||||||
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_paint(outputs_walk->buffer.cr);
|
cairo_paint(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
cairo_restore(outputs_walk->buffer.cr);
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
|
|
||||||
if (!config.disable_ws) {
|
if (!config.disable_ws) {
|
||||||
|
@ -1844,30 +1846,32 @@ void draw_bars(bool unhide) {
|
||||||
unhide = true;
|
unhide = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw the border of the button. */
|
||||||
cairo_save(outputs_walk->buffer.cr);
|
cairo_save(outputs_walk->buffer.cr);
|
||||||
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
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_set_source_color(&(outputs_walk->buffer), border_color);
|
||||||
cairo_rectangle(outputs_walk->buffer.cr, workspace_width, logical_px(1),
|
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),
|
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));
|
font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1));
|
||||||
cairo_fill(outputs_walk->buffer.cr);
|
cairo_fill(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
|
|
||||||
/* Draw the inside of the button. */
|
/* Draw the inside of the button. */
|
||||||
|
cairo_save(outputs_walk->buffer.cr);
|
||||||
|
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_set_source_color(&(outputs_walk->buffer), bg_color);
|
cairo_set_source_color(&(outputs_walk->buffer), bg_color);
|
||||||
cairo_rectangle(outputs_walk->buffer.cr, workspace_width + logical_px(1), 2 * logical_px(1),
|
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),
|
ws_walk->name_width + 2 * logical_px(ws_hoff_px),
|
||||||
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));
|
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));
|
||||||
cairo_fill(outputs_walk->buffer.cr);
|
cairo_fill(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
cairo_restore(outputs_walk->buffer.cr);
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
|
|
||||||
set_font_colors(outputs_walk->buffer.gc, fg_color.colorpixel, bg_color.colorpixel);
|
cairo_draw_text(ws_walk->name, &(outputs_walk->buffer), fg_color, bg_color,
|
||||||
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),
|
||||||
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
|
logical_px(ws_voff_px),
|
||||||
logical_px(ws_voff_px),
|
ws_walk->name_width);
|
||||||
ws_walk->name_width);
|
|
||||||
|
|
||||||
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width;
|
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width;
|
||||||
if (TAILQ_NEXT(ws_walk, tailq) != NULL)
|
if (TAILQ_NEXT(ws_walk, tailq) != NULL)
|
||||||
|
@ -1883,29 +1887,28 @@ void draw_bars(bool unhide) {
|
||||||
|
|
||||||
cairo_save(outputs_walk->buffer.cr);
|
cairo_save(outputs_walk->buffer.cr);
|
||||||
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
||||||
|
|
||||||
cairo_set_source_color(&(outputs_walk->buffer), colors.binding_mode_border);
|
cairo_set_source_color(&(outputs_walk->buffer), colors.binding_mode_border);
|
||||||
cairo_rectangle(outputs_walk->buffer.cr, workspace_width, logical_px(1),
|
cairo_rectangle(outputs_walk->buffer.cr, workspace_width, logical_px(1),
|
||||||
binding.width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1),
|
binding.width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1),
|
||||||
font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1));
|
font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1));
|
||||||
cairo_fill(outputs_walk->buffer.cr);
|
cairo_fill(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
|
|
||||||
|
cairo_save(outputs_walk->buffer.cr);
|
||||||
|
cairo_set_operator(outputs_walk->buffer.cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_set_source_color(&(outputs_walk->buffer), bg_color);
|
cairo_set_source_color(&(outputs_walk->buffer), bg_color);
|
||||||
cairo_rectangle(outputs_walk->buffer.cr, workspace_width + logical_px(1), 2 * logical_px(1),
|
cairo_rectangle(outputs_walk->buffer.cr, workspace_width + logical_px(1), 2 * logical_px(1),
|
||||||
binding.width + 2 * logical_px(ws_hoff_px),
|
binding.width + 2 * logical_px(ws_hoff_px),
|
||||||
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));
|
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));
|
||||||
cairo_fill(outputs_walk->buffer.cr);
|
cairo_fill(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
cairo_restore(outputs_walk->buffer.cr);
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
|
|
||||||
set_font_colors(outputs_walk->buffer.gc, fg_color.colorpixel, bg_color.colorpixel);
|
cairo_draw_text(binding.name, &(outputs_walk->buffer), fg_color, bg_color,
|
||||||
draw_text(binding.name,
|
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
|
||||||
outputs_walk->buffer.id,
|
logical_px(ws_voff_px),
|
||||||
outputs_walk->buffer.gc,
|
binding.width);
|
||||||
visual_type,
|
|
||||||
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
|
|
||||||
logical_px(ws_voff_px),
|
|
||||||
binding.width);
|
|
||||||
|
|
||||||
unhide = true;
|
unhide = true;
|
||||||
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + binding.width;
|
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + binding.width;
|
||||||
|
@ -1940,6 +1943,7 @@ void draw_bars(bool unhide) {
|
||||||
cairo_set_source_surface(outputs_walk->buffer.cr, statusline_surface.surface, x_dest - x_src, 0);
|
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_rectangle(outputs_walk->buffer.cr, x_dest, 0, (int16_t)visible_statusline_width, (int16_t)bar_height);
|
||||||
cairo_fill(outputs_walk->buffer.cr);
|
cairo_fill(outputs_walk->buffer.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->buffer.surface);
|
||||||
cairo_restore(outputs_walk->buffer.cr);
|
cairo_restore(outputs_walk->buffer.cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1974,6 +1978,7 @@ void redraw_bars(void) {
|
||||||
cairo_set_source_surface(outputs_walk->bar.cr, outputs_walk->buffer.surface, 0, 0);
|
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_rectangle(outputs_walk->bar.cr, 0, 0, outputs_walk->rect.w, outputs_walk->rect.h);
|
||||||
cairo_fill(outputs_walk->bar.cr);
|
cairo_fill(outputs_walk->bar.cr);
|
||||||
|
cairo_surface_flush(outputs_walk->bar.surface);
|
||||||
cairo_restore(outputs_walk->bar.cr);
|
cairo_restore(outputs_walk->bar.cr);
|
||||||
|
|
||||||
xcb_flush(xcb_connection);
|
xcb_flush(xcb_connection);
|
||||||
|
|
Loading…
Reference in New Issue