commit - c2ca3402b92d106af09010320b729704fb5c379b
commit + f04a5f5c2efc8b90ca3004c28f534b3cee737c2c
blob - 7e4e035b5bc8a122de59be66afa1586aa74232c2
blob + e148a4ee2d2e5c52dda8a64e7bf4698776d74e51
--- bxnotify.c
+++ bxnotify.c
static int total_height;
static time_t start_time;
static char reg_path[256];
+/* Global runtime configuration (defaults from config.h) */
+static int cfg_width = WIN_WIDTH;
+static int cfg_win_x = WIN_X;
+static int cfg_win_y = WIN_Y;
+static int cfg_padding = PADDING;
+static int cfg_border_width = BORDER_WIDTH;
+static int cfg_align = ALIGN;
+static int cfg_duration = DURATION;
+static const char *cfg_fg = FG_COLOR;
+static const char *cfg_bg = BG_COLOR;
+static const char *cfg_border = BORDER_COLOR;
+static const char *cfg_font = FONT;
/* Forward Declarations */
static void die(const char *fmt, ...);
int
main(int argc, char *argv[])
{
+ int opt;
+ while ((opt = getopt(argc, argv, "d:f:F:B:C:a:")) != -1) {
+ switch (opt) {
+ case 'd': cfg_duration = atoi(optarg); break;
+ case 'f': cfg_font = optarg; break;
+ case 'F': cfg_fg = optarg; break;
+ case 'B': cfg_bg = optarg; break;
+ case 'C': cfg_border = optarg; break;
+ case 'a': cfg_align = atoi(optarg); break;
+ default:
+ die("usage: bxnotify [-d duration] [-f font] [-F fg] [-B bg] [-a align]\n");
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
signal(SIGUSR1, sigusr1);
-
- /* TODO: parse cli flags, override config.h */
-
readstdin();
init_display();
calc_layout();
screen = DefaultScreen(dpy);
- if (!(font = XftFontOpenName(dpy, screen, FONT)))
+ if (!(font = XftFontOpenName(dpy, screen, cfg_font)))
die("bxnotify: cannot load font\n");
}
for (int i = 0; i < tb.count; i++) {
char *line = tb.lines[i];
- while (measure_text(line) > WIN_WIDTH) {
+ while (measure_text(line) > cfg_width) {
/* Find break point */
char *p = line + strlen(line);
- while (p > line && measure_text(line) > WIN_WIDTH) {
+ while (p > line && measure_text(line) > cfg_width) {
while (p > line && *p != ' ') p--;
if (p == line) break; /* Cannot wrap, forced break */
*p = '\0';
free(tb.lines);
tb.lines = wrapped;
tb.count = wrapped_count;
- total_height = (tb.count * line_h) + ((tb.count + 1) * PADDING) + (2 * BORDER_WIDTH);
+ total_height = (tb.count * line_h) + ((tb.count + 1) * cfg_padding) + (2 * cfg_border_width);
}
static void
get_and_register_stack_y(int my_h)
{
int fd = open(reg_path, O_RDWR | O_CREAT, 0644);
- if (fd == -1) return WIN_Y; /* Fallback if file fails to open */
+ if (fd == -1) return cfg_win_y; /* Fallback if file fails to open */
/* Wait for exclusive lock - blocks until no other bxnotify is reading/writing */
flock(fd, LOCK_EX);
- int my_y = WIN_Y;
+ int my_y = cfg_win_y;
int lowest_y = 0;
/* Store valid PIDs so we can rewrite the file cleanly */
}
/* 2. Calculate our Y position */
- my_y = (lowest_y > 0) ? lowest_y + 16 : WIN_Y;
+ my_y = (lowest_y > 0) ? lowest_y + 16 : cfg_win_y;
/* 3. Clear file and rewrite with valid PIDs + our new one */
ftruncate(fd, 0); /* Erase file contents */
setup(int y, int win_h)
{
XSetWindowAttributes swa;
- int win_w = WIN_WIDTH + 2 * BORDER_WIDTH;
- int x = DisplayWidth(dpy, screen) - win_w - WIN_X;
+ int win_w = cfg_width + 2 * cfg_border_width;
+ int x = DisplayWidth(dpy, screen) - win_w - cfg_win_x;
swa.override_redirect = True;
swa.background_pixel = bg.pixel;
&swa);
/* Allocate colors and draw context... */
- if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), FG_COLOR, &fg))
+ if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), cfg_fg, &fg))
die("bxnotify: cannot allocate fg color\n");
- if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), BG_COLOR, &bg))
+ if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), cfg_bg, &bg))
die("bxnotify: cannot allocate bg color\n");
- if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), BORDER_COLOR, &border))
+ if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), cfg_border, &border))
die("bxnotify: cannot allocate border color\n");
xft_draw = XftDrawCreate(dpy, win, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen));
{
int line_h = font->ascent + font->descent;
/* Redraw background... */
- XftDrawRect(xft_draw, &border, 0, 0, WIN_WIDTH + 2 * BORDER_WIDTH, total_height);
- XftDrawRect(xft_draw, &bg, BORDER_WIDTH, BORDER_WIDTH, WIN_WIDTH, total_height - 2 * BORDER_WIDTH);
+ XftDrawRect(xft_draw, &border, 0, 0, cfg_width + 2 * cfg_border_width, total_height);
+ XftDrawRect(xft_draw, &bg, cfg_border_width, cfg_border_width, cfg_width, total_height - 2 * cfg_border_width);
for (int i = 0; i < tb.count; i++) {
/* Calculate Y for this specific line */
- int y = PADDING + BORDER_WIDTH + (i * line_h) + font->ascent;
+ int y = cfg_padding + cfg_border_width + (i * line_h) + font->ascent;
int x;
XGlyphInfo ext;
XftTextExtentsUtf8(dpy, font, (XftChar8 *)tb.lines[i], strlen(tb.lines[i]), &ext);
- switch (ALIGN) {
- case 0: x = BORDER_WIDTH + PADDING; break;
- case 1: x = BORDER_WIDTH + (WIN_WIDTH - ext.width) / 2; break;
- case 2: x = BORDER_WIDTH + (WIN_WIDTH - ext.width - PADDING); break;
- default: x = BORDER_WIDTH + PADDING; break;
+ switch (cfg_align) {
+ case 0: x = cfg_border_width + cfg_padding; break;
+ case 1: x = cfg_border_width + (cfg_width - ext.width) / 2; break;
+ case 2: x = cfg_border_width + (cfg_width - ext.width - cfg_padding); break;
+ default: x = cfg_border_width + cfg_padding; break;
}
XftDrawStringUtf8(xft_draw, &fg, font, x, y, (XftChar8 *)tb.lines[i], strlen(tb.lines[i]));
}
}
}
/* Check duration timeout */
- if (DURATION > 0 && (time(NULL) - start_time) >= DURATION)
+ if (cfg_duration > 0 && (time(NULL) - start_time) >= cfg_duration)
running = 0;
struct timespec ts = {0, 10000000}; /* 10 milliseconds */