Use 32-bit visual by default if available.

With this patch, we use 32-bit visuals per default whenever it is
available. Otherwise, we fall back to the actual root window's
depth, which will typically be 24-bit.

Before this patch, we already used 32-bit depth for containers with
a window that uses 32-bit. However, this means that we didn't use
32-bit for split parent containers on which decoration is drawn.
For 32-bit windows using transparency, this caused a graphical glitch
because the decoration pixmap behind it would show through. This
behavior is fixed with this change.

relates to #1278
This commit is contained in:
Ingo Bürk 2015-11-17 12:50:06 +01:00
parent d2126027ce
commit 780cb8d15d
7 changed files with 77 additions and 49 deletions

View File

@ -499,11 +499,14 @@ typedef struct color_t {
double red; double red;
double green; double green;
double blue; double blue;
double alpha;
/* The colorpixel we use for direct XCB calls. */ /* The colorpixel we use for direct XCB calls. */
uint32_t colorpixel; uint32_t colorpixel;
} color_t; } color_t;
#define COLOR_TRANSPARENT ((color_t){.red = 0.0, .green = 0.0, .blue = 0.0, .colorpixel = 0})
/* A wrapper grouping an XCB drawable and both a graphics context /* A wrapper grouping an XCB drawable and both a graphics context
* and the corresponding cairo objects representing it. */ * and the corresponding cairo objects representing it. */
typedef struct surface_t { typedef struct surface_t {

View File

@ -139,6 +139,11 @@ void xcb_set_root_cursor(int cursor);
* *
*/ */
uint16_t get_visual_depth(xcb_visualid_t visual_id); uint16_t get_visual_depth(xcb_visualid_t visual_id);
/**
* Get visual type specified by visualid
*
*/
xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id); xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id);
/** /**

View File

@ -38,7 +38,7 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac
void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_drawable_t drawable, void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_drawable_t drawable,
xcb_visualtype_t *visual, int width, int height) { xcb_visualtype_t *visual, int width, int height) {
surface->id = drawable; surface->id = drawable;
surface->visual_type = (visual == NULL) ? visual_type : visual; surface->visual_type = ((visual == NULL) ? visual_type : visual);
surface->width = width; surface->width = width;
surface->height = height; surface->height = height;
@ -87,15 +87,25 @@ void draw_util_surface_set_size(surface_t *surface, int width, int height) {
* *
*/ */
color_t draw_util_hex_to_color(const char *color) { color_t draw_util_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[1], color[2], '\0'},
{color[3], color[4], '\0'}, {color[3], color[4], '\0'},
{color[5], color[6], '\0'}}; {color[5], color[6], '\0'},
{alpha[0], alpha[1], '\0'}};
return (color_t){ return (color_t){
.red = strtol(groups[0], NULL, 16) / 255.0, .red = strtol(groups[0], NULL, 16) / 255.0,
.green = strtol(groups[1], NULL, 16) / 255.0, .green = strtol(groups[1], NULL, 16) / 255.0,
.blue = strtol(groups[2], 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)};
} }
@ -107,7 +117,7 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac
RETURN_UNLESS_SURFACE_INITIALIZED(surface); RETURN_UNLESS_SURFACE_INITIALIZED(surface);
#ifdef CAIRO_SUPPORT #ifdef CAIRO_SUPPORT
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);
#else #else
uint32_t colorpixel = color.colorpixel; uint32_t colorpixel = color.colorpixel;
xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,

View File

@ -47,7 +47,7 @@ Con *con_new_skeleton(Con *parent, i3Window *window) {
new->depth = window->depth; new->depth = window->depth;
new->window->aspect_ratio = 0.0; new->window->aspect_ratio = 0.0;
} else { } else {
new->depth = XCB_COPY_FROM_PARENT; new->depth = root_depth;
} }
DLOG("opening window\n"); DLOG("opening window\n");

View File

@ -59,7 +59,6 @@ xcb_window_t root;
* pixmaps. Will use 32 bit depth and an appropriate visual, if available, * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
* otherwise the root windows default (usually 24 bit TrueColor). */ * otherwise the root windows default (usually 24 bit TrueColor). */
uint8_t root_depth; uint8_t root_depth;
xcb_visualid_t visual_id;
xcb_visualtype_t *visual_type; xcb_visualtype_t *visual_type;
xcb_colormap_t colormap; xcb_colormap_t colormap;
@ -482,16 +481,29 @@ int main(int argc, char *argv[]) {
#include "atoms.xmacro" #include "atoms.xmacro"
#undef xmacro #undef xmacro
/* By default, we use the same depth and visual as the root window, which
* usually is TrueColor (24 bit depth) and the corresponding visual.
* However, we also check if a 32 bit depth and visual are available (for
* transparency) and use it if so. */
root_depth = root_screen->root_depth; root_depth = root_screen->root_depth;
visual_id = root_screen->root_visual;
visual_type = get_visualtype(root_screen);
colormap = root_screen->default_colormap; colormap = root_screen->default_colormap;
visual_type = xcb_aux_find_visual_by_attrs(root_screen, -1, 32);
if (visual_type != NULL) {
root_depth = xcb_aux_get_depth_of_visual(root_screen, visual_type->visual_id);
colormap = xcb_generate_id(conn);
DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id); xcb_void_cookie_t cm_cookie = xcb_create_colormap_checked(conn,
XCB_COLORMAP_ALLOC_NONE,
colormap,
root,
visual_type->visual_id);
xcb_generic_error_t *error = xcb_request_check(conn, cm_cookie);
if (error != NULL) {
ELOG("Could not create colormap. Error code: %d\n", error->error_code);
exit(EXIT_FAILURE);
}
} else {
visual_type = get_visualtype(root_screen);
}
DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_type->visual_id);
DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d, dpi = %d\n", DLOG("root_screen->height_in_pixels = %d, root_screen->height_in_millimeters = %d, dpi = %d\n",
root_screen->height_in_pixels, root_screen->height_in_millimeters, root_screen->height_in_pixels, root_screen->height_in_millimeters,
(int)((double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters)); (int)((double)root_screen->height_in_pixels * 25.4 / (double)root_screen->height_in_millimeters));

65
src/x.c
View File

@ -101,47 +101,32 @@ void x_con_init(Con *con, uint16_t depth) {
uint32_t mask = 0; uint32_t mask = 0;
uint32_t values[5]; uint32_t values[5];
xcb_visualid_t visual = XCB_COPY_FROM_PARENT; /* For custom visuals, we need to create a colormap before creating
xcb_colormap_t win_colormap = XCB_NONE; * this window. It will be freed directly after creating the window. */
if (depth != root_depth && depth != XCB_COPY_FROM_PARENT) { xcb_visualid_t visual = get_visualid_by_depth(depth);
/* For custom visuals, we need to create a colormap before creating xcb_colormap_t win_colormap = xcb_generate_id(conn);
* this window. It will be freed directly after creating the window. */ xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual);
visual = get_visualid_by_depth(depth);
win_colormap = xcb_generate_id(conn);
xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual);
/* We explicitly set a background color and border color (even though we /* We explicitly set a background color and border color (even though we
* dont even have a border) because the X11 server requires us to when * dont even have a border) because the X11 server requires us to when
* using 32 bit color depths, see * using 32 bit color depths, see
* http://stackoverflow.com/questions/3645632 */ * http://stackoverflow.com/questions/3645632 */
mask |= XCB_CW_BACK_PIXEL; mask |= XCB_CW_BACK_PIXEL;
values[0] = root_screen->black_pixel; values[0] = root_screen->black_pixel;
mask |= XCB_CW_BORDER_PIXEL; mask |= XCB_CW_BORDER_PIXEL;
values[1] = root_screen->black_pixel; values[1] = root_screen->black_pixel;
/* our own frames should not be managed */ /* our own frames should not be managed */
mask |= XCB_CW_OVERRIDE_REDIRECT; mask |= XCB_CW_OVERRIDE_REDIRECT;
values[2] = 1; values[2] = 1;
/* see include/xcb.h for the FRAME_EVENT_MASK */ /* see include/xcb.h for the FRAME_EVENT_MASK */
mask |= XCB_CW_EVENT_MASK; mask |= XCB_CW_EVENT_MASK;
values[3] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW; values[3] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
mask |= XCB_CW_COLORMAP; mask |= XCB_CW_COLORMAP;
values[4] = win_colormap; values[4] = win_colormap;
} else {
/* our own frames should not be managed */
mask = XCB_CW_OVERRIDE_REDIRECT;
values[0] = 1;
/* see include/xcb.h for the FRAME_EVENT_MASK */
mask |= XCB_CW_EVENT_MASK;
values[1] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
mask |= XCB_CW_COLORMAP;
values[2] = colormap;
}
Rect dims = {-15, -15, 10, 10}; Rect dims = {-15, -15, 10, 10};
xcb_window_t frame_id = create_window(conn, dims, depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values); xcb_window_t frame_id = create_window(conn, dims, depth, visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
@ -523,6 +508,14 @@ void x_draw_decoration(Con *con) {
if (parent->frame_buffer.id == XCB_NONE) if (parent->frame_buffer.id == XCB_NONE)
goto copy_pixmaps; goto copy_pixmaps;
/* For the first child, we clear the parent pixmap to ensure there's no
* garbage left on there. This is important to avoid tearing when using
* transparency. */
if (con == TAILQ_FIRST(&(con->parent->nodes_head))) {
draw_util_clear_surface(conn, &(con->parent->frame_buffer), COLOR_TRANSPARENT);
FREE(con->parent->deco_render_params);
}
/* 4: paint the bar */ /* 4: paint the bar */
draw_util_rectangle(conn, &(parent->frame_buffer), p->color->background, draw_util_rectangle(conn, &(parent->frame_buffer), p->color->background,
con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height); con->deco_rect.x, con->deco_rect.y, con->deco_rect.width, con->deco_rect.height);

View File

@ -252,6 +252,11 @@ uint16_t get_visual_depth(xcb_visualid_t visual_id) {
} }
return 0; return 0;
} }
/*
* Get visual type specified by visualid
*
*/
xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id) { xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id) {
xcb_depth_iterator_t depth_iter; xcb_depth_iterator_t depth_iter;