diff options
-rw-r--r-- | slock.c | 60 |
1 files changed, 38 insertions, 22 deletions
@@ -223,6 +223,7 @@ unlockscreen(Display *dpy, Lock *lock) | |||
223 | return; | 223 | return; |
224 | 224 | ||
225 | XUngrabPointer(dpy, CurrentTime); | 225 | XUngrabPointer(dpy, CurrentTime); |
226 | XUngrabKeyboard(dpy, CurrentTime); | ||
226 | XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0); | 227 | XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0); |
227 | XFreePixmap(dpy, lock->pmap); | 228 | XFreePixmap(dpy, lock->pmap); |
228 | XDestroyWindow(dpy, lock->win); | 229 | XDestroyWindow(dpy, lock->win); |
@@ -241,7 +242,7 @@ static Lock * | |||
241 | lockscreen(Display *dpy, int screen) | 242 | lockscreen(Display *dpy, int screen) |
242 | { | 243 | { |
243 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; | 244 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; |
244 | int i; | 245 | int i, ptgrab, kbgrab; |
245 | Lock *lock; | 246 | Lock *lock; |
246 | XColor color, dummy; | 247 | XColor color, dummy; |
247 | XSetWindowAttributes wa; | 248 | XSetWindowAttributes wa; |
@@ -268,30 +269,45 @@ lockscreen(Display *dpy, int screen) | |||
268 | invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); | 269 | invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); |
269 | XDefineCursor(dpy, lock->win, invisible); | 270 | XDefineCursor(dpy, lock->win, invisible); |
270 | 271 | ||
271 | /* Try to grab mouse pointer *and* keyboard, else fail the lock */ | 272 | /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */ |
272 | if (XGrabPointer(dpy, lock->root, False, ButtonPressMask | | 273 | for (i = 6, ptgrab = kbgrab = -1; i; --i) { |
273 | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, | 274 | if (ptgrab != GrabSuccess) { |
274 | None, invisible, CurrentTime) != GrabSuccess) { | 275 | ptgrab = XGrabPointer(dpy, lock->root, False, |
275 | fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen); | 276 | ButtonPressMask | ButtonReleaseMask | |
276 | running = 0; | 277 | PointerMotionMask, GrabModeAsync, |
277 | unlockscreen(dpy, lock); | 278 | GrabModeAsync, None, invisible, CurrentTime); |
278 | return NULL; | 279 | } |
279 | } | 280 | if (kbgrab != GrabSuccess) { |
281 | kbgrab = XGrabKeyboard(dpy, lock->root, True, | ||
282 | GrabModeAsync, GrabModeAsync, CurrentTime); | ||
283 | } | ||
280 | 284 | ||
281 | if (XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, | 285 | /* input is grabbed: we can lock the screen */ |
282 | CurrentTime) != GrabSuccess) { | 286 | if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { |
283 | fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); | 287 | XMapRaised(dpy, lock->win); |
284 | running = 0; | 288 | if (rr) |
285 | unlockscreen(dpy, lock); | 289 | XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); |
286 | return NULL; | 290 | |
287 | } | 291 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); |
292 | return lock; | ||
293 | } | ||
288 | 294 | ||
289 | XMapRaised(dpy, lock->win); | 295 | /* retry on AlreadyGrabbed but fail on other errors */ |
290 | if (rr) | 296 | if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) || |
291 | XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); | 297 | (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess)) |
298 | break; | ||
292 | 299 | ||
293 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); | 300 | usleep(100000); |
294 | return lock; | 301 | } |
302 | |||
303 | /* we couldn't grab all input: fail out */ | ||
304 | if (ptgrab != GrabSuccess) | ||
305 | fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen); | ||
306 | if (kbgrab != GrabSuccess) | ||
307 | fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen); | ||
308 | running = 0; | ||
309 | unlockscreen(dpy, lock); | ||
310 | return NULL; | ||
295 | } | 311 | } |
296 | 312 | ||
297 | static void | 313 | static void |