2 * Copyright 2007 Kim woelders
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 #include <X11/Xatom.h>
25 #include "clientwin.h"
27 static Atom atom_wm_state = None;
30 * Check if window has given property
33 Window_Has_Property(Display * dpy, Window win, Atom atom)
37 unsigned char *prop_ret;
38 unsigned long bytes_after, num_ret;
42 XGetWindowProperty(dpy, win, atom, 0, 0, False, AnyPropertyType,
43 &type_ret, &format_ret, &num_ret,
44 &bytes_after, &prop_ret);
48 return (type_ret != None) ? True : False;
52 * Check if window is viewable
55 Window_Is_Viewable(Display * dpy, Window win)
58 XWindowAttributes xwa;
60 XGetWindowAttributes(dpy, win, &xwa);
62 ok = (xwa.class == InputOutput) && (xwa.map_state == IsViewable);
68 * Find a window that has WM_STATE set in the window tree below win.
69 * Unmapped/unviewable windows are not considered valid matches.
70 * Children are searched in top-down stacking order.
71 * The first matching window is returned, None if no match is found.
74 Find_Client_In_Children(Display * dpy, Window win)
78 unsigned int n_children;
81 if (!XQueryTree(dpy, win, &root, &parent, &children, &n_children))
86 /* Check each child for WM_STATE and other validity */
88 for (i = (int) n_children - 1; i >= 0; i--) {
89 if (!Window_Is_Viewable(dpy, children[i])) {
90 children[i] = None; /* Don't bother descending into this one */
93 if (!Window_Has_Property(dpy, children[i], atom_wm_state))
101 /* No children matched, now descend into each child */
102 for (i = (int) n_children - 1; i >= 0; i--) {
103 if (children[i] == None)
105 win = Find_Client_In_Children(dpy, children[i]);
117 * Find virtual roots (_NET_VIRTUAL_ROOTS)
119 static unsigned long *
120 Find_Roots(Display * dpy, Window root, unsigned int *num)
124 unsigned char *prop_ret;
125 unsigned long bytes_after, num_ret;
129 atom = XInternAtom(dpy, "_NET_VIRTUAL_ROOTS", False);
135 if (XGetWindowProperty(dpy, root, atom, 0, 0x7fffffff, False,
136 XA_WINDOW, &type_ret, &format_ret, &num_ret,
137 &bytes_after, &prop_ret) != Success)
140 if (prop_ret && type_ret == XA_WINDOW && format_ret == 32) {
142 return ((unsigned long *) prop_ret);
151 * Find child window at pointer location
154 Find_Child_At_Pointer(Display * dpy, Window win)
156 Window root_return, child_return;
160 XQueryPointer(dpy, win, &root_return, &child_return,
161 &dummyi, &dummyi, &dummyi, &dummyi, &dummyu);
167 * Find client window at pointer location
169 * root is the root window.
170 * subwin is the subwindow reported by a ButtonPress event on root.
172 * If the WM uses virtual roots subwin may be a virtual root.
173 * If so, we descend the window stack at the pointer location and assume the
174 * child is the client or one of its WM frame windows.
175 * This will of course work only if the virtual roots are children of the real
179 Find_Client(Display * dpy, Window root, Window subwin)
181 unsigned long *roots;
182 unsigned int i, n_roots;
185 /* Check if subwin is a virtual root */
186 roots = Find_Roots(dpy, root, &n_roots);
187 for (i = 0; i < n_roots; i++) {
188 if (subwin != roots[i])
190 win = Find_Child_At_Pointer(dpy, subwin);
192 return subwin; /* No child - Return virtual root. */
199 if (atom_wm_state == None) {
200 atom_wm_state = XInternAtom(dpy, "WM_STATE", False);
205 /* Check if subwin has WM_STATE */
206 if (Window_Has_Property(dpy, subwin, atom_wm_state))
209 /* Attempt to find a client window in subwin's children */
210 win = Find_Client_In_Children(dpy, subwin);
212 return win; /* Found a client */
214 /* Did not find a client */