]> git.armaanb.net Git - slock.git/blobdiff - slock.c
Move screen unlocking inside cleanup()
[slock.git] / slock.c
diff --git a/slock.c b/slock.c
index 4980325f9fd9df80528cb256e6cf4aa6459a8a2c..068227985bfa9bb5efd768a7af98dffe4ad26153 100644 (file)
--- a/slock.c
+++ b/slock.c
@@ -223,6 +223,7 @@ unlockscreen(Display *dpy, Lock *lock)
                return;
 
        XUngrabPointer(dpy, CurrentTime);
+       XUngrabKeyboard(dpy, CurrentTime);
        XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0);
        XFreePixmap(dpy, lock->pmap);
        XDestroyWindow(dpy, lock->win);
@@ -233,6 +234,11 @@ unlockscreen(Display *dpy, Lock *lock)
 static void
 cleanup(Display *dpy)
 {
+       int s;
+
+       for (s = 0; s < nscreens; ++s)
+               unlockscreen(dpy, locks[s]);
+
        free(locks);
        XCloseDisplay(dpy);
 }
@@ -241,7 +247,7 @@ static Lock *
 lockscreen(Display *dpy, int screen)
 {
        char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
-       int i;
+       int i, ptgrab, kbgrab;
        Lock *lock;
        XColor color, dummy;
        XSetWindowAttributes wa;
@@ -268,30 +274,43 @@ lockscreen(Display *dpy, int screen)
        invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0);
        XDefineCursor(dpy, lock->win, invisible);
 
-       /* Try to grab mouse pointer *and* keyboard, else fail the lock */
-       if (XGrabPointer(dpy, lock->root, False, ButtonPressMask |
-           ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync,
-           None, invisible, CurrentTime) != GrabSuccess) {
-               fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen);
-               running = 0;
-               unlockscreen(dpy, lock);
-               return NULL;
-       }
+       /* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */
+       for (i = 6, ptgrab = kbgrab = -1; i; --i) {
+               if (ptgrab != GrabSuccess) {
+                       ptgrab = XGrabPointer(dpy, lock->root, False,
+                                ButtonPressMask | ButtonReleaseMask |
+                                PointerMotionMask, GrabModeAsync,
+                                GrabModeAsync, None, invisible, CurrentTime);
+               }
+               if (kbgrab != GrabSuccess) {
+                       kbgrab = XGrabKeyboard(dpy, lock->root, True,
+                                GrabModeAsync, GrabModeAsync, CurrentTime);
+               }
 
-       if (XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync,
-           CurrentTime) != GrabSuccess) {
-               fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen);
-               running = 0;
-               unlockscreen(dpy, lock);
-               return NULL;
-       }
+               /* input is grabbed: we can lock the screen */
+               if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
+                       XMapRaised(dpy, lock->win);
+                       if (rr)
+                               XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
+
+                       XSelectInput(dpy, lock->root, SubstructureNotifyMask);
+                       return lock;
+               }
 
-       XMapRaised(dpy, lock->win);
-       if (rr)
-               XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
+               /* retry on AlreadyGrabbed but fail on other errors */
+               if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) ||
+                   (kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess))
+                       break;
 
-       XSelectInput(dpy, lock->root, SubstructureNotifyMask);
-       return lock;
+               usleep(100000);
+       }
+
+       /* we couldn't grab all input: fail out */
+       if (ptgrab != GrabSuccess)
+               fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen);
+       if (kbgrab != GrabSuccess)
+               fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen);
+       return NULL;
 }
 
 static void
@@ -343,19 +362,21 @@ main(int argc, char **argv) {
 
        /* get number of screens in display "dpy" and blank them */
        nscreens = ScreenCount(dpy);
-       if (!(locks = malloc(sizeof(Lock *) * nscreens))) {
+       if (!(locks = calloc(nscreens, sizeof(Lock *)))) {
                XCloseDisplay(dpy);
                die("slock: out of memory\n");
        }
        for (nlocks = 0, s = 0; s < nscreens; s++) {
                if ((locks[s] = lockscreen(dpy, s)) != NULL)
                        nlocks++;
+               else
+                       break;
        }
        XSync(dpy, 0);
 
-       /* did we actually manage to lock anything? */
-       if (nlocks == 0) {
-               /* nothing to protect */
+       /* did we manage to lock everything? */
+       if (nlocks != nscreens) {
+               running = 0;
                cleanup(dpy);
                return 1;
        }
@@ -384,9 +405,6 @@ main(int argc, char **argv) {
 #endif
 
        /* password ok, unlock everything and quit */
-       for (s = 0; s < nscreens; s++)
-               unlockscreen(dpy, locks[s]);
-
        cleanup(dpy);
 
        return 0;