]> git.sur5r.net Git - i3/i3/commitdiff
Use 32-bit visual by default if available.
authorIngo Bürk <ingo.buerk@tngtech.com>
Tue, 17 Nov 2015 11:50:06 +0000 (12:50 +0100)
committerIngo Bürk <ingo.buerk@tngtech.com>
Mon, 23 Nov 2015 21:18:02 +0000 (22:18 +0100)
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

include/libi3.h
include/xcb.h
libi3/draw_util.c
src/con.c
src/main.c
src/x.c
src/xcb.c

index 02988837ebcdf3240f166d3ab94f561a1e73c240..08b0140280b9d996a93c8bbb063b0f659ae8f749 100644 (file)
@@ -499,11 +499,14 @@ typedef struct color_t {
     double red;
     double green;
     double blue;
+    double alpha;
 
     /* The colorpixel we use for direct XCB calls. */
     uint32_t colorpixel;
 } 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
  * and the corresponding cairo objects representing it. */
 typedef struct surface_t {
index 7fae41f5dc0525c1f72c7c6f782b6370aa21559f..86019c5d958dbe0284af58df8ee328d4100ff051 100644 (file)
@@ -139,6 +139,11 @@ void xcb_set_root_cursor(int cursor);
  *
  */
 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);
 
 /**
index 4015ba92faf0270b2369f9c6f0cdbea0b74382ed..f6c53865b4937cd0feb60cfa0f2249d37d2b7a84 100644 (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,
                             xcb_visualtype_t *visual, int width, int height) {
     surface->id = drawable;
-    surface->visual_type = (visual == NULL) ? visual_type : visual;
+    surface->visual_type = ((visual == NULL) ? visual_type : visual);
     surface->width = width;
     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) {
-    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)};
 }
 
@@ -107,7 +117,7 @@ static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surfac
     RETURN_UNLESS_SURFACE_INITIALIZED(surface);
 
 #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
     uint32_t colorpixel = color.colorpixel;
     xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
index 03fd0ee6c163da2c8be3b50c9dd8bf53b4bdd6e1..64dbec69bc30941ea0d79e261a3d60cc9834b051 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -47,7 +47,7 @@ Con *con_new_skeleton(Con *parent, i3Window *window) {
         new->depth = window->depth;
         new->window->aspect_ratio = 0.0;
     } else {
-        new->depth = XCB_COPY_FROM_PARENT;
+        new->depth = root_depth;
     }
     DLOG("opening window\n");
 
index 1e0ec4a5501c0ca7f4b56a0a114b736089ee9322..9c67b42a0cca6ddd930f5ed324e40f229eacec3a 100644 (file)
@@ -59,7 +59,6 @@ xcb_window_t root;
  * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
  * otherwise the root window’s default (usually 24 bit TrueColor). */
 uint8_t root_depth;
-xcb_visualid_t visual_id;
 xcb_visualtype_t *visual_type;
 xcb_colormap_t colormap;
 
@@ -482,16 +481,29 @@ int main(int argc, char *argv[]) {
 #include "atoms.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;
-    visual_id = root_screen->root_visual;
-    visual_type = get_visualtype(root_screen);
     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);
+
+        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_id);
+    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",
          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));
diff --git a/src/x.c b/src/x.c
index 17970fb8922f0dae464eb373decaf7b73b38ad8c..f1f971e94286fec0c1422f3375def5ca867462f7 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -101,47 +101,32 @@ void x_con_init(Con *con, uint16_t depth) {
     uint32_t mask = 0;
     uint32_t values[5];
 
-    xcb_visualid_t visual = XCB_COPY_FROM_PARENT;
-    xcb_colormap_t win_colormap = XCB_NONE;
-    if (depth != root_depth && depth != XCB_COPY_FROM_PARENT) {
-        /* For custom visuals, we need to create a colormap before creating
-         * this window. It will be freed directly after creating the window. */
-        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
-         * don’t even have a border) because the X11 server requires us to when
-         * using 32 bit color depths, see
-         * http://stackoverflow.com/questions/3645632 */
-        mask |= XCB_CW_BACK_PIXEL;
-        values[0] = root_screen->black_pixel;
-
-        mask |= XCB_CW_BORDER_PIXEL;
-        values[1] = root_screen->black_pixel;
-
-        /* our own frames should not be managed */
-        mask |= XCB_CW_OVERRIDE_REDIRECT;
-        values[2] = 1;
-
-        /* see include/xcb.h for the FRAME_EVENT_MASK */
-        mask |= XCB_CW_EVENT_MASK;
-        values[3] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
-
-        mask |= XCB_CW_COLORMAP;
-        values[4] = win_colormap;
-    } else {
-        /* our own frames should not be managed */
-        mask = XCB_CW_OVERRIDE_REDIRECT;
-        values[0] = 1;
+    /* For custom visuals, we need to create a colormap before creating
+     * this window. It will be freed directly after creating the window. */
+    xcb_visualid_t visual = get_visualid_by_depth(depth);
+    xcb_colormap_t win_colormap = xcb_generate_id(conn);
+    xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, win_colormap, root, visual);
 
-        /* see include/xcb.h for the FRAME_EVENT_MASK */
-        mask |= XCB_CW_EVENT_MASK;
-        values[1] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
+    /* We explicitly set a background color and border color (even though we
+     * don’t even have a border) because the X11 server requires us to when
+     * using 32 bit color depths, see
+     * http://stackoverflow.com/questions/3645632 */
+    mask |= XCB_CW_BACK_PIXEL;
+    values[0] = root_screen->black_pixel;
 
-        mask |= XCB_CW_COLORMAP;
-        values[2] = colormap;
-    }
+    mask |= XCB_CW_BORDER_PIXEL;
+    values[1] = root_screen->black_pixel;
+
+    /* our own frames should not be managed */
+    mask |= XCB_CW_OVERRIDE_REDIRECT;
+    values[2] = 1;
+
+    /* see include/xcb.h for the FRAME_EVENT_MASK */
+    mask |= XCB_CW_EVENT_MASK;
+    values[3] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
+
+    mask |= XCB_CW_COLORMAP;
+    values[4] = win_colormap;
 
     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);
@@ -523,6 +508,14 @@ void x_draw_decoration(Con *con) {
     if (parent->frame_buffer.id == XCB_NONE)
         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 */
     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);
index 60fd421239480b1939a0c18dc83544007ad706e2..07f9281a58dba2f5284c58fe1aa256f8acf67eae 100644 (file)
--- a/src/xcb.c
+++ b/src/xcb.c
@@ -252,6 +252,11 @@ uint16_t get_visual_depth(xcb_visualid_t visual_id) {
     }
     return 0;
 }
+
+/*
+ * Get visual type specified by visualid
+ *
+ */
 xcb_visualtype_t *get_visualtype_by_id(xcb_visualid_t visual_id) {
     xcb_depth_iterator_t depth_iter;