commit - 7bb4fd609f572b48d95a3328750a34a7add0916e
commit + c2ca3402b92d106af09010320b729704fb5c379b
blob - ee6b7aad582c69a1d19eb4900b05e370dafcdfbf
blob + 7e4e035b5bc8a122de59be66afa1586aa74232c2
--- bxnotify.c
+++ bxnotify.c
#include <unistd.h>
#include <sys/file.h>
#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include <X11/Xft/Xft.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
#include "config.h"
static void cleanup(void);
static void sigusr1(int sig);
static int measure_text(const char *text);
+static int (*xerrorxlib)(Display *, XErrorEvent *);
static void init_display(void);
static void calc_layout(void);
static void init_reg_path(void);
static int get_and_register_stack_y(int my_h);
static void unregister_position(void);
+static int get_oldest_pid(void);
static void setup(int y, int win_h);
static void readstdin(void);
static void draw(void);
die("bxnotify: no input received\n");
}
+static int
+xerror(Display *dpy, XErrorEvent *ee)
+{
+ /* Silently ignore BadAccess from XGrabKey - another instance has the grab */
+ if (ee->error_code == BadAccess && ee->request_code == 33)
+ return 0;
+ return xerrorxlib(dpy, ee);
+}
+
static void
init_display(void)
{
if (!(dpy = XOpenDisplay(NULL)))
die("bxnotify: cannot open display\n");
+ xerrorxlib = XSetErrorHandler(xerror);
+
screen = DefaultScreen(dpy);
if (!(font = XftFontOpenName(dpy, screen, FONT)))
}
}
+static int
+get_oldest_pid(void)
+{
+ int fd = open(reg_path, O_RDONLY);
+ if (fd == -1) return getpid();
+
+ flock(fd, LOCK_SH);
+ FILE *f = fdopen(fd, "r");
+
+ int min_y = 99999;
+ int oldest_pid = getpid();
+
+ if (f) {
+ char line[64];
+ int pid, y, h;
+
+ while (fgets(line, sizeof(line), f)) {
+ if (sscanf(line, "%d %d %d", &pid, &y, &h) == 3) {
+ if (kill(pid, 0) == 0 && y < min_y) {
+ min_y = y;
+ oldest_pid = pid;
+ }
+ }
+ }
+ fclose(f);
+ } else {
+ close(fd);
+ }
+
+ return oldest_pid;
+}
+
static void
setup(int y, int win_h)
{
swa.override_redirect = True;
swa.background_pixel = bg.pixel;
swa.border_pixel = 0;
- swa.event_mask = ExposureMask;
+ swa.event_mask = ExposureMask | KeyPressMask;
win = XCreateWindow(dpy, RootWindow(dpy, screen), x, y,
win_w, win_h, 0,
XSetClassHint(dpy, win, &ch);
XMapWindow(dpy, win);
+
+ /* Register the passive grab for key press Mod4+q */
+ XGrabKey(dpy, XKeysymToKeycode(dpy, XK_q), Mod4Mask, RootWindow(dpy, screen), True, GrabModeAsync, GrabModeAsync);
}
static void
{
XEvent ev;
+ KeySym q = XStringToKeysym("q");
+
while (running) {
if (XPending(dpy)) {
XNextEvent(dpy, &ev);
- if (ev.type == Expose)
+ if (ev.type == Expose) {
draw();
+ } else if (ev.type == KeyPress) {
+ if (XLookupKeysym(&ev.xkey, 0) == q && (ev.xkey.state & Mod4Mask)) {
+ int oldest = get_oldest_pid();
+ if (oldest==getpid())
+ running = 0;
+ else if (oldest > 0)
+ kill(oldest, SIGUSR1);
+ }
+ }
}
-
/* Check duration timeout */
if (DURATION > 0 && (time(NULL) - start_time) >= DURATION)
running = 0;
struct timespec ts = {0, 10000000}; /* 10 milliseconds */
nanosleep(&ts, NULL);
-
}
}