diff options
-rw-r--r-- | slock.c | 78 |
1 files changed, 23 insertions, 55 deletions
@@ -33,18 +33,18 @@ enum { | |||
33 | 33 | ||
34 | #include "config.h" | 34 | #include "config.h" |
35 | 35 | ||
36 | typedef struct { | 36 | struct 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 | ||
43 | static Lock **locks; | 43 | struct xrandr { |
44 | static int nscreens; | 44 | int active; |
45 | static Bool rr; | 45 | int evbase; |
46 | static int rrevbase; | 46 | int errbase; |
47 | static int rrerrbase; | 47 | }; |
48 | 48 | ||
49 | static void | 49 | static void |
50 | die(const char *errstr, ...) | 50 | die(const char *errstr, ...) |
@@ -123,7 +123,8 @@ getpw(void) | |||
123 | } | 123 | } |
124 | 124 | ||
125 | static void | 125 | static void |
126 | readpw(Display *dpy, const char *pws) | 126 | readpw(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 | ||
210 | static void | 211 | static struct lock * |
211 | unlockscreen(Display *dpy, Lock *lock) | 212 | lockscreen(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 | |||
225 | static void | ||
226 | cleanup(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 | |||
237 | static Lock * | ||
238 | lockscreen(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 | ||
313 | int | 287 | int |
314 | main(int argc, char **argv) { | 288 | main(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 | } |