summaryrefslogtreecommitdiff
path: root/slock.c
diff options
context:
space:
mode:
Diffstat (limited to 'slock.c')
-rw-r--r--slock.c223
1 files changed, 145 insertions, 78 deletions
diff --git a/slock.c b/slock.c
index 6d73074..fd275b0 100644
--- a/slock.c
+++ b/slock.c
@@ -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;
}