test: the popup's stacking and its map state are one observation
popupabove() took the stacking order from XQueryTree and then the map state of each child from a round trip of its own. The daemon raises and maps between those, in that order and in one flush, so the loop could pair a stale order -- popup still below the client, where it was created -- with a fresh IsViewable, and report the raise that had already happened as a popup stacked below the client. 1 run in 25 under load, which is the worst kind: often enough to teach you to re-run a red instead of reading it. Widening the gap to 300ms shows it with no load at all, and shows the fix is the right one. Same test, same widener, 15 runs each: before pass=11 fail=4 after pass=15 fail=0 XGrabServer is what makes the two one observation, and the widener is then harmless because nothing can raise inside it. Unwidened, 20 runs clean. Nothing about win.c was wrong: the popup does go above, and the test now only says so when it is looking at a single moment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -405,6 +405,9 @@ testcallbacks(Display *dpy, XIM im, Window win)
|
|||||||
/*
|
/*
|
||||||
* The popup is the one viewable override-redirect window on the private
|
* The popup is the one viewable override-redirect window on the private
|
||||||
* display; created before the client window, it must still stack above it.
|
* display; created before the client window, it must still stack above it.
|
||||||
|
* The order and the map states have to be one observation: the daemon
|
||||||
|
* raises and maps between two ungrabbed round trips, and a stale order read
|
||||||
|
* against a fresh map state says the popup is below when it is not.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
popupabove(Display *dpy, Window client)
|
popupabove(Display *dpy, Window client)
|
||||||
@@ -419,8 +422,11 @@ popupabove(Display *dpy, Window client)
|
|||||||
for(;;){
|
for(;;){
|
||||||
above = 0;
|
above = 0;
|
||||||
root = DefaultRootWindow(dpy);
|
root = DefaultRootWindow(dpy);
|
||||||
if(!XQueryTree(dpy, root, &root, &parent, &kids, &n))
|
XGrabServer(dpy);
|
||||||
|
if(!XQueryTree(dpy, root, &root, &parent, &kids, &n)){
|
||||||
|
XUngrabServer(dpy);
|
||||||
return fail("query the window tree");
|
return fail("query the window tree");
|
||||||
|
}
|
||||||
for(i = 0; i < n; i++){
|
for(i = 0; i < n; i++){
|
||||||
if(kids[i] == client)
|
if(kids[i] == client)
|
||||||
above = 1;
|
above = 1;
|
||||||
@@ -429,6 +435,7 @@ popupabove(Display *dpy, Window client)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
XFree(kids);
|
XFree(kids);
|
||||||
|
XUngrabServer(dpy);
|
||||||
if(i < n)
|
if(i < n)
|
||||||
return above || fail("popup is stacked below the client");
|
return above || fail("popup is stacked below the client");
|
||||||
if(leftms(deadline) == 0)
|
if(leftms(deadline) == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user