slock

simple X display locker utility
git clone git://git.suckless.org/slock
Log | Files | Refs | README | LICENSE

commit e378f735d857f7da124177e3540912d920be5022
parent 1f66885fbf36c726b7615060d3c98cbf74218d13
Author: Quentin Rameau <quinq@fifth.space>
Date:   Thu,  1 Sep 2016 13:46:51 +0200

Re-introduce the waiting loop for input grabbing

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.

Diffstat:
slock.c | 60++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 22 deletions(-)

diff --git 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); @@ -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; @@ -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