From: Axel Wagner Date: Sat, 21 Aug 2010 11:09:34 +0000 (+0200) Subject: Implement double-buffering to get rid of flickering X-Git-Tag: 4.0.1~7^2~36^2~5 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=fe24eb748c98c8dea36dc0da5948ea118771215b;p=i3%2Fi3 Implement double-buffering to get rid of flickering --- diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index 837aa50b..69a34a12 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -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 */ diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index ae1c8278..ed578700 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -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; } }