diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 23:10:39 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-25 23:10:39 +0000 |
commit | da11eed5cd62f052f6b335f21ebb451ec2b3e510 (patch) | |
tree | d9fe5b512f84e387c811da9995cb813bf05384d8 /chrome/common/x11_util.cc | |
parent | 118a632596b37ec311c0f0788399239a07104868 (diff) | |
download | chromium_src-da11eed5cd62f052f6b335f21ebb451ec2b3e510.zip chromium_src-da11eed5cd62f052f6b335f21ebb451ec2b3e510.tar.gz chromium_src-da11eed5cd62f052f6b335f21ebb451ec2b3e510.tar.bz2 |
Two tab dragging fixes for various window managers:
* Reverse the order of enumeration when enumerating all top-level windows. XQueryTree returns the list of windows in bottom-to-top order, while DockInfo expects the windows in top-to-bottom order (ratpoison WM, Awesome WM).
* Extend the enumeration one level deeper for window managers that parent top-level windows into an unnamed real top-level window (ion WM).
BUG=14004
TEST=Extensive tab dragging in the following WMs: Metacity, Compiz, kwm, ion3, xmonad, ratpoison, awesome.
Review URL: http://codereview.chromium.org/149028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19303 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/x11_util.cc')
-rw-r--r-- | chrome/common/x11_util.cc | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc index da3eb7d..5e8efd8 100644 --- a/chrome/common/x11_util.cc +++ b/chrome/common/x11_util.cc @@ -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,23 +163,58 @@ bool GetWindowRect(XID window, gfx::Rect* rect) { 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); - return true; + + // 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; + } + + // 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) { |