aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slock.c78
1 files changed, 23 insertions, 55 deletions
diff --git a/slock.c b/slock.c
index 7127ebe..f423f8c 100644
--- a/slock.c
+++ b/slock.c
@@ -33,18 +33,18 @@ enum {
33 33
34#include "config.h" 34#include "config.h"
35 35
36typedef struct { 36struct lock {
37 int screen; 37 int screen;
38 Window root, win; 38 Window root, win;
39 Pixmap pmap; 39 Pixmap pmap;
40 unsigned long colors[NUMCOLS]; 40 unsigned long colors[NUMCOLS];
41} Lock; 41};
42 42
43static Lock **locks; 43struct xrandr {
44static int nscreens; 44 int active;
45static Bool rr; 45 int evbase;
46static int rrevbase; 46 int errbase;
47static int rrerrbase; 47};
48 48
49static void 49static void
50die(const char *errstr, ...) 50die(const char *errstr, ...)
@@ -123,7 +123,8 @@ getpw(void)
123} 123}
124 124
125static void 125static void
126readpw(Display *dpy, const char *pws) 126readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
127 const char *pws)
127{ 128{
128 char buf[32], passwd[256], *encrypted; 129 char buf[32], passwd[256], *encrypted;
129 int num, screen, running, failure; 130 int num, screen, running, failure;
@@ -194,7 +195,7 @@ readpw(Display *dpy, const char *pws)
194 } 195 }
195 oldc = color; 196 oldc = color;
196 } 197 }
197 } else if (rr && ev.type == rrevbase + RRScreenChangeNotify) { 198 } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) {
198 XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev; 199 XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev;
199 for (screen = 0; screen < nscreens; screen++) { 200 for (screen = 0; screen < nscreens; screen++) {
200 if (locks[screen]->win == rre->window) { 201 if (locks[screen]->win == rre->window) {
@@ -207,44 +208,17 @@ readpw(Display *dpy, const char *pws)
207 } 208 }
208} 209}
209 210
210static void 211static struct lock *
211unlockscreen(Display *dpy, Lock *lock) 212lockscreen(Display *dpy, struct xrandr *rr, int screen)
212{
213 if(dpy == NULL || lock == NULL)
214 return;
215
216 XUngrabPointer(dpy, CurrentTime);
217 XUngrabKeyboard(dpy, CurrentTime);
218 XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0);
219 XFreePixmap(dpy, lock->pmap);
220 XDestroyWindow(dpy, lock->win);
221
222 free(lock);
223}
224
225static void
226cleanup(Display *dpy)
227{
228 int s;
229
230 for (s = 0; s < nscreens; ++s)
231 unlockscreen(dpy, locks[s]);
232
233 free(locks);
234 XCloseDisplay(dpy);
235}
236
237static Lock *
238lockscreen(Display *dpy, int screen)
239{ 213{
240 char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; 214 char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
241 int i, ptgrab, kbgrab; 215 int i, ptgrab, kbgrab;
242 Lock *lock; 216 struct lock *lock;
243 XColor color, dummy; 217 XColor color, dummy;
244 XSetWindowAttributes wa; 218 XSetWindowAttributes wa;
245 Cursor invisible; 219 Cursor invisible;
246 220
247 if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock)))) 221 if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock))))
248 return NULL; 222 return NULL;
249 223
250 lock->screen = screen; 224 lock->screen = screen;
@@ -281,7 +255,7 @@ lockscreen(Display *dpy, int screen)
281 /* input is grabbed: we can lock the screen */ 255 /* input is grabbed: we can lock the screen */
282 if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { 256 if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
283 XMapRaised(dpy, lock->win); 257 XMapRaised(dpy, lock->win);
284 if (rr) 258 if (rr->active)
285 XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); 259 XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
286 260
287 XSelectInput(dpy, lock->root, SubstructureNotifyMask); 261 XSelectInput(dpy, lock->root, SubstructureNotifyMask);
@@ -312,13 +286,15 @@ usage(void)
312 286
313int 287int
314main(int argc, char **argv) { 288main(int argc, char **argv) {
289 struct xrandr rr;
290 struct lock **locks;
315 struct passwd *pwd; 291 struct passwd *pwd;
316 struct group *grp; 292 struct group *grp;
317 uid_t duid; 293 uid_t duid;
318 gid_t dgid; 294 gid_t dgid;
319 const char *pws; 295 const char *pws;
320 Display *dpy; 296 Display *dpy;
321 int s, nlocks; 297 int s, nlocks, nscreens;
322 298
323 ARGBEGIN { 299 ARGBEGIN {
324 case 'v': 300 case 'v':
@@ -360,16 +336,14 @@ main(int argc, char **argv) {
360 die("slock: setuid: %s\n", strerror(errno)); 336 die("slock: setuid: %s\n", strerror(errno));
361 337
362 /* check for Xrandr support */ 338 /* check for Xrandr support */
363 rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); 339 rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
364 340
365 /* get number of screens in display "dpy" and blank them */ 341 /* get number of screens in display "dpy" and blank them */
366 nscreens = ScreenCount(dpy); 342 nscreens = ScreenCount(dpy);
367 if (!(locks = calloc(nscreens, sizeof(Lock *)))) { 343 if (!(locks = calloc(nscreens, sizeof(struct lock *))))
368 XCloseDisplay(dpy);
369 die("slock: out of memory\n"); 344 die("slock: out of memory\n");
370 }
371 for (nlocks = 0, s = 0; s < nscreens; s++) { 345 for (nlocks = 0, s = 0; s < nscreens; s++) {
372 if ((locks[s] = lockscreen(dpy, s)) != NULL) 346 if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
373 nlocks++; 347 nlocks++;
374 else 348 else
375 break; 349 break;
@@ -377,16 +351,13 @@ main(int argc, char **argv) {
377 XSync(dpy, 0); 351 XSync(dpy, 0);
378 352
379 /* did we manage to lock everything? */ 353 /* did we manage to lock everything? */
380 if (nlocks != nscreens) { 354 if (nlocks != nscreens)
381 cleanup(dpy);
382 return 1; 355 return 1;
383 }
384 356
385 /* run post-lock command */ 357 /* run post-lock command */
386 if (argc > 0) { 358 if (argc > 0) {
387 switch (fork()) { 359 switch (fork()) {
388 case -1: 360 case -1:
389 cleanup(dpy);
390 die("slock: fork failed: %s\n", strerror(errno)); 361 die("slock: fork failed: %s\n", strerror(errno));
391 case 0: 362 case 0:
392 if (close(ConnectionNumber(dpy)) < 0) 363 if (close(ConnectionNumber(dpy)) < 0)
@@ -399,10 +370,7 @@ main(int argc, char **argv) {
399 } 370 }
400 371
401 /* everything is now blank. Wait for the correct password */ 372 /* everything is now blank. Wait for the correct password */
402 readpw(dpy, pws); 373 readpw(dpy, &rr, locks, nscreens, pws);
403
404 /* password ok, unlock everything and quit */
405 cleanup(dpy);
406 374
407 return 0; 375 return 0;
408} 376}