[hackers] [PATCH 2/4] Re-introduce the waiting loop for input grabbing

From: Quentin Rameau <quinq_AT_fifth.space>
Date: Thu, 1 Sep 2016 13:46:51 +0200

We actually “need” to wait a little for input to be released before
locking for cases where slock is spawned from other graphical
applications using keybindings.
This undoes the misbehaviour I introduced in c2f9757, sorry for the mess.
---
 slock.c | 60 ++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/slock.c b/slock.c
index 4980325..97c7489 100644
--- a/slock.c
+++ b/slock.c
_AT_@ -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);
_AT_@ -241,7 +242,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;
_AT_@ -268,30 +269,45 @@ 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);
+	running = 0;
+	unlockscreen(dpy, lock);
+	return NULL;
 }
 
 static void
-- 
2.9.3
Received on Thu Sep 01 2016 - 13:46:51 CEST

This archive was generated by hypermail 2.3.0 : Thu Sep 01 2016 - 13:48:33 CEST