nfy

Minimal and daemonless notification program for X
git clone git://git.christosmarg.xyz/nfy.git
Log | Files | Refs | README | LICENSE

commit 2ea859e1c31d6071fd9597628f53439b46b679a4
parent da5b823adc490bc9c91f8acdd3fa5ba624000332
Author: Christos Margiolis <christos@margiolis.net>
Date:   Wed, 27 Jan 2021 01:52:12 +0200

added Xrandr(3) support to handle multiple screens, improved padding window sizes

Diffstat:
MLICENSE | 2+-
MMakefile | 2+-
MREADME | 16+++++++++++-----
Mconfig.h | 9++++++---
Mconfig.mk | 14+++++++-------
Mnfy.1 | 21+++++++++++++++++++--
Mnfy.c | 55++++++++++++++++++++++++++++++++-----------------------
7 files changed, 77 insertions(+), 42 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020-present, Christos Margiolis. +Copyright (c) 2021-present, Christos Margiolis. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Makefile b/Makefile @@ -1,5 +1,5 @@ # See LICENSE file for copyright and license details. -# nfy - minimal notification program +# nfy - a minimal and daemonless notification program for X .POSIX: include config.mk diff --git a/README b/README @@ -1,16 +1,22 @@ -nfy - a minimal notification program for X -========================================== +nfy - a minimal and daemonless notification program for X +========================================================= nfy creates a temporary notification popup window and displays all the arguments that were passed to it. +Dependencies: +------------- +- Xlib +- libXft +- libXrandr + Usage: ----- -First of all, edit config.mk and config.h to match your particular +Edit config.mk and config.h to match your particular setup and preferences. $ make - # make install - nfy str... + # make install clean + $ nfy str... nfy will be installed in /usr/local/bin by default. Configuration is done by editing config.h and recompiling diff --git a/config.h b/config.h @@ -1,11 +1,14 @@ +/* See LICENSE file for copyright and license details. */ enum { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT }; /* Window positions */ static const char *bgcol = "#453588"; /* Background color */ static const char *bordercol = "#282828"; /* Border color */ static const char *fontcol = "#ebdbb2"; /* Font color */ static const char *fonts = "monospace:size=15"; /* Font */ -static const int borderw = 2; /* Border width */ +static const int padding = 15; /* Padding (pixels) */ +static const int borderw = 2; /* Border width (pixels) */ static const int duration = 3; /* Notification duration (seconds) */ static const int pos = TOP_RIGHT; /* Window position */ -static const int mx = 10; /* Margin X */ -static const int my = 25; /* Margin Y */ +static const int mx = 10; /* Margin X (pixels) */ +static const int my = 25; /* Margin Y (pixels) */ static const int maxlen = 250; /* Max window length (pixels) */ +static const int linespace = 10; /* Line spacing (pixels) */ diff --git a/config.mk b/config.mk @@ -8,23 +8,23 @@ MAN_DIR = ${PREFIX}/share/man/man1 BIN_DIR = ${PREFIX}/bin # includes and libs -#X11INC = /usr/local/include -#X11LIB = /usr/local/lib +X11INC = /usr/local/include +X11LIB = /usr/local/lib # Linux -X11INC = /usr/X11R6/include -X11LIB = /usr/X11R6/lib +#X11INC = /usr/X11R6/include +#X11LIB = /usr/X11R6/lib FREETYPELIBS = -lfontconfig -lXft -#FREETYPEINC = ${X11INC}/freetype2 +FREETYPEINC = ${X11INC}/freetype2 # Linux -FREETYPEINC = /usr/include/freetype2 +#FREETYPEINC = /usr/include/freetype2 # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L \ -D_XOPEN_SOURCE=700 -DVERSION=\"${VERSION}\" CFLAGS = -std=c99 -pedantic -Wall -Os -I${X11INC} -I${FREETYPEINC} ${CPPFLAGS} -LDFLAGS = -L${X11LIB} ${FREETYPELIBS} -lX11 +LDFLAGS = -L${X11LIB} ${FREETYPELIBS} -lX11 -lXrandr # utils CP = cp -f diff --git a/nfy.1 b/nfy.1 @@ -3,13 +3,30 @@ .Os .Sh NAME .Nm nfy -.Nd a minimal notification program for X +.Nd a minimal and daemonless notification program for X .Sh SYNOPSIS .Nm .Ar str... .Sh DESCRIPTION .Nm creates a temporary notification popup window and displays -all the arguments that were passed to it. +all the arguments that were passed to it. It uses the +.Xr Xft 3 +library to render fonts and colors, and +.Xr Xrandr 3 +to handle screen sizes. All configuration is done by +editing the 'config.h' file in the source code. +.Sh USAGE +If the string is not surrounded in quotes, +.Nm +will print one line for each word. +.Sh SIGNALS +.Nm +handles only SIGALRM, SIGTERM and SIGINT. It receives a +SIGALRM signal by default after the specified duration +of the notification. +.Sh SEE ALSO +.Xr signal 3 , +.Xr alarm 3 .Sh AUTHORS .An Christos Margiolis Aq Mt christos@christosmarg.xyz diff --git a/nfy.c b/nfy.c @@ -1,3 +1,4 @@ +/* See LICENSE file for copyright and license details. */ #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -7,6 +8,7 @@ #include <X11/Xlib.h> #include <X11/Xft/Xft.h> +#include <X11/extensions/Xrandr.h> #include "config.h" @@ -51,6 +53,8 @@ main(int argc, char *argv[]) XftColor color; XftFont *font; XftDraw *drw; + XRRScreenResources *screens; + XRRCrtcInfo *info = NULL; struct sigaction sig; int scr, scrw, scrh; int x, y, w, h, th; @@ -61,10 +65,15 @@ main(int argc, char *argv[]) if (!(dpy = XOpenDisplay(NULL))) die("cannot open display"); + scr = DefaultScreen(dpy); + screens = XRRGetScreenResources(dpy, RootWindow(dpy, scr)); + info = XRRGetCrtcInfo(dpy, screens, screens->crtcs[0]); + scrw = info->width; + scrh = info->height; + vis = DefaultVisual(dpy, scr); colormap = DefaultColormap(dpy, scr); - XftColorAllocName(dpy, vis, colormap, bgcol, &color); attrs.background_pixel = color.pixel; XftColorAllocName(dpy, vis, colormap, bordercol, &color); @@ -85,29 +94,27 @@ main(int argc, char *argv[]) w = len; } - w = w * (font->descent << 1) + borderw; - h = (th + (borderw << 2)) * argc; - scrw = DisplayWidth(dpy, scr); - scrh = DisplayHeight(dpy, scr); + w *= th + borderw; + h = th * (argc - 1) + (linespace * (argc - 2)) + (padding << 1); switch (pos) { - case TOP_LEFT: - x = mx; - y = my; - break; - case TOP_RIGHT: - default: - x = scrw - w - my; - y = my; - break; - case BOTTOM_LEFT: - x = mx; - y = scrh - h - my; - break; - case BOTTOM_RIGHT: - x = scrw - w - mx; - y = scrh - h - my; - break; + case TOP_LEFT: + x = mx; + y = my; + break; + case TOP_RIGHT: + default: + x = scrw - w - my; + y = my; + break; + case BOTTOM_LEFT: + x = mx; + y = scrh - h - my; + break; + case BOTTOM_RIGHT: + x = scrw - w - mx; + y = scrh - h - my; + break; } win = XCreateWindow(dpy, RootWindow(dpy, scr), x, y, w, h, borderw, @@ -137,7 +144,7 @@ main(int argc, char *argv[]) XClearWindow(dpy, win); for (i = 1; i < argc; i++) XftDrawStringUtf8(drw, &color, font, - borderw, (th + (borderw << 2)) * i, + w >> 3, linespace * (i - 1) + th * i + padding, (FcChar8 *)argv[i], strlen(argv[i])); } else if (ev.type == ButtonPress) break; @@ -146,6 +153,8 @@ main(int argc, char *argv[]) XftDrawDestroy(drw); XftColorFree(dpy, vis, colormap, &color); XftFontClose(dpy, font); + XRRFreeCrtcInfo(info); + XRRFreeScreenResources(screens); XCloseDisplay(dpy); return 0;