Re-introduce the waiting loop for input grabbing - slock - simple X display locker utility
 (HTM) git clone git://git.suckless.org/slock
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e378f735d857f7da124177e3540912d920be5022
 (DIR) parent 1f66885fbf36c726b7615060d3c98cbf74218d13
 (HTM) 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:
         M slock.c                             |      60 ++++++++++++++++++++------------
       
       1 file changed, 38 insertions(+), 22 deletions(-)
       ---
 (DIR) 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