Add transparency support. Reworked EWMH stuff, fixes #20.

This commit is contained in:
LemonBoy 2013-09-02 13:35:32 +00:00
parent 216162c7eb
commit d87fc1f0c8
3 changed files with 69 additions and 70 deletions

View File

@ -1,10 +1,11 @@
b(ar) a(in't) r(ecursive) b(ar) a(in't) r(ecursive)
========================= =========================
2012 (C) The Lemon Man 2012-2013 (C) The Lemon Man
A lightweight bar based on XCB (yay). Provides foreground/background color A lightweight bar based on XCB (yay). Provides foreground/background color
switching along with text alignment (screw you dzen!), full utf8 support switching along with text alignment (screw you dzen!), full utf8 support
and reduced memory footprint. Nothing less and nothing more. and reduced memory footprint. It also supports transparency when using a
compositor such as compton. Nothing less and nothing more.
Options Options
------- -------
@ -13,6 +14,7 @@ bar accepts a couple of command line switches.
``` ```
-h Show the help and bail out. -h Show the help and bail out.
-p Make the bar permanent. -p Make the bar permanent.
-f Force docking (use this if your WM isn't EWMH compliant)
-b Show the bar at the bottom of the screen. -b Show the bar at the bottom of the screen.
``` ```

127
bar.c
View File

@ -44,6 +44,7 @@ static xcb_gcontext_t clear_gc;
static xcb_gcontext_t underl_gc; static xcb_gcontext_t underl_gc;
static int bar_width; static int bar_width;
static int bar_bottom = BAR_BOTTOM; static int bar_bottom = BAR_BOTTOM;
static int force_docking = 0;
static fontset_item_t fontset[FONT_MAX]; static fontset_item_t fontset[FONT_MAX];
static fontset_item_t *sel_font = NULL; static fontset_item_t *sel_font = NULL;
@ -240,72 +241,67 @@ font_load (const char **font_list)
return 0; return 0;
} }
int enum {
set_ewmh_atoms (xcb_window_t root) NET_WM_WINDOW_TYPE,
NET_WM_WINDOW_TYPE_DOCK,
NET_WM_DESKTOP,
NET_WM_STRUT_PARTIAL,
NET_WM_STRUT,
NET_WM_STATE,
NET_WM_WINDOW_OPACITY,
NET_WM_STATE_STICKY,
NET_WM_STATE_ABOVE,
};
void
set_ewmh_atoms ()
{ {
xcb_intern_atom_cookie_t cookies[5]; const char *atom_names[] = {
xcb_intern_atom_reply_t *reply; "_NET_WM_WINDOW_TYPE",
xcb_get_property_reply_t *reply1; "_NET_WM_WINDOW_TYPE_DOCK",
xcb_atom_t atoms[5]; "_NET_WM_DESKTOP",
int compliance_lvl; "_NET_WM_STRUT_PARTIAL",
uint32_t v[12] = {0}; "_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",
};
const int atoms = sizeof(atom_names)/sizeof(char *);
xcb_intern_atom_cookie_t atom_cookie[atoms];
xcb_atom_t atom_list[atoms];
xcb_intern_atom_reply_t *atom_reply;
int strut[12] = {0};
cookies[0] = xcb_intern_atom (c, 0, strlen ("_NET_WM_WINDOW_TYPE") , "_NET_WM_WINDOW_TYPE"); /* As suggested fetch all the cookies first (yum!) and then retrieve the
cookies[1] = xcb_intern_atom (c, 0, strlen ("_NET_WM_WINDOW_TYPE_DOCK"), "_NET_WM_WINDOW_TYPE_DOCK"); * atoms to exploit the async'ness */
cookies[2] = xcb_intern_atom (c, 0, strlen ("_NET_WM_DESKTOP") , "_NET_WM_DESKTOP"); for (int i = 0; i < atoms; i++)
cookies[3] = xcb_intern_atom (c, 0, strlen ("_NET_WM_STRUT_PARTIAL") , "_NET_WM_STRUT_PARTIAL"); atom_cookie[i] = xcb_intern_atom(c, 0, strlen(atom_names[i]), atom_names[i]);
cookies[4] = xcb_intern_atom (c, 0, strlen ("_NET_SUPPORTED") , "_NET_SUPPORTED");
reply = xcb_intern_atom_reply (c, cookies[0], NULL); for (int i = 0; i < atoms; i++) {
atoms[0] = reply->atom; free (reply); atom_reply = xcb_intern_atom_reply(c, atom_cookie[i], NULL);
reply = xcb_intern_atom_reply (c, cookies[1], NULL); if (!atom_reply)
atoms[1] = reply->atom; free (reply); return;
reply = xcb_intern_atom_reply (c, cookies[2], NULL); atom_list[i] = atom_reply->atom;
atoms[2] = reply->atom; free (reply); free(atom_reply);
reply = xcb_intern_atom_reply (c, cookies[3], NULL);
atoms[3] = reply->atom; free (reply);
reply = xcb_intern_atom_reply (c, cookies[4], NULL);
atoms[4] = reply->atom; free (reply);
compliance_lvl = 0;
reply1 = xcb_get_property_reply (c, xcb_get_property (c, 0, root, atoms[4], XCB_ATOM_ATOM, 0, -1), NULL);
if (!reply)
return compliance_lvl;
for (xcb_atom_t *a = xcb_get_property_value (reply1);
a && a != xcb_get_property_value_end (reply1).data;
a++)
{
/* Set the _NET_WM_WINDOW_TYPE_DOCK state */
if (*a == atoms[0]) {
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atoms[0], XCB_ATOM_ATOM, 32, 1, &atoms[1]);
compliance_lvl++;
} }
/* Show on every desktop */
if (*a == atoms[2]) { /* Prepare the strut array */
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atoms[2], XCB_ATOM_CARDINAL, 32, 1,
(const uint32_t []){ 0xffffffff } );
compliance_lvl++;
}
/* Tell the WM that this space is for the bar */
if (*a == atoms[3]) {
if (bar_bottom) { if (bar_bottom) {
v[3] = BAR_HEIGHT; strut[3] = BAR_HEIGHT;
v[11] = bar_width; strut[11] = bar_width;
} else {
strut[2] = BAR_HEIGHT;
strut[9] = bar_width;
} }
else {
v[2] = BAR_HEIGHT;
v[8] = bar_width;
}
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atoms[3], XCB_ATOM_CARDINAL, 32, 12, v);
compliance_lvl++;
}
}
free (reply1);
/* If the wm supports at least 2 NET atoms then mark as compliant */ xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_WINDOW_OPACITY], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){ (uint32_t)(BAR_OPACITY * 0xffffffff) } );
return (compliance_lvl > 1); xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, 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, win, atom_list[NET_WM_STATE], XCB_ATOM_ATOM, 32, 2, &atom_list[NET_WM_STATE_STICKY]);
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_DESKTOP], XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){ -1 } );
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, strut);
xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, atom_list[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, strut);
} }
void void
@ -340,11 +336,10 @@ init (void)
BAR_HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, BAR_HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE }); XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE });
/* Set EWMH hints */ /* For WM that support EWMH atoms */
int ewmh_docking = set_ewmh_atoms (root); set_ewmh_atoms();
/* Quirk for wm not supporting the EWMH docking method */ xcb_change_window_attributes (c, win, XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){ force_docking });
xcb_change_window_attributes (c, win, XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){ !ewmh_docking });
/* Create a temporary canvas */ /* Create a temporary canvas */
canvas = xcb_generate_id (c); canvas = xcb_generate_id (c);
@ -362,8 +357,6 @@ init (void)
/* Make the bar visible */ /* Make the bar visible */
xcb_map_window (c, win); xcb_map_window (c, win);
/* Send a configure event. Needed to make bar work with Openbox */
xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, (const uint32_t []){ BAR_OFFSET, y });
xcb_flush (c); xcb_flush (c);
} }
@ -412,16 +405,18 @@ main (int argc, char **argv)
int permanent = 0; int permanent = 0;
char ch; char ch;
while ((ch = getopt (argc, argv, "phb")) != -1) { while ((ch = getopt (argc, argv, "phbf")) != -1) {
switch (ch) { switch (ch) {
case 'h': case 'h':
printf ("usage: %s [-p | -h] [-b]\n" printf ("usage: %s [-p | -h] [-b]\n"
"\t-h Show this help\n" "\t-h Show this help\n"
"\t-b Put bar at the bottom of the screen\n" "\t-b Put bar at the bottom of the screen\n"
"\t-f Force docking (use this if your WM isn't EWMH compliant)\n"
"\t-p Don't close after the data ends\n", argv[0]); "\t-p Don't close after the data ends\n", argv[0]);
exit (0); exit (0);
case 'p': permanent = 1; break; case 'p': permanent = 1; break;
case 'b': bar_bottom = 1; break; case 'b': bar_bottom = 1; break;
case 'f': force_docking = 1; break;
} }
} }

View File

@ -14,6 +14,8 @@
#define BAR_FONT "-*-terminus-medium-r-normal-*-12-*-*-*-c-*-*-1","fixed" #define BAR_FONT "-*-terminus-medium-r-normal-*-12-*-*-*-c-*-*-1","fixed"
/* Some fonts don't set the right width for some chars, pheex it */ /* Some fonts don't set the right width for some chars, pheex it */
#define BAR_FONT_FALLBACK_WIDTH 6 #define BAR_FONT_FALLBACK_WIDTH 6
/* Define the opacity of the bar (requires a compositor such as compton) */
#define BAR_OPACITY 1.0 /* 0 is invisible, 1 is opaque */
/* Color palette */ /* Color palette */
#define BACKGROUND 0x232c31 #define BACKGROUND 0x232c31
#define COLOR0 0x2d3c46 #define COLOR0 0x2d3c46