| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file defines utility functions for X11 (Linux only). This code has been | 5 // This file defines utility functions for X11 (Linux only). This code has been |
| 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support | 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support |
| 7 // remains woefully incomplete. | 7 // remains woefully incomplete. |
| 8 | 8 |
| 9 #include "chrome/common/x11_util.h" | 9 #include "chrome/common/x11_util.h" |
| 10 | 10 |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 | 12 |
| 13 #include <gdk/gdk.h> | 13 #include <gdk/gdk.h> |
| 14 #include <gdk/gdkx.h> | 14 #include <gdk/gdkx.h> |
| 15 #include <gtk/gtk.h> | 15 #include <gtk/gtk.h> |
| 16 | 16 |
| 17 #include <sys/ipc.h> | 17 #include <sys/ipc.h> |
| 18 #include <sys/shm.h> | 18 #include <sys/shm.h> |
| 19 | 19 |
| 20 #include <set> |
| 21 |
| 20 #include "base/logging.h" | 22 #include "base/logging.h" |
| 21 #include "base/gfx/size.h" | 23 #include "base/gfx/size.h" |
| 22 #include "base/thread.h" | 24 #include "base/thread.h" |
| 23 #include "chrome/common/x11_util_internal.h" | 25 #include "chrome/common/x11_util_internal.h" |
| 24 | 26 |
| 25 namespace x11_util { | 27 namespace x11_util { |
| 26 | 28 |
| 27 Display* GetXDisplay() { | 29 Display* GetXDisplay() { |
| 28 static Display* display = NULL; | 30 static Display* display = NULL; |
| 29 | 31 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 return false; | 156 return false; |
| 155 | 157 |
| 156 if (!XTranslateCoordinates(GetSecondaryDisplay(), window, root, | 158 if (!XTranslateCoordinates(GetSecondaryDisplay(), window, root, |
| 157 0, 0, &x, &y, &child)) | 159 0, 0, &x, &y, &child)) |
| 158 return false; | 160 return false; |
| 159 | 161 |
| 160 *rect = gfx::Rect(x, y, width, height); | 162 *rect = gfx::Rect(x, y, width, height); |
| 161 return true; | 163 return true; |
| 162 } | 164 } |
| 163 | 165 |
| 164 bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate) { | 166 // Returns true if |window| is a named window. |
| 165 XID root = GetX11RootWindow(); | 167 bool IsWindowNamed(XID window) { |
| 166 XID parent; | 168 XTextProperty prop; |
| 167 XID* children; | 169 if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) |
| 170 return false; |
| 171 |
| 172 XFree(prop.value); |
| 173 return true; |
| 174 } |
| 175 |
| 176 bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, |
| 177 const int max_depth, int depth) { |
| 178 if (depth > max_depth) |
| 179 return false; |
| 180 |
| 181 XID root, parent, *children; |
| 168 unsigned int num_children; | 182 unsigned int num_children; |
| 169 int status = XQueryTree(GetXDisplay(), root, &root, &parent, | 183 int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, |
| 170 &children, &num_children); | 184 &num_children); |
| 171 if (status == 0) | 185 if (status == 0) |
| 172 return false; | 186 return false; |
| 173 | 187 |
| 174 for (unsigned int i = 0; i < num_children; i++) { | 188 std::set<XID> windows; |
| 175 if (delegate->ShouldStopIterating(children[i])) | 189 for (unsigned int i = 0; i < num_children; i++) |
| 176 break; | 190 windows.insert(children[i]); |
| 191 |
| 192 XFree(children); |
| 193 |
| 194 // XQueryTree returns the children of |window| in bottom-to-top order, so |
| 195 // reverse-iterate the list to check the windows from top-to-bottom. |
| 196 std::set<XID>::reverse_iterator iter; |
| 197 for (iter = windows.rbegin(); iter != windows.rend(); iter++) { |
| 198 if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter)) |
| 199 return true; |
| 177 } | 200 } |
| 178 | 201 |
| 179 XFree(children); | 202 // If we're at this point, we didn't find the window we're looking for at the |
| 180 return true; | 203 // current level, so we need to recurse to the next level. We use a second |
| 204 // loop because the recursion and call to XQueryTree are expensive and is only |
| 205 // needed for a small number of cases. |
| 206 depth++; |
| 207 for (iter = windows.rbegin(); iter != windows.rend(); iter++) { |
| 208 if (EnumerateChildren(delegate, *iter, max_depth, depth)) |
| 209 return true; |
| 210 } |
| 211 |
| 212 return false; |
| 213 } |
| 214 |
| 215 bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { |
| 216 XID root = GetX11RootWindow(); |
| 217 return EnumerateChildren(delegate, root, max_depth, 0); |
| 181 } | 218 } |
| 182 | 219 |
| 183 XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { | 220 XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { |
| 184 static XRenderPictFormat* pictformat = NULL; | 221 static XRenderPictFormat* pictformat = NULL; |
| 185 if (pictformat) | 222 if (pictformat) |
| 186 return pictformat; | 223 return pictformat; |
| 187 | 224 |
| 188 DCHECK(QueryRenderSupport(dpy)); | 225 DCHECK(QueryRenderSupport(dpy)); |
| 189 | 226 |
| 190 pictformat = XRenderFindVisualFormat(dpy, visual); | 227 pictformat = XRenderFindVisualFormat(dpy, visual); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 return false; | 348 return false; |
| 312 | 349 |
| 313 if (children) | 350 if (children) |
| 314 XFree(children); | 351 XFree(children); |
| 315 | 352 |
| 316 *parent_is_root = root_window == *parent_window; | 353 *parent_is_root = root_window == *parent_window; |
| 317 return true; | 354 return true; |
| 318 } | 355 } |
| 319 | 356 |
| 320 } // namespace x11_util | 357 } // namespace x11_util |
| OLD | NEW |