Introduce per-screen pixmaps. Text alignment works again. And underlines/overlines. Also, fixes.
This commit is contained in:
parent
072c4aa3a1
commit
08f30bd636
133
bar.c
133
bar.c
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||||
#define indexof(c,s) (strchr(s,c)-s)
|
#define indexof(c,s) (strchr((s),(c))-(s))
|
||||||
|
|
||||||
typedef struct font_t {
|
typedef struct font_t {
|
||||||
xcb_font_t ptr;
|
xcb_font_t ptr;
|
||||||
|
@ -31,6 +31,7 @@ typedef struct monitor_t {
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
|
xcb_pixmap_t pixmap;
|
||||||
struct monitor_t *prev, *next;
|
struct monitor_t *prev, *next;
|
||||||
} monitor_t;
|
} monitor_t;
|
||||||
|
|
||||||
|
@ -45,10 +46,17 @@ enum {
|
||||||
ALIGN_R
|
ALIGN_R
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GC_DRAW = 0,
|
||||||
|
GC_CLEAR,
|
||||||
|
GC_ATTR,
|
||||||
|
GC_MAX
|
||||||
|
};
|
||||||
|
|
||||||
static xcb_connection_t *c;
|
static xcb_connection_t *c;
|
||||||
static xcb_screen_t *scr;
|
static xcb_screen_t *scr;
|
||||||
static xcb_drawable_t canvas;
|
static xcb_drawable_t canvas;
|
||||||
static xcb_gcontext_t gc[3];
|
static xcb_gcontext_t gc[GC_MAX];
|
||||||
static monitor_t *monhead, *montail;
|
static monitor_t *monhead, *montail;
|
||||||
static font_t *main_font, *alt_font;
|
static font_t *main_font, *alt_font;
|
||||||
static uint32_t attrs = 0;
|
static uint32_t attrs = 0;
|
||||||
|
@ -64,15 +72,15 @@ static uint32_t dfgc, dbgc;
|
||||||
void
|
void
|
||||||
update_gc (void)
|
update_gc (void)
|
||||||
{
|
{
|
||||||
xcb_change_gc(c, gc[0], XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, (const uint32_t []){ fgc, bgc });
|
xcb_change_gc(c, gc[GC_DRAW], XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, (const uint32_t []){ fgc, bgc });
|
||||||
xcb_change_gc(c, gc[1], XCB_GC_FOREGROUND, (const uint32_t []){ bgc });
|
xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []){ bgc });
|
||||||
xcb_change_gc(c, gc[2], XCB_GC_FOREGROUND, (const uint32_t []){ ugc });
|
xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []){ ugc });
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fill_rect (xcb_gcontext_t gc, int x, int y, int width, int height)
|
fill_rect (xcb_drawable_t d, xcb_gcontext_t gc, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
xcb_poly_fill_rectangle(c, canvas, gc, 1, (const xcb_rectangle_t []){ { x, y, width, height } });
|
xcb_poly_fill_rectangle(c, d, gc, 1, (const xcb_rectangle_t []){ { x, y, width, height } });
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -86,31 +94,31 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
|
||||||
|
|
||||||
switch (align) {
|
switch (align) {
|
||||||
case ALIGN_C:
|
case ALIGN_C:
|
||||||
xcb_copy_area(c, canvas, canvas, gc[0], mon->width / 2 - x / 2 + mon->x, 0,
|
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 0,
|
||||||
mon->width / 2 - (x + ch_width) / 2 + mon->x, 0, x, bh);
|
mon->width / 2 - (x + ch_width) / 2, 0, x, bh);
|
||||||
x = mon->width / 2 - (x + ch_width) / 2 + x;
|
x = mon->width / 2 - (x + ch_width) / 2 + x;
|
||||||
break;
|
break;
|
||||||
case ALIGN_R:
|
case ALIGN_R:
|
||||||
xcb_copy_area(c, canvas, canvas, gc[0], mon->width - x + mon->x, 0,
|
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0,
|
||||||
mon->width - x - ch_width + mon->x, 0, x, bh);
|
mon->width - x - ch_width, 0, x, bh);
|
||||||
x = mon->width - ch_width;
|
x = mon->width - ch_width;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the background first */
|
/* Draw the background first */
|
||||||
fill_rect(gc[1], x + mon->x, 0, ch_width, bh);
|
fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh);
|
||||||
|
|
||||||
/* xcb accepts string in UCS-2 BE, so swap */
|
/* xcb accepts string in UCS-2 BE, so swap */
|
||||||
ch = (ch >> 8) | (ch << 8);
|
ch = (ch >> 8) | (ch << 8);
|
||||||
|
|
||||||
/* String baseline coordinates */
|
/* String baseline coordinates */
|
||||||
xcb_image_text_16(c, 1, canvas, gc[0], x + mon->x, bh / 2 + cur_font->height / 2 - cur_font->descent, (xcb_char2b_t *)&ch);
|
xcb_image_text_16(c, 1, mon->pixmap, gc[GC_DRAW], x, bh / 2 + cur_font->height / 2 - cur_font->descent, (xcb_char2b_t *)&ch);
|
||||||
|
|
||||||
/* We can render both at the same time */
|
/* We can render both at the same time */
|
||||||
if (attrs & ATTR_OVERL)
|
if (attrs & ATTR_OVERL)
|
||||||
fill_rect(gc[2], x + mon->x, 0, ch_width, bu);
|
fill_rect(mon->pixmap, gc[GC_ATTR], x, 0, ch_width, bu);
|
||||||
if (attrs & ATTR_UNDERL)
|
if (attrs & ATTR_UNDERL)
|
||||||
fill_rect(gc[2], x + mon->x, bh-bu, ch_width, bu);
|
fill_rect(mon->pixmap, gc[GC_ATTR], x, bh - bu, ch_width, bu);
|
||||||
|
|
||||||
return ch_width;
|
return ch_width;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +195,7 @@ parse (char *text)
|
||||||
cur_font = main_font;
|
cur_font = main_font;
|
||||||
cur_mon = monhead;
|
cur_mon = monhead;
|
||||||
|
|
||||||
fill_rect(gc[1], 0, 0, bw, bh);
|
fill_rect(cur_mon->pixmap, gc[GC_CLEAR], 0, 0, bw, bh);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (*p == '\0' || *p == '\n')
|
if (*p == '\0' || *p == '\n')
|
||||||
|
@ -220,19 +228,24 @@ parse (char *text)
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
if (*p == '+' && cur_mon->next)
|
if (*p == '+' && cur_mon->next)
|
||||||
{ cur_mon = cur_mon->next; pos_x = 0; }
|
{ cur_mon = cur_mon->next; }
|
||||||
if (*p == '-' && cur_mon->prev)
|
else if (*p == '-' && cur_mon->prev)
|
||||||
{ cur_mon = cur_mon->prev; pos_x = 0; }
|
{ cur_mon = cur_mon->prev; }
|
||||||
if (*p == 'f')
|
else if (*p == 'f')
|
||||||
{ cur_mon = monhead; pos_x = 0; }
|
{ cur_mon = monhead; }
|
||||||
if (*p == 'l')
|
else if (*p == 'l')
|
||||||
{ cur_mon = montail ? montail : monhead; pos_x = 0; }
|
{ cur_mon = montail ? montail : monhead; }
|
||||||
if (isdigit(*p))
|
else if (isdigit(*p))
|
||||||
{ cur_mon = monhead;
|
{ cur_mon = monhead;
|
||||||
for (int i = 0; i != *p-'0' && cur_mon->next; i++)
|
for (int i = 0; i != *p-'0' && cur_mon->next; i++)
|
||||||
cur_mon = cur_mon->next;
|
cur_mon = cur_mon->next;
|
||||||
}
|
}
|
||||||
p++;
|
else
|
||||||
|
{ p++; continue; }
|
||||||
|
|
||||||
|
p+;
|
||||||
|
pos_x = 0;
|
||||||
|
fill_rect(cur_mon->pixmap, gc[GC_CLEAR], 0, 0, cur_mon->width, bh);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* In case of error keep parsing after the closing } */
|
/* In case of error keep parsing after the closing } */
|
||||||
|
@ -266,7 +279,7 @@ parse (char *text)
|
||||||
/* If the character is outside the main font charset use the alternate font */
|
/* If the character is outside the main font charset use the alternate font */
|
||||||
cur_font = (ucs < main_font->char_min || ucs > main_font->char_max) ? alt_font : main_font;
|
cur_font = (ucs < main_font->char_min || ucs > main_font->char_max) ? alt_font : main_font;
|
||||||
|
|
||||||
xcb_change_gc(c, gc[0] , XCB_GC_FONT, (const uint32_t []){ cur_font->ptr });
|
xcb_change_gc(c, gc[GC_DRAW] , XCB_GC_FONT, (const uint32_t []){ cur_font->ptr });
|
||||||
|
|
||||||
pos_x += draw_char(cur_mon, cur_font, pos_x, align, ucs);
|
pos_x += draw_char(cur_mon, cur_font, pos_x, align, ucs);
|
||||||
}
|
}
|
||||||
|
@ -395,11 +408,14 @@ monitor_new (int x, int y, int width, int height)
|
||||||
xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root,
|
xcb_create_window(c, XCB_COPY_FROM_PARENT, ret->window, scr->root,
|
||||||
x, win_y, width, bh, 0,
|
x, win_y, width, bh, 0,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
|
||||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
||||||
(const uint32_t []){ bgc, XCB_EVENT_MASK_EXPOSURE });
|
(const uint32_t []){ bgc, dock, XCB_EVENT_MASK_EXPOSURE });
|
||||||
|
|
||||||
xcb_change_window_attributes(c, ret->window, XCB_CW_OVERRIDE_REDIRECT,
|
ret->pixmap = xcb_generate_id(c);
|
||||||
(const uint32_t []){ dock });
|
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);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -605,8 +621,8 @@ void
|
||||||
init (void)
|
init (void)
|
||||||
{
|
{
|
||||||
/* If I fits I sits */
|
/* If I fits I sits */
|
||||||
if (bw < 0 || bw > scr->width_in_pixels)
|
if (bw < 0)
|
||||||
bw = scr->width_in_pixels;
|
bw = scr->width_in_pixels - bx;
|
||||||
|
|
||||||
/* Load the fonts */
|
/* Load the fonts */
|
||||||
main_font = font_load(mfont ? mfont : "fixed");
|
main_font = font_load(mfont ? mfont : "fixed");
|
||||||
|
@ -622,7 +638,19 @@ init (void)
|
||||||
|
|
||||||
/* Adjust the height */
|
/* Adjust the height */
|
||||||
if (bh < 0 || bh > scr->height_in_pixels)
|
if (bh < 0 || bh > scr->height_in_pixels)
|
||||||
bh = main_font->height + 1;
|
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 */
|
/* Generate a list of screens */
|
||||||
const xcb_query_extension_reply_t *qe_reply;
|
const xcb_query_extension_reply_t *qe_reply;
|
||||||
|
@ -660,23 +688,6 @@ init (void)
|
||||||
/* For WM that support EWMH atoms */
|
/* For WM that support EWMH atoms */
|
||||||
set_ewmh_atoms();
|
set_ewmh_atoms();
|
||||||
|
|
||||||
/* Create a temporary canvas */
|
|
||||||
canvas = xcb_generate_id(c);
|
|
||||||
xcb_create_pixmap(c, scr->root_depth, canvas, scr->root, bw, bh);
|
|
||||||
|
|
||||||
/* Default to the classic B/W combo */
|
|
||||||
ugc = fgc;
|
|
||||||
|
|
||||||
/* Create the gc for drawing */
|
|
||||||
gc[0] = xcb_generate_id(c);
|
|
||||||
xcb_create_gc(c, gc[0], scr->root, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []){ fgc, bgc });
|
|
||||||
|
|
||||||
gc[1] = xcb_generate_id(c);
|
|
||||||
xcb_create_gc(c, gc[1], scr->root, XCB_GC_FOREGROUND, (const uint32_t []){ bgc });
|
|
||||||
|
|
||||||
gc[2] = xcb_generate_id(c);
|
|
||||||
xcb_create_gc(c, gc[2], scr->root, XCB_GC_FOREGROUND, (const uint32_t []){ bgc });
|
|
||||||
|
|
||||||
/* Make the bar visible */
|
/* Make the bar visible */
|
||||||
for (monitor_t *mon = monhead; mon; mon = mon->next)
|
for (monitor_t *mon = monhead; mon; mon = mon->next)
|
||||||
xcb_map_window(c, mon->window);
|
xcb_map_window(c, mon->window);
|
||||||
|
@ -699,18 +710,18 @@ cleanup (void)
|
||||||
|
|
||||||
while (monhead) {
|
while (monhead) {
|
||||||
monitor_t *next = monhead->next;
|
monitor_t *next = monhead->next;
|
||||||
|
xcb_destroy_window(c, monhead->window);
|
||||||
|
xcb_free_pixmap(c, monhead->pixmap);
|
||||||
free(monhead);
|
free(monhead);
|
||||||
monhead = next;
|
monhead = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canvas)
|
if (gc[GC_DRAW])
|
||||||
xcb_free_pixmap(c, canvas);
|
xcb_free_gc(c, gc[GC_DRAW]);
|
||||||
if (gc[0])
|
if (gc[GC_CLEAR])
|
||||||
xcb_free_gc(c, gc[0]);
|
xcb_free_gc(c, gc[GC_CLEAR]);
|
||||||
if (gc[1])
|
if (gc[GC_ATTR])
|
||||||
xcb_free_gc(c, gc[1]);
|
xcb_free_gc(c, gc[GC_ATTR]);
|
||||||
if (gc[2])
|
|
||||||
xcb_free_gc(c, gc[2]);
|
|
||||||
if (c)
|
if (c)
|
||||||
xcb_disconnect(c);
|
xcb_disconnect(c);
|
||||||
}
|
}
|
||||||
|
@ -855,8 +866,6 @@ main (int argc, char **argv)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bu >= bh)
|
|
||||||
bu %= bh;
|
|
||||||
if (ba > 1.0f)
|
if (ba > 1.0f)
|
||||||
ba = 1.0f;
|
ba = 1.0f;
|
||||||
if (ba < 0.0f)
|
if (ba < 0.0f)
|
||||||
|
@ -866,8 +875,6 @@ main (int argc, char **argv)
|
||||||
init();
|
init();
|
||||||
/* Get the fd to Xserver */
|
/* Get the fd to Xserver */
|
||||||
pollin[1].fd = xcb_get_file_descriptor(c);
|
pollin[1].fd = xcb_get_file_descriptor(c);
|
||||||
/* Clear the bar */
|
|
||||||
fill_rect(gc[1], 0, 0, bw, bh);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bool redraw = false;
|
bool redraw = false;
|
||||||
|
@ -901,7 +908,7 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
if (redraw) { /* Copy our temporary pixmap onto the window */
|
if (redraw) { /* Copy our temporary pixmap onto the window */
|
||||||
for (monitor_t *mon = monhead; mon; mon = mon->next) {
|
for (monitor_t *mon = monhead; mon; mon = mon->next) {
|
||||||
xcb_copy_area(c, canvas, mon->window, gc[0], mon->x, 0, 0, 0, mon->width, bh);
|
xcb_copy_area(c, mon->pixmap, mon->window, gc[GC_DRAW], 0, 0, 0, 0, mon->width, bh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user