]> git.sur5r.net Git - i3/i3/commitdiff
Implement support for chosing a 32 bit visual (necessary for pseudo-transparency...
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 28 Jan 2012 16:09:02 +0000 (16:09 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Wed, 15 Feb 2012 18:56:07 +0000 (18:56 +0000)
You need to specify the --enable-32bit-visual flag when starting i3. This is
done because everything feels sluggish on my system when using a 32 bit visual
instead of a 24 bit visual. Fast > fancy.

include/i3.h
libi3/get_colorpixel.c
src/main.c
src/x.c
src/xcb.c

index dbe477bee26817b248ba675d5cb5a26bc2fc44e9..bd40f16b9eb8e79937d562937fab9fc743394a90 100644 (file)
@@ -50,7 +50,14 @@ extern TAILQ_HEAD(ws_assignments_head, Workspace_Assignment) ws_assignments;
 extern TAILQ_HEAD(assignments_head, Assignment) assignments;
 extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
 extern xcb_screen_t *root_screen;
+
+/* Color depth, visual id and colormap to use when creating windows and
+ * pixmaps. Will use 32 bit depth and an appropriate visual, if available,
+ * otherwise the root window’s default (usually 24 bit TrueColor). */
 extern uint8_t root_depth;
+extern xcb_visualid_t visual_id;
+extern xcb_colormap_t colormap;
+
 extern bool xcursor_supported, xkb_supported;
 extern xcb_window_t root;
 extern struct ev_loop *main_loop;
index 73bbef3d52448ba6911f742132eeefc64253f60f..b093594e10484d74677752756798062b5178719b 100644 (file)
@@ -2,7 +2,7 @@
  * vim:ts=4:sw=4:expandtab
  *
  * i3 - an improved dynamic tiling window manager
- * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
  *
  */
 #include <stdlib.h>
@@ -32,5 +32,7 @@ uint32_t get_colorpixel(const char *hex) {
     uint8_t g = strtol(strgroups[1], NULL, 16);
     uint8_t b = strtol(strgroups[2], NULL, 16);
 
-    return (r << 16 | g << 8 | b);
+    /* We set the first 8 bits high to have 100% opacity in case of a 32 bit
+     * color depth visual. */
+    return (0xFF << 24) | (r << 16 | g << 8 | b);
 }
index 7738dacc12e1e6725e975cce0446dd97fa5f6fde..76ea838d71ce9143f4cbfe552fefdff0901d8714 100644 (file)
@@ -53,7 +53,13 @@ xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
 
 xcb_screen_t *root_screen;
 xcb_window_t root;
+
+/* Color depth, visual id and colormap to use when creating windows and
+ * 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_colormap_t colormap;
 
 struct ev_loop *main_loop;
 
@@ -244,6 +250,7 @@ int main(int argc, char *argv[]) {
     bool delete_layout_path = false;
     bool force_xinerama = false;
     bool disable_signalhandler = false;
+    bool enable_32bit_visual = false;
     static struct option long_options[] = {
         {"no-autostart", no_argument, 0, 'a'},
         {"config", required_argument, 0, 'c'},
@@ -258,9 +265,12 @@ int main(int argc, char *argv[]) {
         {"shmlog_size", required_argument, 0, 0},
         {"get-socketpath", no_argument, 0, 0},
         {"get_socketpath", no_argument, 0, 0},
+        {"enable-32bit-visual", no_argument, 0, 0},
+        {"enable_32bit_visual", no_argument, 0, 0},
         {0, 0, 0, 0}
     };
     int option_index = 0, opt;
+    xcb_void_cookie_t colormap_cookie;
 
     setlocale(LC_ALL, "");
 
@@ -358,6 +368,11 @@ int main(int argc, char *argv[]) {
                     layout_path = sstrdup(optarg);
                     delete_layout_path = true;
                     break;
+                } else if (strcmp(long_options[option_index].name, "enable_32bit_visual") == 0 ||
+                           strcmp(long_options[option_index].name, "enable-32bit-visual") == 0) {
+                    LOG("Enabling 32 bit visual (if available)\n");
+                    enable_32bit_visual = true;
+                    break;
                 }
                 /* fall-through */
             default:
@@ -384,6 +399,10 @@ int main(int argc, char *argv[]) {
                                 "\tto 0 disables SHM logging entirely.\n"
                                 "\tThe default is %d bytes.\n", shmlog_size);
                 fprintf(stderr, "\n");
+                fprintf(stderr, "\t--enable-32bit-visual\n"
+                                "\tMakes i3 use a 32 bit visual, if available. Necessary for\n"
+                                "\tpseudo-transparency with xcompmgr.\n");
+                fprintf(stderr, "\n");
                 fprintf(stderr, "If you pass plain text arguments, i3 will interpret them as a command\n"
                                 "to send to a currently running i3 (like i3-msg). This allows you to\n"
                                 "use nice and logical commands, such as:\n"
@@ -494,7 +513,38 @@ int main(int argc, char *argv[]) {
 
     root_screen = xcb_aux_get_screen(conn, conn_screen);
     root = root_screen->root;
+
+    /* 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;
+    colormap = root_screen->default_colormap;
+
+    if (enable_32bit_visual) {
+        xcb_depth_iterator_t depth_iter;
+        xcb_visualtype_iterator_t visual_iter;
+        for (depth_iter = xcb_screen_allowed_depths_iterator(root_screen);
+             depth_iter.rem;
+             xcb_depth_next(&depth_iter)) {
+            if (depth_iter.data->depth != 32)
+                continue;
+            visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+            if (!visual_iter.rem)
+                continue;
+
+            visual_id = visual_iter.data->visual_id;
+            root_depth = depth_iter.data->depth;
+            colormap = xcb_generate_id(conn);
+            colormap_cookie = xcb_create_colormap_checked(conn, XCB_COLORMAP_ALLOC_NONE, colormap, root, visual_id);
+            DLOG("Found a visual with 32 bit depth.\n");
+            break;
+        }
+    }
+
+    DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id);
+
     xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(conn, root);
     xcb_query_pointer_cookie_t pointercookie = xcb_query_pointer(conn, root);
 
@@ -524,6 +574,20 @@ int main(int argc, char *argv[]) {
     cookie = xcb_change_window_attributes_checked(conn, root, mask, values);
     check_error(conn, cookie, "Another window manager seems to be running");
 
+    /* By now we already checked for replies once, so let’s see if colormap
+     * creation worked (if requested). */
+    if (colormap != root_screen->default_colormap) {
+        xcb_generic_error_t *error = xcb_request_check(conn, colormap_cookie);
+        if (error != NULL) {
+            ELOG("Could not create ColorMap for 32 bit visual, falling back to X11 default.\n");
+            root_depth = root_screen->root_depth;
+            visual_id = root_screen->root_visual;
+            colormap = root_screen->default_colormap;
+            DLOG("root_depth = %d, visual_id = 0x%08x.\n", root_depth, visual_id);
+            free(error);
+        }
+    }
+
     xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(conn, gcookie, NULL);
     if (greply == NULL) {
         ELOG("Could not get geometry of the root window, exiting\n");
diff --git a/src/x.c b/src/x.c
index e4e768ea3c0d38ffa34a06b454093cebb7437fcd..fe64d3ecca6be7f3a4daf3190ca4b347df1a3c5f 100644 (file)
--- a/src/x.c
+++ b/src/x.c
@@ -90,15 +90,28 @@ void x_con_init(Con *con) {
      * get the initial geometry right */
 
     uint32_t mask = 0;
-    uint32_t values[2];
+    uint32_t values[5];
+
+    /* 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[0] = 1;
+    values[2] = 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;
+    values[3] = FRAME_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW;
+
+    mask |= XCB_CW_COLORMAP;
+    values[4] = colormap;
 
     Rect dims = { -15, -15, 10, 10 };
     con->frame = create_window(conn, dims, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCURSOR_CURSOR_POINTER, false, mask, values);
index 48906a26148145ffe3cbaa62ad2ef87b97bc20a9..5aa74b32b396d51dabc5ab934540bcc8ec2cfcdc 100644 (file)
--- a/src/xcb.c
+++ b/src/xcb.c
@@ -20,8 +20,17 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims, uint16_t window_cl
         enum xcursor_cursor_t cursor, bool map, uint32_t mask, uint32_t *values) {
     xcb_window_t result = xcb_generate_id(conn);
 
-    /* If the window class is XCB_WINDOW_CLASS_INPUT_ONLY, depth has to be 0 */
-    uint16_t depth = (window_class == XCB_WINDOW_CLASS_INPUT_ONLY ? 0 : XCB_COPY_FROM_PARENT);
+    /* By default, the color depth determined in src/main.c is used (32 bit if
+     * available, otherwise the X11 root window’s default depth). */
+    uint16_t depth = root_depth;
+    xcb_visualid_t visual = visual_id;
+
+    /* If the window class is XCB_WINDOW_CLASS_INPUT_ONLY, we copy depth and
+     * visual id from the parent window. */
+    if (window_class == XCB_WINDOW_CLASS_INPUT_ONLY) {
+        depth = XCB_COPY_FROM_PARENT;
+        visual = XCB_COPY_FROM_PARENT;
+    }
 
     xcb_create_window(conn,
             depth,
@@ -30,7 +39,7 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims, uint16_t window_cl
             dims.x, dims.y, dims.width, dims.height, /* dimensions */
             0, /* border = 0, we draw our own */
             window_class,
-            XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
+            visual,
             mask,
             values);