diff options
author | Benjamin Chausse <benjamin@chausse.xyz> | 2022-03-05 15:26:44 -0500 |
---|---|---|
committer | Benjamin Chausse <benjamin@chausse.xyz> | 2022-03-05 15:26:44 -0500 |
commit | 5214f4e3ea62575ad3f214493436f6aafc0eb7a0 (patch) | |
tree | 7702d41f64717a050156ee2c05c8bcac2845b863 /slock.c | |
parent | 454002c4d6646d04136635d988d867231e2fcdd6 (diff) |
Rewrite with dwmlogo pam xresources
Diffstat (limited to 'slock.c')
-rw-r--r-- | slock.c | 223 |
1 files changed, 145 insertions, 78 deletions
@@ -1,11 +1,13 @@ /* See LICENSE file for license details. */ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 500 +#define LENGTH(X) (sizeof X / sizeof X[0]) #if HAVE_SHADOW_H #include <shadow.h> #endif #include <ctype.h> #include <errno.h> +#include <math.h> #include <grp.h> #include <pwd.h> #include <stdarg.h> @@ -13,13 +15,16 @@ #include <stdio.h> #include <string.h> #include <unistd.h> -#include <time.h> #include <sys/types.h> #include <X11/extensions/Xrandr.h> -#include <X11/extensions/dpms.h> +#ifdef XINERAMA +#include <X11/extensions/Xinerama.h> +#endif #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xutil.h> +#include <X11/Xft/Xft.h> +#include <X11/Xresource.h> #include <security/pam_appl.h> #include <security/pam_misc.h> @@ -31,22 +36,40 @@ static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_resp struct pam_conv pamc = {pam_conv, NULL}; char passwd[256]; -static time_t locktime; - enum { + BACKGROUND, INIT, INPUT, FAILED, - BLOCKS, - PAM, + PAM, NUMCOLS }; +/* Xresources preferences */ +enum resource_type { + STRING = 0, + INTEGER = 1, + FLOAT = 2 +}; + +typedef struct { + char *name; + enum resource_type type; + void *dst; +} ResourcePref; + +#include "config.h" + struct lock { int screen; Window root, win; Pixmap pmap; unsigned long colors[NUMCOLS]; + unsigned int x, y; + unsigned int xoff, yoff, mw, mh; + Drawable drawable; + GC gc; + XRectangle rectangles[LENGTH(rectangles)]; }; struct xrandr { @@ -55,8 +78,6 @@ struct xrandr { int errbase; }; -#include "config.h" - static void die(const char *errstr, ...) { @@ -119,39 +140,6 @@ dontkillme(void) } #endif -static void -draw_key_feedback(Display *dpy, struct lock **locks, int screen) -{ - XGCValues gr_values; - - Window win = locks[screen]->win; - Window root_win; - - gr_values.foreground = locks[screen]->colors[BLOCKS]; - GC gc = XCreateGC(dpy, win, GCForeground, &gr_values); - - int width = blocks_width, - height = blocks_height, - x = blocks_x, - y = blocks_y; - - if (height == 0 || width == 0) { - int _x, _y; - unsigned int screen_width, screen_height, _b, _d; - XGetGeometry(dpy, win, &root_win, &_x, &_y, &screen_width, &screen_height, &_b, &_d); - width = width ? width : screen_width; - height = height ? height : screen_height; - } - - unsigned int block_width = width / blocks_count; - unsigned int position = rand() % blocks_count; - - XClearWindow(dpy, win); - XFillRectangle(dpy, win, gc, x + position*block_width, y, block_width, height); - - XFreeGC(dpy, gc); -} - static const char * gethash(void) { @@ -196,6 +184,32 @@ gethash(void) } static void +resizerectangles(struct lock *lock) +{ + int i; + + for (i = 0; i < LENGTH(rectangles); i++){ + lock->rectangles[i].x = (rectangles[i].x * logosize) + + lock->xoff + ((lock->mw) / 2) - (logow / 2 * logosize); + lock->rectangles[i].y = (rectangles[i].y * logosize) + + lock->yoff + ((lock->mh) / 2) - (logoh / 2 * logosize); + lock->rectangles[i].width = rectangles[i].width * logosize; + lock->rectangles[i].height = rectangles[i].height * logosize; + } +} + +static void +drawlogo(Display *dpy, struct lock *lock, int color) +{ + XSetForeground(dpy, lock->gc, lock->colors[BACKGROUND]); + XFillRectangle(dpy, lock->drawable, lock->gc, 0, 0, lock->x, lock->y); + XSetForeground(dpy, lock->gc, lock->colors[color]); + XFillRectangles(dpy, lock->drawable, lock->gc, lock->rectangles, LENGTH(rectangles)); + XCopyArea(dpy, lock->drawable, lock->win, lock->gc, 0, 0, lock->x, lock->y, 0, 0); + XSync(dpy, False); +} + +static void readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, const char *hash) { @@ -213,7 +227,6 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, oldc = INIT; while (running && !XNextEvent(dpy, &ev)) { - running = !((time(NULL) - locktime < timetocancel) && (ev.type == MotionNotify)); if (ev.type == KeyPress) { explicit_bzero(&buf, sizeof(buf)); num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); @@ -234,10 +247,8 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, passwd[len] = '\0'; errno = 0; retval = pam_start(pam_service, hash, &pamc, &pamh); - color = PAM; for (screen = 0; screen < nscreens; screen++) { - XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]); - XClearWindow(dpy, locks[screen]->win); + drawlogo(dpy, locks[screen], PAM); XRaiseWindow(dpy, locks[screen]->win); } XSync(dpy, False); @@ -274,18 +285,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, memcpy(passwd + len, buf, num); len += num; } - if (blocks_enabled) - for (screen = 0; screen < nscreens; screen++) - draw_key_feedback(dpy, locks, screen); break; } color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); if (running && oldc != color) { for (screen = 0; screen < nscreens; screen++) { - XSetWindowBackground(dpy, - locks[screen]->win, - locks[screen]->colors[color]); - XClearWindow(dpy, locks[screen]->win); + drawlogo(dpy, locks[screen], color); } oldc = color; } @@ -320,6 +325,10 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) XColor color, dummy; XSetWindowAttributes wa; Cursor invisible; +#ifdef XINERAMA + XineramaScreenInfo *info; + int n; +#endif if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) return NULL; @@ -333,12 +342,31 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) lock->colors[i] = color.pixel; } + lock->x = DisplayWidth(dpy, lock->screen); + lock->y = DisplayHeight(dpy, lock->screen); +#ifdef XINERAMA + if ((info = XineramaQueryScreens(dpy, &n))) { + lock->xoff = info[0].x_org; + lock->yoff = info[0].y_org; + lock->mw = info[0].width; + lock->mh = info[0].height; + } else +#endif + { + lock->xoff = lock->yoff = 0; + lock->mw = lock->x; + lock->mh = lock->y; + } + lock->drawable = XCreatePixmap(dpy, lock->root, + lock->x, lock->y, DefaultDepth(dpy, screen)); + lock->gc = XCreateGC(dpy, lock->root, 0, NULL); + XSetLineAttributes(dpy, lock->gc, 1, LineSolid, CapButt, JoinMiter); + /* init */ wa.override_redirect = 1; - wa.background_pixel = lock->colors[INIT]; + wa.background_pixel = lock->colors[BACKGROUND]; lock->win = XCreateWindow(dpy, lock->root, 0, 0, - DisplayWidth(dpy, lock->screen), - DisplayHeight(dpy, lock->screen), + lock->x, lock->y, 0, DefaultDepth(dpy, lock->screen), CopyFromParent, DefaultVisual(dpy, lock->screen), @@ -348,6 +376,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) &color, &color, 0, 0); XDefineCursor(dpy, lock->win, invisible); + resizerectangles(lock); + /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) { if (ptgrab != GrabSuccess) { @@ -368,7 +398,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); XSelectInput(dpy, lock->root, SubstructureNotifyMask); - locktime = time(NULL); + drawlogo(dpy, lock, INIT); return lock; } @@ -390,6 +420,57 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) return NULL; } +int +resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) +{ + char **sdst = dst; + int *idst = dst; + float *fdst = dst; + + char fullname[256]; + char fullclass[256]; + char *type; + XrmValue ret; + + snprintf(fullname, sizeof(fullname), "%s.%s", "slock", name); + snprintf(fullclass, sizeof(fullclass), "%s.%s", "Slock", name); + fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0'; + + XrmGetResource(db, fullname, fullclass, &type, &ret); + if (ret.addr == NULL || strncmp("String", type, 64)) + return 1; + + switch (rtype) { + case STRING: + *sdst = ret.addr; + break; + case INTEGER: + *idst = strtoul(ret.addr, NULL, 10); + break; + case FLOAT: + *fdst = strtof(ret.addr, NULL); + break; + } + return 0; +} + +void +config_init(Display *dpy) +{ + char *resm; + XrmDatabase db; + ResourcePref *p; + + XrmInitialize(); + resm = XResourceManagerString(dpy); + if (!resm) + return; + + db = XrmGetStringDatabase(resm); + for (p = resources; p < resources + LEN(resources); p++) + resource_load(db, p->name, p->type, p->dst); +} + static void usage(void) { @@ -407,7 +488,6 @@ main(int argc, char **argv) { const char *hash; Display *dpy; int s, nlocks, nscreens; - CARD16 standby, suspend, off; ARGBEGIN { case 'v': @@ -448,9 +528,7 @@ main(int argc, char **argv) { if (setuid(duid) < 0) die("slock: setuid: %s\n", strerror(errno)); - time_t t; - srand((unsigned) time(&t)); - + config_init(dpy); /* check for Xrandr support */ rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); @@ -471,20 +549,6 @@ main(int argc, char **argv) { if (nlocks != nscreens) return 1; - /* DPMS magic to disable the monitor */ - if (!DPMSCapable(dpy)) - die("slock: DPMSCapable failed\n"); - if (!DPMSEnable(dpy)) - die("slock: DPMSEnable failed\n"); - if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) - die("slock: DPMSGetTimeouts failed\n"); - if (!standby || !suspend || !off) - die("slock: at least one DPMS variable is zero\n"); - if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime)) - die("slock: DPMSSetTimeouts failed\n"); - - XSync(dpy, 0); - /* run post-lock command */ if (argc > 0) { switch (fork()) { @@ -502,9 +566,12 @@ main(int argc, char **argv) { /* everything is now blank. Wait for the correct password */ readpw(dpy, &rr, locks, nscreens, hash); - /* reset DPMS values to inital ones */ - DPMSSetTimeouts(dpy, standby, suspend, off); - XSync(dpy, 0); + for (nlocks = 0, s = 0; s < nscreens; s++) { + XFreePixmap(dpy, locks[s]->drawable); + XFreeGC(dpy, locks[s]->gc); + } + XSync(dpy, 0); + XCloseDisplay(dpy); return 0; } |