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