123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- * Copyright 2007 Kim woelders
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
- #include <X11/Xatom.h>
- #include <X11/Xlib.h>
- #include "clientwin.h"
- static Atom atom_wm_state = None;
- /*
- * Check if window has given property
- */
- 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;
- }
- /*
- * Check if window is viewable
- */
- 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;
- }
- /*
- * Find a window that has WM_STATE set in the window tree below win.
- * Unmapped/unviewable windows are not considered valid matches.
- * Children are searched in top-down stacking order.
- * The first matching window is returned, None if no match is found.
- */
- static 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;
- /* Check each child for WM_STATE and other validity */
- win = None;
- for (i = (int) n_children - 1; i >= 0; i--) {
- if (!Window_Is_Viewable(dpy, children[i])) {
- children[i] = None; /* Don't bother descending into this one */
- continue;
- }
- if (!Window_Has_Property(dpy, children[i], atom_wm_state))
- continue;
- /* Got one */
- win = children[i];
- goto done;
- }
- /* No children matched, now descend into each child */
- 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;
- }
- /*
- * Find virtual roots (_NET_VIRTUAL_ROOTS)
- */
- static unsigned long *
- Find_Roots(Display * dpy, Window root, unsigned long *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;
- }
- /*
- * Find child window at pointer location
- */
- 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;
- }
- /*
- * Find client window at pointer location
- *
- * root is the root window.
- * subwin is the subwindow reported by a ButtonPress event on root.
- *
- * If the WM uses virtual roots subwin may be a virtual root.
- * If so, we descend the window stack at the pointer location and assume the
- * child is the client or one of its WM frame windows.
- * This will of course work only if the virtual roots are children of the real
- * root.
- */
- Window
- Find_Client(Display * dpy, Window root, Window subwin)
- {
- unsigned long *roots;
- unsigned long i, n_roots;
- Window win;
- /* Check if subwin is a virtual root */
- 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; /* No child - Return virtual root. */
- 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;
- }
- /* Check if subwin has WM_STATE */
- if (Window_Has_Property(dpy, subwin, atom_wm_state))
- return subwin;
- /* Attempt to find a client window in subwin's children */
- win = Find_Client_In_Children(dpy, subwin);
- if (win != None)
- return win; /* Found a client */
- /* Did not find a client */
- return subwin;
- }
|