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 |