By the way, what I'm doing seems to cause a semi-infinite loop in the X
server. At least on two not identical versions of the X server, on
NetBSD and Xubuntu.

The scenario is a bit dirty, but that should not cause such an effect of
course.

Here is what happens: VICE wants to focus on some external window (the
xterm from which it was started). The actual focussing requires the
window to be de-iconified otherwise there's a fatal X error. So here's
the code:


    /* if a matching window was found, raise it and transfer focus to it */
    if (foundwin) {
        int width, height;

        DBG(("using win: %lx\n", (long)foundwin));
        XMapRaised(display, foundwin);
        XSync(display, False);
        /* the window manager may ignore the request to raise the window (for
           example because it is minimized). we have to check if the window
           is actually visible, because a call to XSetInputFocus will crash if
           it is not. */
        /* if (getwinstate (display, foundwin)) { */
        if (wait_for_deiconify_other(foundwin, &width, &height)) {
            XSetInputFocus(display, foundwin, RevertToParent, CurrentTime);
            printf("width=%d, height=%d\n", width, height);
            XWarpPointer(display, 0, foundwin,  0, 0, 0, 0,  width/2, height/2);
            XSync(display, False);
        }
    }


/*
 * Wait for some other window to become de-iconified, so that it is
 * safe to call XSetInputFocus() on it.
 * I'm a bit worried about this when the window is in another workspace.
 * In such a case a window is typically not mapped (due to the way
 * window managers typically implement workspaces), and it will never
 * get mapped. Nevertheless, with ctwm at least the function will
 * receive state IsViewable in typically 0 or 1 loops.
 */
static int wait_for_deiconify_other(Window w, int *width, int *height)
{
    int loop = 0;

    while (loop < 10) {
        XWindowAttributes wa;

        XGetWindowAttributes(display, w, &wa);
        if (width) {
            *width = wa.width;
        }
        if (height) {
            *height = wa.height;
        }
        if (wa.map_state == IsUnviewable) {
            printf("wait_for_deiconify_other: IsUnviewable, %d loops\n", loop);
            return 0;
        }
        if (wa.map_state == IsViewable) {
            printf("wait_for_deiconify_other: IsViewable, %d loops\n", loop);
            return 1;
        }
        XSync(display, False);
    }

    /* wa.map_state == IsUnmapped */
    printf("wait_for_deiconify_other: IsUnmapped, %d loops\n", loop);
    return 0;
}

If the target window is in another workspace, wait_for_deiconify_other()
prints "wait_for_deiconify_other: IsViewable, 0 loops", but only when
you manually switch to that workspace. In the mean time, the X server
loops, soaking up lots of cpu time, and VICE too but to a lesser extent.
I suppose this must all somehow happen inside XGetWindowAttributes()...

Weird, eh?

-Olaf.
-- 
___ Olaf 'Rhialto' Seibert  -- There's no point being grown-up if you 
\X/ rhialto/at/xs4all.nl    -- can't be childish sometimes. -The 4th Doctor

Reply via email to