+static void x11h_wait_vmstate(void)
+{
+ Atom wm_state = g_xstuff.pXInternAtom(g_xstuff.display, "WM_STATE", False);
+ XEvent evt;
+ int i;
+
+ usleep(20000);
+
+ for (i = 0; i < 20; i++) {
+ while (g_xstuff.pXPending(g_xstuff.display)) {
+ g_xstuff.pXNextEvent(g_xstuff.display, &evt);
+ // printf("w event %d\n", evt.type);
+ if (evt.type == PropertyNotify && evt.xproperty.atom == wm_state)
+ return;
+ }
+ usleep(200000);
+ }
+
+ fprintf(stderr, PFX "timeout waiting for wm_state change\n");
+}
+
+static int x11h_minimize(void)
+{
+ XSetWindowAttributes attributes;
+ Display *display = g_xstuff.display;
+ Window window = g_xstuff.window;
+ int screen = DefaultScreen(g_xstuff.display);
+ int display_width, display_height;
+ XWMHints *wm_hints;
+ XEvent evt;
+
+ g_xstuff.pXWithdrawWindow(display, window, screen);
+
+ attributes.override_redirect = False;
+ g_xstuff.pXChangeWindowAttributes(display, window,
+ CWOverrideRedirect, &attributes);
+
+ wm_hints = g_xstuff.pXGetWMHints(display, window);
+ if (wm_hints == NULL) {
+ wm_hints = XAllocWMHints();
+ wm_hints->flags = 0;
+ }
+ wm_hints->flags |= StateHint;
+ wm_hints->initial_state = IconicState;
+ g_xstuff.pXSetWMHints(display, window, wm_hints);
+ g_xstuff.pXFree(wm_hints);
+ wm_hints = NULL;
+
+ g_xstuff.pXMapWindow(display, window);
+
+ while (g_xstuff.pXNextEvent(display, &evt) == 0)
+ {
+ // printf("m event %d\n", evt.type);
+ switch (evt.type)
+ {
+ case FocusIn:
+ goto out;
+ default:
+ break;
+ }
+ }
+
+out:
+ g_xstuff.pXWithdrawWindow(display, window, screen);
+
+ // must wait for some magic vmstate property change before setting override_redirect
+ x11h_wait_vmstate();
+
+ attributes.override_redirect = True;
+ g_xstuff.pXChangeWindowAttributes(display, window,
+ CWOverrideRedirect, &attributes);
+
+ // fixup window after resize on override_redirect loss
+ display_width = DisplayWidth(display, screen);
+ display_height = DisplayHeight(display, screen);
+ g_xstuff.pXMoveResizeWindow(display, window, 0, 0, display_width, display_height);
+
+ g_xstuff.pXMapWindow(display, window);
+ g_xstuff.pXGrabKeyboard(display, window, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
+
+ // we don't know when event dispatch will be called, so sync now
+ g_xstuff.pXSync(display, False);
+
+ return 0;
+}
+