summaryrefslogtreecommitdiffstats
path: root/chrome/common/x11_util.cc
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:10:39 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-25 23:10:39 +0000
commitda11eed5cd62f052f6b335f21ebb451ec2b3e510 (patch)
treed9fe5b512f84e387c811da9995cb813bf05384d8 /chrome/common/x11_util.cc
parent118a632596b37ec311c0f0788399239a07104868 (diff)
downloadchromium_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.cc59
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) {