]> git.sur5r.net Git - i3/i3/commitdiff
Implement double-buffering to get rid of flickering
authorAxel Wagner <mail@merovius.de>
Sat, 21 Aug 2010 11:09:34 +0000 (13:09 +0200)
committerAxel Wagner <mail@merovius.de>
Sat, 21 Aug 2010 11:27:51 +0000 (13:27 +0200)
i3bar/include/outputs.h
i3bar/src/xcb.c

index 837aa50b26fa38da92861f44abcf3bde78793939..69a34a12189763b96c45e1d348726e376a036bf5 100644 (file)
@@ -43,6 +43,7 @@ struct i3_output {
        rect            rect;         /* The rect (relative to the root-win) */
 
        xcb_window_t    bar;          /* The id of the bar of the output */
+    xcb_pixmap_t    buffer;       /* An extra pixmap for double-buffering */
        xcb_gcontext_t  bargc;        /* The graphical context of the bar */
 
        struct ws_head  *workspaces;  /* The workspaces on this output */
index ae1c8278ad1500298c6bec02c95ea2aca80479f5..ed57870041c26b63c44caecd08e752222d975359 100644 (file)
@@ -221,10 +221,11 @@ void init_xcb(char *fontname) {
 
     /* We load and allocate the font */
     xcb_font = xcb_generate_id(xcb_connection);
-    xcb_open_font(xcb_connection,
-                  xcb_font,
-                  strlen(fontname),
-                  fontname);
+    xcb_void_cookie_t open_font_cookie;
+    open_font_cookie = xcb_open_font_checked(xcb_connection,
+                                             xcb_font,
+                                             strlen(fontname),
+                                             fontname);
 
     /* We also need the fontheight to configure our bars accordingly */
     xcb_list_fonts_with_info_cookie_t cookie;
@@ -249,6 +250,14 @@ void init_xcb(char *fontname) {
     /* Now we get the atoms and save them in a nice data-structure */
     get_atoms();
 
+    xcb_generic_error_t *err = xcb_request_check(xcb_connection,
+                                                 open_font_cookie);
+
+    if (err != NULL) {
+        printf("ERROR: Could not open font! XCB-Error-Code: %d\n", err->error_code);
+        exit(EXIT_FAILURE);
+    }
+
     /* Now we calculate the font-height */
     xcb_list_fonts_with_info_reply_t *reply;
     reply = xcb_list_fonts_with_info_reply(xcb_connection,
@@ -333,46 +342,81 @@ void reconfig_windows() {
             printf("Creating Window for output %s\n", walk->name);
 
             walk->bar = xcb_generate_id(xcb_connection);
+            walk->buffer = xcb_generate_id(xcb_connection);
             mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
             /* Black background */
             values[0] = xcb_screens->black_pixel;
             /* The events we want to receive */
             values[1] = XCB_EVENT_MASK_EXPOSURE |
                         XCB_EVENT_MASK_BUTTON_PRESS;
-            xcb_create_window(xcb_connection,
-                              xcb_screens->root_depth,
-                              walk->bar,
-                              xcb_root,
-                              walk->rect.x, walk->rect.y,
-                              walk->rect.w, font_height + 6,
-                              1,
-                              XCB_WINDOW_CLASS_INPUT_OUTPUT,
-                              xcb_screens->root_visual,
-                              mask,
-                              values);
+
+            xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection,
+                                                                     xcb_screens->root_depth,
+                                                                     walk->bar,
+                                                                     xcb_root,
+                                                                     walk->rect.x, walk->rect.y,
+                                                                     walk->rect.w, font_height + 6,
+                                                                     1,
+                                                                     XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                                                                     xcb_screens->root_visual,
+                                                                     mask,
+                                                                     values);
+            
+            xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection,
+                                                                    xcb_screens->root_depth,
+                                                                    walk->buffer,
+                                                                    walk->bar,
+                                                                    walk->rect.w,
+                                                                    walk->rect.h);
 
             /* We want dock-windows (for now) */
-            xcb_change_property(xcb_connection,
-                                XCB_PROP_MODE_REPLACE,
-                                walk->bar,
-                                atoms[_NET_WM_WINDOW_TYPE],
-                                atoms[ATOM],
-                                32,
-                                1,
-                                (unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
+            xcb_void_cookie_t prop_cookie = xcb_change_property(xcb_connection,
+                                                                XCB_PROP_MODE_REPLACE,
+                                                                walk->bar,
+                                                                atoms[_NET_WM_WINDOW_TYPE],
+                                                                atoms[ATOM],
+                                                                32,
+                                                                1,
+                                                                (unsigned char*) &atoms[_NET_WM_WINDOW_TYPE_DOCK]);
 
             /* We also want a graphics-context (the "canvas" on which we draw) */
             walk->bargc = xcb_generate_id(xcb_connection);
             mask = XCB_GC_FONT;
             values[0] = xcb_font;
-            xcb_create_gc(xcb_connection,
-                          walk->bargc,
-                          walk->bar,
-                          mask,
-                          values);
+
+            xcb_void_cookie_t gc_cookie = xcb_create_gc_checked(xcb_connection,
+                                                                walk->bargc,
+                                                                walk->bar,
+                                                                mask,
+                                                                values);
 
             /* We finally map the bar (display it on screen) */
-            xcb_map_window(xcb_connection, walk->bar);
+            xcb_void_cookie_t map_cookie = xcb_map_window_checked(xcb_connection, walk->bar);
+
+            if ((err = xcb_request_check(xcb_connection, win_cookie)) != NULL) {
+                printf("ERROR: Could not create Window. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+
+            if ((err = xcb_request_check(xcb_connection, pm_cookie)) != NULL) {
+                printf("ERROR: Could not create Pixmap. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+            if ((err = xcb_request_check(xcb_connection, prop_cookie)) != NULL) {
+                printf("ERROR: Could not set dock mode. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+
+            if ((err = xcb_request_check(xcb_connection, gc_cookie)) != NULL) {
+                printf("ERROR: Could not create graphical context. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+
+            if ((err = xcb_request_check(xcb_connection, map_cookie)) != NULL) {
+                printf("ERROR: Could not map window. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
         } else {
             /* We already have a bar, so we just reconfigure it */
             mask = XCB_CONFIG_WINDOW_X |
@@ -384,11 +428,32 @@ void reconfig_windows() {
             values[2] = walk->rect.w;
             values[3] = font_height + 6;
             printf("Reconfiguring Window for output %s to %d,%d\n", walk->name, values[0], values[1]);
-            xcb_configure_window(xcb_connection,
-                                 walk->bar,
-                                 mask,
-                                 values);
-        }
+
+            xcb_void_cookie_t cfg_cookie = xcb_configure_window_checked(xcb_connection,
+                                                                        walk->bar,
+                                                                        mask,
+                                                                        values);
+
+            xcb_free_pixmap(xcb_connection, walk->buffer);
+            walk->buffer = xcb_generate_id(xcb_connection);
+
+            xcb_void_cookie_t pm_cookie = xcb_create_pixmap_checked(xcb_connection,
+                                                                    xcb_screens->root_depth,
+                                                                    walk->buffer,
+                                                                    walk->bar,
+                                                                    walk->rect.w,
+                                                                    walk->rect.h);
+
+            if ((err = xcb_request_check(xcb_connection, cfg_cookie)) != NULL) {
+                printf("ERROR: Could not reconfigure window. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+
+            if ((err = xcb_request_check(xcb_connection, pm_cookie)) != NULL) {
+                printf("ERROR: Could not create Pixmap. XCB-errorcode: %d\n", err->error_code);
+                exit(EXIT_FAILURE);
+            }
+         }
     }
 }
 
@@ -415,7 +480,7 @@ void draw_bars() {
                       &color);
         xcb_rectangle_t rect = { 0, 0, outputs_walk->rect.w, font_height + 6 };
         xcb_poly_fill_rectangle(xcb_connection,
-                                outputs_walk->bar,
+                                outputs_walk->buffer,
                                 outputs_walk->bargc,
                                 1,
                                 &rect);
@@ -437,7 +502,7 @@ void draw_bars() {
             xcb_void_cookie_t cookie;
             cookie = xcb_image_text_16(xcb_connection,
                                        glyph_count,
-                                       outputs_walk->bar,
+                                       outputs_walk->buffer,
                                        outputs_walk->bargc,
                                        outputs_walk->rect.w - get_string_width(text, glyph_count) - 4,
                                        font_height + 1,
@@ -470,7 +535,7 @@ void draw_bars() {
                           &color);
             xcb_rectangle_t rect = { i + 1, 1, ws_walk->name_width + 8, font_height + 4 };
             xcb_poly_fill_rectangle(xcb_connection,
-                                    outputs_walk->bar,
+                                    outputs_walk->buffer,
                                     outputs_walk->bargc,
                                     1,
                                     &rect);
@@ -481,13 +546,22 @@ void draw_bars() {
                           &color);
             xcb_image_text_16(xcb_connection,
                               ws_walk->name_glyphs,
-                              outputs_walk->bar,
+                              outputs_walk->buffer,
                               outputs_walk->bargc,
                               i + 5, font_height + 1,
                               ws_walk->ucs2_name);
             i += 10 + ws_walk->name_width;
         }
 
+        xcb_copy_area(xcb_connection,
+                      outputs_walk->buffer,
+                      outputs_walk->bar,
+                      outputs_walk->bargc,
+                      0, 0,
+                      0, 0,
+                      outputs_walk->rect.w,
+                      outputs_walk->rect.h);
+
         i = 0;
     }
 }