Index: chrome/common/x11_util.cc |
=================================================================== |
--- chrome/common/x11_util.cc (revision 19271) |
+++ chrome/common/x11_util.cc (working copy) |
@@ -17,6 +17,8 @@ |
#include <sys/ipc.h> |
#include <sys/shm.h> |
+#include <set> |
+ |
#include "base/logging.h" |
#include "base/gfx/size.h" |
#include "base/thread.h" |
@@ -161,25 +163,60 @@ |
return true; |
} |
-bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate) { |
- XID root = GetX11RootWindow(); |
- XID parent; |
- XID* children; |
+// Returns true if |window| is a named window. |
+bool IsWindowNamed(XID window) { |
+ XTextProperty prop; |
+ if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) |
+ return false; |
+ |
+ XFree(prop.value); |
+ return true; |
+} |
+ |
+bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, |
+ const int max_depth, int depth) { |
+ if (depth > max_depth) |
+ return false; |
+ |
+ XID root, parent, *children; |
unsigned int num_children; |
- int status = XQueryTree(GetXDisplay(), root, &root, &parent, |
- &children, &num_children); |
+ int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, |
+ &num_children); |
if (status == 0) |
return false; |
- for (unsigned int i = 0; i < num_children; i++) { |
- if (delegate->ShouldStopIterating(children[i])) |
- break; |
+ std::set<XID> windows; |
+ for (unsigned int i = 0; i < num_children; i++) |
+ windows.insert(children[i]); |
+ |
+ XFree(children); |
+ |
+ // XQueryTree returns the children of |window| in bottom-to-top order, so |
+ // reverse-iterate the list to check the windows from top-to-bottom. |
+ std::set<XID>::reverse_iterator iter; |
+ for (iter = windows.rbegin(); iter != windows.rend(); iter++) { |
+ if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter)) |
+ return true; |
} |
- XFree(children); |
- return true; |
+ // If we're at this point, we didn't find the window we're looking for at the |
+ // current level, so we need to recurse to the next level. We use a second |
+ // loop because the recursion and call to XQueryTree are expensive and is only |
+ // needed for a small number of cases. |
+ depth++; |
+ for (iter = windows.rbegin(); iter != windows.rend(); iter++) { |
+ if (EnumerateChildren(delegate, *iter, max_depth, depth)) |
+ return true; |
+ } |
+ |
+ return false; |
} |
+bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { |
+ XID root = GetX11RootWindow(); |
+ return EnumerateChildren(delegate, root, max_depth, 0); |
+} |
+ |
XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { |
static XRenderPictFormat* pictformat = NULL; |
if (pictformat) |