#include <X11/Xatom.h>
#include <X11/Xlib.h>
static Atom atom_wm_state = None;
static Bool
Window_Has_Property(Display * dpy, Window win, Atom atom)
{
Atom type_ret;
int format_ret;
unsigned char *prop_ret;
unsigned long bytes_after, num_ret;
type_ret = None;
prop_ret = NULL;
XGetWindowProperty(dpy, win, atom, 0, 0, False, AnyPropertyType,
&type_ret, &format_ret, &num_ret,
&bytes_after, &prop_ret);
if (prop_ret)
XFree(prop_ret);
return (type_ret != None) ? True : False;
}
static Bool
Window_Is_Viewable(Display * dpy, Window win)
{
Bool ok;
XWindowAttributes xwa;
XGetWindowAttributes(dpy, win, &xwa);
ok = (xwa.class == InputOutput) && (xwa.map_state == IsViewable);
return ok;
}
Window
Find_Client_In_Children(Display * dpy, Window win)
{
Window root, parent;
Window *children;
unsigned int n_children;
int i;
if (!XQueryTree(dpy, win, &root, &parent, &children, &n_children))
return None;
if (!children)
return None;
win = None;
for (i = (int) n_children - 1; i >= 0; i--) {
if (!Window_Is_Viewable(dpy, children[i])) {
children[i] = None;
continue;
}
if (!Window_Has_Property(dpy, children[i], atom_wm_state))
continue;
win = children[i];
goto done;
}
for (i = (int) n_children - 1; i >= 0; i--) {
if (children[i] == None)
continue;
win = Find_Client_In_Children(dpy, children[i]);
if (win != None)
break;
}
done:
XFree(children);
return win;
}
unsigned long *
Find_Roots(Display * dpy, Window root, unsigned int *num)
{
Atom type_ret;
int format_ret;
unsigned char *prop_ret;
unsigned long bytes_after, num_ret;
Atom atom;
*num = 0;
atom = XInternAtom(dpy, "_NET_VIRTUAL_ROOTS", False);
if (!atom)
return NULL;
type_ret = None;
prop_ret = NULL;
if (XGetWindowProperty(dpy, root, atom, 0, 0x7fffffff, False,
XA_WINDOW, &type_ret, &format_ret, &num_ret,
&bytes_after, &prop_ret) != Success)
return NULL;
if (prop_ret && type_ret == XA_WINDOW && format_ret == 32) {
*num = num_ret;
return ((unsigned long *) prop_ret);
}
if (prop_ret)
XFree(prop_ret);
return NULL;
}
static Window
Find_Child_At_Pointer(Display * dpy, Window win)
{
Window root_return, child_return;
int dummyi;
unsigned int dummyu;
XQueryPointer(dpy, win, &root_return, &child_return,
&dummyi, &dummyi, &dummyi, &dummyi, &dummyu);
return child_return;
}
Window
Find_Client(Display * dpy, Window root, Window subwin)
{
unsigned long *roots;
unsigned int i, n_roots;
Window win;
roots = Find_Roots(dpy, root, &n_roots);
for (i = 0; i < n_roots; i++) {
if (subwin != roots[i])
continue;
win = Find_Child_At_Pointer(dpy, subwin);
if (win == None)
return subwin;
subwin = win;
break;
}
if (roots)
XFree(roots);
if (atom_wm_state == None) {
atom_wm_state = XInternAtom(dpy, "WM_STATE", False);
if (!atom_wm_state)
return subwin;
}
if (Window_Has_Property(dpy, subwin, atom_wm_state))
return subwin;
win = Find_Client_In_Children(dpy, subwin);
if (win != None)
return win;
return subwin;
}