commit 92220f3e67c2a19d8f8fd39b9d890a7d91f3c4e1
Author: Michael Constantine Dimopoulos <mk@mcdim.xyz>
Date: Fri, 3 Nov 2023 23:20:52 +0000
Initial working code
Diffstat:
| A | Makefile | | | 2 | ++ |
| A | config.h | | | 13 | +++++++++++++ |
| A | sxalert.c | | | 145 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,2 @@
+sxalert:
+ gcc sxalert.c -I/usr/include/freetype2/ -lXft -lX11 -lfreetype
diff --git a/config.h b/config.h
@@ -0,0 +1,13 @@
+/* simpleXalert Configuration */
+
+#define BUFFER 2054
+
+/* default appearance */
+
+static char text_color[7] = "A0A0A0";
+static char bg_color[7] = "300000";
+static char border_color[7] = "530000";
+
+static int border_width = 5;
+
+const char *fontname = "DejaVu Sans Mono:size=12:antialias=true";
diff --git a/sxalert.c b/sxalert.c
@@ -0,0 +1,145 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xft/Xft.h>
+
+#define VERSION "v0.1"
+
+#include "config.h"
+
+static void
+die(const char *msg, int code)
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(code);
+}
+
+static void
+usage(const char *bin)
+{
+ printf("Usage: %s [arguments] \"title\" \"text\" \"text\"\n", bin);
+ exit(0);
+}
+
+static void
+help(void)
+{
+ printf("sXalert %s\n", VERSION);
+ printf("Alert utility for X\n\n");
+ printf(" -c color in hex:hex:hex format\n");
+ printf(" -s time in seconds\n");
+ printf(" -b border width in pixels\n");
+ printf(" -h print help panel & exit\n\n");
+}
+
+static int
+hex2int(char *str)
+{
+ int num;
+ sscanf(str, "%x", &num);
+ return num;
+}
+
+static void
+draw(int border, char **lines, int linecount, int linestart)
+{
+ //const char *fontname = "DejaVu Sans Mono:size=12:antialias=true";
+
+ Display *dpy = XOpenDisplay(NULL);
+ if (!dpy)
+ die("cannot open X11 display\n", EXIT_FAILURE);
+ int scr = DefaultScreen(dpy);
+ Visual *visual = DefaultVisual(dpy, scr);
+ Colormap cmap = DefaultColormap(dpy, scr);
+
+ XftColor color;
+ XGlyphInfo extents;
+ XftFont *font = XftFontOpenName(dpy, scr, fontname);
+ if (!font)
+ die("cannot load font\n", EXIT_FAILURE);
+ if (!XftColorAllocName(dpy, visual, cmap, "#ffffff", &color))
+ //if (!XftColorAllocName(dpy, visual, cmap, "#0dff00", &color))
+ die("cannot allocate xft color\n", EXIT_FAILURE);
+ XftTextExtentsUtf8(dpy, font, (XftChar8*)lines[0], strlen(lines[0]), &extents);
+ int text_height = extents.height;
+ int text_width = extents.width; /* for some reason this is always 61 */
+ printf("text_width: %d\n", text_width);
+
+ int height = (linecount - linestart) * (text_height * 2) + text_height;
+ printf("height:%d\n", (linecount-linestart));
+
+ Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 1500, 50, 400, height, border, hex2int(border_color), hex2int(bg_color));
+ /* make window fixed */
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = True;
+ XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attributes);
+
+ XSelectInput(dpy, win, ExposureMask | KeyPressMask);
+ XMapWindow(dpy, win);
+
+ XftDraw *draw = XftDrawCreate(dpy, win, visual, cmap);
+
+ while(1) {
+ XEvent ev;
+
+ XNextEvent(dpy, &ev);
+ if (ev.type == Expose) {
+ int spacing = text_height * 2;
+ for (int i=linestart; i<linecount; i++) {
+ XftDrawStringUtf8(draw, &color, font, 10, spacing, (XftChar8 *)lines[i], strlen(lines[i]));
+ spacing += text_height * 2;
+ }
+ } else if (ev.type == KeyPress) {
+ break;
+ }
+ }
+
+ /* cleanup */
+ XftColorFree(dpy, visual, cmap, &color);
+ XftDrawDestroy(draw);
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+}
+
+int
+main(int argc, char **argv)
+{
+ int s = 3;
+ int c;
+ char text[BUFFER];
+ extern char *optarg;
+
+ printf("text_color: %s\n", text_color);
+
+ while ((c = getopt(argc, argv, "s:b:vh")) != -1 ) {
+ switch (c) {
+ case 'v':
+ die(VERSION, EXIT_SUCCESS);
+ case 'h':
+ help();
+ usage(argv[0]);
+ case 's':
+ s=atoi(optarg);
+ break;
+ case 'b':
+ border_width=atoi(optarg); /* overwrite default in config.h */
+ break;
+ }
+ }
+
+ /* can be removed */
+ /*printf("b=%d\n", border_width);
+ if (optind < argc) {
+ printf("argc=%d\n", argc);
+ printf("optind=%d\n", optind);
+ printf("optind=%s\n", argv[optind]);
+ }*/
+
+ draw(border_width, argv, argc, optind);
+
+ return 0;
+}