diff --git a/Makefile b/Makefile index d340002..3d36030 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,14 @@ +BINDIR = $(HOME)/bin CFLAGS = -Wall LDLIBS = -lX11 -all: xss xsswin xcursorpos xkeygrab magic +BINARIES = xss xsswin xcursorpos xkeygrab xbell magic + +all: $(BINARIES) + +install: $(BINARIES) + cp $(BINARIES) $(BINDIR) xss: LDLIBS += -lXss -.PHONY: all +.PHONY: all install diff --git a/README b/README index 9644bd5..ed0d15b 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ == xss == -`xss` uses the nearly 20-year-old MIT-SCREEN-SAVER extension to launch a +`xss` uses the decades-old MIT-SCREEN-SAVER extension to launch a program when the X server turns on the built-in screen saver. `xsswin` makes a full-screen black window and runs some other program, @@ -12,6 +12,8 @@ stdout. `xcursorpos` prints out the x and y coordinates of the cursor. +`xbell` sounds the X server's bell. + `magic` is a reimplementation of the "magic" screen saver from After Dark. It probably doesn't work with an 8-bit color pallette. @@ -28,18 +30,42 @@ Run like `xautolock`: xss xlock -mode qix & +Launch a program called "screenlock" when you're idle: -Shell script to run `magic` while waiting for a pass word from the keybord. Won't -do anything if the cursor is in the upper-left corner: + xss screenlock + +An simple "screenlock" script: #! /bin/sh - xcursorpos | (read x y; [ $x -lt 20 -a $y -lt 20 ]) && exit 0 - xsswin magic XSS_WINDOW & - pid=$! + xsswin magic XSS_WINDOW & pid=$! xkeygrab | (while read l; do [ "$l" != "secret" ] && break; done) kill $pid +A more complex "screenlock" script which locks the screen awaiting a +pass phrase with the right md5 checksum. After 4 seconds of being +locked, it pauses mpd (iff it was playing). When the screen is +unlocked, mpd is resumed (iff it was playing beforehand). The script +won't lock if the cursor's at the top of the screen. + + #! /bin/sh + + xcursorpos | (read x y; [ $y -lt 20 ]) && exit 0 + mpc | fgrep -q '[playing]' && playing=1 + xsswin magic XSS_WINDOW 2>/dev/null & xsswin=$! + (sleep 4; [ $playing ] && kill -0 $xsswin 2>/dev/null && mpc --no-status pause) & + xkeygrab | ( + while read l; do + md5s=$(echo -n $l | md5sum | cut -d\ -f1) + if [ $md5s = 'a37c87558d98e9fe0484e09070268be1' ]; then + break + fi + xbell + done + ) + kill $xsswin + [ $playing ] && mpc --no-status play + Download -------- @@ -50,6 +76,13 @@ commit](http://woozle.org/~neale/repos/?p=xss;a=snapshot) or use git: git clone http://woozle.org/~neale/repos/xss/ +Bugs +---- + +* Sometimes xss quits launching anything. I suspect it's not getting + SIGCHLD for some reason. + + History ------- diff --git a/xkeygrab.c b/xkeygrab.c index 9434711..8810e5d 100644 --- a/xkeygrab.c +++ b/xkeygrab.c @@ -40,34 +40,34 @@ main(int argc, char *argv[]) char obuf[4096]; int obuflen = 0; struct pollfd fds[2]; - int i; if (! (display = XOpenDisplay(NULL))) raise("cannot open display"); root = DefaultRootWindow(display); - for (i = 0; i < 3; ) { - if ((! (i & 1)) && (GrabSuccess == XGrabKeyboard(display, root, - True, - GrabModeAsync, GrabModeAsync, - CurrentTime))) { - i |= 1; - } - if ((! (i & 2)) && (GrabSuccess == XGrabPointer(display, root, - False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, - None, None, CurrentTime))) { - i |= 2; - } - (void)poll(NULL, 0, 100); - } fds[0].fd = STDOUT_FILENO; fds[0].events = 0; fds[1].fd = ConnectionNumber(display); fds[1].events = POLLIN; while (1) { + int tograb = 3; int ret; - ret = poll(fds, 2, -1); + if (tograb) { + if ((tograb & 1) && (GrabSuccess == XGrabKeyboard(display, root, + True, + GrabModeAsync, GrabModeAsync, + CurrentTime))) { + tograb |= 1; + } + if ((tograb & 2) && (GrabSuccess == XGrabPointer(display, root, + False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + None, None, CurrentTime))) { + tograb |= 2; + } + } + + ret = poll(fds, 2, (tograb?100:-1)); if (fds[0].revents & POLLERR) { break; diff --git a/xss.c b/xss.c index 5fc1673..303da67 100644 --- a/xss.c +++ b/xss.c @@ -63,9 +63,7 @@ main(int argc, char *argv[]) root = RootWindow(display, screen); XScreenSaverSelectInput(display, root, ScreenSaverNotifyMask); - /* Tell X to make the screen saver window 1 pixel by 1 pixel and off - the visible area, since we'll be creating our own. I suspect jwz - is just blowing smoke. */ + /* Tell X to show its provided window off the screen. We make our own. */ { XSetWindowAttributes attr;