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 308 additions and 378 deletions

3
.gitignore vendored
View File

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

View File

@ -3,5 +3,8 @@ compiler:
- clang - clang
- gcc - gcc
before_install: 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 script: make

View File

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

View File

@ -1,16 +1,16 @@
=head1 NAME =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> =for HTML <a href="https://travis-ci.org/LemonBoy/bar"><img src="https://travis-ci.org/LemonBoy/bar.svg?branch=master"></a>
=head1 SYNOPSIS =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 =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 =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> =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> =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> =item B<-u> I<pixel>
@ -46,17 +55,21 @@ Sets the underline width in pixels. The default is 1.
=item B<-B> I<color> =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> =item B<-F> I<color>
Set the foreground color of the bar. Accepts the same color formats as B<-B>. 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 =back
=head1 FORMATTING =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 =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. 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> =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. 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> =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> =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>: =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}> 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. 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> =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 =over
@ -156,7 +177,7 @@ Draw a line under the text.
=head1 OUTPUT =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 =head1 WWW
@ -164,7 +185,7 @@ L<git repository|https://github.com/LemonBoy/bar>
=head1 AUTHOR =head1 AUTHOR
2012-2014 (C) The Lemon Man 2012-2017 (C) The Lemon Man
Xinerama support was kindly contributed by Stebalien Xinerama support was kindly contributed by Stebalien

View File

@ -1,4 +1,5 @@
// vim:sw=4:ts=4:et: // vim:sw=4:ts=4:et:
#define _POSIX_C_SOURCE 200809L
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -11,7 +12,9 @@
#include <errno.h> #include <errno.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcbext.h> #include <xcb/xcbext.h>
#if WITH_XINERAMA
#include <xcb/xinerama.h> #include <xcb/xinerama.h>
#endif
#include <xcb/randr.h> #include <xcb/randr.h>
// Here be dragons // Here be dragons
@ -22,7 +25,7 @@
typedef struct font_t { typedef struct font_t {
xcb_font_t ptr; xcb_font_t ptr;
int descent, height; int descent, height, width;
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;
@ -36,27 +39,28 @@ typedef struct monitor_t {
} monitor_t; } monitor_t;
typedef struct area_t { typedef struct area_t {
bool active; unsigned int begin:16;
int begin, end, align, button; unsigned int end:16;
bool active:1;
int align:3;
unsigned int button:3;
xcb_window_t window; xcb_window_t window;
char *cmd; char *cmd;
} area_t; } area_t;
typedef union rgba_t { typedef union rgba_t {
struct { struct {
uint8_t r;
uint8_t g;
uint8_t b; uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a; uint8_t a;
}; };
uint32_t v; uint32_t v;
} rgba_t; } rgba_t;
#define N 20
typedef struct area_stack_t { typedef struct area_stack_t {
int pos; int at, max;
area_t slot[N]; area_t *area;
} area_stack_t; } area_stack_t;
enum { enum {
@ -94,8 +98,8 @@ static bool topbar = true;
static int bw = -1, bh = -1, bx = 0, by = 0; static int bw = -1, bh = -1, bx = 0, by = 0;
static int bu = 1; // Underline height static int bu = 1; // Underline height
static rgba_t fgc, bgc, ugc; static rgba_t fgc, bgc, ugc;
static rgba_t dfgc, dbgc; static rgba_t dfgc, dbgc, dugc;
static area_stack_t astack; static area_stack_t area_stack;
void void
update_gc (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) uint32_t len, const uint16_t *str)
{ {
static const xcb_protocol_request_t xcb_req = { static const xcb_protocol_request_t xcb_req = {
5, // count 5, // count
0, // ext 0, // ext
XCB_POLY_TEXT_16, // opcode XCB_POLY_TEXT_16, // opcode
1 // isvoid 1 // isvoid
}; };
struct iovec xcb_parts[7]; struct iovec xcb_parts[7];
uint8_t xcb_lendelta[2]; uint8_t xcb_lendelta[2];
@ -180,144 +184,60 @@ 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_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); xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret; return xcb_ret;
} }
#define pad_to(x, to) (((x) + (to) - 1) & ~((to) - 1))
typedef struct xbm_t {
int width;
int height;
uint8_t *bits;
size_t bits_size;
} xbm_t;
xbm_t xbm_cache[20];
int xbm_cache_elem = 0;
int int
xbm_parse (char *path) shift (monitor_t *mon, int x, int align, int ch_width)
{
FILE *fp;
char line[4096];
int xbm_height, xcb_width;
fp = fopen(path, "r");
if (!fp)
return 0;
while (fgets(line, sizeof(line), fp)) {
}
}
xbm_t *
xbm_load (uint8_t *bits, int width, int height)
{
const xcb_setup_t *setup = xcb_get_setup(c);
uint8_t *buf;
int width_b, line;
xbm_t *ico = &xbm_cache[xbm_cache_elem];
// XCB_IMAGE_ORDER_LSB_FIRST
// bitmap_format_bit_order
width_b = (width + 7) / 8;
line = pad_to(width_b, setup->bitmap_format_scanline_pad >> 3);
buf = malloc(height * line);
if (!buf)
return NULL;
// Despite the naming, this is actually a stencil
for (int i = 0; i < height * width_b; i++)
bits[i] = ~bits[i];
for (int i = 0; i < height; i++)
memcpy(buf + (i * line),
bits + (i * width_b),
width_b);
ico->width = width;
ico->height = height;
ico->bits = buf;
ico->bits_size = height * line;
xbm_cache_elem++;
return ico;
}
int
pixmap_shift (monitor_t *mon, int x, int align, int w)
{ {
switch (align) { switch (align) {
case ALIGN_L:
return x;
case ALIGN_C: case ALIGN_C:
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW],
mon->width / 2 - x / 2, 0, mon->width / 2 - x / 2, 0,
mon->width / 2 - (x + w) / 2, 0, mon->width / 2 - (x + ch_width) / 2, 0,
x, bh); x, bh);
return mon->width / 2 - (x + w) / 2 + x; x = mon->width / 2 - (x + ch_width) / 2 + x;
break;
case ALIGN_R: case ALIGN_R:
xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW],
mon->width - x, 0, mon->width - x, 0,
mon->width - x - w, 0, mon->width - x - ch_width, 0,
x, bh); x, bh);
return mon->width - w; x = mon->width - ch_width;
break;
} }
return 0; // Draw the background first
fill_rect(mon->pixmap, gc[GC_CLEAR], x, 0, ch_width, bh);
return x;
} }
int void
draw_icon (monitor_t *mon, int x, xbm_t *icon, int align) draw_lines (monitor_t *mon, int x, int w)
{ {
xcb_gcontext_t tmp_gc; /* We can render both at the same time */
xcb_pixmap_t mask; 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);
}
x = pixmap_shift(mon, x, align, icon->width); void
draw_shift (monitor_t *mon, int x, int align, int w)
mask = xcb_generate_id(c); {
xcb_create_pixmap(c, 1, mask, mon->pixmap, icon->width, icon->height); x = shift(mon, x, align, w);
draw_lines(mon, x, w);
tmp_gc = xcb_generate_id(c);
xcb_create_gc(c, tmp_gc, mask, 0, NULL);
xcb_put_image(
c,
XCB_IMAGE_FORMAT_XY_BITMAP,
mask,
tmp_gc,
icon->width, icon->height,
0, 0,
0, 1,
icon->bits_size, icon->bits);
xcb_free_gc(c, tmp_gc);
xcb_change_gc(c, gc[GC_DRAW], XCB_GC_CLIP_MASK, (const uint32_t []){ mask });
xcb_change_gc(c, gc[GC_DRAW], XCB_GC_CLIP_ORIGIN_X | XCB_GC_CLIP_ORIGIN_Y,
(const uint32_t []){ x, bh / 2 - icon->height / 2 });
xcb_poly_fill_rectangle(c, mon->pixmap, gc[GC_DRAW], 1,
(const xcb_rectangle_t []){ { 0, 0, bw, bh } });
xcb_change_gc(c, gc[GC_DRAW], XCB_GC_CLIP_MASK, (const uint32_t []){ XCB_NONE });
xcb_free_pixmap(c, mask);
return icon->width;
} }
int int
draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch)
{ {
int ch_width = cur_font->width_lut[ch - cur_font->char_min].character_width; int ch_width = (cur_font->width_lut) ?
cur_font->width_lut[ch - cur_font->char_min].character_width:
cur_font->width;
x = pixmap_shift(mon, x, align, ch_width); x = shift(mon, x, align, ch_width);
// Draw the background first
fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, ch_width, bh);
// xcb accepts string in UCS-2 BE, so swap // xcb accepts string in UCS-2 BE, so swap
ch = (ch >> 8) | (ch << 8); ch = (ch >> 8) | (ch << 8);
@ -327,29 +247,15 @@ 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, x, bh / 2 + cur_font->height / 2 - cur_font->descent,
1, &ch); 1, &ch);
// We can render both at the same time draw_lines(mon, x, ch_width);
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);
return ch_width; return ch_width;
} }
static unsigned char fox_bits[] = {
0x70, 0x88, 0xC4, 0xE2, 0x7E, 0x32, 0x09, 0x07
0x81, 0xC3, 0xBD, 0xFF, 0x99, 0xDB, 0x7E, 0x18,
};
int xbm_w = 8;
int xbm_h = 8;
rgba_t rgba_t
parse_color (const char *str, char **end, const rgba_t def) parse_color (const char *str, char **end, const rgba_t def)
{ {
xcb_alloc_named_color_reply_t *nc_reply;
int string_len; int string_len;
rgba_t ret;
char *ep; char *ep;
if (!str) if (!str)
@ -364,61 +270,61 @@ parse_color (const char *str, char **end, const rgba_t def)
} }
// Hex representation // Hex representation
if (str[0] == '#') { if (str[0] != '#') {
errno = 0;
rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16);
if (end) if (end)
*end = ep; *end = (char *)str;
// Some error checking is definitely good fprintf(stderr, "Invalid color specified\n");
if (errno) { return def;
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;
} }
// Actual color name, resolve it errno = 0;
for (string_len = 0; isalpha(str[string_len]); string_len++) rgba_t tmp = (rgba_t)(uint32_t)strtoul(str + 1, &ep, 16);
;
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);
if (end) 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 void
set_attribute (const char modifier, const char attribute) set_attribute (const char modifier, const char attribute)
{ {
@ -441,10 +347,9 @@ area_t *
area_get (xcb_window_t win, const int btn, const int x) area_get (xcb_window_t win, const int btn, const int x)
{ {
// Looping backwards ensures that we get the innermost area first // Looping backwards ensures that we get the innermost area first
for (int i = astack.pos; i >= 0; i--) { for (int i = area_stack.at - 1; i >= 0; i--) {
area_t *a = &astack.slot[i]; area_t *a = &area_stack.area[i];
if (a->window == win && a->button == btn if (a->window == win && a->button == btn && x >= a->begin && x < a->end)
&& x >= a->begin && x < a->end)
return a; return a;
} }
return NULL; return NULL;
@ -458,10 +363,11 @@ area_shift (xcb_window_t win, const int align, int delta)
if (align == ALIGN_C) if (align == ALIGN_C)
delta /= 2; delta /= 2;
for (int i = 0; i < astack.pos; i++) { for (int i = 0; i < area_stack.at; i++) {
if (astack.slot[i].window == win && astack.slot[i].align == align) { area_t *a = &area_stack.area[i];
astack.slot[i].begin -= delta; if (a->window == win && a->align == align && !a->active) {
astack.slot[i].end -= delta; a->begin -= delta;
a->end -= delta;
} }
} }
} }
@ -478,13 +384,15 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
*end = str; *end = str;
// Find most recent unclosed area. // 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 // 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; return false;
}
const int size = x - a->begin; const int size = x - a->begin;
@ -507,11 +415,12 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
return true; return true;
} }
if (astack.pos >= N) { if (area_stack.at + 1 > area_stack.max) {
fprintf(stderr, "astack overflow!\n"); fprintf(stderr, "Cannot add any more clickable areas (used %d/%d)\n",
area_stack.at, area_stack.max);
return false; 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 // Found the closing : and check if it's just an escaped one
for (trail = strchr(++str, ':'); trail && trail[-1] == '\\'; trail = strchr(trail + 1, ':')) for (trail = strchr(++str, ':'); trail && trail[-1] == '\\'; trail = strchr(trail + 1, ':'))
@ -550,10 +459,13 @@ area_add (char *str, const char *optend, char **end, monitor_t *mon, const int x
bool bool
font_has_glyph (font_t *font, const uint16_t c) font_has_glyph (font_t *font, const uint16_t c)
{ {
return (c >= font->char_min && if (c < font->char_min || c > font->char_max)
c <= font->char_max && return false;
font->width_lut &&
font->width_lut[c - font->char_min].character_width); 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 // returns NULL if character cannot be printed
@ -564,7 +476,7 @@ select_drawable_font (const uint16_t c)
if (font_index != -1 && font_has_glyph(font_list[font_index - 1], c)) if (font_index != -1 && font_has_glyph(font_list[font_index - 1], c))
return font_list[font_index - 1]; 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. // If the font can draw the character, return it.
for (int i = 0; i < font_count; i++) { for (int i = 0; i < font_count; i++) {
if (font_has_glyph(font_list[i], c)) if (font_has_glyph(font_list[i], c))
@ -579,14 +491,15 @@ parse (char *text)
font_t *cur_font; font_t *cur_font;
monitor_t *cur_mon; monitor_t *cur_mon;
int pos_x, align, button; int pos_x, align, button;
char *p = text, *end; char *p = text, *block_end, *ep;
rgba_t tmp; rgba_t tmp;
pos_x = 0; pos_x = 0;
align = ALIGN_L; align = ALIGN_L;
cur_mon = monhead; 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) for (monitor_t *m = monhead; m != NULL; m = m->next)
fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh); fill_rect(m->pixmap, gc[GC_CLEAR], 0, 0, m->width, bh);
@ -595,8 +508,10 @@ parse (char *text)
if (*p == '\0' || *p == '\n') if (*p == '\0' || *p == '\n')
return; return;
if (*p == '%' && p++ && *p == '{' && (end = strchr(p++, '}'))) { if (p[0] == '%' && p[1] == '{' && (block_end = strchr(p++, '}'))) {
while (p < end) { p++;
while (p < block_end) {
int w;
while (isspace(*p)) while (isspace(*p))
p++; p++;
@ -621,12 +536,13 @@ parse (char *text)
// The range is 1-5 // The range is 1-5
if (isdigit(*p) && (*p > '0' && *p < '6')) if (isdigit(*p) && (*p > '0' && *p < '6'))
button = *p++ - '0'; 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; 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, dugc); update_gc(); break;
case 'S': case 'S':
if (*p == '+' && cur_mon->next) if (*p == '+' && cur_mon->next)
@ -648,35 +564,48 @@ parse (char *text)
p++; p++;
pos_x = 0; pos_x = 0;
break; 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': case 'T':
font_index = (int)strtoul(p, NULL, 10); if (*p == '-') { //Reset to automatic font selection
// 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; font_index = -1;
p = end; p++;
break; break;
} else if (isdigit(*p)) {
case 'i': font_index = (int)strtoul(p, &ep, 10);
; // User-specified 'font_index' ∊ (0,font_count]
int icon_index = (int)strtoul(p, NULL, 10); // Otherwise just fallback to the automatic font selection
if (icon_index < xbm_cache_elem) { if (!font_index || font_index > font_count)
int w = draw_icon(cur_mon, pos_x, &xbm_cache[0], align); font_index = -1;
pos_x += w; p = ep;
area_shift(cur_mon->window, align, w); break;
} else {
fprintf(stderr, "Invalid font slot \"%c\"\n", *p++); //Swallow the token
break;
} }
p = end;
break;
// In case of error keep parsing after the closing } // In case of error keep parsing after the closing }
default: default:
p = end; p = block_end;
} }
} }
// Eat the trailing } // Eat the trailing }
p++; p++;
} else { // utf-8 -> ucs-2 } else { // utf-8 -> ucs-2
// Escaped % symbol, eat the first one
if (p[0] == '%' && p[1] == '%')
p++;
uint8_t *utf = (uint8_t *)p; uint8_t *utf = (uint8_t *)p;
uint16_t ucs; uint16_t ucs;
@ -705,7 +634,7 @@ parse (char *text)
ucs = 0xfffd; ucs = 0xfffd;
p += 5; p += 5;
} }
// Siz byte utf8 sequence // Six byte utf8 sequence
else if ((utf[0] & 0xfe) == 0xfc) { else if ((utf[0] & 0xfe) == 0xfc) {
ucs = 0xfffd; ucs = 0xfffd;
p += 6; p += 6;
@ -723,16 +652,21 @@ 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 });
int w = 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;
pos_x += w;
area_shift(cur_mon->window, align, w); area_shift(cur_mon->window, align, w);
} }
} }
} }
font_t * void
font_load (const char *str) 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_cookie_t queryreq;
xcb_query_font_reply_t *font_info; xcb_query_font_reply_t *font_info;
xcb_void_cookie_t cookie; xcb_void_cookie_t cookie;
@ -740,16 +674,16 @@ font_load (const char *str)
font = xcb_generate_id(c); 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)) { if (xcb_request_check (c, cookie)) {
fprintf(stderr, "Could not load font \"%s\"\n", str); fprintf(stderr, "Could not load font \"%s\"\n", pattern);
return NULL; return;
} }
font_t *ret = calloc(1, sizeof(font_t)); font_t *ret = calloc(1, sizeof(font_t));
if (!ret) if (!ret)
return NULL; return;
queryreq = xcb_query_font(c, font); queryreq = xcb_query_font(c, font);
font_info = xcb_query_font_reply(c, queryreq, NULL); font_info = xcb_query_font_reply(c, queryreq, NULL);
@ -757,6 +691,7 @@ font_load (const char *str)
ret->ptr = font; ret->ptr = font;
ret->descent = font_info->font_descent; ret->descent = font_info->font_descent;
ret->height = font_info->font_ascent + 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_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; ret->char_min = font_info->min_byte1 << 8 | font_info->min_char_or_byte2;
@ -769,7 +704,7 @@ font_load (const char *str)
free(font_info); free(font_info);
return ret; font_list[font_count++] = ret;
} }
enum { enum {
@ -821,11 +756,11 @@ set_ewmh_atoms (void)
if (topbar) { if (topbar) {
strut[2] = bh; strut[2] = bh;
strut[8] = mon->x; strut[8] = mon->x;
strut[9] = mon->x + mon->width; strut[9] = mon->x + mon->width - 1;
} else { } else {
strut[3] = bh; strut[3] = bh;
strut[10] = mon->x; 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]); 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]);
@ -889,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 *r1 = (xcb_rectangle_t *)p1;
const xcb_rectangle_t *r2 = (xcb_rectangle_t *)p2; 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; 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; return 0;
} }
@ -941,6 +881,9 @@ monitor_create_chain (xcb_rectangle_t *rects, const int num)
min(width, rects[i].width - left), min(width, rects[i].width - left),
rects[i].height); rects[i].height);
if (!mon)
break;
monitor_add(mon); monitor_add(mon);
width -= rects[i].width - left; width -= rects[i].width - left;
@ -1025,7 +968,7 @@ get_randr_monitors (void)
continue; continue;
for (j = 0; j < num; j++) { for (j = 0; j < num; j++) {
// Does I countain J ? // Does I contain J ?
if (i != j && rects[j].width) { 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 && if (rects[j].x >= rects[i].x && rects[j].x + rects[j].width <= rects[i].x + rects[i].width &&
@ -1051,6 +994,7 @@ get_randr_monitors (void)
monitor_create_chain(r, valid); monitor_create_chain(r, valid);
} }
#ifdef WITH_XINERAMA
void void
get_xinerama_monitors (void) get_xinerama_monitors (void)
{ {
@ -1079,6 +1023,7 @@ get_xinerama_monitors (void)
monitor_create_chain(rects, screens); monitor_create_chain(rects, screens);
} }
#endif
xcb_visualid_t xcb_visualid_t
get_visual (void) get_visual (void)
@ -1101,7 +1046,7 @@ get_visual (void)
return scr->root_visual; 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 bool
parse_geometry_string (char *str, int *tmp) parse_geometry_string (char *str, int *tmp)
{ {
@ -1152,46 +1097,6 @@ parse_geometry_string (char *str, int *tmp)
return true; 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 void
xconn (void) xconn (void)
{ {
@ -1213,15 +1118,11 @@ xconn (void)
} }
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 // Try to load a default font
if (!font_count) if (!font_count)
parse_font_list(fallback_font); font_load("fixed");
// We tried and failed hard, there's something wrong // We tried and failed hard, there's something wrong
if (!font_count) if (!font_count)
@ -1239,7 +1140,7 @@ init (void)
// Generate a list of screens // Generate a list of screens
const xcb_query_extension_reply_t *qe_reply; const xcb_query_extension_reply_t *qe_reply;
// Initialiaze monitor list head and tail // Initialize monitor list head and tail
monhead = montail = NULL; monhead = montail = NULL;
// Check if RandR is present // Check if RandR is present
@ -1247,7 +1148,9 @@ init (void)
if (qe_reply && qe_reply->present) { if (qe_reply && qe_reply->present) {
get_randr_monitors(); get_randr_monitors();
} else { }
#if WITH_XINERAMA
else {
qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id); qe_reply = xcb_get_extension_data(c, &xcb_xinerama_id);
// Check if Xinerama extension is present and active // Check if Xinerama extension is present and active
@ -1261,6 +1164,7 @@ init (void)
free(xia_reply); free(xia_reply);
} }
} }
#endif
if (!monhead) { if (!monhead) {
// If I fits I sits // If I fits I sits
@ -1305,6 +1209,10 @@ init (void)
// Make sure that the window really gets in the place it's supposed to be // Make sure that the window really gets in the place it's supposed to be
// Some WM such as Openbox need this // 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 }); 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); xcb_flush(c);
@ -1313,6 +1221,8 @@ init (void)
void void
cleanup (void) cleanup (void)
{ {
free(area_stack.area);
for (int i = 0; i < font_count; i++) { for (int i = 0; i < font_count; i++) {
xcb_close_font(c, font_list[i]->ptr); xcb_close_font(c, font_list[i]->ptr);
free(font_list[i]->width_lut); free(font_list[i]->width_lut);
@ -1359,47 +1269,72 @@ main (int argc, char **argv)
char input[4096] = {0, }; char input[4096] = {0, };
bool permanent = false; bool permanent = false;
int geom_v[4] = { -1, -1, 0, 0 }; int geom_v[4] = { -1, -1, 0, 0 };
int ch; int ch, areas;
char *wm_name;
// Install the parachute! // Install the parachute!
atexit(cleanup); atexit(cleanup);
signal(SIGINT, sighandle); signal(SIGINT, sighandle);
signal(SIGTERM, 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 // Connect to the Xserver and initialize scr
xconn(); xconn();
// B/W combo while ((ch = getopt(argc, argv, "hg:bdf:a:pu:B:F:U:n:")) != -1) {
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) {
switch (ch) { switch (ch) {
case 'h': 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-h Show this help\n"
"\t-g Set the bar geometry {width}x{height}+{xoffset}+{yoffset}\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-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-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-u Set the underline/overline height in pixels\n"
"\t-B Set background color in #AARRGGBB\n" "\t-B Set background color in #AARRGGBB\n"
"\t-F Set foreground color in #AARRGGBB\n", argv[0]); "\t-F Set foreground color in #AARRGGBB\n", argv[0]);
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
case 'g': (void)parse_geometry_string(optarg, geom_v); break; case 'g': (void)parse_geometry_string(optarg, geom_v); break;
case 'p': permanent = true; break; case 'p': permanent = true; break;
case 'n': wm_name = strdup(optarg); break;
case 'b': topbar = false; break; case 'b': topbar = false; break;
case 'd': dock = true; 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 'u': bu = strtoul(optarg, NULL, 10); break;
case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)scr->black_pixel); break; case 'B': dbgc = bgc = parse_color(optarg, NULL, (rgba_t)0x00000000U); break;
case 'F': dfgc = fgc = parse_color(optarg, NULL, (rgba_t)scr->white_pixel); 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 // Copy the geometry values in place
bw = geom_v[0]; bw = geom_v[0];
bh = geom_v[1]; bh = geom_v[1];
@ -1407,12 +1342,12 @@ main (int argc, char **argv)
by = geom_v[3]; by = geom_v[3];
// Do the heavy lifting // 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 // Get the fd to Xserver
pollin[1].fd = xcb_get_file_descriptor(c); pollin[1].fd = xcb_get_file_descriptor(c);
xbm_load (fox_bits, xbm_w, xbm_h);
for (;;) { for (;;) {
bool redraw = false; bool redraw = false;
@ -1432,7 +1367,7 @@ main (int argc, char **argv)
parse(input); parse(input);
redraw = true; 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))) { while ((ev = xcb_poll_for_event(c))) {
expose_ev = (xcb_expose_event_t *)ev; expose_ev = (xcb_expose_event_t *)ev;
@ -1447,8 +1382,8 @@ main (int argc, char **argv)
area_t *area = area_get(press_ev->event, press_ev->detail, press_ev->event_x); area_t *area = area_get(press_ev->event, press_ev->detail, press_ev->event_x);
// Respond to the click // Respond to the click
if (area) { if (area) {
write(STDOUT_FILENO, area->cmd, strlen(area->cmd)); (void)write(STDOUT_FILENO, area->cmd, strlen(area->cmd));
write(STDOUT_FILENO, "\n", 1); (void)write(STDOUT_FILENO, "\n", 1);
} }
} }
break; 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;
}
}
}