diff options
| author | Anselm R Garbe <garbeam@gmail.com> | 2009-11-26 12:53:26 +0000 | 
|---|---|---|
| committer | Anselm R Garbe <garbeam@gmail.com> | 2009-11-26 12:53:26 +0000 | 
| commit | 732d2b3bf5da3a1883b3246062aa556a59b8517c (patch) | |
| tree | 85dcc7c6506f933d327bc801972e3791e0140948 | |
| parent | 0cb05bdb75ac13f010d51e267007ca1c869763ec (diff) | |
| download | slock-732d2b3bf5da3a1883b3246062aa556a59b8517c.tar.gz slock-732d2b3bf5da3a1883b3246062aa556a59b8517c.tar.xz  | |
applied Fernando Silveira's multiscreen patch for old style multihead setups
| -rw-r--r-- | slock.c | 220 | 
1 files changed, 151 insertions, 69 deletions
@@ -5,6 +5,7 @@  #endif  #include <ctype.h> +#include <errno.h>  #include <pwd.h>  #include <stdarg.h>  #include <stdlib.h> @@ -15,31 +16,42 @@  #include <X11/keysym.h>  #include <X11/Xlib.h>  #include <X11/Xutil.h> -#include <X11/extensions/dpms.h>  #if HAVE_BSD_AUTH  #include <login_cap.h>  #include <bsd_auth.h>  #endif +struct st_lock { +	int screen; +	Window root, w; +	Pixmap pmap; +}; + +extern const char *__progname; +  static void  die(const char *errstr, ...) {  	va_list ap; +	fprintf(stderr, "%s: ", __progname);  	va_start(ap, errstr);  	vfprintf(stderr, errstr, ap);  	va_end(ap); +	fprintf(stderr, "\n"); +	fflush(stderr); +  	exit(EXIT_FAILURE);  }  #ifndef HAVE_BSD_AUTH  static const char * -get_password() { /* only run as root */ +get_password(void) { /* only run as root */  	const char *rval;  	struct passwd *pw;  	if(geteuid() != 0) -		die("slock: cannot retrieve password entry (make sure to suid slock)\n"); +		die("cannot retrieve password entry (make sure to suid slock)");  	pw = getpwuid(getuid());  	endpwent();  	rval =  pw->pw_passwd; @@ -55,81 +67,34 @@ get_password() { /* only run as root */  	/* drop privileges */  	if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) -		die("slock: cannot drop privileges\n"); +		die("cannot drop privileges");  	return rval;  }  #endif -int -main(int argc, char **argv) { -	char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; +static void +#ifdef HAVE_BSD_AUTH +read_password(Display *dpy) +#else +read_password(Display *dpy, const char *pws) +#endif +{  	char buf[32], passwd[256]; -	int num, screen; +	int num; -#ifndef HAVE_BSD_AUTH -	const char *pws; -#endif  	unsigned int len;  	Bool running = True; -	Cursor invisible; -	Display *dpy;  	KeySym ksym; -	Pixmap pmap; -	Window root, w; -	XColor black, dummy;  	XEvent ev; -	XSetWindowAttributes wa; -	CARD16 standby, suspend, off; - -	if((argc == 2) && !strcmp("-v", argv[1])) -		die("slock-"VERSION", © 2006-2008 Anselm R Garbe\n"); -	else if(argc != 1) -		die("usage: slock [-v]\n"); - -#ifndef HAVE_BSD_AUTH -	pws = get_password(); -#endif - -	if(!(dpy = XOpenDisplay(0))) -		die("slock: cannot open display\n"); -	screen = DefaultScreen(dpy); -	root = RootWindow(dpy, screen); -	/* init */ -	wa.override_redirect = 1; -	wa.background_pixel = BlackPixel(dpy, screen); -	w = XCreateWindow(dpy, root, 0, 0, DisplayWidth(dpy, screen), DisplayHeight(dpy, screen), -			0, DefaultDepth(dpy, screen), CopyFromParent, -			DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa); -	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy); -	pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8); -	invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0); -	XDefineCursor(dpy, w, invisible); -	XMapRaised(dpy, w); -	for(len = 1000; len; len--) { -		if(XGrabPointer(dpy, root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, -			GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) -			break; -		usleep(1000); -	} -	if((running = running && (len > 0))) { -		for(len = 1000; len; len--) { -			if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) -				== GrabSuccess) -				break; -			usleep(1000); -		} -		running = (len > 0); -	}  	len = 0; -	XSync(dpy, False); +	running = True; -	if(DPMSCapable(dpy)) { /* save and customize DPMS settings */ -		DPMSGetTimeouts(dpy, &standby, &suspend, &off); -		DPMSSetTimeouts(dpy, 10, 30, 90); -	} +	/* As "slock" stands for "Simple X display locker", the DPMS settings +	 * had been removed and you can set it with "xset" or some other +	 * utility. This way the user can easily set a customized DPMS +	 * timeout. */ -	/* main event loop */  	while(running && !XNextEvent(dpy, &ev)) {  		if(ev.type == KeyPress) {  			buf[0] = 0; @@ -172,12 +137,129 @@ main(int argc, char **argv) {  			}  		}  	} -	if(DPMSCapable(dpy)) { /* restore DPMS settings */ -		DPMSSetTimeouts(dpy, standby, suspend, off); -	} +} + +static void +unlockscreen(Display *dpy, struct st_lock *lock) { +	if (dpy == NULL || lock == NULL) +		return; +  	XUngrabPointer(dpy, CurrentTime); -	XFreePixmap(dpy, pmap); -	XDestroyWindow(dpy, w); +	XFreePixmap(dpy, lock->pmap); +	XDestroyWindow(dpy, lock->w); + +	free(lock); +} + +static struct st_lock * +lockscreen(Display *dpy, int screen) { +	char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; +	unsigned int len; +	struct st_lock *lock; +	Bool running = True; +	XColor black, dummy; +	XSetWindowAttributes wa; +	Cursor invisible; + +	if (dpy == NULL || screen < 0) +		return NULL; + +	lock = malloc(sizeof(struct st_lock)); +	if (lock == NULL) +		return NULL; + +	lock->screen = screen; + +	lock->root = RootWindow(dpy, lock->screen); + +	/* init */ +	wa.override_redirect = 1; +	wa.background_pixel = BlackPixel(dpy, lock->screen); +	lock->w = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), +			0, DefaultDepth(dpy, lock->screen), CopyFromParent, +			DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); +	XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), "black", &black, &dummy); +	lock->pmap = XCreateBitmapFromData(dpy, lock->w, curs, 8, 8); +	invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &black, &black, 0, 0); +	XDefineCursor(dpy, lock->w, invisible); +	XMapRaised(dpy, lock->w); +	for(len = 1000; len; len--) { +		if(XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, +			GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) +			break; +		usleep(1000); +	} +	if((running = running && (len > 0))) { +		for(len = 1000; len; len--) { +			if(XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) +				== GrabSuccess) +				break; +			usleep(1000); +		} +		running = (len > 0); +	} + +	if (!running) { +		unlockscreen(dpy, lock); +		lock = NULL; +	} + +	return lock; +} + +static void +usage(void) { +	fprintf(stderr, "usage: %s -v", __progname); +	exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) { +#ifndef HAVE_BSD_AUTH +	const char *pws; +#endif +	Display *dpy; +	int nscreens, screen; + +	struct st_lock **locks; + +	if((argc == 2) && !strcmp("-v", argv[1])) +		die("slock-%s, © 2006-2008 Anselm R Garbe", VERSION); +	else if(argc != 1) +		usage(); + +#ifndef HAVE_BSD_AUTH +	pws = get_password(); +#endif + +	if(!(dpy = XOpenDisplay(0))) +		die("cannot open display"); + +	/* Get the number of screens in display "dpy" and blank them all. */ +	nscreens = ScreenCount(dpy); +	locks = malloc(sizeof(struct st_lock *) * nscreens); +	if (locks == NULL) +		die("malloc: %s", strerror(errno)); + +	for (screen = 0; screen < nscreens; screen++) +		locks[screen] = lockscreen(dpy, screen); + +	XSync(dpy, False); + +	/* Everything is now blank. Now wait for the correct password. */ +#ifdef HAVE_BSD_AUTH +	read_password(dpy); +#else +	read_password(dpy, pws); +#endif + +	/* Password ok, unlock everything and quit. */ +	for (screen = 0; screen < nscreens; screen++) +		unlockscreen(dpy, locks[screen]); + +	free(locks); +  	XCloseDisplay(dpy); +  	return 0;  }  | 
