Make xmenu wait for another process to ungrab

Xmenu didn't wait for another process to ungrab the poiter or keyboard,
ending up in erroneous behavior.  Now it waits.
This commit is contained in:
phillbush 2020-05-19 09:17:06 -03:00
parent c49dad285c
commit 85003546a2

55
xmenu.c
View File

@ -77,13 +77,14 @@ static void getcolor(const char *s, XftColor *color);
static void getresources(void);
static void setupdc(void);
static void setupgeom(void);
static void setupgrab(void);
static struct Item *allocitem(const char *label, const char *output);
static struct Menu *allocmenu(struct Menu *parent, struct Item *list, unsigned level);
static void getmenuitem(Window win, int y, struct Menu **menu_ret, struct Item **item_ret);
static void drawmenu(void);
static void calcscreengeom(void);
static void calcmenu(struct Menu *menu);
static void grabpointer(void);
static void grabkeyboard(void);
static void setcurrmenu(struct Menu *currmenu_new);
static void parsestdin(void);
static void run(void);
@ -156,8 +157,10 @@ main(int argc, char *argv[])
calcmenu(rootmenu);
/* grab mouse and keyboard */
if (override_redirect)
setupgrab();
if (override_redirect) {
grabpointer();
grabkeyboard();
}
/* map root menu */
currmenu = rootmenu;
@ -256,19 +259,6 @@ setupgeom(void)
geom.separator = separatorsize;
}
/* grab pointer */
static void
setupgrab(void)
{
if (XGrabPointer(dpy, rootwin, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, None,
None, CurrentTime) != GrabSuccess)
errx(1, "cannot grab pointer");
if (XGrabKeyboard(dpy, rootwin, True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess)
errx(1, "cannot grab keyboard");
}
/* allocate an item */
static struct Item *
allocitem(const char *label, const char *output)
@ -523,6 +513,39 @@ calcmenu(struct Menu *menu)
}
}
/* try to grab pointer, we may have to wait for another process to ungrab */
static void
grabpointer(void)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
int i;
for (i = 0; i < 1000; i++) {
if (XGrabPointer(dpy, rootwin, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, None,
None, CurrentTime) == GrabSuccess)
return;
nanosleep(&ts, NULL);
}
errx(1, "cannot grab keyboard");
}
/* try to grab keyboard, we may have to wait for another process to ungrab */
static void
grabkeyboard(void)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
int i;
for (i = 0; i < 1000; i++) {
if (XGrabKeyboard(dpy, rootwin, True, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess)
return;
nanosleep(&ts, NULL);
}
errx(1, "cannot grab keyboard");
}
/* get menu and item of given window and position */
static void
getmenuitem(Window win, int y,