summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/common/gtk_util.cc20
-rw-r--r--chrome/common/x11_util.cc51
-rw-r--r--chrome/common/x11_util.h6
-rw-r--r--chrome/common/x11_util_internal.h3
4 files changed, 59 insertions, 21 deletions
diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc
index 16ce02b..83ddddd 100644
--- a/chrome/common/gtk_util.cc
+++ b/chrome/common/gtk_util.cc
@@ -251,9 +251,8 @@ bool IsScreenComposited() {
}
void EnumerateTopLevelWindows(x11_util::EnumerateWindowsDelegate* delegate) {
- GdkScreen* screen = gdk_screen_get_default();
- GList* stack = gdk_screen_get_window_stack(screen);
- if (!stack) {
+ std::vector<XID> stack;
+ if (!x11_util::GetXWindowStack(&stack)) {
// Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
// to old school enumeration of all X windows. Some WMs parent 'top-level'
// windows in unnamed actual top-level windows (ion WM), so extend the
@@ -263,18 +262,11 @@ void EnumerateTopLevelWindows(x11_util::EnumerateWindowsDelegate* delegate) {
return;
}
- for (GList* iter = g_list_last(stack); iter; iter = iter->prev) {
- GdkWindow* window = static_cast<GdkWindow*>(iter->data);
- if (!gdk_window_is_visible(window))
- continue;
-
- XID xid = GDK_WINDOW_XID(window);
- if (delegate->ShouldStopIterating(xid))
- break;
+ std::vector<XID>::iterator iter;
+ for (iter = stack.begin(); iter != stack.end(); iter++) {
+ if (delegate->ShouldStopIterating(*iter))
+ return;
}
-
- g_list_foreach(stack, (GFunc)g_object_unref, NULL);
- g_list_free(stack);
}
void SetButtonTriggersNavigation(GtkWidget* button) {
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc
index 1305fe1..0921c6e 100644
--- a/chrome/common/x11_util.cc
+++ b/chrome/common/x11_util.cc
@@ -8,8 +8,6 @@
#include "chrome/common/x11_util.h"
-#include <string.h>
-
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
@@ -276,10 +274,11 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window,
// 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;
+ if (++depth <= max_depth) {
+ for (iter = windows.rbegin(); iter != windows.rend(); iter++) {
+ if (EnumerateChildren(delegate, *iter, max_depth, depth))
+ return true;
+ }
}
return false;
@@ -290,6 +289,46 @@ bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) {
return EnumerateChildren(delegate, root, max_depth, 0);
}
+bool GetXWindowStack(std::vector<XID>* windows) {
+ windows->clear();
+
+ static Atom atom = XInternAtom(GetXDisplay(),
+ "_NET_CLIENT_LIST_STACKING", False);
+
+ Atom type;
+ int format;
+ unsigned long count;
+ unsigned long bytes_after;
+ unsigned char *data = NULL;
+ if (XGetWindowProperty(GetXDisplay(),
+ GetX11RootWindow(),
+ atom,
+ 0, // offset
+ ~0L, // length
+ False, // delete
+ AnyPropertyType, // requested type
+ &type,
+ &format,
+ &count,
+ &bytes_after,
+ &data) != Success) {
+ return false;
+ }
+
+ bool result = false;
+ if (type == XA_WINDOW && format == 32 && data && count > 0) {
+ result = true;
+ XID* stack = reinterpret_cast<XID*>(data);
+ for (unsigned long i = 0; i < count; i++)
+ windows->insert(windows->begin(), stack[i]);
+ }
+
+ if (data)
+ XFree(data);
+
+ return result;
+}
+
XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) {
static XRenderPictFormat* pictformat = NULL;
if (pictformat)
diff --git a/chrome/common/x11_util.h b/chrome/common/x11_util.h
index 09b1c2b..a3dbb2a 100644
--- a/chrome/common/x11_util.h
+++ b/chrome/common/x11_util.h
@@ -11,6 +11,9 @@
// we use a void* for Visual*). The Xlib headers are highly polluting so we try
// hard to limit their spread into the rest of the code.
+#include <string>
+#include <vector>
+
#include "base/gfx/rect.h"
#include "base/task.h"
@@ -80,6 +83,9 @@ class EnumerateWindowsDelegate {
// windows up to a depth of |max_depth|.
bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth);
+// Returns a list of top-level windows in top-to-bottom stacking order.
+bool GetXWindowStack(std::vector<XID>* windows);
+
// Return a handle to a server side pixmap. |shared_memory_key| is a SysV
// IPC key. The shared memory region must contain 32-bit pixels.
XID AttachSharedMemory(Display* display, int shared_memory_support);
diff --git a/chrome/common/x11_util_internal.h b/chrome/common/x11_util_internal.h
index 1a7b604..52a8a8c 100644
--- a/chrome/common/x11_util_internal.h
+++ b/chrome/common/x11_util_internal.h
@@ -12,6 +12,7 @@
// when needed.
extern "C" {
+#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xrender.h>
@@ -28,4 +29,4 @@ namespace x11_util {
XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual);
};
-#endif // CHROME_COMMON_X11_UTIL_H_
+#endif // CHROME_COMMON_X11_UTIL_INTERNAL_H_