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.
/* draw the prompt … */
if (prompt != NULL) {
/* 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);
}
/* … 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));
/* restore font color */
set_font_colors(pixmap_gc, color_text, color_background);
/* 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));
logical_px(4) + logical_px(4),
logical_px(4) + logical_px(4),
rect.width - logical_px(4) - logical_px(4));
values[1] = color_button_background;
set_font_colors(pixmap_gc, color_text, color_button_background);
/* the x term seems to set left/right padding */
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));
y - w - line_width + logical_px(6),
logical_px(4) + logical_px(3),
rect.width - y + w + line_width - logical_px(6));
double red;
double green;
double blue;
double red;
double green;
double blue;
/* For compatibility, we also store the colorpixel for now. */
uint32_t colorpixel;
/* For compatibility, we also store the colorpixel for now. */
uint32_t colorpixel;
*/
#include <stdlib.h>
#include <err.h>
*/
#include <stdlib.h>
#include <err.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <cairo/cairo-xcb.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <cairo/cairo-xcb.h>
#include "libi3.h"
xcb_connection_t *xcb_connection;
#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.
/*
* Initialize the cairo surface to represent the given drawable.
if (xcb_request_failed(gc_cookie, "Could not create graphical context"))
exit(EXIT_FAILURE);
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);
}
surface->cr = cairo_create(surface->surface);
}
*
*/
color_t cairo_hex_to_color(const char *color) {
*
*/
color_t cairo_hex_to_color(const char *color) {
+ 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[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,
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)};
}
.colorpixel = get_colorpixel(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_rgb(surface->cr, color.red, color.green, color.blue);
+ cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
/* Icon size (based on font size) */
int icon_size;
/* 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;
/* Overall height of the bar (based on font size) */
int bar_height;
uint32_t center_x = x - sep_offset;
if (config.separator_symbol == NULL) {
/* Draw a classic one pixel, vertical separator. */
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_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);
} 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);
}
}
separator_x, logical_px(ws_voff_px), x - separator_x);
}
}
realloc_sl_buffer();
/* Clear the statusline pixmap. */
realloc_sl_buffer();
/* Clear the statusline pixmap. */
+ cairo_save(statusline_surface.cr);
cairo_set_source_color(&statusline_surface, colors.bar_bg);
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;
/* Draw the text of each block. */
uint32_t x = 0;
}
set_font_colors(statusline_surface.gc, fg_color.colorpixel, colors.bar_bg.colorpixel);
}
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. */
x += block->width + block->sep_block_width + block->x_offset + block->x_append;
/* If this is not the last block, draw a separator. */
ELOG("No output found\n");
return;
}
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
/* 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
root_screen = xcb_aux_get_screen(xcb_connection, screen);
xcb_root = root_screen->root;
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,
/* 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,
statusline_id,
xcb_root,
root_screen->width_in_pixels,
statusline_id,
xcb_root,
root_screen->width_in_pixels,
/* tray support: we need a window to own the selection */
selwin = xcb_generate_id(xcb_connection);
/* 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,
xcb_create_window(xcb_connection,
- root_screen->root_depth,
selwin,
xcb_root,
-1, -1,
1, 1,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
selwin,
xcb_root,
-1, -1,
1, 1,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
- root_screen->root_visual,
+ visual_type->visual_id,
+ xcb_change_property(xcb_connection,
+ XCB_PROP_MODE_REPLACE,
+ selwin,
+ atoms[_NET_SYSTEM_TRAY_VISUAL],
+ XCB_ATOM_VISUALID,
+ 32,
+ 1,
+ &visual_type->visual_id);
xcb_pixmap_t statusline_id = xcb_generate_id(xcb_connection);
xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection,
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,
statusline_id,
xcb_root,
MAX(root_screen->width_in_pixels, statusline_width),
statusline_id,
xcb_root,
MAX(root_screen->width_in_pixels, statusline_width),
xcb_window_t bar_id = xcb_generate_id(xcb_connection);
xcb_pixmap_t buffer_id = xcb_generate_id(xcb_connection);
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[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 */
/* 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
* */
/* 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. */
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;
+ values[4] = colormap;
+
xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection,
xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection,
- root_screen->root_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,
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,
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,
buffer_id,
bar_id,
walk->rect.w,
buffer_id,
bar_id,
walk->rect.w,
DLOG("Recreating buffer for output %s\n", walk->name);
xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection,
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,
walk->buffer.id,
walk->bar.id,
walk->rect.w,
walk->buffer.id,
walk->bar.id,
walk->rect.w,
/* Oh shit, an active output without an own bar. Create it now! */
reconfig_windows(false);
}
/* Oh shit, an active output without an own bar. Create it now! */
reconfig_windows(false);
}
/* First things first: clear the backbuffer */
/* First things first: clear the backbuffer */
+ cairo_save(outputs_walk->buffer.cr);
cairo_set_source_color(&(outputs_walk->buffer), colors.bar_bg);
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;
if (!config.disable_ws) {
i3_ws *ws_walk;
+ 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);
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_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);
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);
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
logical_px(ws_voff_px),
ws_walk->name_width);
color_t fg_color = colors.binding_mode_fg;
color_t bg_color = colors.binding_mode_bg;
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),
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),
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));
cairo_fill(outputs_walk->buffer.cr);
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,
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,
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
logical_px(ws_voff_px),
binding.width);
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
logical_px(ws_voff_px),
binding.width);
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);
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_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);
if (!outputs_walk->active) {
continue;
}
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_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);
}
}
xcb_flush(xcb_connection);
}
}
* Text must be specified as an i3String.
*
*/
* 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.
/**
* ASCII version of draw_text to print static strings.
*
*/
static void draw_text_pango(const char *text, size_t text_len,
*
*/
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,
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;
cairo_t *cr = cairo_create(surface);
PangoLayout *layout = create_layout_with_dpi(cr);
gint height;
* Text must be specified as an i3String.
*
*/
* 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);
assert(savedFont != NULL);
+ if (visual == NULL) {
+ visual = root_visual_type;
+ }
switch (savedFont->type) {
case FONT_TYPE_NONE:
switch (savedFont->type) {
case FONT_TYPE_NONE:
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
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));
if (text_len > 255) {
/* The text is too long to draw it directly to X */
i3String *str = i3string_from_utf8(text);
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 */
i3string_free(str);
} else {
/* X11 coordinates for fonts start at the baseline */
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(text, strlen(text),
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);
DLOG("con %p (placeholder 0x%08x) line %d: %s\n", state->con, state->window, n, serialized);
i3String *str = i3string_from_utf8(serialized);
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);
i3string_free(str);
n++;
free(serialized);
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);
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);
i3string_free(line);
xcb_flush(conn);
xcb_aux_sync(conn);
if (i == backtrace_string_index)
set_font_colors(pixmap_gc, get_colorpixel(bt_colour), get_colorpixel("#000000"));
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 */
8, 5 + i * font_height, width - 16);
/* and reset the colour again for other lines */
FREE(formatted_mark);
mark_width = predict_text_width(mark);
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);
con->deco_rect.x + con->deco_rect.width - mark_width - logical_px(2),
con->deco_rect.y + text_offset_y, mark_width);
i3String *title = win->title_format == NULL ? win->name : window_parse_title_format(win);
draw_text(title,
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)
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)