Compare commits

...

50 Commits
v1.1 ... 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
5 changed files with 259 additions and 180 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,5 +1,5 @@
# This snippet has been shmelessly stol^Hborrowed from thestinger's repose Makefile
VERSION = 1.1
VERSION = 1.3
GIT_DESC=$(shell test -d .git && git describe --always 2>/dev/null)
ifneq "$(GIT_DESC)" ""

View File

@ -6,7 +6,7 @@ lemonbar - Featherweight lemon-scented bar
=head1 SYNOPSIS
I<lemonbar> [-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
@ -34,29 +34,42 @@ Force docking without asking the window manager. This is needed if the window ma
=item B<-f> I<font>
Comma separated list of fonts, lemonbar 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 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>
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
lemonbar 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 the 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, lemonbar 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,7 +111,7 @@ 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}>
@ -168,7 +185,7 @@ L<git repository|https://github.com/LemonBoy/bar>
=head1 AUTHOR
2012-2015 (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,8 +39,11 @@ 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;
@ -52,11 +58,9 @@ typedef union rgba_t {
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)
@ -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],
@ -207,6 +210,34 @@ 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);
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 allocate the 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,8 +363,8 @@ 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++) {
area_t *a = &astack.slot[i];
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;
@ -360,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;
@ -389,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, ':'))
@ -432,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
@ -468,7 +498,8 @@ parse (char *text)
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);
@ -477,8 +508,10 @@ parse (char *text)
if (*p == '\0' || *p == '\n')
return;
if (*p == '%' && p++ && *p == '{' && (block_end = strchr(p++, '}'))) {
if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) {
p++;
while (p < block_end) {
int w;
while (isspace(*p))
p++;
@ -503,12 +536,13 @@ parse (char *text)
// The range is 1-5
if (isdigit(*p) && (*p > '0' && *p < '6'))
button = *p++ - '0';
area_add(p, block_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)
@ -530,15 +564,35 @@ 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, &ep, 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 = ep;
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:
@ -548,6 +602,10 @@ parse (char *text)
// 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;
@ -576,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;
@ -601,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;
@ -611,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);
@ -628,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;
@ -640,7 +704,7 @@ font_load (const char *str)
free(font_info);
return ret;
font_list[font_count++] = ret;
}
enum {
@ -692,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]);
@ -760,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;
}
@ -925,6 +994,7 @@ get_randr_monitors (void)
monitor_create_chain(r, valid);
}
#ifdef WITH_XINERAMA
void
get_xinerama_monitors (void)
{
@ -953,6 +1023,7 @@ get_xinerama_monitors (void)
monitor_create_chain(rects, screens);
}
#endif
xcb_visualid_t
get_visual (void)
@ -1026,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)
{
@ -1089,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)
@ -1123,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
@ -1137,6 +1164,7 @@ init (void)
free(xia_reply);
}
}
#endif
if (!monhead) {
// If I fits I sits
@ -1181,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);
@ -1189,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);
@ -1235,48 +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 ("lemonbar version %s\n", VERSION);
printf ("usage: %s [-h | -g | -b | -d | -f | -a | -p | -u | -B | -F]\n"
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 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];
@ -1284,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);
@ -1322,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;