Merge branch 'wip' into wip-monitor-opts
Conflicts: bar.c
This commit is contained in:
commit
e7d86b4a8b
|
@ -90,6 +90,12 @@ Set the text foreground color. The parameter I<color> can be I<-> or a color in
|
||||||
|
|
||||||
Set the text underline color. The parameter I<color> can be I<-> or a color in one of the formats mentioned before. The special value I<-> resets the color to the default one.
|
Set the text underline color. The parameter I<color> can be I<-> or a color in one of the formats mentioned before. The special value I<-> resets the color to the default one.
|
||||||
|
|
||||||
|
=item B<A>:I<command>:
|
||||||
|
|
||||||
|
Create a clickable area starting from the current position, when the area is clicked I<command> is executed. The area is closed when a B<A> token, not followed by : is encountered.
|
||||||
|
|
||||||
|
Eg. I<%{A:reboot:} Click here to reboot %{A}>
|
||||||
|
|
||||||
=item B<S>I<dir>
|
=item B<S>I<dir>
|
||||||
|
|
||||||
Change the monitor bar is rendering to. I<dir> can be either
|
Change the monitor bar is rendering to. I<dir> can be either
|
||||||
|
@ -155,3 +161,5 @@ L<git repository|https://github.com/LemonBoy/bar>
|
||||||
Xinerama support was kindly contributed by Stebalien
|
Xinerama support was kindly contributed by Stebalien
|
||||||
|
|
||||||
RandR support was kindly contributed by jvvv
|
RandR support was kindly contributed by jvvv
|
||||||
|
|
||||||
|
Clickable areas support was heavily based off u-ra contribution
|
||||||
|
|
199
bar.c
199
bar.c
|
@ -18,24 +18,34 @@
|
||||||
#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))
|
||||||
#define MONITORS_MAX 32
|
#define MONITORS_MAX 32
|
||||||
|
#define N 10
|
||||||
|
|
||||||
typedef struct font_t {
|
typedef struct font_t {
|
||||||
xcb_font_t ptr;
|
xcb_font_t ptr;
|
||||||
uint32_t descent;
|
int descent, height;
|
||||||
uint32_t height;
|
|
||||||
uint16_t char_max;
|
uint16_t char_max;
|
||||||
uint16_t char_min;
|
uint16_t char_min;
|
||||||
xcb_charinfo_t *width_lut;
|
xcb_charinfo_t *width_lut;
|
||||||
} font_t;
|
} font_t;
|
||||||
|
|
||||||
typedef struct monitor_t {
|
typedef struct monitor_t {
|
||||||
uint32_t x;
|
int x, width;
|
||||||
uint32_t width;
|
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
xcb_pixmap_t pixmap;
|
xcb_pixmap_t pixmap;
|
||||||
struct monitor_t *prev, *next;
|
struct monitor_t *prev, *next;
|
||||||
} monitor_t;
|
} monitor_t;
|
||||||
|
|
||||||
|
typedef struct area_t {
|
||||||
|
int begin, end, align;
|
||||||
|
xcb_window_t window;
|
||||||
|
char *cmd;
|
||||||
|
} area_t;
|
||||||
|
|
||||||
|
typedef struct area_stack_t {
|
||||||
|
int pos;
|
||||||
|
area_t slot[N];
|
||||||
|
} area_stack_t;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ATTR_OVERL = (1<<0),
|
ATTR_OVERL = (1<<0),
|
||||||
ATTR_UNDERL = (1<<1),
|
ATTR_UNDERL = (1<<1),
|
||||||
|
@ -56,7 +66,6 @@ enum {
|
||||||
|
|
||||||
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_gcontext_t gc[GC_MAX];
|
static xcb_gcontext_t gc[GC_MAX];
|
||||||
static xcb_visualid_t visual;
|
static xcb_visualid_t visual;
|
||||||
static xcb_colormap_t colormap;
|
static xcb_colormap_t colormap;
|
||||||
|
@ -70,39 +79,11 @@ static int bu = 1; /* Underline height */
|
||||||
static char *mfont, *afont;
|
static char *mfont, *afont;
|
||||||
static uint32_t fgc, bgc, ugc;
|
static uint32_t fgc, bgc, ugc;
|
||||||
static uint32_t dfgc, dbgc;
|
static uint32_t dfgc, dbgc;
|
||||||
|
static area_stack_t astack;
|
||||||
static uint32_t mons = 0;
|
static uint32_t mons = 0;
|
||||||
static int nmons = 0;
|
static int nmons = 0;
|
||||||
static int monlist[MONITORS_MAX];
|
static int monlist[MONITORS_MAX];
|
||||||
|
|
||||||
void
|
|
||||||
set_monitor (int n)
|
|
||||||
{
|
|
||||||
if (n >= MONITORS_MAX || n < 0) {
|
|
||||||
fprintf(stderr, "Invalic monitor specified: %d\n", n);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mons |= 1 << n;
|
|
||||||
monlist[nmons++] = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_monitor_pos (int n)
|
|
||||||
{
|
|
||||||
if (n < MONITORS_MAX && (mons & (1 << n)))
|
|
||||||
for (int i = 0; i < nmons; i++)
|
|
||||||
if (monlist[i] == n)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_monitor_at_pos (int n)
|
|
||||||
{
|
|
||||||
if (n < nmons)
|
|
||||||
return monlist[n];
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
update_gc (void)
|
update_gc (void)
|
||||||
{
|
{
|
||||||
|
@ -130,7 +111,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
|
||||||
case ALIGN_C:
|
case ALIGN_C:
|
||||||
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width / 2 - x / 2, 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, 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 - ch_width / 2 + x / 2;
|
||||||
break;
|
break;
|
||||||
case ALIGN_R:
|
case ALIGN_R:
|
||||||
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0,
|
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], mon->width - x, 0,
|
||||||
|
@ -220,6 +201,94 @@ set_attribute (const char modifier, const char attribute)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
area_t *
|
||||||
|
area_get (xcb_window_t win, const int x)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < astack.pos; i++)
|
||||||
|
if (astack.slot[i].window == win && x > astack.slot[i].begin && x < astack.slot[i].end)
|
||||||
|
return &astack.slot[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
area_shift (xcb_window_t win, const int align, int delta)
|
||||||
|
{
|
||||||
|
if (align == ALIGN_L)
|
||||||
|
return;
|
||||||
|
if (align == ALIGN_C)
|
||||||
|
delta /= 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < astack.pos; i++) {
|
||||||
|
if (astack.slot[i].window == win && astack.slot[i].align == align) {
|
||||||
|
astack.slot[i].begin -= delta;
|
||||||
|
astack.slot[i].end -= delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x, const int align)
|
||||||
|
{
|
||||||
|
char *p = str;
|
||||||
|
area_t *a = &astack.slot[astack.pos];
|
||||||
|
|
||||||
|
if (astack.pos == N) {
|
||||||
|
fprintf(stderr, "astack overflow!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A wild close area tag appeared! */
|
||||||
|
if (*p != ':') {
|
||||||
|
*end = p;
|
||||||
|
|
||||||
|
/* Basic safety checks */
|
||||||
|
if (!a->cmd || a->align != align || a->window != mon->window)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int size = x - a->begin;
|
||||||
|
|
||||||
|
switch (align) {
|
||||||
|
case ALIGN_L:
|
||||||
|
a->end = x;
|
||||||
|
break;
|
||||||
|
case ALIGN_C:
|
||||||
|
a->begin = mon->width / 2 - size / 2 + a->begin / 2;
|
||||||
|
a->end = a->begin + size;
|
||||||
|
break;
|
||||||
|
case ALIGN_R:
|
||||||
|
/* The newest is the rightmost one */
|
||||||
|
a->begin = mon->width - size;
|
||||||
|
a->end = mon->width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
astack.pos++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *trail = strchr(++p, ':');
|
||||||
|
|
||||||
|
/* Find the trailing : and make sure it's whitin the formatting block, also reject empty commands */
|
||||||
|
if (!trail || p == trail || trail > optend) {
|
||||||
|
*end = p;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*trail = '\0';
|
||||||
|
|
||||||
|
/* This is a pointer to the string buffer allocated in the main */
|
||||||
|
a->cmd = p;
|
||||||
|
a->align = align;
|
||||||
|
a->begin = x;
|
||||||
|
a->window = mon->window;
|
||||||
|
|
||||||
|
*end = trail + 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
parse (char *text)
|
parse (char *text)
|
||||||
{
|
{
|
||||||
|
@ -232,9 +301,10 @@ parse (char *text)
|
||||||
|
|
||||||
pos_x = 0;
|
pos_x = 0;
|
||||||
align = ALIGN_L;
|
align = ALIGN_L;
|
||||||
cur_font = main_font;
|
|
||||||
cur_mon = monhead;
|
cur_mon = monhead;
|
||||||
|
|
||||||
|
memset(&astack, 0, sizeof(area_stack_t));
|
||||||
|
|
||||||
for (monitor_t *m = monhead; m; m = m->next)
|
for (monitor_t *m = monhead; m; m = m->next)
|
||||||
fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, bw, bh);
|
fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, bw, bh);
|
||||||
|
|
||||||
|
@ -263,6 +333,10 @@ parse (char *text)
|
||||||
case 'c': pos_x = 0; align = ALIGN_C; break;
|
case 'c': pos_x = 0; align = ALIGN_C; break;
|
||||||
case 'r': pos_x = 0; align = ALIGN_R; break;
|
case 'r': pos_x = 0; align = ALIGN_R; break;
|
||||||
|
|
||||||
|
case 'A':
|
||||||
|
area_add(p, end, &p, cur_mon, pos_x, align);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'B': bgc = parse_color(p, &p, dbgc); update_gc(); break;
|
case 'B': bgc = parse_color(p, &p, dbgc); update_gc(); break;
|
||||||
case 'F': fgc = parse_color(p, &p, dfgc); update_gc(); break;
|
case 'F': fgc = parse_color(p, &p, dfgc); update_gc(); break;
|
||||||
case 'U': ugc = parse_color(p, &p, dbgc); update_gc(); break;
|
case 'U': ugc = parse_color(p, &p, dbgc); update_gc(); break;
|
||||||
|
@ -321,7 +395,10 @@ parse (char *text)
|
||||||
|
|
||||||
xcb_change_gc(c, gc[GC_DRAW] , 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);
|
int w = draw_char(cur_mon, cur_font, pos_x, align, ucs);
|
||||||
|
|
||||||
|
pos_x += w;
|
||||||
|
area_shift(cur_mon->window, align, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,7 +506,7 @@ monitor_new (int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
monitor_t *ret;
|
monitor_t *ret;
|
||||||
|
|
||||||
ret = malloc(sizeof(monitor_t));
|
ret = calloc(1, sizeof(monitor_t));
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
fprintf(stderr, "Failed to allocate new monitor\n");
|
fprintf(stderr, "Failed to allocate new monitor\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -447,7 +524,7 @@ monitor_new (int x, int y, int width, int height)
|
||||||
x, win_y, width, bh, 0,
|
x, win_y, width, bh, 0,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, visual,
|
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,
|
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 });
|
(const uint32_t []){ bgc, bgc, dock, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS, colormap });
|
||||||
|
|
||||||
ret->pixmap = xcb_generate_id(c);
|
ret->pixmap = xcb_generate_id(c);
|
||||||
xcb_create_pixmap(c, depth, ret->pixmap, ret->window, width, bh);
|
xcb_create_pixmap(c, depth, ret->pixmap, ret->window, width, bh);
|
||||||
|
@ -485,6 +562,35 @@ rect_sort_cb (const void *p1, const void *p2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_monitor (int n)
|
||||||
|
{
|
||||||
|
if (n >= MONITORS_MAX || n < 0) {
|
||||||
|
fprintf(stderr, "Invalic monitor specified: %d\n", n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mons |= 1 << n;
|
||||||
|
monlist[nmons++] = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_monitor_pos (int n)
|
||||||
|
{
|
||||||
|
if (n < MONITORS_MAX && (mons & (1 << n)))
|
||||||
|
for (int i = 0; i < nmons; i++)
|
||||||
|
if (monlist[i] == n)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_monitor_at_pos (int n)
|
||||||
|
{
|
||||||
|
if (n < nmons)
|
||||||
|
return monlist[n];
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monitor_create_chain (xcb_rectangle_t *rects, const int num)
|
monitor_create_chain (xcb_rectangle_t *rects, const int num)
|
||||||
{
|
{
|
||||||
|
@ -548,7 +654,6 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num)
|
||||||
void
|
void
|
||||||
get_randr_monitors (void)
|
get_randr_monitors (void)
|
||||||
{
|
{
|
||||||
xcb_generic_error_t *err;
|
|
||||||
xcb_randr_get_screen_resources_current_reply_t *rres_reply;
|
xcb_randr_get_screen_resources_current_reply_t *rres_reply;
|
||||||
xcb_randr_output_t *outputs;
|
xcb_randr_output_t *outputs;
|
||||||
int i, j, num, valid = 0;
|
int i, j, num, valid = 0;
|
||||||
|
@ -653,7 +758,7 @@ get_xinerama_monitors (void)
|
||||||
{
|
{
|
||||||
xcb_xinerama_query_screens_reply_t *xqs_reply;
|
xcb_xinerama_query_screens_reply_t *xqs_reply;
|
||||||
xcb_xinerama_screen_info_iterator_t iter;
|
xcb_xinerama_screen_info_iterator_t iter;
|
||||||
int screens, width = bw;
|
int screens;
|
||||||
|
|
||||||
xqs_reply = xcb_xinerama_query_screens_reply(c,
|
xqs_reply = xcb_xinerama_query_screens_reply(c,
|
||||||
xcb_xinerama_query_screens_unchecked(c), NULL);
|
xcb_xinerama_query_screens_unchecked(c), NULL);
|
||||||
|
@ -952,6 +1057,7 @@ main (int argc, char **argv)
|
||||||
};
|
};
|
||||||
xcb_generic_event_t *ev;
|
xcb_generic_event_t *ev;
|
||||||
xcb_expose_event_t *expose_ev;
|
xcb_expose_event_t *expose_ev;
|
||||||
|
xcb_button_press_event_t *press_ev;
|
||||||
char input[2048] = {0, };
|
char input[2048] = {0, };
|
||||||
bool permanent = false;
|
bool permanent = false;
|
||||||
int geom_v[4] = { -1, -1, 0, 0 };
|
int geom_v[4] = { -1, -1, 0, 0 };
|
||||||
|
@ -1029,7 +1135,16 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
switch (ev->response_type & 0x7F) {
|
switch (ev->response_type & 0x7F) {
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
if (expose_ev->count == 0) redraw = true;
|
if (expose_ev->count == 0)
|
||||||
|
redraw = true;
|
||||||
|
break;
|
||||||
|
case XCB_BUTTON_PRESS:
|
||||||
|
press_ev = (xcb_button_press_event_t *)ev;
|
||||||
|
/* Respond to left click */
|
||||||
|
if (press_ev->detail == XCB_BUTTON_INDEX_1) {
|
||||||
|
area_t *a = area_get(press_ev->event, press_ev->event_x);
|
||||||
|
if (a) system(a->cmd);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user