mirror of
https://github.com/Ponce/slackbuilds
synced 2024-11-18 22:06:04 +01:00
0b51634b67
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
351 lines
12 KiB
Diff
351 lines
12 KiB
Diff
diff --git a/README.pod b/README.pod
|
|
index 565f188..f021f3a 100644
|
|
--- a/README.pod
|
|
+++ b/README.pod
|
|
@@ -4,7 +4,7 @@ bar - bar ain't recursive
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
-I<bar> [-h | -g I<width>B<x>I<height>B<+>I<x> | -b | -d | -f I<font> | -p | -u I<pixel> | -B I<color> | -F I<color>]
|
|
+I<bar> [-h | -g I<width>B<x>I<height>B<+>I<x>B<+>I<y> | -b | -d | -f I<font> | -p | -u I<pixel> | -B I<color> | -F I<color>]
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
@@ -18,9 +18,9 @@ B<bar> is a lightweight bar entirely based on XCB. Provides full UTF-8 support,
|
|
|
|
Display the help and exit.
|
|
|
|
-=item B<-g> I<width>B<x>I<height>B<+>I<x>
|
|
+=item B<-g> I<width>B<x>I<height>B<+>I<x>B<+>I<y>
|
|
|
|
-Set the window geometry. If a parameter is omitted it's filled with the default value.
|
|
+Set the window geometry. If a parameter is omitted it's filled with the default value. If the I<y> parameter is specified along with the B<-b> switch then the position is relative to the bottom of the screen.
|
|
|
|
=item B<-b>
|
|
|
|
@@ -86,12 +86,14 @@ 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.
|
|
|
|
-=item B<A>:I<command>:
|
|
+=item B<A>I<button>: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}>
|
|
|
|
+The I<button> field is optional, it defaults to the left button, and it's a number ranging from 1 to 5 which maps to the left, middle, right, scroll down and scroll up movements. Your mileage may vary.
|
|
+
|
|
=item B<S>I<dir>
|
|
|
|
Change the monitor bar is rendering to. I<dir> can be either
|
|
diff --git a/bar.c b/bar.c
|
|
index 1ccc907..1f8c5cf 100644
|
|
--- a/bar.c
|
|
+++ b/bar.c
|
|
@@ -34,12 +34,12 @@ typedef struct monitor_t {
|
|
} monitor_t;
|
|
|
|
typedef struct area_t {
|
|
- int begin, end, align;
|
|
+ int begin, end, align, button;
|
|
xcb_window_t window;
|
|
char *cmd;
|
|
} area_t;
|
|
|
|
-#define N 10
|
|
+#define N 20
|
|
|
|
typedef struct area_stack_t {
|
|
int pos;
|
|
@@ -74,7 +74,7 @@ static font_t *main_font, *alt_font;
|
|
static uint32_t attrs = 0;
|
|
static bool dock = false;
|
|
static bool topbar = true;
|
|
-static int bw = -1, bh = -1, bx = 0;
|
|
+static int bw = -1, bh = -1, bx = 0, by = 0;
|
|
static int bu = 1; /* Underline height */
|
|
static char *mfont, *afont;
|
|
static uint32_t fgc, bgc, ugc;
|
|
@@ -118,7 +118,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
|
|
}
|
|
|
|
/* Draw the background first */
|
|
- fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh);
|
|
+ fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, ch_width, bh);
|
|
|
|
/* xcb accepts string in UCS-2 BE, so swap */
|
|
ch = (ch >> 8) | (ch << 8);
|
|
@@ -156,9 +156,17 @@ parse_color (const char *str, char **end, const uint32_t def)
|
|
if (str[0] == '#') {
|
|
errno = 0;
|
|
uint32_t tmp = strtoul(str + 1, end, 16);
|
|
- /* Some error checking it's good */
|
|
+ /* Some error checking is definitely good */
|
|
if (errno)
|
|
- return def;
|
|
+ tmp = def;
|
|
+ /* Xorg uses colors with premultiplied alpha.
|
|
+ * Don't do anything if we didn't acquire a rgba visual. */
|
|
+ if (visual != scr->root_visual) {
|
|
+ const uint8_t a = ((tmp>>24)&255);
|
|
+ const uint32_t t1 = (tmp&0xff00ff) * (0x100-a);
|
|
+ const uint32_t t2 = (tmp&0x00ff00) * (0x100-a);
|
|
+ tmp = (a<<24)|(t1&0xff00ff)|(t2&0x00ff00);
|
|
+ }
|
|
return tmp;
|
|
}
|
|
|
|
@@ -225,7 +233,7 @@ area_shift (xcb_window_t win, const int align, int delta)
|
|
}
|
|
|
|
bool
|
|
-area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x, const int align)
|
|
+area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x, const int align, const int button)
|
|
{
|
|
char *p = str;
|
|
area_t *a = &astack.slot[astack.pos];
|
|
@@ -280,6 +288,7 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
|
|
a->align = align;
|
|
a->begin = x;
|
|
a->window = mon->window;
|
|
+ a->button = button;
|
|
|
|
*end = trail + 1;
|
|
|
|
@@ -291,8 +300,7 @@ parse (char *text)
|
|
{
|
|
font_t *cur_font;
|
|
monitor_t *cur_mon;
|
|
- int pos_x;
|
|
- int align;
|
|
+ int pos_x, align, button;
|
|
char *p = text, *end;
|
|
uint32_t tmp;
|
|
|
|
@@ -302,7 +310,8 @@ parse (char *text)
|
|
|
|
memset(&astack, 0, sizeof(area_stack_t));
|
|
|
|
- fill_rect(cur_mon->pixmap, gc[GC_CLEAR], 0, 0, bw, bh);
|
|
+ for (monitor_t *m = monhead; m != NULL; m = m->next)
|
|
+ fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh);
|
|
|
|
for (;;) {
|
|
if (*p == '\0' || *p == '\n')
|
|
@@ -330,7 +339,11 @@ parse (char *text)
|
|
case 'r': pos_x = 0; align = ALIGN_R; break;
|
|
|
|
case 'A':
|
|
- area_add(p, end, &p, cur_mon, pos_x, align);
|
|
+ button = XCB_BUTTON_INDEX_1;
|
|
+ /* The range is 1-5 */
|
|
+ if (isdigit(*p) && (*p > '0' && *p < '6'))
|
|
+ button = *p++ - '0';
|
|
+ area_add(p, end, &p, cur_mon, pos_x, align, button);
|
|
break;
|
|
|
|
case 'B': bgc = parse_color(p, &p, dbgc); update_gc(); break;
|
|
@@ -356,7 +369,6 @@ parse (char *text)
|
|
|
|
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 } */
|
|
@@ -513,7 +525,7 @@ monitor_new (int x, int y, int width, int height)
|
|
ret->width = width;
|
|
ret->next = ret->prev = NULL;
|
|
|
|
- int win_y = (topbar ? 0 : height - bh) + y;
|
|
+ int win_y = (topbar ? by : height - bh - by) + y;
|
|
ret->window = xcb_generate_id(c);
|
|
|
|
int depth = (visual == scr->root_visual) ? XCB_COPY_FROM_PARENT : 32;
|
|
@@ -562,14 +574,39 @@ rect_sort_cb (const void *p1, const void *p2)
|
|
void
|
|
monitor_create_chain (xcb_rectangle_t *rects, const int num)
|
|
{
|
|
- int width = bw;
|
|
+ int i;
|
|
+ int width = 0, height = 0;
|
|
int left = bx;
|
|
|
|
/* Sort before use */
|
|
qsort(rects, num, sizeof(xcb_rectangle_t), rect_sort_cb);
|
|
|
|
+ for (i = 0; i < num; i++) {
|
|
+ int h = rects[i].y + rects[i].height;
|
|
+ /* Accumulated width of all monitors */
|
|
+ width += rects[i].width;
|
|
+ /* Get height of screen from y_offset + height of lowest monitor */
|
|
+ if (h >= height)
|
|
+ height = h;
|
|
+ }
|
|
+
|
|
+ if (bw < 0)
|
|
+ bw = width - bx;
|
|
+
|
|
+ if (bh < 0 || bh > height)
|
|
+ bh = main_font->height + bu + 2;
|
|
+
|
|
+ /* Check the geometry */
|
|
+ if (bx + bw > width || by + bh > height) {
|
|
+ fprintf(stderr, "The geometry specified doesn't fit the screen!\n");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
/* Left is a positive number or zero therefore monitors with zero width are excluded */
|
|
- for (int i = 0; i < num; i++) {
|
|
+ width = bw;
|
|
+ for (i = 0; i < num; i++) {
|
|
+ if (rects[i].y + rects[i].height < by)
|
|
+ continue;
|
|
if (rects[i].width > left) {
|
|
monitor_t *mon = monitor_new(
|
|
rects[i].x + left,
|
|
@@ -598,7 +635,7 @@ get_randr_monitors (void)
|
|
{
|
|
xcb_randr_get_screen_resources_current_reply_t *rres_reply;
|
|
xcb_randr_output_t *outputs;
|
|
- int num, valid = 0;
|
|
+ int i, j, num, valid = 0;
|
|
|
|
rres_reply = xcb_randr_get_screen_resources_current_reply(c,
|
|
xcb_randr_get_screen_resources_current(c, scr->root), NULL);
|
|
@@ -621,7 +658,7 @@ get_randr_monitors (void)
|
|
xcb_rectangle_t rects[num];
|
|
|
|
/* Get all outputs */
|
|
- for (int i = 0; i < num; i++) {
|
|
+ for (i = 0; i < num; i++) {
|
|
xcb_randr_get_output_info_reply_t *oi_reply;
|
|
xcb_randr_get_crtc_info_reply_t *ci_reply;
|
|
|
|
@@ -657,11 +694,11 @@ get_randr_monitors (void)
|
|
free(rres_reply);
|
|
|
|
/* Check for clones and inactive outputs */
|
|
- for (int i = 0; i < num; i++) {
|
|
+ for (i = 0; i < num; i++) {
|
|
if (rects[i].width == 0)
|
|
continue;
|
|
|
|
- for (int j = 0; j < num; j++) {
|
|
+ for (j = 0; j < num; j++) {
|
|
/* Does I countain J ? */
|
|
|
|
if (i != j && rects[j].width) {
|
|
@@ -679,7 +716,13 @@ get_randr_monitors (void)
|
|
return;
|
|
}
|
|
|
|
- monitor_create_chain(rects, num);
|
|
+ xcb_rectangle_t r[valid];
|
|
+
|
|
+ for (i = j = 0; i < num && j < valid; i++)
|
|
+ if (rects[i].width != 0)
|
|
+ r[j++] = rects[i];
|
|
+
|
|
+ monitor_create_chain(r, valid);
|
|
}
|
|
|
|
void
|
|
@@ -755,10 +798,6 @@ xconn (void)
|
|
void
|
|
init (void)
|
|
{
|
|
- /* If I fits I sits */
|
|
- if (bw < 0)
|
|
- bw = scr->width_in_pixels - bx;
|
|
-
|
|
/* Load the fonts */
|
|
main_font = font_load(mfont ? mfont : "fixed");
|
|
if (!main_font)
|
|
@@ -771,10 +810,6 @@ init (void)
|
|
/* To make the alignment uniform */
|
|
main_font->height = alt_font->height = max(main_font->height, alt_font->height);
|
|
|
|
- /* Adjust the height */
|
|
- if (bh < 0 || bh > scr->height_in_pixels)
|
|
- bh = main_font->height + bu + 2;
|
|
-
|
|
/* Generate a list of screens */
|
|
const xcb_query_extension_reply_t *qe_reply;
|
|
|
|
@@ -801,9 +836,24 @@ init (void)
|
|
}
|
|
}
|
|
|
|
- if (!monhead)
|
|
+ if (!monhead) {
|
|
+ /* If I fits I sits */
|
|
+ if (bw < 0)
|
|
+ bw = scr->width_in_pixels - bx;
|
|
+
|
|
+ /* Adjust the height */
|
|
+ if (bh < 0 || bh > scr->height_in_pixels)
|
|
+ bh = main_font->height + bu + 2;
|
|
+
|
|
+ /* Check the geometry */
|
|
+ if (bx + bw > scr->width_in_pixels || by + bh > scr->height_in_pixels) {
|
|
+ fprintf(stderr, "The geometry specified doesn't fit the screen!\n");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
/* If no RandR outputs or Xinerama screens, fall back to using whole screen */
|
|
monhead = monitor_new(0, 0, bw, scr->height_in_pixels);
|
|
+ }
|
|
|
|
if (!monhead)
|
|
exit(EXIT_FAILURE);
|
|
@@ -949,7 +999,7 @@ main (int argc, char **argv)
|
|
xcb_generic_event_t *ev;
|
|
xcb_expose_event_t *expose_ev;
|
|
xcb_button_press_event_t *press_ev;
|
|
- char input[2048] = {0, };
|
|
+ char input[4096] = {0, };
|
|
bool permanent = false;
|
|
int geom_v[4] = { -1, -1, 0, 0 };
|
|
|
|
@@ -973,7 +1023,7 @@ main (int argc, char **argv)
|
|
case 'h':
|
|
printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F]\n"
|
|
"\t-h Show this help\n"
|
|
- "\t-g Set the bar geometry {width}x{height})\n"
|
|
+ "\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\n"
|
|
"\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"
|
|
@@ -997,12 +1047,7 @@ main (int argc, char **argv)
|
|
bw = geom_v[0];
|
|
bh = geom_v[1];
|
|
bx = geom_v[2];
|
|
-
|
|
- /* 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;
|
|
- }
|
|
+ by = geom_v[3];
|
|
|
|
/* Do the heavy lifting */
|
|
init();
|
|
@@ -1035,10 +1080,13 @@ main (int argc, char **argv)
|
|
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 *area = area_get(press_ev->event, press_ev->event_x);
|
|
- if (area) { write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); write(STDOUT_FILENO, "\n", 1); }
|
|
+ /* Respond to the click */
|
|
+ if (area && area->button == press_ev->detail) {
|
|
+ write(STDOUT_FILENO, area->cmd, strlen(area->cmd));
|
|
+ write(STDOUT_FILENO, "\n", 1);
|
|
+ }
|
|
}
|
|
break;
|
|
}
|