Introduce per-screen pixmaps. Text alignment works again. And underlines/overlines. Also, fixes.
This commit is contained in:
parent
072c4aa3a1
commit
08f30bd636
137
bar.c
137
bar.c
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define max(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 {
|
||||
xcb_font_t ptr;
|
||||
|
@ -31,6 +31,7 @@ typedef struct monitor_t {
|
|||
uint32_t x;
|
||||
uint32_t width;
|
||||
xcb_window_t window;
|
||||
xcb_pixmap_t pixmap;
|
||||
struct monitor_t *prev, *next;
|
||||
} monitor_t;
|
||||
|
||||
|
@ -45,10 +46,17 @@ enum {
|
|||
ALIGN_R
|
||||
};
|
||||
|
||||
enum {
|
||||
GC_DRAW = 0,
|
||||
GC_CLEAR,
|
||||
GC_ATTR,
|
||||
GC_MAX
|
||||
};
|
||||
|
||||
static xcb_connection_t *c;
|
||||
static xcb_screen_t *scr;
|
||||
static xcb_drawable_t canvas;
|
||||
static xcb_gcontext_t gc[3];
|
||||
static xcb_gcontext_t gc[GC_MAX];
|
||||
static monitor_t *monhead, *montail;
|
||||
static font_t *main_font, *alt_font;
|
||||
static uint32_t attrs = 0;
|
||||
|
@ -64,15 +72,15 @@ static uint32_t dfgc, dbgc;
|
|||
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[1], 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_DRAW], XCB_GC_BACKGROUND | XCB_GC_FOREGROUND, (const uint32_t []){ fgc, bgc });
|
||||
xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []){ bgc });
|
||||
xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []){ ugc });
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -86,31 +94,31 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
|
|||
|
||||
switch (align) {
|
||||
case ALIGN_C:
|
||||
xcb_copy_area(c, canvas, canvas, gc[0], mon->width / 2 - x / 2 + mon->x, 0,
|
||||
mon->width / 2 - (x + ch_width) / 2 + mon->x, 0, x, bh);
|
||||
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 0,
|
||||
mon->width / 2 - (x + ch_width) / 2, 0, x, bh);
|
||||
x = mon->width / 2 - (x + ch_width) / 2 + x;
|
||||
break;
|
||||
case ALIGN_R:
|
||||
xcb_copy_area(c, canvas, canvas, gc[0], mon->width - x + mon->x, 0,
|
||||
mon->width - x - ch_width + mon->x, 0, x, bh);
|
||||
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0,
|
||||
mon->width - x - ch_width, 0, x, bh);
|
||||
x = mon->width - ch_width;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ch = (ch >> 8) | (ch << 8);
|
||||
|
||||
/* 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 */
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
@ -187,7 +195,7 @@ parse (char *text)
|
|||
cur_font = main_font;
|
||||
cur_mon = monhead;
|
||||
|
||||
fill_rect(gc[1], 0, 0, bw, bh);
|
||||
fill_rect(cur_mon->pixmap, gc[GC_CLEAR], 0, 0, bw, bh);
|
||||
|
||||
for (;;) {
|
||||
if (*p == '\0' || *p == '\n')
|
||||
|
@ -220,19 +228,24 @@ parse (char *text)
|
|||
|
||||
case 'S':
|
||||
if (*p == '+' && cur_mon->next)
|
||||
{ cur_mon = cur_mon->next; pos_x = 0; }
|
||||
if (*p == '-' && cur_mon->prev)
|
||||
{ cur_mon = cur_mon->prev; pos_x = 0; }
|
||||
if (*p == 'f')
|
||||
{ cur_mon = monhead; pos_x = 0; }
|
||||
if (*p == 'l')
|
||||
{ cur_mon = montail ? montail : monhead; pos_x = 0; }
|
||||
if (isdigit(*p))
|
||||
{ cur_mon = cur_mon->next; }
|
||||
else if (*p == '-' && cur_mon->prev)
|
||||
{ cur_mon = cur_mon->prev; }
|
||||
else if (*p == 'f')
|
||||
{ cur_mon = monhead; }
|
||||
else if (*p == 'l')
|
||||
{ cur_mon = montail ? montail : monhead; }
|
||||
else if (isdigit(*p))
|
||||
{ cur_mon = monhead;
|
||||
for (int i = 0; i != *p-'0' && cur_mon->next; i++)
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
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);
|
||||
}
|
||||
|
@ -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,
|
||||
x, win_y, width, bh, 0,
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
|
||||
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
|
||||
(const uint32_t []){ bgc, XCB_EVENT_MASK_EXPOSURE });
|
||||
XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
||||
(const uint32_t []){ bgc, dock, XCB_EVENT_MASK_EXPOSURE });
|
||||
|
||||
xcb_change_window_attributes(c, ret->window, XCB_CW_OVERRIDE_REDIRECT,
|
||||
(const uint32_t []){ dock });
|
||||
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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -605,8 +621,8 @@ void
|
|||
init (void)
|
||||
{
|
||||
/* If I fits I sits */
|
||||
if (bw < 0 || bw > scr->width_in_pixels)
|
||||
bw = scr->width_in_pixels;
|
||||
if (bw < 0)
|
||||
bw = scr->width_in_pixels - bx;
|
||||
|
||||
/* Load the fonts */
|
||||
main_font = font_load(mfont ? mfont : "fixed");
|
||||
|
@ -622,7 +638,19 @@ init (void)
|
|||
|
||||
/* Adjust the height */
|
||||
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 */
|
||||
const xcb_query_extension_reply_t *qe_reply;
|
||||
|
@ -660,23 +688,6 @@ init (void)
|
|||
/* For WM that support 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 */
|
||||
for (monitor_t *mon = monhead; mon; mon = mon->next)
|
||||
xcb_map_window(c, mon->window);
|
||||
|
@ -688,29 +699,29 @@ void
|
|||
cleanup (void)
|
||||
{
|
||||
if (main_font) {
|
||||
xcb_close_font (c, main_font->ptr);
|
||||
xcb_close_font(c, main_font->ptr);
|
||||
free(main_font);
|
||||
}
|
||||
|
||||
if (alt_font) {
|
||||
xcb_close_font (c, alt_font->ptr);
|
||||
xcb_close_font(c, alt_font->ptr);
|
||||
free(alt_font);
|
||||
}
|
||||
|
||||
while (monhead) {
|
||||
monitor_t *next = monhead->next;
|
||||
xcb_destroy_window(c, monhead->window);
|
||||
xcb_free_pixmap(c, monhead->pixmap);
|
||||
free(monhead);
|
||||
monhead = next;
|
||||
}
|
||||
|
||||
if (canvas)
|
||||
xcb_free_pixmap(c, canvas);
|
||||
if (gc[0])
|
||||
xcb_free_gc(c, gc[0]);
|
||||
if (gc[1])
|
||||
xcb_free_gc(c, gc[1]);
|
||||
if (gc[2])
|
||||
xcb_free_gc(c, gc[2]);
|
||||
if (gc[GC_DRAW])
|
||||
xcb_free_gc(c, gc[GC_DRAW]);
|
||||
if (gc[GC_CLEAR])
|
||||
xcb_free_gc(c, gc[GC_CLEAR]);
|
||||
if (gc[GC_ATTR])
|
||||
xcb_free_gc(c, gc[GC_ATTR]);
|
||||
if (c)
|
||||
xcb_disconnect(c);
|
||||
}
|
||||
|
@ -855,8 +866,6 @@ main (int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (bu >= bh)
|
||||
bu %= bh;
|
||||
if (ba > 1.0f)
|
||||
ba = 1.0f;
|
||||
if (ba < 0.0f)
|
||||
|
@ -866,8 +875,6 @@ main (int argc, char **argv)
|
|||
init();
|
||||
/* Get the fd to Xserver */
|
||||
pollin[1].fd = xcb_get_file_descriptor(c);
|
||||
/* Clear the bar */
|
||||
fill_rect(gc[1], 0, 0, bw, bh);
|
||||
|
||||
for (;;) {
|
||||
bool redraw = false;
|
||||
|
@ -901,7 +908,7 @@ main (int argc, char **argv)
|
|||
|
||||
if (redraw) { /* Copy our temporary pixmap onto the window */
|
||||
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