commit 815519f86155a48c10c9525e59dd6cdc638ba07f
parent 89fabc8cd7a2fa29161eebdb94a8579c5d53ea04
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date: Thu, 15 Oct 2026 02:41:46 +0300
Release sxalert 1.0
Diffstat:
11 files changed, 176 insertions(+), 197 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,21 +1,51 @@
# sxalert Makefile
-# GNU GPL v3.0
+# GNU GPL v3.0+
CC=c99
-MD=/usr/share/man/man1/
-
-sxalert: sxalert.c sxalert.h config.h
- $(CC) sxalert.c -I/usr/include/freetype2/ -lXft -lX11 \
- -lfreetype -lXrandr -g -o sxalert \
- -Wall -Wextra -Wpedantic \
- -Wconversion -Wsign-conversion \
- -Wshadow -Wstrict-prototypes \
- -Wmissing-prototypes -Wformat=2
+VERSION=1.0
+DIST=sxalert-$(VERSION)
+
+SRC = sxalert.c sxalert.h config.h
+DOC = sxalert.1 README.txt LICENSE
+FILES = $(SRC) $(DOC) Makefile
+
+PREFIX ?= /usr/local
+BINDIR ?= $(PREFIX)/bin
+MANDIR ?= $(PREFIX)/share/man/man1
+DESTDIR ?=
+
+
+CFLAGS = -Wall -Wextra -Wpedantic \
+ -Wconversion -Wsign-conversion \
+ -Wshadow -Wstrict-prototypes \
+ -Wmissing-prototypes -Wformat=2
+PKGS = xft xrandr x11
+CPPFLAGS += $(shell pkg-config --cflags $(PKGS))
+LDLIBS += $(shell pkg-config --libs $(PKGS))
+
+.PHONY: all clean install uninstall dist
+
+all: sxalert
+
+sxalert: $(SRC)
+ $(CC) $(CPPFLAGS) $(CFLAGS) sxalert.c -o $@ $(LDLIBS)
+
install:
- mv sxalert /bin/sxalert
- cp sxalert.1 $(MD)
+ mkdir -p $(DESTDIR)$(BINDIR)
+ mkdir -p $(DESTDIR)$(MANDIR)
+ install -m 755 sxalert $(DESTDIR)$(BINDIR)
+ install -m 644 sxalert.1 $(DESTDIR)$(MANDIR)
+
uninstall:
- rm /bin/sxalert
- rm $(MD)sxalert.1
+ rm -f $(DESTDIR)$(BINDIR)/sxalert
+ rm -f $(DESTDIR)$(MANDIR)/sxalert.1
+
clean:
- rm sxalert
+ rm -f sxalert
+
+dist:
+ mkdir $(DIST)
+ cp $(FILES) $(DIST)/
+ tar -czf $(DIST).tar.gz $(DIST)
+ rm -rf $(DIST)
+ sha256sum $(DIST).tar.gz > $(DIST).tar.gz.sha256
diff --git a/README.md b/README.md
@@ -3,77 +3,5 @@
Simple alert pop-up utility for X.
-## Features
-+ Alert & exit -- no daemon
-+ Freetype scalable fonts
-+ UTF-8 support
-+ Configurable & scriptable with shell
-+ Dynamic screen positioning & sizing
-
-## Dependencies
-A c99 compiler, `make`, `Xlib` and `Xft`.
-
-## Build & install
-In order to build, execute the following commands:
-```
-$ git clone git://mcdim.xyz/sxalert.git && cd sxalert
-$ make sxalert
-```
-And to install on /bin:
-```
-$ sudo make install
-```
-
-## Usage
-You can simply run the tool with each argument being a line of text
-```
-$ ./sxalert "First line" "Second line"
-```
-You can also set color, border width & duration:
-```
-$ ./sxalert -d 1000 -b 5 -t FFFFFF -g 000000 -r FFFFFF "First line" "Second line"
-```
-These will overwrite the defaults defined in `config.h`
-
-## Return values
-sxalert returns:
-+ 0 - Left click on the notification window
-+ 1 - Midde click on the notification window
-+ 2 - Right click on the notification window
-+ 3 - Time out
-
-Yes, this does mean that sxalert returns non-zero values even with normal
-execution, but for a good reason. This makes sxalert excellent for shell
-scripts. For example:
-
-You can set your mail to read with an acknowledgment
-
-```
-$ sxalert "New Mail" && mail-set-to-read
-```
-
-Or you can create a more elaborate interaction
-
-```
-sxalert "New Mail: X" "Left click to set to read" \
- "Middle click to delete" \
- "Right click to close"
-rc=$?
-
-case $rc in
-0)
- mail-set-to-read x
- ;;
-1)
- mail-delete x
- ;;
-2)
- echo "Unread mail"
- ;;
-```
-
-## Optional D-Bus daemon hack
-I've created a small Shell script called [sxalertd](https://github.com/MichaelDim02/sxalertd) that can run as a daemon to read the D-Bus and use sxalert to draw the notifications. The script & parsing method are a little hacky but work quite well.
-
-## Credit
-The logo is the Alectryon! The rooster image is by Leys, Thomson W. from the 1883 book "Brett's colonists' guide and cyclopaedia" for New Zealand settlers. The font is Byzantine, and the logo was created in GIMP.
+See [README.txt](README.txt) for documentation,
+installation instructions, and usage examples.
diff --git a/README.txt b/README.txt
@@ -25,7 +25,7 @@
Simple X Alert
==============
-Simple alert pop-up utility for X.
+Simple alert utility for X.
Features
--------
@@ -34,25 +34,28 @@ Features
+ UTF-8 support
+ Configurable & scriptable with shell
+ Dynamic screen positioning & sizing
++ Runtime color customization
++ Multi-monitor support
++ Concurrent notifications serialization
Dependencies
------------
-A c99 compiler, make, Xlib and Xft.
+A c99 compiler, make, libc, Xlib and Xft.
Build & install
---------------
-In order to build, execute the following commands:
+To build:
$ git clone git://mcdim.xyz/sxalert.git && cd sxalert
$ make sxalert
-And to install on /bin:
+To install:
$ sudo make install
Usage
-----
-You can simply run the tool with each argument being a line of text"
+You can simply run the tool with each argument representing a line of text:
$ sxalert "First line" "Second line"
@@ -60,11 +63,11 @@ You can also set color, border width & duration:
$ sxalert -d 1000 -b 5 -t FFFFFF -g 000000 -r FFFFFF "Hello world!"
-These will overwrite the defaults defined in `config.h`
+These will override the defaults defined in `config.h`
sxalert can read from standard input:
- $ sxalert < banner.txt
+ $ sxalert -s < banner.txt
$ { printf '%s\n' '===== BUILD FAILED ====='; \
tail -n 20 build.log; } \
@@ -74,7 +77,7 @@ Return values
-------------
sxalert returns:
0 - Left click on the notification window
-1 - Midde click on the notification window
+1 - Middle click on the notification window
2 - Right click on the notification window
3 - Time out
@@ -109,9 +112,16 @@ Optional D-Bus daemon hack
--------------------------
I've created a small Shell script called sxalertd that can run as a pseudo
daemon that intercepts D-Bus and uses sxalert to draw the notifications.
-It's not a proper daemon, and does not own the process, but can work fine.
-method are a little hacky but work quite well.
-(https://github.com/MichaelDim02/sxalertd)
+A little hacky but works well enough.
+(https://mcdim.xyz/git/sxalertd/log.html)
+
+Colophon
+--------
+Author: Michail Konstantinos Dimopoulos
+Copyright (C) 2023, 2026 Michail Konstantinos Dimopoulos
+License: GNU General Public License 3.0 or later (GPL-3.0-or-later)
+ See LICENSE for more information
+Patches: <hackers@mcdim.xyz>
Credit
------
diff --git a/config.h b/config.h
@@ -1,6 +1,6 @@
/* sxalert - simple notification program for X
*
- * Copyright (C) 2026 Michail Konstantinos Dimopoulos
+ * Copyright (C) 2023, 2026 Michail Konstantinos Dimopoulos
* License: GPL-3.0-or-later (see LICENSE)
*/
diff --git a/patches/wal_colors/README.txt b/patches/wal_colors/README.txt
@@ -1,10 +0,0 @@
-wal colors patch
-================
-Verion: 0.2
-tested sxalert version: 1.0
-tested pywal version: 3.3.0
-
-Read background & foreground colors from pywal's Xresources file.
-Make sure to edit the directory in the config file.
-
-Author: Michail Konstantinos Dimopoulos
diff --git a/patches/wal_colors/wal.diff b/patches/wal_colors/wal.diff
@@ -1,71 +0,0 @@
---- ../sxalert_simplification_attempt/config.h 2026-09-19 00:57:10.187027307 +0300
-+++ config.h 2026-09-19 01:23:35.202912393 +0300
-@@ -29,3 +29,5 @@
- .font = "DejaVu Sans Mono:size=13:antialias=true",
- .text_height = 10,
- };
-+
-+const char *xresources = "/home/michael/.cache/wal/colors.Xresources"; /* wal */
---- ../sxalert_simplification_attempt/sxalert.h 2026-09-01 15:36:58.132156170 +0300
-+++ sxalert.h 2026-09-19 01:23:11.668554392 +0300
-@@ -1,6 +1,8 @@
- #ifndef SXALERT_H
- #define SXALERT_H
-
-+#define XR_BUFFER 128
-+
- struct alert {
- int duration;
- char text_color[7];
---- ../sxalert_simplification_attempt/sxalert.c 2026-09-19 00:59:47.056450915 +0300
-+++ sxalert.c 2026-09-19 01:19:07.926615607 +0300
-@@ -63,6 +63,40 @@
- return max;
- }
-
-+void
-+get_xresources_colors(struct alert *a)
-+{
-+ FILE *f = fopen(xresources, "r");
-+ if (!f) {
-+ fprintf(stderr, "Could not open file: %s\n", xresources);
-+ exit(EXIT_FAILURE);
-+ }
-+
-+ char buffer[XR_BUFFER];
-+
-+ char colors[2][8];
-+ int clr_i=0;
-+
-+ char *arr[2];
-+
-+ for (int i=0; i<4; i++) {
-+ fgets(buffer, sizeof(buffer), f);
-+
-+ if (i <= 1) continue;
-+
-+ arr[0] = strtok(buffer, "#");
-+ arr[1] = strtok(NULL, "#\n");
-+
-+ strncpy(colors[clr_i++], arr[1], 7);
-+ }
-+
-+ strcpy(a->text_color, colors[0]);
-+ strcpy(a->border_color, colors[0]);
-+ strcpy(a->bg_color, colors[1]);
-+
-+ fclose(f);
-+}
-+
- static int
- get_width(Display *dpy, XftFont *font, struct alert *a)
- {
-@@ -258,6 +292,8 @@
-
- struct alert a = default_alert;
-
-+ get_xresources_colors(&a);
-+
- while ((c = getopt(argc, argv, "d:b:t:g:r:vh")) != -1 ) {
- switch (c) {
- case 'v':
diff --git a/patches/xresources/README.txt b/patches/xresources/README.txt
@@ -0,0 +1,8 @@
+xresources patch
+================
+sxalert version: 1.0
+
+Read background & foreground colors from Xresources file.
+Make sure to edit the directory in the config file.
+
+Author: Michail Konstantinos Dimopoulos
diff --git a/patches/xresources/sxalert-1.0-xresources.diff b/patches/xresources/sxalert-1.0-xresources.diff
@@ -0,0 +1,74 @@
+diff -ruN old/config.h new/config.h
+--- old/config.h 2026-10-15 02:27:36.895141358 +0300
++++ new/config.h 2026-10-15 02:22:29.877680526 +0300
+@@ -28,3 +28,5 @@
+ .font = "DejaVu Sans Mono:size=13:antialias=true",
+ .text_height = 10,
+ };
++
++const char *xresources = "/home/michael/.cache/wal/colors.Xresources"; /* wal */
+diff -ruN old/sxalert.c new/sxalert.c
+--- old/sxalert.c 2026-10-15 02:27:29.337141729 +0300
++++ new/sxalert.c 2026-10-15 02:24:51.835149470 +0300
+@@ -66,6 +66,40 @@
+ return max;
+ }
+
++static void
++get_xresources_colors(struct alert *a)
++{
++ FILE *f = fopen(xresources, "r");
++ if (!f) {
++ fprintf(stderr, "Could not open file: %s\n", xresources);
++ exit(EXIT_FAILURE);
++ }
++
++ char buffer[XR_BUFFER];
++
++ char colors[2][8];
++ int clr_i=0;
++
++ char *arr[2];
++
++ for (int i=0; i<4; i++) {
++ fgets(buffer, sizeof(buffer), f);
++
++ if (i <= 1) continue;
++
++ arr[0] = strtok(buffer, "#");
++ arr[1] = strtok(NULL, "#\n");
++
++ strncpy(colors[clr_i++], arr[1], 7);
++ }
++
++ strcpy(a->text_color, colors[0]);
++ strcpy(a->border_color, colors[0]);
++ strcpy(a->bg_color, colors[1]);
++
++ fclose(f);
++}
++
+ static int
+ get_width(Display *dpy, XftFont *font, struct alert *a)
+ {
+@@ -301,6 +335,8 @@
+ if (flock(fd, LOCK_EX) == -1)
+ return 1;
+
++ get_xresources_colors(&a);
++
+ int cmd_lines_len = argc - optind;
+ char **lines = argv + optind;
+
+diff -ruN old/sxalert.h new/sxalert.h
+--- old/sxalert.h 2026-10-15 02:27:32.357141581 +0300
++++ new/sxalert.h 2026-10-15 02:22:29.877893651 +0300
+@@ -7,6 +7,8 @@
+ #ifndef SXALERT_H
+ #define SXALERT_H
+
++#define XR_BUFFER 128
++
+ struct alert {
+ int duration;
+ char text_color[7];
diff --git a/sxalert.1 b/sxalert.1
@@ -1,6 +1,6 @@
.\" Manpage for sxalert
-.TH man 1 "13 Oct 2026" "1.0" "sxalert manual page"
+.TH man 1 "15 Oct 2026" "1.0" "sxalert manual page"
.SH NAME
sxalert \- Simple X Alert
@@ -30,6 +30,7 @@ command-line arguments, or both, appending the latter to the former.
Mouse interactions produce distinct exit statuses, allowing sxalert
to be used in shell scripts. It allows for runtime visual
customizability through command-line arguments.
+Concurrent notifications are serialized using an advisory file lock.
.SH OPTIONS
diff --git a/sxalert.c b/sxalert.c
@@ -1,6 +1,6 @@
/* sxalert - simple notification program for X
*
- * Copyright (C) 2026 Michail Konstantinos Dimopoulos
+ * Copyright (C) 2023, 2026 Michail Konstantinos Dimopoulos
* License: GPL-3.0-or-later (see LICENSE)
*/
@@ -14,6 +14,7 @@
#include <poll.h>
#include <X11/Xft/Xft.h>
#include <X11/extensions/Xrandr.h>
+#include <sys/file.h>
#include "config.h"
@@ -29,17 +30,19 @@ die(const char *msg, int code)
static inline void
help(char *bin)
{
- printf("sxalert %s - Alert utility for X\n\n"
- " -t text hex color (eg FFFFFF)\n"
- " -g background hex color\n"
- " -r border hex color\n"
- " -b border width in pixels\n"
- " -d duration in milliseconds\n"
- " -s read from stdin\n\n"
- " -v print version & exit\n"
- " -h print help panel & exit\n\n"
- "Usage: %s [arguments] \"text\" \"text\" \"text\"\n",
- VERSION, bin);
+ printf("sxalert %s - simple alert utility for X\n\n"
+ "Options:\n"
+ " -t color Set text color (hexadecimal, e.g., FFFFFF)\n"
+ " -g color Set background hex color\n"
+ " -r color Set border color\n"
+ " -b width Set border width in pixels\n"
+ " -d duration Set duration in milliseconds\n"
+ " -s Read from standard input\n"
+ " -v Print version and exit\n"
+ " -h Print help and exit\n\n"
+ "Usage: %s [-s] [-t color] [-g color] [-r color]\n"
+ " %*s [-b width] [-d duration] [line ...]\n",
+ VERSION, bin, (int)strlen(bin), "");
exit(0);
}
@@ -292,6 +295,12 @@ main(int argc, char **argv)
}
}
+ int fd = open("/tmp/sxalert.lock", O_CREAT | O_RDWR, 0600);
+ if (fd == -1)
+ return 1;
+ if (flock(fd, LOCK_EX) == -1)
+ return 1;
+
int cmd_lines_len = argc - optind;
char **lines = argv + optind;
@@ -299,7 +308,7 @@ main(int argc, char **argv)
a.lines = lines;
a.lines_len = cmd_lines_len;
draw(a);
- return 4;
+ return 3;
}
FILE *f = tmpfile();
diff --git a/sxalert.h b/sxalert.h
@@ -1,6 +1,6 @@
/* sxalert - simple notification program for X
*
- * Copyright (C) 2026 Michail Konstantinos Dimopoulos
+ * Copyright (C) 2023, 2026 Michail Konstantinos Dimopoulos
* License: GPL-3.0-or-later (see LICENSE)
*/