From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 24-MAY-1989 04:55
To:	MRGATE::"ARISIA::EVERHART"
Subj:	DECwindows pseudo-root - sample code

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Tue, 23 MAY 89 14:38:13 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Tue, 23 May 89 14:21:34 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA10811; Tue, 23 May 89 14:09:13 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 23 May 89 04:16:03 GMT
From: munnari!otc!metro!basser!usage!csdvx0!decus!taylort@uunet.uu.net  (Trevor Taylor)
Organization: DECUS, South Pacific Chapter
Subject: DECwindows pseudo-root - sample code
Message-Id: <136@decus.com.au>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

Pseudo-Root Window for DECwindows

The DECwindows window manager creates a "pseudo-root" window which
completely covers the real root window. This means that any code
which modifies the root has no visible effect. To get around this
problem, use the following code to determine the window ID of
the pseudo-root instead of the X call RootWindow(dpy).

Usually, the required window is the first grandchild of the
real root. However, this code is a little more general than
that and looks for the first descendent which covers the
entire screen.

DEC gurus out there --- Is this the right thing to do?


	Trevor Taylor


/*-------------- Cut here ----------------*/
/*
	pseudo_root - Return the Window ID of the Pseudo Root

	NOTE: This routine is required for DECwindows
	because the true root window is hidden behind
	a pseudo-root window created by the window manager.

	Calling Sequence:
		root_win = pseudo_root(display, screen);
	where:
		display must already be opened and
		screen is usually DefaultScreen(display).

*/

#include <X11/Xlib.h>

#define	NULL	0L

static void chase_root();

static int done;
static Window last_win;
static int root_x, root_y, root_width, root_height;
static int root_bw, root_depth;


Window pseudo_root(dpy, screen)
Display *dpy;
int screen;
{
    Window root, win;

    /* Start at the real root */
    root = RootWindow(dpy, screen);

    /* Get the geometry of the root */
    if (XGetGeometry(dpy, root, &win, &root_x, &root_y, 
			&root_width, &root_height,
			&root_bw, &root_depth))
    {
	/* Set up for the tree walk */
	done = False;
	last_win = root;

	/* Run down the tree to find the pseudo root */
	chase_root(dpy, root);
	return last_win;
    }
    else
	/* Classic case of "this should never happen" */
	return root;

} /*** End pseudo_root() ***/


/*
	chase_root - Internal to this module

	This is a recursive routine for descending the window tree.

	It looks for the first window which does NOT overlay the root,
	then returns with the ID of the last window it saw in the
	global variable last_win.

	NOTE: The parameters of the root window must be set up before
	calling chase_root().
*/

static void chase_root (dpy, w)
Display *dpy;
Window w;
{
    Window root, parent;
    unsigned int nchildren;
    Window *children = NULL;
    Status status;
    int n;
    int x, y, rx, ry;
    unsigned int width, height, bw, depth;

    /* Insurance */
    if (done)
	return;

    if (XGetGeometry(dpy, w, &root, &x, &y, &width, &height, &bw, &depth))
    {
	/*
	    If this window does not exactly overlay the root
	    then we have gone one too far, i.e., we have finished.
	*/
	if ( (x != root_x) ||
	     (y != root_y) ||
	     (width  != root_width) ||
	     (height != root_height) )
	{
	    done = True;
	    return;
	}

	/* Otherwise, remember where we got up to and continue */
	else
	    last_win = w;
    }

    else
	/* We are in trouble if this happens!!! */
	return;

    if (!XQueryTree (dpy, w, &root, &parent, &children, &nchildren))
	/* Likewise, we hope we never get here!!! */
	return;

    for (n = 0; n < nchildren; n++)
    {
	chase_root (dpy, children[n]);
	if (done)
	    break;
    }
#ifdef VMS
    if (children) XFree ((char *) children);
#else
    if (children) free ((char *) children);
#endif
    return;

} /*** End chase_root() ***/

