Compare commits

...

61 Commits
xbm ... master

Author SHA1 Message Date
LemonBoy 35183ab81d
Merge pull request #210 from dmgk/master
Update VERSION
2018-01-15 13:56:51 +01:00
Dmitri Goutnik 09b5a9b8ba Update VERSION 2018-01-12 16:51:57 -05:00
LemonBoy 2f255b1756 Release version 1.3 2017-11-20 11:47:43 +01:00
LemonBoy 8cd84e8edf Merge pull request #202 from felixkiss/patch-1
Fix typo
2017-07-07 07:36:12 +02:00
Felix Kiss b721a37ab0 Fix typo 2017-07-06 22:54:51 +02:00
LemonBoy 1411d260a4 Correctly handle escaped % symbols 2017-05-09 15:56:59 +02:00
LemonBoy 50fe7d2083 Merge pull request #193 from baskerville/fix-end-x
Fix {top,bottom}_end_x strut value
2016-11-16 12:25:06 +01:00
Bastien Dejean 84be3d8dbf Fix {top,bottom}_end_x strut value
The maximum x coordinate of a pixel inside the rectangle (x, y, w, h) is x+w-1.

The specs (https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317564416)
provides an example that corroborates the fact that the range is inclusive: bottom_end_x is 2303.
This value can be interpreted as 1280+1024-1.
2016-11-16 10:14:27 +01:00
LemonBoy d680ea4256 Set the WM_NAME for all the windows.
Don't set repeatedly the property for the first window only.
Thanks to @otommod for noticing this.
2016-05-22 20:09:26 +02:00
LemonBoy 44a708b7a4 Don't use optarg directly when parsing the -n switch argument. 2016-05-22 15:31:42 +02:00
LemonBoy 40f08d5245 Silence a warning about write() result being unused. 2016-04-23 09:06:00 +02:00
LemonBoy 3dbdf9d078 Update the .travis.yml to build all the features 2016-04-23 09:02:46 +02:00
LemonBoy a3fb967ad9 Make it possible to build lemonbar w/o XINERAMA support 2016-04-23 08:59:38 +02:00
TheLemonMan ae5a3a477a Merge pull request #170 from Stebalien/pixel-offset
Pixel Offset
2016-04-23 08:24:09 +02:00
Steven Allen f2662d75c8 Add pixel offset
Add a formatting command to offset the text position by a pixel amount.
2016-02-19 11:35:22 -05:00
Giuseppe 3020df1923 Merge pull request #169 from vyp/literal-percent
Document literal percent sign under formatting
2016-02-19 11:57:35 +01:00
xd1le 13dcc66cae Document literal percent sign under formatting
`B<%{>` and `B<}>` on the same line have been changed to `C<%{>` and
`C<}>` for consistency.
2016-02-19 21:50:27 +11:00
Giuseppe c788534107 Merge pull request #165 from JeromeBon/feature_issue161_default_underline_color
Implement [Issue #161 - Feature request]
2016-01-19 15:18:14 +01:00
Jérôme Bon 0f2cfbab28 Implement [Issue #161 - Feature request]
Feature: add a parametere to set the default underline color.
Usage: lemonbar -Ucolor

By the way this also fix a strange behavior whereas '%{+u}correct%{U-}strange'
made the second underline of the same color as the background instead of the foreground.
2016-01-19 14:41:00 +01:00
Giuseppe 61985278f2 Merge pull request #162 from baskerville/master
Commands in clickable areas aren't executed
2016-01-03 18:39:11 +01:00
Bastien Dejean d3d7a87b66 Commands in clickable areas aren't executed 2015-12-23 12:03:08 +01:00
LemonBoy 7c8eb7495b Fix an off-by-one error in 'area_get'.
Fixes #160.
2015-12-15 19:05:39 +01:00
Giuseppe f26b88272e Merge pull request #159 from AdamNiederer/patch-1
Fix Typo
2015-12-11 09:22:50 +01:00
Adam Niederer 214ad63925 Fix Typo
Siz -> Six in comment
2015-12-10 17:59:58 -05:00
Giuseppe 495ac4e546 Merge pull request #158 from sector-f/master
Added -a and -o to README.pod (and, therefore, the man page)
2015-11-16 18:43:23 +01:00
Adam e4ea4071ab Added -a to README.pod (and, therefore, the man page) 2015-11-16 12:17:17 -05:00
Giuseppe 63ed303553 Merge pull request #157 from krypt-n/scroll-fix
Fix the missing scrolling wheel support.
2015-11-16 17:24:31 +01:00
krypt-n e0aee14533 Saving 4 byte of memory on 32-Bit systems 2015-11-15 23:06:19 +01:00
krypt-n da26209013 Fix LemonBoy/bar#154 and krypt-n/bar#18
Widening the bitfield by 1 would be a solution aswell.
Problem was that an int:3 has a range of -4 to 3, buttons 4 and 5 did not
fit into it
2015-11-15 13:24:36 +01:00
LemonBoy 2c0f57c584 Prevent load_font calls before connecting to X 2015-10-30 16:11:22 +01:00
Bastien Dejean 3b5baa93b1 The WM_NAME option takes an argument 2015-10-30 16:11:22 +01:00
LemonBoy 531c575575 Allow the user to set the WM_NAME atom value 2015-10-24 14:44:41 +02:00
LemonBoy 6580e2d4f7 Warn the user when the area geometry is invalid 2015-10-24 14:35:36 +02:00
LemonBoy 255c93dc7a Make the number of clickable areas configurable. 2015-10-24 14:28:51 +02:00
LemonBoy 38422c5014 Don't parse named colors. Expand #rgb format. 2015-10-24 14:04:37 +02:00
Giuseppe 1585d7257d Merge pull request #150 from neeasade/monitor_sort
Fix monitor sorting with mix of portrait and landscape layout.
2015-10-21 19:30:56 +02:00
Nathan Isom 7f8a79131b Account for height of monitors in sorting. 2015-10-21 12:24:04 -05:00
neeasade 177deb0860 bar -> lemonbar in .gitignore, remove config.h in .gitignore 2015-10-20 19:56:29 -05:00
Giuseppe b331ee3927 Merge pull request #137 from chadvoegele/master
Keep percent signs if not followed by {} block.
2015-10-10 16:00:40 +02:00
chad 71ed0d3375 Rewrite *p, *(p+1) as p[0], p[1] for readability. 2015-09-27 15:21:49 -05:00
Chad Voegele 63a55dd06c Keep percent signs if not followed by {} block.
The before code would skip a percent sign even if it was not followed by a {}
block. The after code checks the same condition but only advances p if a {} block
is found and otherwise passes it through as text.
2015-09-27 15:16:56 -05:00
Giuseppe a390ef6a5c Merge pull request #132 from krypt-n/font-count-fix
Don't exceed maximum number of fonts
2015-07-22 23:07:45 +02:00
Giuseppe 04d22b4ae5 Merge pull request #141 from DelusionalLogic/master
Fixed font selection
2015-07-22 23:04:30 +02:00
Jesper Jensen 73d8c58286 Conform to coding standard and errors
An error will not be printed if the parameter to `T` is not valid (- or
a number) and the token will be eaten (just like when an invalid
attribute is found)
2015-07-22 22:55:06 +02:00
Jesper Jensen 49fdc25f37 Fixed font selection
Font selection now correctly handles - as a special case.

This change is also reflected in the documentation.
2015-07-22 17:39:31 +02:00
krypt-n a8fa2766fb Check force_count to be lower than MAX_FONT_COUNT 2015-06-02 09:27:53 +02:00
LemonBoy a9f285fd28 Update the usage text
The -f option doesn't accept a comma separated list of font names anymore
2015-05-03 17:06:36 +02:00
LemonBoy 7880eac8c9 Minor change to -f handling
Remove the ability of the -f switch to accept a comma-separated list of fonts. The user is expected
to use multiple times -f whenever he wants to specify one or more fonts. This has the side effect of
enabling the user to use fonts whose name contains a comma.
2015-04-23 23:07:42 +02:00
LemonBoy 25c3441925 travis: Run a apt-get update before installing the needed packages 2015-04-15 11:04:53 +02:00
LemonBoy b82d96a68e Use the maximum width reported by the font if the attributes table isn't found 2015-04-15 10:21:52 +02:00
LemonBoy ebb625b529 Minor spelling errors 2015-03-15 21:35:54 +01:00
LemonBoy 72106b17b1 Change the project name to lemonbar 2015-03-14 13:51:29 +01:00
LemonBoy 19167c2e55 Remove the now useless palette.pl script 2015-03-08 19:45:47 +01:00
LemonBoy fe4ff881dd Fix a silly error when redrawing the background. Fixes #108 and #82 2015-03-03 11:29:35 +01:00
Giuseppe 75dbf3397e Merge pull request #106 from otommod/click-fix
Fix #105
2015-02-27 15:53:19 +01:00
Otto Modinos eeb88f8ae0 fix non left alignments causing wrong clicks 2015-02-27 15:57:19 +02:00
LemonBoy d32cd8bce9 Prevent a NULL pointer deference if monitor_create fails 2015-02-18 12:52:24 +01:00
LemonBoy 5186f68658 Fix the 'T' command parsing 2015-02-16 14:22:34 +01:00
LemonBoy 4ee19586a3 Put the elements of rgba_t in the right order. Thanks to @mrshankly for noticing it 2015-02-15 23:54:04 +01:00
Giuseppe 1ef64eab99 Merge pull request #104 from andornaut/patch-1
Document #97 - Nested clickable areas
2015-02-14 00:47:02 +01:00
andornaut ab3a49962f Document #97 - Nested clickable areas 2015-02-13 18:43:50 -05:00
6 changed files with 311 additions and 251 deletions

3
.gitignore vendored
View File

@ -1,5 +1,4 @@
config.h
bar
lemonbar
*.o
*.swp
*~

View File

@ -3,5 +3,8 @@ compiler:
- clang
- gcc
before_install:
- sudo apt-get install -qq libx11-xcb-dev libxcb-randr0-dev libxcb-xinerama0-dev
- sudo apt-get update -qq
- sudo apt-get install -y libx11-xcb-dev libxcb-randr0-dev libxcb-xinerama0-dev
env:
- CFLAGS='-DWITH_XINERAMA=1'
script: make

View File

@ -1,11 +1,19 @@
CC ?= gcc
CFLAGS = -Wall -std=c99 -Os
LDFLAGS = -lxcb -lxcb-xinerama -lxcb-randr
CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long\
-Wsign-conversion -Wconversion -Wimplicit-function-declaration
# This snippet has been shmelessly stol^Hborrowed from thestinger's repose Makefile
VERSION = 1.3
GIT_DESC=$(shell test -d .git && git describe --always 2>/dev/null)
EXEC = bar
SRCS = bar.c
ifneq "$(GIT_DESC)" ""
VERSION=$(GIT_DESC)
endif
CC ?= gcc
CFLAGS += -Wall -std=c99 -Os -DVERSION="\"$(VERSION)\""
LDFLAGS += -lxcb -lxcb-xinerama -lxcb-randr
CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long \
-Wsign-conversion -Wconversion -Wimplicit-function-declaration
EXEC = lemonbar
SRCS = lemonbar.c
OBJS = ${SRCS:.c=.o}
PREFIX?=/usr
@ -14,7 +22,7 @@ BINDIR=${PREFIX}/bin
all: ${EXEC}
doc: README.pod
pod2man --section=1 --center="bar Manual" --name "bar" --release="bar $(shell git describe --always)" README.pod > bar.1
pod2man --section=1 --center="lemonbar Manual" --name "lemonbar" --release="lemonbar $(VERSION)" README.pod > lemonbar.1
.c.o:
${CC} ${CFLAGS} -o $@ -c $<
@ -29,12 +37,12 @@ clean:
rm -f ./*.o ./*.1
rm -f ./${EXEC}
install: bar doc
install -D -m 755 bar ${DESTDIR}${BINDIR}/bar
install -D -m 644 bar.1 ${DESTDIR}${PREFIX}/share/man/man1/bar.1
install: lemonbar doc
install -D -m 755 lemonbar ${DESTDIR}${BINDIR}/lemonbar
install -D -m 644 lemonbar.1 ${DESTDIR}${PREFIX}/share/man/man1/lemonbar.1
uninstall:
rm -f ${DESTDIR}${BINDIR}/bar
rm -f $(DESTDIR)$(PREFIX)/share/man/man1/bar.1
rm -f ${DESTDIR}${BINDIR}/lemonbar
rm -f $(DESTDIR)$(PREFIX)/share/man/man1/lemonbar.1
.PHONY: all debug clean install

View File

@ -1,16 +1,16 @@
=head1 NAME
bar - bar ain't recursive
lemonbar - Featherweight lemon-scented bar
=for HTML <a href="https://travis-ci.org/LemonBoy/bar"><img src="https://travis-ci.org/LemonBoy/bar.svg?branch=master"></a>
=head1 SYNOPSIS
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>]
I<lemonbar> [-h | -g I<width>B<x>I<height>B<+>I<x>B<+>I<y> | -b | -d | -f I<font> | -p | -n I<name> | -u I<pixel> | -B I<color> | -F I<color> | -U I<color>]
=head1 DESCRIPTION
B<bar> is a lightweight bar entirely based on XCB. Provides full UTF-8 support, basic formatting, RandR and Xinerama support and EWMH compliance without wasting your precious memory.
B<lemonbar> (formerly known as B<bar>) is a lightweight bar entirely based on XCB. Provides full UTF-8 support, basic formatting, RandR and Xinerama support and EWMH compliance without wasting your precious memory.
=head1 OPTIONS
@ -34,11 +34,20 @@ Force docking without asking the window manager. This is needed if the window ma
=item B<-f> I<font>
Comma separated list of fonts, bar supports a maximum of five fonts (the limit can be tweaked by changing the MAX_FONT_COUNT parameter in the source).
Define the font to load into one of the five slots (the number of slots is hardcoded and can be tweaked by
changing the MAX_FONT_COUNT parameter in the source code).
=item B<-a> I<number>
Set number of clickable areas (default is 10)
=item B<-p>
Make bar permanent, don't exit after the standard input is closed.
Make the bar permanent, don't exit after the standard input is closed.
=item B<-n> I<name>
Set the WM_NAME atom value for the bar.
=item B<-u> I<pixel>
@ -46,17 +55,21 @@ Sets the underline width in pixels. The default is 1.
=item B<-B> I<color>
Set the background color of the bar. I<color> might be either in hex format (#aarrggbb) or in the symbolic name format (eg. white, indianred, darkgray). If no compositor such as compton or xcompmgr is running the alpha channel is silently ignored.
Set the background color of the bar. I<color> must be specified in the hex format (#aarrggbb, #rrggbb, #rgb). If no compositor such as compton or xcompmgr is running the alpha channel is silently ignored.
=item B<-F> I<color>
Set the foreground color of the bar. Accepts the same color formats as B<-B>.
=item B<-U> I<color>
Set the underline color of the bar. Accepts the same color formats as B<-B>.
=back
=head1 FORMATTING
bar provides a screenrc-inspired formatting syntax to allow full customization at runtime. Every formatting block is opened with B<%{> and closed by B<}> and accepts the following commands, the parser tries it's best to handle malformed input.
lemonbar provides a screenrc-inspired formatting syntax to allow full customization at runtime. Every formatting block is opened with C<%{> and closed by C<}> and accepts the following commands, the parser tries its best to handle malformed input. Use C<%%> to get a literal percent sign (C<%>).
=over
@ -76,6 +89,10 @@ Aligns the following text to the center of the screen.
Aligns the following text to the right side of the screen.
=item B<O>I<width>
Offset the current position by I<width> pixels in the alignment direction.
=item B<B>I<color>
Set the text background 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.
@ -86,7 +103,7 @@ Set the text foreground color. The parameter I<color> can be I<-> or a color in
=item B<T>I<index>
Set the font used to draw the following text. The parameter I<index> is a 1-based index of the font list supplied to bar. Any other value (for example I<->) resets bar to normal behaviour (matching the first font that can be used for that character). If the selected font can't be used to draw a character, bar will fall back to normal behaviour for that character.
Set the font used to draw the following text. The parameter I<index> can either be I<-> or the 1-based index of the slot which contains the desired font. If the parameter is I<-> lemonbar resets to the normal behavior (matching the first font that can be used for the character). If the selected font can't be used to draw a character, lemonbar will fall back to normal behavior for that character
=item B<U>I<color>
@ -94,15 +111,19 @@ Set the text underline color. The parameter I<color> can be I<-> or a color in o
=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.
Create a clickable area starting from the current position, when the area is clicked I<command> is printed on stdout. 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 up and scroll down movements. Your mileage may vary.
Nested clickable areas can trigger different commands.
Eg. I<%{A:reboot:}%{A3:halt:} Left click to reboot, right click to shutdown %{A}%{A}>
=item B<S>I<dir>
Change the monitor bar is rendering to. I<dir> can be either
Change the monitor the bar is rendered to. I<dir> can be either
=over
@ -156,7 +177,7 @@ Draw a line under the text.
=head1 OUTPUT
Clicking on an area makes bar output the command to stdout, followed by a newline, allowing the user to pipe it into a script, execute it or simply ignore it. Simple and powerful, that's it.
Clicking on an area makes lemonbar output the command to stdout, followed by a newline, allowing the user to pipe it into a script, execute it or simply ignore it. Simple and powerful, that's it.
=head1 WWW
@ -164,7 +185,7 @@ L<git repository|https://github.com/LemonBoy/bar>
=head1 AUTHOR
2012-2014 (C) The Lemon Man
2012-2017 (C) The Lemon Man
Xinerama support was kindly contributed by Stebalien

View File

@ -1,4 +1,5 @@
// vim:sw=4:ts=4:et:
#define _POSIX_C_SOURCE 200809L
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -11,7 +12,9 @@
#include <errno.h>
#include <xcb/xcb.h>
#include <xcb/xcbext.h>
#if WITH_XINERAMA
#include <xcb/xinerama.h>
#endif
#include <xcb/randr.h>
// Here be dragons
@ -22,7 +25,7 @@
typedef struct font_t {
xcb_font_t ptr;
int descent, height;
int descent, height, width;
uint16_t char_max;
uint16_t char_min;
xcb_charinfo_t *width_lut;
@ -36,27 +39,28 @@ typedef struct monitor_t {
} monitor_t;
typedef struct area_t {
bool active;
int begin, end, align, button;
unsigned int begin:16;
unsigned int end:16;
bool active:1;
int align:3;
unsigned int button:3;
xcb_window_t window;
char *cmd;
} area_t;
typedef union rgba_t {
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
uint32_t v;
} rgba_t;
#define N 20
typedef struct area_stack_t {
int pos;
area_t slot[N];
int at, max;
area_t *area;
} area_stack_t;
enum {
@ -94,8 +98,8 @@ static bool topbar = true;
static int bw = -1, bh = -1, bx = 0, by = 0;
static int bu = 1; // Underline height
static rgba_t fgc, bgc, ugc;
static rgba_t dfgc, dbgc;
static area_stack_t astack;
static rgba_t dfgc, dbgc, dugc;
static area_stack_t area_stack;
void
update_gc (void)
@ -147,10 +151,10 @@ xcb_void_cookie_t xcb_poly_text_16_simple(xcb_connection_t * c,
uint32_t len, const uint16_t *str)
{
static const xcb_protocol_request_t xcb_req = {
5, // count
0, // ext
XCB_POLY_TEXT_16, // opcode
1 // isvoid
5, // count
0, // ext
XCB_POLY_TEXT_16, // opcode
1 // isvoid
};
struct iovec xcb_parts[7];
uint8_t xcb_lendelta[2];
@ -180,14 +184,13 @@ xcb_void_cookie_t xcb_poly_text_16_simple(xcb_connection_t * c,
xcb_parts[6].iov_len = -(xcb_parts[4].iov_len + xcb_parts[5].iov_len) & 3;
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
int
draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
shift (monitor_t *mon, int x, int align, int ch_width)
{
int ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width;
switch (align) {
case ALIGN_C:
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW],
@ -206,7 +209,35 @@ 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, by, ch_width, bh);
fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh);
return x;
}
void
draw_lines (monitor_t *mon, int x, int w)
{
/* We can render both at the same time */
if (attrs & ATTR_OVERL)
fill_rect(mon->pixmap, gc[GC_ATTR], x, 0, w, bu);
if (attrs & ATTR_UNDERL)
fill_rect(mon->pixmap, gc[GC_ATTR], x, bh - bu, w, bu);
}
void
draw_shift (monitor_t *mon, int x, int align, int w)
{
x = shift(mon, x, align, w);
draw_lines(mon, x, w);
}
int
draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
{
int ch_width = (cur_font->width_lut) ?
cur_font->width_lut[ch - cur_font->char_min].character_width:
cur_font->width;
x = shift(mon, x, align, ch_width);
// xcb accepts string in UCS-2 BE, so swap
ch = (ch >> 8) | (ch << 8);
@ -216,11 +247,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
x, bh / 2 + cur_font->height / 2 - cur_font->descent,
1, &ch);
// We can render both at the same time
if (attrs & ATTR_OVERL)
fill_rect(mon->pixmap, gc[GC_ATTR], x, 0, ch_width, bu);
if (attrs & ATTR_UNDERL)
fill_rect(mon->pixmap, gc[GC_ATTR], x, bh - bu, ch_width, bu);
draw_lines(mon, x, ch_width);
return ch_width;
}
@ -228,9 +255,7 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
rgba_t
parse_color (const char *str, char **end, const rgba_t def)
{
xcb_alloc_named_color_reply_t *nc_reply;
int string_len;
rgba_t ret;
char *ep;
if (!str)
@ -245,61 +270,61 @@ parse_color (const char *str, char **end, const rgba_t def)
}
// Hex representation
if (str[0] == '#') {
errno = 0;
rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16);
if (str[0] != '#') {
if (end)
*end = ep;
*end = (char *)str;
// Some error checking is definitely good
if (errno) {
fprintf(stderr, "Invalid color specified\n");
return def;
}
string_len = ep - (str + 1);
// If the code is in #rrggbb form then assume it's opaque
if (string_len <= 6)
tmp.a = 255;
// Premultiply the alpha in
if (tmp.a) {
// The components are clamped automagically as the rgba_t is made of uint8_t
return (rgba_t){
.r = (tmp.r * tmp.a) / 255,
.g = (tmp.g * tmp.a) / 255,
.b = (tmp.b * tmp.a) / 255,
.a = tmp.a,
};
}
return (rgba_t)0U;
fprintf(stderr, "Invalid color specified\n");
return def;
}
// Actual color name, resolve it
for (string_len = 0; isalpha(str[string_len]); string_len++)
;
nc_reply = xcb_alloc_named_color_reply(c, xcb_alloc_named_color(c, colormap, string_len, str), NULL);
if (!nc_reply)
fprintf(stderr, "Could not alloc color \"%.*s\"\n", string_len, str);
ret = nc_reply?
(rgba_t)nc_reply->pixel:
def;
free(nc_reply);
errno = 0;
rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16);
if (end)
*end = (char *)str + string_len;
*end = ep;
return ret;
// Some error checking is definitely good
if (errno) {
fprintf(stderr, "Invalid color specified\n");
return def;
}
string_len = ep - (str + 1);
switch (string_len) {
case 3:
// Expand the #rgb format into #rrggbb (aa is set to 0xff)
tmp.v = (tmp.v & 0xf00) * 0x1100
| (tmp.v & 0x0f0) * 0x0110
| (tmp.v & 0x00f) * 0x0011;
case 6:
// If the code is in #rrggbb form then assume it's opaque
tmp.a = 255;
break;
case 7:
case 8:
// Colors in #aarrggbb format, those need no adjustments
break;
default:
fprintf(stderr, "Invalid color specified\n");
return def;
}
// Premultiply the alpha in
if (tmp.a) {
// The components are clamped automagically as the rgba_t is made of uint8_t
return (rgba_t){
.r = (tmp.r * tmp.a) / 255,
.g = (tmp.g * tmp.a) / 255,
.b = (tmp.b * tmp.a) / 255,
.a = tmp.a,
};
}
return (rgba_t)0U;
}
void
set_attribute (const char modifier, const char attribute)
{
@ -322,10 +347,9 @@ area_t *
area_get (xcb_window_t win, const int btn, const int x)
{
// Looping backwards ensures that we get the innermost area first
for (int i = astack.pos; i >= 0; i--) {
area_t *a = &astack.slot[i];
if (a->window == win && a->button == btn
&& x >= a->begin && x < a->end)
for (int i = area_stack.at - 1; i >= 0; i--) {
area_t *a = &area_stack.area[i];
if (a->window == win && a->button == btn && x >= a->begin && x < a->end)
return a;
}
return NULL;
@ -339,10 +363,11 @@ area_shift (xcb_window_t win, const int align, int delta)
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;
for (int i = 0; i < area_stack.at; i++) {
area_t *a = &area_stack.area[i];
if (a->window == win && a->align == align && !a->active) {
a->begin -= delta;
a->end -= delta;
}
}
}
@ -359,13 +384,15 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
*end = str;
// Find most recent unclosed area.
for (i = astack.pos - 1; i >= 0 && !astack.slot[i].active; i--)
for (i = area_stack.at - 1; i >= 0 && !area_stack.area[i].active; i--)
;
a = &astack.slot[i];
a = &area_stack.area[i];
// Basic safety checks
if (!a->cmd || a->align != align || a->window != mon->window)
if (!a->cmd || a->align != align || a->window != mon->window) {
fprintf(stderr, "Invalid geometry for the clickable area\n");
return false;
}
const int size = x - a->begin;
@ -388,11 +415,12 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
return true;
}
if (astack.pos >= N) {
fprintf(stderr, "astack overflow!\n");
if (area_stack.at + 1 > area_stack.max) {
fprintf(stderr, "Cannot add any more clickable areas (used %d/%d)\n",
area_stack.at, area_stack.max);
return false;
}
a = &astack.slot[astack.pos++];
a = &area_stack.area[area_stack.at++];
// Found the closing : and check if it's just an escaped one
for (trail = strchr(++str, ':'); trail && trail[-1] == '\\'; trail = strchr(trail + 1, ':'))
@ -431,10 +459,13 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
bool
font_has_glyph (font_t *font, const uint16_t c)
{
return (c >= font->char_min &&
c <= font->char_max &&
font->width_lut &&
font->width_lut[c - font->char_min].character_width);
if (c < font->char_min || c > font->char_max)
return false;
if (font->width_lut && font->width_lut[c - font->char_min].character_width == 0)
return false;
return true;
}
// returns NULL if character cannot be printed
@ -445,7 +476,7 @@ select_drawable_font (const uint16_t c)
if (font_index != -1 && font_has_glyph(font_list[font_index - 1], c))
return font_list[font_index - 1];
// If the end is reached without finding an apropriate font, return NULL.
// If the end is reached without finding an appropriate font, return NULL.
// If the font can draw the character, return it.
for (int i = 0; i < font_count; i++) {
if (font_has_glyph(font_list[i], c))
@ -460,14 +491,15 @@ parse (char *text)
font_t *cur_font;
monitor_t *cur_mon;
int pos_x, align, button;
char *p = text, *end;
char *p = text, *block_end, *ep;
rgba_t tmp;
pos_x = 0;
align = ALIGN_L;
cur_mon = monhead;
memset(&astack, 0, sizeof(area_stack_t));
// Reset the stack position
area_stack.at = 0;
for (monitor_t *m = monhead; m != NULL; m = m->next)
fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh);
@ -476,8 +508,10 @@ parse (char *text)
if (*p == '\0' || *p == '\n')
return;
if (*p == '%' && p++ && *p == '{' && (end = strchr(p++, '}'))) {
while (p < end) {
if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) {
p++;
while (p < block_end) {
int w;
while (isspace(*p))
p++;
@ -502,12 +536,13 @@ parse (char *text)
// 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);
if (!area_add(p, block_end, &p, cur_mon, pos_x, align, button))
return;
break;
case 'B': bgc = parse_color(p, &p, dbgc); 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, dugc); update_gc(); break;
case 'S':
if (*p == '+' && cur_mon->next)
@ -529,24 +564,48 @@ parse (char *text)
p++;
pos_x = 0;
break;
case 'O':
errno = 0;
w = (int) strtoul(p, &p, 10);
if (errno)
continue;
draw_shift(cur_mon, pos_x, align, w);
pos_x += w;
area_shift(cur_mon->window, align, w);
break;
case 'T':
font_index = (int)strtoul(p, NULL, 10);
// User-specified 'font_index' ∊ (0,font_count]
// Otherwise just fallback to the automatic font selection
if (!font_index || font_index > font_count)
if (*p == '-') { //Reset to automatic font selection
font_index = -1;
p = end;
break;
p++;
break;
} else if (isdigit(*p)) {
font_index = (int)strtoul(p, &ep, 10);
// User-specified 'font_index' ∊ (0,font_count]
// Otherwise just fallback to the automatic font selection
if (!font_index || font_index > font_count)
font_index = -1;
p = ep;
break;
} else {
fprintf(stderr, "Invalid font slot \"%c\"\n", *p++); //Swallow the token
break;
}
// In case of error keep parsing after the closing }
default:
p = end;
p = block_end;
}
}
// Eat the trailing }
p++;
} else { // utf-8 -> ucs-2
// Escaped % symbol, eat the first one
if (p[0] == '%' && p[1] == '%')
p++;
uint8_t *utf = (uint8_t *)p;
uint16_t ucs;
@ -575,7 +634,7 @@ parse (char *text)
ucs = 0xfffd;
p += 5;
}
// Siz byte utf8 sequence
// Six byte utf8 sequence
else if ((utf[0] & 0xfe) == 0xfc) {
ucs = 0xfffd;
p += 6;
@ -600,9 +659,14 @@ parse (char *text)
}
}
font_t *
font_load (const char *str)
void
font_load (const char *pattern)
{
if (font_count >= MAX_FONT_COUNT) {
fprintf(stderr, "Max font count reached. Could not load font \"%s\"\n", pattern);
return;
}
xcb_query_font_cookie_t queryreq;
xcb_query_font_reply_t *font_info;
xcb_void_cookie_t cookie;
@ -610,16 +674,16 @@ font_load (const char *str)
font = xcb_generate_id(c);
cookie = xcb_open_font_checked(c, font, strlen(str), str);
cookie = xcb_open_font_checked(c, font, strlen(pattern), pattern);
if (xcb_request_check (c, cookie)) {
fprintf(stderr, "Could not load font \"%s\"\n", str);
return NULL;
fprintf(stderr, "Could not load font \"%s\"\n", pattern);
return;
}
font_t *ret = calloc(1, sizeof(font_t));
if (!ret)
return NULL;
return;
queryreq = xcb_query_font(c, font);
font_info = xcb_query_font_reply(c, queryreq, NULL);
@ -627,6 +691,7 @@ font_load (const char *str)
ret->ptr = font;
ret->descent = font_info->font_descent;
ret->height = font_info->font_ascent + font_info->font_descent;
ret->width = font_info->max_bounds.character_width;
ret->char_max = font_info->max_byte1 << 8 | font_info->max_char_or_byte2;
ret->char_min = font_info->min_byte1 << 8 | font_info->min_char_or_byte2;
@ -639,7 +704,7 @@ font_load (const char *str)
free(font_info);
return ret;
font_list[font_count++] = ret;
}
enum {
@ -691,11 +756,11 @@ set_ewmh_atoms (void)
if (topbar) {
strut[2] = bh;
strut[8] = mon->x;
strut[9] = mon->x + mon->width;
strut[9] = mon->x + mon->width - 1;
} else {
strut[3] = bh;
strut[10] = mon->x;
strut[11] = mon->x + mon->width;
strut[11] = mon->x + mon->width - 1;
}
xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, atom_list[NET_WM_WINDOW_TYPE], XCB_ATOM_ATOM, 32, 1, &atom_list[NET_WM_WINDOW_TYPE_DOCK]);
@ -759,10 +824,15 @@ rect_sort_cb (const void *p1, const void *p2)
const xcb_rectangle_t *r1 = (xcb_rectangle_t *)p1;
const xcb_rectangle_t *r2 = (xcb_rectangle_t *)p2;
if (r1->x < r2->x || r1->y < r2->y)
if (r1->x < r2->x || r1->y + r1->height <= r2->y)
{
return -1;
if (r1->x > r2->x || r1->y > r2->y)
return 1;
}
if (r1->x > r2->x || r1->y + r1->height > r2->y)
{
return 1;
}
return 0;
}
@ -811,6 +881,9 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num)
min(width, rects[i].width - left),
rects[i].height);
if (!mon)
break;
monitor_add(mon);
width -= rects[i].width - left;
@ -895,7 +968,7 @@ get_randr_monitors (void)
continue;
for (j = 0; j < num; j++) {
// Does I countain J ?
// Does I contain J ?
if (i != j && rects[j].width) {
if (rects[j].x >= rects[i].x && rects[j].x + rects[j].width <= rects[i].x + rects[i].width &&
@ -921,6 +994,7 @@ get_randr_monitors (void)
monitor_create_chain(r, valid);
}
#ifdef WITH_XINERAMA
void
get_xinerama_monitors (void)
{
@ -949,6 +1023,7 @@ get_xinerama_monitors (void)
monitor_create_chain(rects, screens);
}
#endif
xcb_visualid_t
get_visual (void)
@ -971,7 +1046,7 @@ get_visual (void)
return scr->root_visual;
}
// Parse an X-styled geometry string, we don't support signed offsets tho.
// Parse an X-styled geometry string, we don't support signed offsets though.
bool
parse_geometry_string (char *str, int *tmp)
{
@ -1022,48 +1097,6 @@ parse_geometry_string (char *str, int *tmp)
return true;
}
void
parse_font_list (char *str)
{
char *tok, *end;
if (!str)
return;
tok = strtok(str, ",");
while (tok) {
if (font_count > MAX_FONT_COUNT - 1) {
fprintf(stderr, "Too many fonts; maximum %i\n", MAX_FONT_COUNT);
return;
}
// Strip the leading and trailing whitespaces
while (isspace(*tok) || iscntrl(*tok))
tok++;
end = tok + strlen(tok) - 1;
while ((end > tok && isspace(*end)) || iscntrl(*end))
end--;
*(end + 1) = '\0';
if (tok[0]) {
// Load the selected font
font_t *font = font_load(tok);
if (font)
font_list[font_count++] = font;
}
else
fprintf(stderr, "Empty font name, skipping...\n");
tok = strtok(NULL, ",");
}
}
void
xconn (void)
{
@ -1085,15 +1118,11 @@ xconn (void)
}
void
init (void)
init (char *wm_name)
{
// This has to be declared as an array because otherwise the compiler would turn it into a const
// string, making strtok choke very hard on this
char fallback_font[] = "fixed";
// Try to load a default font
if (!font_count)
parse_font_list(fallback_font);
font_load("fixed");
// We tried and failed hard, there's something wrong
if (!font_count)
@ -1111,7 +1140,7 @@ init (void)
// Generate a list of screens
const xcb_query_extension_reply_t *qe_reply;
// Initialiaze monitor list head and tail
// Initialize monitor list head and tail
monhead = montail = NULL;
// Check if RandR is present
@ -1119,7 +1148,9 @@ init (void)
if (qe_reply && qe_reply->present) {
get_randr_monitors();
} else {
}
#if WITH_XINERAMA
else {
qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id);
// Check if Xinerama extension is present and active
@ -1133,6 +1164,7 @@ init (void)
free(xia_reply);
}
}
#endif
if (!monhead) {
// If I fits I sits
@ -1177,6 +1209,10 @@ init (void)
// Make sure that the window really gets in the place it's supposed to be
// Some WM such as Openbox need this
xcb_configure_window(c, mon->window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, (const uint32_t []){ mon->x, mon->y });
// Set the WM_NAME atom to the user specified value
if (wm_name)
xcb_change_property(c, XCB_PROP_MODE_REPLACE, mon->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8 ,strlen(wm_name), wm_name);
}
xcb_flush(c);
@ -1185,6 +1221,8 @@ init (void)
void
cleanup (void)
{
free(area_stack.area);
for (int i = 0; i < font_count; i++) {
xcb_close_font(c, font_list[i]->ptr);
free(font_list[i]->width_lut);
@ -1231,47 +1269,72 @@ main (int argc, char **argv)
char input[4096] = {0, };
bool permanent = false;
int geom_v[4] = { -1, -1, 0, 0 };
int ch;
int ch, areas;
char *wm_name;
// Install the parachute!
atexit(cleanup);
signal(SIGINT, sighandle);
signal(SIGTERM, sighandle);
// B/W combo
dbgc = bgc = (rgba_t)0x00000000U;
dfgc = fgc = (rgba_t)0xffffffffU;
dugc = ugc = fgc;
// A safe default
areas = 10;
wm_name = NULL;
// Connect to the Xserver and initialize scr
xconn();
// B/W combo
dbgc = bgc = parse_color("black", NULL, (rgba_t)scr->black_pixel);
dfgc = fgc = parse_color("white", NULL, (rgba_t)scr->white_pixel);
ugc = fgc;
while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:")) != -1) {
while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:U:n:")) != -1) {
switch (ch) {
case 'h':
printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F]\n"
printf ("lemonbar version %s\n", VERSION);
printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -n | -u | -B | -F]\n"
"\t-h Show this help\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-b Put the 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"
"\t-f Set the font name to use\n"
"\t-a Number of clickable areas available (default is 10)\n"
"\t-p Don't close after the data ends\n"
"\t-n Set the WM_NAME atom to the specified value for this bar\n"
"\t-u Set the underline/overline height in pixels\n"
"\t-B Set background color in #AARRGGBB\n"
"\t-F Set foreground color in #AARRGGBB\n", argv[0]);
exit (EXIT_SUCCESS);
case 'g': (void)parse_geometry_string(optarg, geom_v); break;
case 'p': permanent = true; break;
case 'n': wm_name = strdup(optarg); break;
case 'b': topbar = false; break;
case 'd': dock = true; break;
case 'f': parse_font_list(optarg); break;
case 'f': font_load(optarg); break;
case 'u': bu = strtoul(optarg, NULL, 10); break;
case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break;
case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)scr->white_pixel); break;
case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)0x00000000U); break;
case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)0xffffffffU); break;
case 'U': dugc = ugc = parse_color(optarg, NULL, fgc); break;
case 'a': areas = strtoul(optarg, NULL, 10); break;
}
}
// Initialize the stack holding the clickable areas
area_stack.at = 0;
area_stack.max = areas;
if (areas) {
area_stack.area = calloc(areas, sizeof(area_t));
if (!area_stack.area) {
fprintf(stderr, "Could not allocate enough memory for %d clickable areas, try lowering the number\n", areas);
return EXIT_FAILURE;
}
}
else
area_stack.area = NULL;
// Copy the geometry values in place
bw = geom_v[0];
bh = geom_v[1];
@ -1279,7 +1342,9 @@ main (int argc, char **argv)
by = geom_v[3];
// Do the heavy lifting
init();
init(wm_name);
// The string is strdup'd when the command line arguments are parsed
free(wm_name);
// Get the fd to Xserver
pollin[1].fd = xcb_get_file_descriptor(c);
@ -1302,7 +1367,7 @@ main (int argc, char **argv)
parse(input);
redraw = true;
}
if (pollin[1].revents & POLLIN) { // Xserver broadcasted an event
if (pollin[1].revents & POLLIN) { // The event comes from the Xorg server
while ((ev = xcb_poll_for_event(c))) {
expose_ev = (xcb_expose_event_t *)ev;
@ -1317,8 +1382,8 @@ main (int argc, char **argv)
area_t *area = area_get(press_ev->event, press_ev->detail, press_ev->event_x);
// Respond to the click
if (area) {
write(STDOUT_FILENO, area->cmd, strlen(area->cmd));
write(STDOUT_FILENO, "\n", 1);
(void)write(STDOUT_FILENO, area->cmd, strlen(area->cmd));
(void)write(STDOUT_FILENO, "\n", 1);
}
}
break;

View File

@ -1,36 +0,0 @@
#!/usr/bin/env perl
#
# palette.pl
#
# Converts your .Xdefault/.Xresources colors into a ready to paste palette
# for bar. It takes your foreground/background settings into account and if
# it cant find them it leaves COLOR0/COLOR1 undefined.
#
use strict;
use warnings;
open (F, "<".$ARGV[0]) || die "Can't open!";
our %vars = ();
while (<F>) {
# Don't match comments
if ($_ !~ m/^\s*!/) {
# It's a define!
if ($_ =~ m/^\s*#define\s+(\w+)\s+#([0-9A-Fa-f]{1,6})/) {
$vars{"$1"} = hex($2);
}
elsif ($_ =~ m/^\s*\w*\*(background|foreground|color\d)\s*:\s*([\w\d#]+)/) {
my ($name, $value) = (uc $1, $2);
# Check if it's a color
if (substr($value, 0, 1) eq '#') {
$value = hex(substr($value, 1));
} else {
$value = $vars{"$value"};
}
printf "#define $name 0x%06x\n", $value;
}
}
}