From 4d5f9b60e30b8ffa117b71cc9115152464373e32 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 24 Feb 2014 12:35:56 +0000 Subject: [PATCH] Use 32bit visuals when available --- README.pod | 4 +- bar.c | 110 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/README.pod b/README.pod index 6f3be14..412e0bd 100644 --- a/README.pod +++ b/README.pod @@ -4,7 +4,7 @@ bar - bar ain't recursive =head1 SYNOPSIS -I [-h | -g IBIB<+>I | -b | -d | -f I | -a I| -p | -u I | -B I | -F I] +I [-h | -g IBIB<+>I | -b | -d | -f I | -p | -u I | -B I | -F I] =head1 DESCRIPTION @@ -48,7 +48,7 @@ Sets the underline width in pixels. The default is 1. =item B<-B> I -Set the background color of the bar. I might be either in hex format (#rrggbb) or in the symbolic name format (eg. white, brightred, darkgray). +Set the background color of the bar. I might be either in hex format (#aarrggbb) or in the symbolic name format (eg. white, brightred, darkgray). If no compositor such as compton or xcompmgr is running the alpha channel is silently ignored. =item B<-F> I diff --git a/bar.c b/bar.c index 636a946..5d17968 100644 --- a/bar.c +++ b/bar.c @@ -57,10 +57,11 @@ static xcb_connection_t *c; static xcb_screen_t *scr; static xcb_drawable_t canvas; static xcb_gcontext_t gc[GC_MAX]; +static xcb_visualid_t visual; +static xcb_colormap_t colormap; static monitor_t *monhead, *montail; static font_t *main_font, *alt_font; static uint32_t attrs = 0; -static float ba = 1.0f; /* bar alpha */ static bool dock = false; static bool topbar = true; static int bw = -1, bh = -1, bx = 0; @@ -140,16 +141,22 @@ parse_color (const char *str, char **end, const uint32_t def) return def; } - /* Hex rapresentation */ - if (str[0] == '#') - return strtoul(str + 1, end, 16); + /* Hex representation */ + if (str[0] == '#') { + errno = 0; + uint32_t tmp = strtoul(str + 1, end, 16); + /* Some error checking it's good */ + if (errno) + return def; + return tmp; + } /* Actual color name, resolve it */ str_len = 0; while (isalpha(str[str_len])) str_len++; - nc_reply = xcb_alloc_named_color_reply(c, xcb_alloc_named_color(c, scr->default_colormap, str_len, str), NULL); + nc_reply = xcb_alloc_named_color_reply(c, xcb_alloc_named_color(c, colormap, str_len, str), NULL); if (!nc_reply) fprintf(stderr, "Could not alloc color \"%.*s\"\n", str_len, str); @@ -327,7 +334,6 @@ enum { NET_WM_STRUT_PARTIAL, NET_WM_STRUT, NET_WM_STATE, - NET_WM_WINDOW_OPACITY, NET_WM_STATE_STICKY, NET_WM_STATE_ABOVE, }; @@ -342,7 +348,6 @@ set_ewmh_atoms (void) "_NET_WM_STRUT_PARTIAL", "_NET_WM_STRUT", "_NET_WM_STATE", - "_NET_WM_WINDOW_OPACITY", /* Leave those at the end since are batch-set */ "_NET_WM_STATE_STICKY", "_NET_WM_STATE_ABOVE", @@ -378,7 +383,6 @@ set_ewmh_atoms (void) strut[11] = mon->x + mon->width; } - xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_OPACITY], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){ (uint32_t)(ba * 0xffffffff) } ); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM, 32, 1, &atom_list[NET_WM_WINDOW_TYPE_DOCK]); xcb_change_property(c, XCB_PROP_MODE_APPEND, mon->window, atom_list[NET_WM_STATE], XCB_ATOM_ATOM, 32, 2, &atom_list[NET_WM_STATE_STICKY]); xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_DESKTOP], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){ -1 } ); @@ -405,17 +409,15 @@ monitor_new (int x, int y, int width, int height) int win_y = (topbar ? 0 : height - bh) + y; ret->window = xcb_generate_id(c); - xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root, + int depth = (visual == scr->root_visual) ? XCB_COPY_FROM_PARENT : 32; + xcb_create_window(c, depth, ret->window, scr->root, x, win_y, width, bh, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, - XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, - (const uint32_t []){ bgc, dock, XCB_EVENT_MASK_EXPOSURE }); + XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, + XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, + (const uint32_t []){ bgc, bgc, dock, XCB_EVENT_MASK_EXPOSURE, colormap }); ret->pixmap = xcb_generate_id(c); - xcb_create_pixmap(c, scr->root_depth, ret->pixmap, scr->root, width, bh); - - /* Clear the bar */ - fill_rect(ret->pixmap, gc[GC_CLEAR], 0, 0, width, bh); + xcb_create_pixmap(c, depth, ret->pixmap, ret->window, width, bh); return ret; } @@ -603,6 +605,27 @@ get_xinerama_monitors (void) monitor_create_chain(rects, screens); } +xcb_visualid_t +get_visual (void) +{ + xcb_depth_iterator_t iter; + + iter = xcb_screen_allowed_depths_iterator(scr); + + /* Try to find a RGBA visual */ + while (iter.rem) { + xcb_visualtype_t *vis = xcb_depth_visuals(iter.data); + + if (iter.data->depth == 32) + return vis->visual_id; + + xcb_depth_next(&iter); + } + + /* Fallback to the default one */ + return scr->root_visual; +} + void xconn (void) { @@ -615,6 +638,12 @@ xconn (void) /* Grab infos from the first screen */ scr = xcb_setup_roots_iterator(xcb_get_setup(c)).data; + + /* Try to get a RGBA visual and build the colormap for that */ + visual = get_visual(); + + colormap = xcb_generate_id(c); + xcb_create_colormap(c, XCB_COLORMAP_ALLOC_NONE, colormap, scr->root, visual); } void @@ -640,18 +669,6 @@ init (void) if (bh < 0 || bh > scr->height_in_pixels) bh = main_font->height + bu + 2; - ugc = fgc; - - /* Create the gc for drawing */ - gc[GC_DRAW] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_DRAW], scr->root, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []){ fgc, bgc }); - - gc[GC_CLEAR] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_CLEAR], scr->root, XCB_GC_FOREGROUND, (const uint32_t []){ bgc }); - - gc[GC_ATTR] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_ATTR], scr->root, XCB_GC_FOREGROUND, (const uint32_t []){ ugc }); - /* Generate a list of screens */ const xcb_query_extension_reply_t *qe_reply; @@ -688,9 +705,21 @@ init (void) /* For WM that support EWMH atoms */ set_ewmh_atoms(); - /* Make the bar visible */ - for (monitor_t *mon = monhead; mon; mon = mon->next) + /* Create the gc for drawing */ + gc[GC_DRAW] = xcb_generate_id(c); + xcb_create_gc(c, gc[GC_DRAW], monhead->pixmap, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []){ fgc, bgc }); + + gc[GC_CLEAR] = xcb_generate_id(c); + xcb_create_gc(c, gc[GC_CLEAR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ bgc }); + + gc[GC_ATTR] = xcb_generate_id(c); + xcb_create_gc(c, gc[GC_ATTR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ ugc }); + + /* Make the bar visible and clear the pixmap */ + for (monitor_t *mon = monhead; mon; mon = mon->next) { + fill_rect(mon->pixmap, gc[GC_CLEAR], 0, 0, mon->width, bh); xcb_map_window(c, mon->window); + } xcb_flush(c); } @@ -716,6 +745,8 @@ cleanup (void) monhead = next; } + xcb_free_colormap(c, colormap); + if (gc[GC_DRAW]) xcb_free_gc(c, gc[GC_DRAW]); if (gc[GC_CLEAR]) @@ -824,8 +855,10 @@ main (int argc, char **argv) xconn(); /* B/W combo */ - dbgc = bgc = scr->black_pixel; - dfgc = fgc = scr->white_pixel; + dbgc = bgc = parse_color("black", NULL, scr->black_pixel); + dfgc = fgc = parse_color("white", NULL, scr->white_pixel); + + ugc = fgc; char ch; while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) { @@ -837,13 +870,11 @@ main (int argc, char **argv) "\t-b Put bar at the bottom of the screen\n" "\t-d Force docking (use this if your WM isn't EWMH compliant)\n" "\t-f Bar font list, comma separated\n" - "\t-a Set the bar alpha ranging from 0.0 to 1.0 (requires a compositor)\n" "\t-p Don't close after the data ends\n" "\t-u Set the underline/overline height in pixels\n" - "\t-B Set background color in #RRGGBB\n" - "\t-F Set foreground color in #RRGGBB\n", argv[0]); + "\t-B Set background color in #AARRGGBB\n" + "\t-F Set foreground color in #AARRGGBB\n", argv[0]); exit (EXIT_SUCCESS); - case 'a': ba = strtof(optarg, NULL); break; case 'g': (void)parse_geometry_string(optarg, geom_v); break; case 'p': permanent = true; break; case 'b': topbar = false; break; @@ -860,17 +891,12 @@ main (int argc, char **argv) bh = geom_v[1]; bx = geom_v[2]; - /* Sanitize the arguments */ + /* Check the geometry */ if (bx >= scr->width_in_pixels || bx + bw > scr->width_in_pixels) { fprintf(stderr, "The geometry specified doesn't fit the screen!\n"); return EXIT_FAILURE; } - if (ba > 1.0f) - ba = 1.0f; - if (ba < 0.0f) - ba = 0.0f; - /* Do the heavy lifting */ init(); /* Get the fd to Xserver */