From: Mark Wooding Date: Sun, 24 Apr 2022 11:16:34 +0000 (+0100) Subject: xrepaint.c: Map all of the windows, and then wait for them all. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/xtoys/commitdiff_plain/6935312784f67deae46153e7c0761142dbec0024 xrepaint.c: Map all of the windows, and then wait for them all. This will be faster on displays with multiple screens. If anyone still has one of those. --- diff --git a/xrepaint.c b/xrepaint.c index 5a454a8..b957650 100644 --- a/xrepaint.c +++ b/xrepaint.c @@ -36,6 +36,7 @@ #include +#include #include #include #include @@ -72,18 +73,12 @@ Options:\n\ fp); } -static void repaint(Screen *sc) +static Window cover_screen(Screen *sc) { - /* Repaint the screen SC. - * - * Annoyingly, `XClearWindow' uses `ClipByChildren' semantics, and there's - * no way to change that. The best idea I can come up with is to drop - * another window in front and take it away again. - */ + /* Make, map, and return a window completely covering the screen SC. */ Window w; XSetWindowAttributes attr; - XEvent ev; attr.background_pixel = 0; attr.event_mask = StructureNotifyMask | VisibilityChangeMask | ExposureMask | KeyPressMask | ButtonPressMask; @@ -94,8 +89,7 @@ static void repaint(Screen *sc) DefaultVisualOfScreen(sc), CWBackPixel | CWEventMask | CWOverrideRedirect, &attr); XMapWindow(dpy, w); - do XNextEvent(dpy, &ev); - while (ev.type != Expose && ev.type != KeyPress && ev.type != ButtonPress); + return (w); } int main(int argc, char *argv[]) @@ -103,7 +97,9 @@ int main(int argc, char *argv[]) const char *display = 0; unsigned f = 0; struct timeval tv; - int i; + XEvent ev; + Window *win, w; + int i, n; #define f_only 1u #define f_bogus 2u @@ -139,15 +135,35 @@ int main(int argc, char *argv[]) dpy = XOpenDisplay(display); if (!dpy) { die(EXIT_FAILURE, "couldn't open display"); } - /* Do the repainting thing. */ - if (f & f_only) - repaint(DefaultScreenOfDisplay(dpy)); - else { - for (i = 0; i < ScreenCount(dpy); i++) - repaint(ScreenOfDisplay(dpy, i)); + /* Annoyingly, `XClearWindow' uses `ClipByChildren' semantics, and there's + * no way to change that. The best idea I can come up with is to drop + * windows over the top of each screen and take them away again. The + * latter part is easy because they'll disappear when we close the + * display. + * + * Start by making and mapping the windows. + */ + n = f&f_only ? 1 : ScreenCount(dpy); + win = xmalloc(n*sizeof(Window)); + if (f&f_only) + win[0] = cover_screen(DefaultScreenOfDisplay(dpy)); + else for (i = 0; i < n; i++) + win[i] = cover_screen(ScreenOfDisplay(dpy, i)); + + /* Now we wait until they're all obviously mapped. */ + while (n) { + XNextEvent(dpy, &ev); + switch (ev.type) { + case Expose: case KeyPress: case ButtonPress: + w = ev.xany.window; goto window_visible; + window_visible: + for (i = 0; i < n; i++) + if (w == win[i]) { win[i] = win[--n]; break; } + break; + } } - /* Wait for a bit. This is an awful hack. */ + /* Finally, we must wait for a bit longer. This is an awful hack. */ tv.tv_sec = 0; tv.tv_usec = 50*1000; select(0, 0, 0, 0, &tv);