From: Quentin Rameau Date: Thu, 1 Sep 2016 11:46:51 +0000 (+0200) Subject: Re-introduce the waiting loop for input grabbing X-Git-Url: https://git.danieliu.xyz/?a=commitdiff_plain;h=e378f735d857f7da124177e3540912d920be5022;p=slock.git 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. --- diff --git a/slock.c b/slock.c index 4980325..97c7489 100644 --- 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