diff options
-rw-r--r-- | chrome/common/gtk_util.cc | 20 | ||||
-rw-r--r-- | chrome/common/x11_util.cc | 51 | ||||
-rw-r--r-- | chrome/common/x11_util.h | 6 | ||||
-rw-r--r-- | chrome/common/x11_util_internal.h | 3 |
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_ |