OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/base/x/x11_util.h" | 9 #include "ui/base/x/x11_util.h" |
10 | 10 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 #include "ui/gfx/gdk_compat.h" | 65 #include "ui/gfx/gdk_compat.h" |
66 #include "ui/gfx/gtk_compat.h" | 66 #include "ui/gfx/gtk_compat.h" |
67 #endif | 67 #endif |
68 | 68 |
69 namespace ui { | 69 namespace ui { |
70 | 70 |
71 namespace { | 71 namespace { |
72 | 72 |
73 // Used to cache the XRenderPictFormat for a visual/display pair. | 73 // Used to cache the XRenderPictFormat for a visual/display pair. |
74 struct CachedPictFormat { | 74 struct CachedPictFormat { |
75 bool equals(Display* display, Visual* visual) const { | 75 bool equals(XDisplay* display, Visual* visual) const { |
76 return display == this->display && visual == this->visual; | 76 return display == this->display && visual == this->visual; |
77 } | 77 } |
78 | 78 |
79 Display* display; | 79 XDisplay* display; |
80 Visual* visual; | 80 Visual* visual; |
81 XRenderPictFormat* format; | 81 XRenderPictFormat* format; |
82 }; | 82 }; |
83 | 83 |
84 typedef std::list<CachedPictFormat> CachedPictFormats; | 84 typedef std::list<CachedPictFormat> CachedPictFormats; |
85 | 85 |
86 // Returns the cache of pict formats. | 86 // Returns the cache of pict formats. |
87 CachedPictFormats* get_cached_pict_formats() { | 87 CachedPictFormats* get_cached_pict_formats() { |
88 static CachedPictFormats* formats = NULL; | 88 static CachedPictFormats* formats = NULL; |
89 if (!formats) | 89 if (!formats) |
90 formats = new CachedPictFormats(); | 90 formats = new CachedPictFormats(); |
91 return formats; | 91 return formats; |
92 } | 92 } |
93 | 93 |
94 // Maximum number of CachedPictFormats we keep around. | 94 // Maximum number of CachedPictFormats we keep around. |
95 const size_t kMaxCacheSize = 5; | 95 const size_t kMaxCacheSize = 5; |
96 | 96 |
97 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { | 97 int DefaultX11ErrorHandler(XDisplay* d, XErrorEvent* e) { |
98 if (base::MessageLoop::current()) { | 98 if (base::MessageLoop::current()) { |
99 base::MessageLoop::current()->PostTask( | 99 base::MessageLoop::current()->PostTask( |
100 FROM_HERE, base::Bind(&LogErrorEventDescription, d, *e)); | 100 FROM_HERE, base::Bind(&LogErrorEventDescription, d, *e)); |
101 } else { | 101 } else { |
102 LOG(ERROR) | 102 LOG(ERROR) |
103 << "X error received: " | 103 << "X error received: " |
104 << "serial " << e->serial << ", " | 104 << "serial " << e->serial << ", " |
105 << "error_code " << static_cast<int>(e->error_code) << ", " | 105 << "error_code " << static_cast<int>(e->error_code) << ", " |
106 << "request_code " << static_cast<int>(e->request_code) << ", " | 106 << "request_code " << static_cast<int>(e->request_code) << ", " |
107 << "minor_code " << static_cast<int>(e->minor_code); | 107 << "minor_code " << static_cast<int>(e->minor_code); |
108 } | 108 } |
109 return 0; | 109 return 0; |
110 } | 110 } |
111 | 111 |
112 int DefaultX11IOErrorHandler(Display* d) { | 112 int DefaultX11IOErrorHandler(XDisplay* d) { |
113 // If there's an IO error it likely means the X server has gone away | 113 // If there's an IO error it likely means the X server has gone away |
114 LOG(ERROR) << "X IO error received (X server probably went away)"; | 114 LOG(ERROR) << "X IO error received (X server probably went away)"; |
115 _exit(1); | 115 _exit(1); |
116 } | 116 } |
117 | 117 |
118 // Note: The caller should free the resulting value data. | 118 // Note: The caller should free the resulting value data. |
119 bool GetProperty(XID window, const std::string& property_name, long max_length, | 119 bool GetProperty(XID window, const std::string& property_name, long max_length, |
120 Atom* type, int* format, unsigned long* num_items, | 120 Atom* type, int* format, unsigned long* num_items, |
121 unsigned char** property) { | 121 unsigned char** property) { |
122 Atom property_atom = GetAtom(property_name.c_str()); | 122 Atom property_atom = GetAtom(property_name.c_str()); |
123 unsigned long remaining_bytes = 0; | 123 unsigned long remaining_bytes = 0; |
124 return XGetWindowProperty(GetXDisplay(), | 124 return XGetWindowProperty(gfx::GetXDisplay(), |
125 window, | 125 window, |
126 property_atom, | 126 property_atom, |
127 0, // offset into property data to read | 127 0, // offset into property data to read |
128 max_length, // max length to get | 128 max_length, // max length to get |
129 False, // deleted | 129 False, // deleted |
130 AnyPropertyType, | 130 AnyPropertyType, |
131 type, | 131 type, |
132 format, | 132 format, |
133 num_items, | 133 num_items, |
134 &remaining_bytes, | 134 &remaining_bytes, |
(...skipping 17 matching lines...) Expand all Loading... |
152 case ui::ET_KEY_RELEASED: | 152 case ui::ET_KEY_RELEASED: |
153 return KeyRelease; | 153 return KeyRelease; |
154 default: | 154 default: |
155 return 0; | 155 return 0; |
156 } | 156 } |
157 } | 157 } |
158 | 158 |
159 // Converts KeyboardCode to XKeyEvent keycode. | 159 // Converts KeyboardCode to XKeyEvent keycode. |
160 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code, | 160 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code, |
161 int flags, | 161 int flags, |
162 Display* display) { | 162 XDisplay* display) { |
163 const int keysym = XKeysymForWindowsKeyCode(key_code, | 163 const int keysym = XKeysymForWindowsKeyCode(key_code, |
164 flags & ui::EF_SHIFT_DOWN); | 164 flags & ui::EF_SHIFT_DOWN); |
165 // Tests assume the keycode for XK_less is equal to the one of XK_comma, | 165 // Tests assume the keycode for XK_less is equal to the one of XK_comma, |
166 // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for | 166 // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for |
167 // XK_comma. Here we convert the value for XK_less to the value for XK_comma. | 167 // XK_comma. Here we convert the value for XK_less to the value for XK_comma. |
168 return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym); | 168 return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym); |
169 } | 169 } |
170 | 170 |
171 // A process wide singleton that manages the usage of X cursors. | 171 // A process wide singleton that manages the usage of X cursors. |
172 class XCursorCache { | 172 class XCursorCache { |
173 public: | 173 public: |
174 XCursorCache() {} | 174 XCursorCache() {} |
175 ~XCursorCache() { | 175 ~XCursorCache() { |
176 Clear(); | 176 Clear(); |
177 } | 177 } |
178 | 178 |
179 ::Cursor GetCursor(int cursor_shape) { | 179 ::Cursor GetCursor(int cursor_shape) { |
180 // Lookup cursor by attempting to insert a null value, which avoids | 180 // Lookup cursor by attempting to insert a null value, which avoids |
181 // a second pass through the map after a cache miss. | 181 // a second pass through the map after a cache miss. |
182 std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert( | 182 std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert( |
183 std::make_pair(cursor_shape, 0)); | 183 std::make_pair(cursor_shape, 0)); |
184 if (it.second) { | 184 if (it.second) { |
185 Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); | 185 XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); |
186 it.first->second = XCreateFontCursor(display, cursor_shape); | 186 it.first->second = XCreateFontCursor(display, cursor_shape); |
187 } | 187 } |
188 return it.first->second; | 188 return it.first->second; |
189 } | 189 } |
190 | 190 |
191 void Clear() { | 191 void Clear() { |
192 Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); | 192 XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); |
193 for (std::map<int, ::Cursor>::iterator it = | 193 for (std::map<int, ::Cursor>::iterator it = |
194 cache_.begin(); it != cache_.end(); ++it) { | 194 cache_.begin(); it != cache_.end(); ++it) { |
195 XFreeCursor(display, it->second); | 195 XFreeCursor(display, it->second); |
196 } | 196 } |
197 cache_.clear(); | 197 cache_.clear(); |
198 } | 198 } |
199 | 199 |
200 private: | 200 private: |
201 // Maps X11 font cursor shapes to Cursor IDs. | 201 // Maps X11 font cursor shapes to Cursor IDs. |
202 std::map<int, ::Cursor> cache_; | 202 std::map<int, ::Cursor> cache_; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 | 236 |
237 private: | 237 private: |
238 friend struct DefaultSingletonTraits<XCustomCursorCache>; | 238 friend struct DefaultSingletonTraits<XCustomCursorCache>; |
239 | 239 |
240 class XCustomCursor { | 240 class XCustomCursor { |
241 public: | 241 public: |
242 // This takes ownership of the image. | 242 // This takes ownership of the image. |
243 XCustomCursor(XcursorImage* image) | 243 XCustomCursor(XcursorImage* image) |
244 : image_(image), | 244 : image_(image), |
245 ref_(1) { | 245 ref_(1) { |
246 cursor_ = XcursorImageLoadCursor(GetXDisplay(), image); | 246 cursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image); |
247 } | 247 } |
248 | 248 |
249 ~XCustomCursor() { | 249 ~XCustomCursor() { |
250 XcursorImageDestroy(image_); | 250 XcursorImageDestroy(image_); |
251 XFreeCursor(GetXDisplay(), cursor_); | 251 XFreeCursor(gfx::GetXDisplay(), cursor_); |
252 } | 252 } |
253 | 253 |
254 ::Cursor cursor() const { return cursor_; } | 254 ::Cursor cursor() const { return cursor_; } |
255 | 255 |
256 void Ref() { | 256 void Ref() { |
257 ++ref_; | 257 ++ref_; |
258 } | 258 } |
259 | 259 |
260 // Returns true if the cursor was destroyed because of the unref. | 260 // Returns true if the cursor was destroyed because of the unref. |
261 bool Unref() { | 261 bool Unref() { |
(...skipping 23 matching lines...) Expand all Loading... |
285 #endif // defined(USE_AURA) | 285 #endif // defined(USE_AURA) |
286 | 286 |
287 // A singleton object that remembers remappings of mouse buttons. | 287 // A singleton object that remembers remappings of mouse buttons. |
288 class XButtonMap { | 288 class XButtonMap { |
289 public: | 289 public: |
290 static XButtonMap* GetInstance() { | 290 static XButtonMap* GetInstance() { |
291 return Singleton<XButtonMap>::get(); | 291 return Singleton<XButtonMap>::get(); |
292 } | 292 } |
293 | 293 |
294 void UpdateMapping() { | 294 void UpdateMapping() { |
295 count_ = XGetPointerMapping(ui::GetXDisplay(), map_, arraysize(map_)); | 295 count_ = XGetPointerMapping(gfx::GetXDisplay(), map_, arraysize(map_)); |
296 } | 296 } |
297 | 297 |
298 int GetMappedButton(int button) { | 298 int GetMappedButton(int button) { |
299 return button > 0 && button <= count_ ? map_[button - 1] : button; | 299 return button > 0 && button <= count_ ? map_[button - 1] : button; |
300 } | 300 } |
301 | 301 |
302 private: | 302 private: |
303 friend struct DefaultSingletonTraits<XButtonMap>; | 303 friend struct DefaultSingletonTraits<XButtonMap>; |
304 | 304 |
305 XButtonMap() { | 305 XButtonMap() { |
306 UpdateMapping(); | 306 UpdateMapping(); |
307 } | 307 } |
308 | 308 |
309 ~XButtonMap() {} | 309 ~XButtonMap() {} |
310 | 310 |
311 unsigned char map_[256]; | 311 unsigned char map_[256]; |
312 int count_; | 312 int count_; |
313 | 313 |
314 DISALLOW_COPY_AND_ASSIGN(XButtonMap); | 314 DISALLOW_COPY_AND_ASSIGN(XButtonMap); |
315 }; | 315 }; |
316 | 316 |
317 bool IsShapeAvailable() { | 317 bool IsShapeAvailable() { |
318 int dummy; | 318 int dummy; |
319 static bool is_shape_available = | 319 static bool is_shape_available = |
320 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); | 320 XShapeQueryExtension(gfx::GetXDisplay(), &dummy, &dummy); |
321 return is_shape_available; | 321 return is_shape_available; |
322 | 322 |
323 } | 323 } |
324 | 324 |
325 } // namespace | 325 } // namespace |
326 | 326 |
327 bool XDisplayExists() { | 327 bool XDisplayExists() { |
328 return (GetXDisplay() != NULL); | 328 return (gfx::GetXDisplay() != NULL); |
329 } | 329 } |
330 | 330 |
331 Display* GetXDisplay() { | 331 static SharedMemorySupport DoQuerySharedMemorySupport(XDisplay* dpy) { |
332 return base::MessagePumpForUI::GetDefaultXDisplay(); | |
333 } | |
334 | |
335 static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { | |
336 int dummy; | 332 int dummy; |
337 Bool pixmaps_supported; | 333 Bool pixmaps_supported; |
338 // Query the server's support for XSHM. | 334 // Query the server's support for XSHM. |
339 if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) | 335 if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) |
340 return SHARED_MEMORY_NONE; | 336 return SHARED_MEMORY_NONE; |
341 | 337 |
342 #if defined(OS_FREEBSD) | 338 #if defined(OS_FREEBSD) |
343 // On FreeBSD we can't access the shared memory after it was marked for | 339 // On FreeBSD we can't access the shared memory after it was marked for |
344 // deletion, unless this behaviour is explicitly enabled by the user. | 340 // deletion, unless this behaviour is explicitly enabled by the user. |
345 // In case it's not enabled disable shared memory support. | 341 // In case it's not enabled disable shared memory support. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; | 378 LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; |
383 return SHARED_MEMORY_NONE; | 379 return SHARED_MEMORY_NONE; |
384 } | 380 } |
385 | 381 |
386 VLOG(1) << "X attached to shared memory segment " << shmkey; | 382 VLOG(1) << "X attached to shared memory segment " << shmkey; |
387 | 383 |
388 XShmDetach(dpy, &shminfo); | 384 XShmDetach(dpy, &shminfo); |
389 return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; | 385 return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; |
390 } | 386 } |
391 | 387 |
392 SharedMemorySupport QuerySharedMemorySupport(Display* dpy) { | 388 SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy) { |
393 static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; | 389 static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; |
394 static bool shared_memory_support_cached = false; | 390 static bool shared_memory_support_cached = false; |
395 | 391 |
396 if (shared_memory_support_cached) | 392 if (shared_memory_support_cached) |
397 return shared_memory_support; | 393 return shared_memory_support; |
398 | 394 |
399 shared_memory_support = DoQuerySharedMemorySupport(dpy); | 395 shared_memory_support = DoQuerySharedMemorySupport(dpy); |
400 shared_memory_support_cached = true; | 396 shared_memory_support_cached = true; |
401 | 397 |
402 return shared_memory_support; | 398 return shared_memory_support; |
403 } | 399 } |
404 | 400 |
405 bool QueryRenderSupport(Display* dpy) { | 401 bool QueryRenderSupport(XDisplay* dpy) { |
406 static bool render_supported = false; | 402 static bool render_supported = false; |
407 static bool render_supported_cached = false; | 403 static bool render_supported_cached = false; |
408 | 404 |
409 if (render_supported_cached) | 405 if (render_supported_cached) |
410 return render_supported; | 406 return render_supported; |
411 | 407 |
412 // We don't care about the version of Xrender since all the features which | 408 // We don't care about the version of Xrender since all the features which |
413 // we use are included in every version. | 409 // we use are included in every version. |
414 int dummy; | 410 int dummy; |
415 render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); | 411 render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); |
416 render_supported_cached = true; | 412 render_supported_cached = true; |
417 | 413 |
418 return render_supported; | 414 return render_supported; |
419 } | 415 } |
420 | 416 |
421 int GetDefaultScreen(Display* display) { | 417 int GetDefaultScreen(XDisplay* display) { |
422 return XDefaultScreen(display); | 418 return XDefaultScreen(display); |
423 } | 419 } |
424 | 420 |
425 ::Cursor GetXCursor(int cursor_shape) { | 421 ::Cursor GetXCursor(int cursor_shape) { |
426 if (!cursor_cache) | 422 if (!cursor_cache) |
427 cursor_cache = new XCursorCache; | 423 cursor_cache = new XCursorCache; |
428 return cursor_cache->GetCursor(cursor_shape); | 424 return cursor_cache->GetCursor(cursor_shape); |
429 } | 425 } |
430 | 426 |
431 void ResetXCursorCache() { | 427 void ResetXCursorCache() { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 482 } |
487 | 483 |
488 return image; | 484 return image; |
489 } | 485 } |
490 | 486 |
491 | 487 |
492 int CoalescePendingMotionEvents(const XEvent* xev, | 488 int CoalescePendingMotionEvents(const XEvent* xev, |
493 XEvent* last_event) { | 489 XEvent* last_event) { |
494 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); | 490 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
495 int num_coalesced = 0; | 491 int num_coalesced = 0; |
496 Display* display = xev->xany.display; | 492 XDisplay* display = xev->xany.display; |
497 int event_type = xev->xgeneric.evtype; | 493 int event_type = xev->xgeneric.evtype; |
498 | 494 |
499 DCHECK_EQ(event_type, XI_Motion); | 495 DCHECK_EQ(event_type, XI_Motion); |
500 | 496 |
501 while (XPending(display)) { | 497 while (XPending(display)) { |
502 XEvent next_event; | 498 XEvent next_event; |
503 XPeekEvent(display, &next_event); | 499 XPeekEvent(display, &next_event); |
504 | 500 |
505 // If we can't get the cookie, abort the check. | 501 // If we can't get the cookie, abort the check. |
506 if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) | 502 if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 ui::EventTimeFromNative(const_cast<XEvent*>(xev)); | 552 ui::EventTimeFromNative(const_cast<XEvent*>(xev)); |
557 UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced); | 553 UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced); |
558 UMA_HISTOGRAM_TIMES("Event.CoalescedLatency.Mouse", delta); | 554 UMA_HISTOGRAM_TIMES("Event.CoalescedLatency.Mouse", delta); |
559 } | 555 } |
560 return num_coalesced; | 556 return num_coalesced; |
561 } | 557 } |
562 #endif | 558 #endif |
563 | 559 |
564 void HideHostCursor() { | 560 void HideHostCursor() { |
565 CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, | 561 CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, |
566 (CreateInvisibleCursor(), ui::GetXDisplay())); | 562 (CreateInvisibleCursor(), gfx::GetXDisplay())); |
567 XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()), | 563 XDefineCursor(gfx::GetXDisplay(), DefaultRootWindow(gfx::GetXDisplay()), |
568 invisible_cursor.get()); | 564 invisible_cursor.get()); |
569 } | 565 } |
570 | 566 |
571 ::Cursor CreateInvisibleCursor() { | 567 ::Cursor CreateInvisibleCursor() { |
572 Display* xdisplay = ui::GetXDisplay(); | 568 XDisplay* xdisplay = gfx::GetXDisplay(); |
573 ::Cursor invisible_cursor; | 569 ::Cursor invisible_cursor; |
574 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | 570 char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
575 XColor black; | 571 XColor black; |
576 black.red = black.green = black.blue = 0; | 572 black.red = black.green = black.blue = 0; |
577 Pixmap blank = XCreateBitmapFromData(xdisplay, | 573 Pixmap blank = XCreateBitmapFromData(xdisplay, |
578 DefaultRootWindow(xdisplay), | 574 DefaultRootWindow(xdisplay), |
579 nodata, 8, 8); | 575 nodata, 8, 8); |
580 invisible_cursor = XCreatePixmapCursor(xdisplay, blank, blank, | 576 invisible_cursor = XCreatePixmapCursor(xdisplay, blank, blank, |
581 &black, &black, 0, 0); | 577 &black, &black, 0, 0); |
582 XFreePixmap(xdisplay, blank); | 578 XFreePixmap(xdisplay, blank); |
583 return invisible_cursor; | 579 return invisible_cursor; |
584 } | 580 } |
585 | 581 |
586 XID GetX11RootWindow() { | 582 XID GetX11RootWindow() { |
587 return DefaultRootWindow(GetXDisplay()); | 583 return DefaultRootWindow(gfx::GetXDisplay()); |
588 } | 584 } |
589 | 585 |
590 bool GetCurrentDesktop(int* desktop) { | 586 bool GetCurrentDesktop(int* desktop) { |
591 return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); | 587 return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); |
592 } | 588 } |
593 | 589 |
594 #if defined(TOOLKIT_GTK) | 590 #if defined(TOOLKIT_GTK) |
595 XID GetX11WindowFromGtkWidget(GtkWidget* widget) { | 591 XID GetX11WindowFromGtkWidget(GtkWidget* widget) { |
596 return GDK_WINDOW_XID(gtk_widget_get_window(widget)); | 592 return GDK_WINDOW_XID(gtk_widget_get_window(widget)); |
597 } | 593 } |
(...skipping 16 matching lines...) Expand all Loading... |
614 } | 610 } |
615 | 611 |
616 void* GetVisualFromGtkWidget(GtkWidget* widget) { | 612 void* GetVisualFromGtkWidget(GtkWidget* widget) { |
617 return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); | 613 return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); |
618 } | 614 } |
619 #endif // defined(TOOLKIT_GTK) | 615 #endif // defined(TOOLKIT_GTK) |
620 | 616 |
621 void SetHideTitlebarWhenMaximizedProperty(XID window, | 617 void SetHideTitlebarWhenMaximizedProperty(XID window, |
622 HideTitlebarWhenMaximized property) { | 618 HideTitlebarWhenMaximized property) { |
623 uint32 hide = property; | 619 uint32 hide = property; |
624 XChangeProperty(GetXDisplay(), | 620 XChangeProperty(gfx::GetXDisplay(), |
625 window, | 621 window, |
626 GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), | 622 GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), |
627 XA_CARDINAL, | 623 XA_CARDINAL, |
628 32, // size in bits | 624 32, // size in bits |
629 PropModeReplace, | 625 PropModeReplace, |
630 reinterpret_cast<unsigned char*>(&hide), | 626 reinterpret_cast<unsigned char*>(&hide), |
631 1); | 627 1); |
632 } | 628 } |
633 | 629 |
634 void ClearX11DefaultRootWindow() { | 630 void ClearX11DefaultRootWindow() { |
635 Display* display = GetXDisplay(); | 631 XDisplay* display = gfx::GetXDisplay(); |
636 XID root_window = GetX11RootWindow(); | 632 XID root_window = GetX11RootWindow(); |
637 gfx::Rect root_bounds; | 633 gfx::Rect root_bounds; |
638 if (!GetWindowRect(root_window, &root_bounds)) { | 634 if (!GetWindowRect(root_window, &root_bounds)) { |
639 LOG(ERROR) << "Failed to get the bounds of the X11 root window"; | 635 LOG(ERROR) << "Failed to get the bounds of the X11 root window"; |
640 return; | 636 return; |
641 } | 637 } |
642 | 638 |
643 XGCValues gc_values = {0}; | 639 XGCValues gc_values = {0}; |
644 gc_values.foreground = BlackPixel(display, DefaultScreen(display)); | 640 gc_values.foreground = BlackPixel(display, DefaultScreen(display)); |
645 GC gc = XCreateGC(display, root_window, GCForeground, &gc_values); | 641 GC gc = XCreateGC(display, root_window, GCForeground, &gc_values); |
646 XFillRectangle(display, root_window, gc, | 642 XFillRectangle(display, root_window, gc, |
647 root_bounds.x(), | 643 root_bounds.x(), |
648 root_bounds.y(), | 644 root_bounds.y(), |
649 root_bounds.width(), | 645 root_bounds.width(), |
650 root_bounds.height()); | 646 root_bounds.height()); |
651 XFreeGC(display, gc); | 647 XFreeGC(display, gc); |
652 } | 648 } |
653 | 649 |
654 int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { | 650 int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) { |
655 int count; | 651 int count; |
656 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); | 652 XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); |
657 if (!formats) | 653 if (!formats) |
658 return -1; | 654 return -1; |
659 | 655 |
660 int bits_per_pixel = -1; | 656 int bits_per_pixel = -1; |
661 for (int i = 0; i < count; ++i) { | 657 for (int i = 0; i < count; ++i) { |
662 if (formats[i].depth == depth) { | 658 if (formats[i].depth == depth) { |
663 bits_per_pixel = formats[i].bits_per_pixel; | 659 bits_per_pixel = formats[i].bits_per_pixel; |
664 break; | 660 break; |
665 } | 661 } |
666 } | 662 } |
667 | 663 |
668 XFree(formats); | 664 XFree(formats); |
669 return bits_per_pixel; | 665 return bits_per_pixel; |
670 } | 666 } |
671 | 667 |
672 bool IsWindowVisible(XID window) { | 668 bool IsWindowVisible(XID window) { |
673 XWindowAttributes win_attributes; | 669 XWindowAttributes win_attributes; |
674 if (!XGetWindowAttributes(GetXDisplay(), window, &win_attributes)) | 670 if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes)) |
675 return false; | 671 return false; |
676 if (win_attributes.map_state != IsViewable) | 672 if (win_attributes.map_state != IsViewable) |
677 return false; | 673 return false; |
678 // Some compositing window managers (notably kwin) do not actually unmap | 674 // Some compositing window managers (notably kwin) do not actually unmap |
679 // windows on desktop switch, so we also must check the current desktop. | 675 // windows on desktop switch, so we also must check the current desktop. |
680 int window_desktop, current_desktop; | 676 int window_desktop, current_desktop; |
681 return (!GetWindowDesktop(window, &window_desktop) || | 677 return (!GetWindowDesktop(window, &window_desktop) || |
682 !GetCurrentDesktop(¤t_desktop) || | 678 !GetCurrentDesktop(¤t_desktop) || |
683 window_desktop == kAllDesktops || | 679 window_desktop == kAllDesktops || |
684 window_desktop == current_desktop); | 680 window_desktop == current_desktop); |
685 } | 681 } |
686 | 682 |
687 bool GetWindowRect(XID window, gfx::Rect* rect) { | 683 bool GetWindowRect(XID window, gfx::Rect* rect) { |
688 Window root, child; | 684 Window root, child; |
689 int x, y; | 685 int x, y; |
690 unsigned int width, height; | 686 unsigned int width, height; |
691 unsigned int border_width, depth; | 687 unsigned int border_width, depth; |
692 | 688 |
693 if (!XGetGeometry(GetXDisplay(), window, &root, &x, &y, | 689 if (!XGetGeometry(gfx::GetXDisplay(), window, &root, &x, &y, |
694 &width, &height, &border_width, &depth)) | 690 &width, &height, &border_width, &depth)) |
695 return false; | 691 return false; |
696 | 692 |
697 if (!XTranslateCoordinates(GetXDisplay(), window, root, | 693 if (!XTranslateCoordinates(gfx::GetXDisplay(), window, root, |
698 0, 0, &x, &y, &child)) | 694 0, 0, &x, &y, &child)) |
699 return false; | 695 return false; |
700 | 696 |
701 *rect = gfx::Rect(x, y, width, height); | 697 *rect = gfx::Rect(x, y, width, height); |
702 return true; | 698 return true; |
703 } | 699 } |
704 | 700 |
705 | 701 |
706 bool WindowContainsPoint(XID window, gfx::Point screen_loc) { | 702 bool WindowContainsPoint(XID window, gfx::Point screen_loc) { |
707 gfx::Rect window_rect; | 703 gfx::Rect window_rect; |
708 if (!GetWindowRect(window, &window_rect)) | 704 if (!GetWindowRect(window, &window_rect)) |
709 return false; | 705 return false; |
710 | 706 |
711 if (!window_rect.Contains(screen_loc)) | 707 if (!window_rect.Contains(screen_loc)) |
712 return false; | 708 return false; |
713 | 709 |
714 if (!IsShapeAvailable()) | 710 if (!IsShapeAvailable()) |
715 return true; | 711 return true; |
716 | 712 |
717 // According to http://www.x.org/releases/X11R7.6/doc/libXext/shapelib.html, | 713 // According to http://www.x.org/releases/X11R7.6/doc/libXext/shapelib.html, |
718 // if an X display supports the shape extension the bounds of a window are | 714 // if an X display supports the shape extension the bounds of a window are |
719 // defined as the intersection of the window bounds and the interior | 715 // defined as the intersection of the window bounds and the interior |
720 // rectangles. This means to determine if a point is inside a window for the | 716 // rectangles. This means to determine if a point is inside a window for the |
721 // purpose of input handling we have to check the rectangles in the ShapeInput | 717 // purpose of input handling we have to check the rectangles in the ShapeInput |
722 // list. | 718 // list. |
723 int dummy; | 719 int dummy; |
724 int input_rects_size = 0; | 720 int input_rects_size = 0; |
725 XRectangle* input_rects = XShapeGetRectangles( | 721 XRectangle* input_rects = XShapeGetRectangles( |
726 ui::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); | 722 gfx::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); |
727 if (!input_rects) | 723 if (!input_rects) |
728 return true; | 724 return true; |
729 bool is_in_input_rects = false; | 725 bool is_in_input_rects = false; |
730 for (int i = 0; i < input_rects_size; ++i) { | 726 for (int i = 0; i < input_rects_size; ++i) { |
731 // The ShapeInput rects appear to be in window space, so we have to | 727 // The ShapeInput rects appear to be in window space, so we have to |
732 // translate by the window_rect's offset to map to screen space. | 728 // translate by the window_rect's offset to map to screen space. |
733 gfx::Rect input_rect = | 729 gfx::Rect input_rect = |
734 gfx::Rect(input_rects[i].x + window_rect.x(), | 730 gfx::Rect(input_rects[i].x + window_rect.x(), |
735 input_rects[i].y + window_rect.y(), | 731 input_rects[i].y + window_rect.y(), |
736 input_rects[i].width, input_rects[i].height); | 732 input_rects[i].width, input_rects[i].height); |
(...skipping 27 matching lines...) Expand all Loading... |
764 scoped_refptr<base::RefCountedMemory>* out_data, | 760 scoped_refptr<base::RefCountedMemory>* out_data, |
765 size_t* out_data_bytes, | 761 size_t* out_data_bytes, |
766 size_t* out_data_items, | 762 size_t* out_data_items, |
767 Atom* out_type) { | 763 Atom* out_type) { |
768 // Retrieve the data from our window. | 764 // Retrieve the data from our window. |
769 unsigned long nitems = 0; | 765 unsigned long nitems = 0; |
770 unsigned long nbytes = 0; | 766 unsigned long nbytes = 0; |
771 Atom prop_type = None; | 767 Atom prop_type = None; |
772 int prop_format = 0; | 768 int prop_format = 0; |
773 unsigned char* property_data = NULL; | 769 unsigned char* property_data = NULL; |
774 if (XGetWindowProperty(GetXDisplay(), window, property, | 770 if (XGetWindowProperty(gfx::GetXDisplay(), window, property, |
775 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, | 771 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, |
776 AnyPropertyType, &prop_type, &prop_format, | 772 AnyPropertyType, &prop_type, &prop_format, |
777 &nitems, &nbytes, &property_data) != Success) { | 773 &nitems, &nbytes, &property_data) != Success) { |
778 return false; | 774 return false; |
779 } | 775 } |
780 | 776 |
781 if (prop_type == None) | 777 if (prop_type == None) |
782 return false; | 778 return false; |
783 | 779 |
784 size_t bytes = 0; | 780 size_t bytes = 0; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 DCHECK(!value.empty()); | 946 DCHECK(!value.empty()); |
951 Atom name_atom = GetAtom(name.c_str()); | 947 Atom name_atom = GetAtom(name.c_str()); |
952 Atom type_atom = GetAtom(type.c_str()); | 948 Atom type_atom = GetAtom(type.c_str()); |
953 | 949 |
954 // XChangeProperty() expects values of type 32 to be longs. | 950 // XChangeProperty() expects values of type 32 to be longs. |
955 scoped_ptr<long[]> data(new long[value.size()]); | 951 scoped_ptr<long[]> data(new long[value.size()]); |
956 for (size_t i = 0; i < value.size(); ++i) | 952 for (size_t i = 0; i < value.size(); ++i) |
957 data[i] = value[i]; | 953 data[i] = value[i]; |
958 | 954 |
959 X11ErrorTracker err_tracker; | 955 X11ErrorTracker err_tracker; |
960 XChangeProperty(ui::GetXDisplay(), | 956 XChangeProperty(gfx::GetXDisplay(), |
961 window, | 957 window, |
962 name_atom, | 958 name_atom, |
963 type_atom, | 959 type_atom, |
964 32, // size in bits of items in 'value' | 960 32, // size in bits of items in 'value' |
965 PropModeReplace, | 961 PropModeReplace, |
966 reinterpret_cast<const unsigned char*>(data.get()), | 962 reinterpret_cast<const unsigned char*>(data.get()), |
967 value.size()); // num items | 963 value.size()); // num items |
968 return !err_tracker.FoundNewError(); | 964 return !err_tracker.FoundNewError(); |
969 } | 965 } |
970 | 966 |
971 bool SetAtomArrayProperty(XID window, | 967 bool SetAtomArrayProperty(XID window, |
972 const std::string& name, | 968 const std::string& name, |
973 const std::string& type, | 969 const std::string& type, |
974 const std::vector<Atom>& value) { | 970 const std::vector<Atom>& value) { |
975 DCHECK(!value.empty()); | 971 DCHECK(!value.empty()); |
976 Atom name_atom = GetAtom(name.c_str()); | 972 Atom name_atom = GetAtom(name.c_str()); |
977 Atom type_atom = GetAtom(type.c_str()); | 973 Atom type_atom = GetAtom(type.c_str()); |
978 | 974 |
979 // XChangeProperty() expects values of type 32 to be longs. | 975 // XChangeProperty() expects values of type 32 to be longs. |
980 scoped_ptr<Atom[]> data(new Atom[value.size()]); | 976 scoped_ptr<Atom[]> data(new Atom[value.size()]); |
981 for (size_t i = 0; i < value.size(); ++i) | 977 for (size_t i = 0; i < value.size(); ++i) |
982 data[i] = value[i]; | 978 data[i] = value[i]; |
983 | 979 |
984 X11ErrorTracker err_tracker; | 980 X11ErrorTracker err_tracker; |
985 XChangeProperty(ui::GetXDisplay(), | 981 XChangeProperty(gfx::GetXDisplay(), |
986 window, | 982 window, |
987 name_atom, | 983 name_atom, |
988 type_atom, | 984 type_atom, |
989 32, // size in bits of items in 'value' | 985 32, // size in bits of items in 'value' |
990 PropModeReplace, | 986 PropModeReplace, |
991 reinterpret_cast<const unsigned char*>(data.get()), | 987 reinterpret_cast<const unsigned char*>(data.get()), |
992 value.size()); // num items | 988 value.size()); // num items |
993 return !err_tracker.FoundNewError(); | 989 return !err_tracker.FoundNewError(); |
994 } | 990 } |
995 | 991 |
996 Atom GetAtom(const char* name) { | 992 Atom GetAtom(const char* name) { |
997 #if defined(TOOLKIT_GTK) | 993 #if defined(TOOLKIT_GTK) |
998 return gdk_x11_get_xatom_by_name_for_display( | 994 return gdk_x11_get_xatom_by_name_for_display( |
999 gdk_display_get_default(), name); | 995 gdk_display_get_default(), name); |
1000 #else | 996 #else |
1001 // TODO(derat): Cache atoms to avoid round-trips to the server. | 997 // TODO(derat): Cache atoms to avoid round-trips to the server. |
1002 return XInternAtom(GetXDisplay(), name, false); | 998 return XInternAtom(gfx::GetXDisplay(), name, false); |
1003 #endif | 999 #endif |
1004 } | 1000 } |
1005 | 1001 |
1006 void SetWindowClassHint(Display* display, | 1002 void SetWindowClassHint(XDisplay* display, |
1007 XID window, | 1003 XID window, |
1008 std::string res_name, | 1004 std::string res_name, |
1009 std::string res_class) { | 1005 std::string res_class) { |
1010 XClassHint class_hints; | 1006 XClassHint class_hints; |
1011 // const_cast is safe because XSetClassHint does not modify the strings. | 1007 // const_cast is safe because XSetClassHint does not modify the strings. |
1012 // Just to be safe, the res_name and res_class parameters are local copies, | 1008 // Just to be safe, the res_name and res_class parameters are local copies, |
1013 // not const references. | 1009 // not const references. |
1014 class_hints.res_name = const_cast<char*>(res_name.c_str()); | 1010 class_hints.res_name = const_cast<char*>(res_name.c_str()); |
1015 class_hints.res_class = const_cast<char*>(res_class.c_str()); | 1011 class_hints.res_class = const_cast<char*>(res_class.c_str()); |
1016 XSetClassHint(display, window, &class_hints); | 1012 XSetClassHint(display, window, &class_hints); |
1017 } | 1013 } |
1018 | 1014 |
1019 XID GetParentWindow(XID window) { | 1015 XID GetParentWindow(XID window) { |
1020 XID root = None; | 1016 XID root = None; |
1021 XID parent = None; | 1017 XID parent = None; |
1022 XID* children = NULL; | 1018 XID* children = NULL; |
1023 unsigned int num_children = 0; | 1019 unsigned int num_children = 0; |
1024 XQueryTree(GetXDisplay(), window, &root, &parent, &children, &num_children); | 1020 XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, &num_childre
n); |
1025 if (children) | 1021 if (children) |
1026 XFree(children); | 1022 XFree(children); |
1027 return parent; | 1023 return parent; |
1028 } | 1024 } |
1029 | 1025 |
1030 XID GetHighestAncestorWindow(XID window, XID root) { | 1026 XID GetHighestAncestorWindow(XID window, XID root) { |
1031 while (true) { | 1027 while (true) { |
1032 XID parent = GetParentWindow(window); | 1028 XID parent = GetParentWindow(window); |
1033 if (parent == None) | 1029 if (parent == None) |
1034 return None; | 1030 return None; |
1035 if (parent == root) | 1031 if (parent == root) |
1036 return window; | 1032 return window; |
1037 window = parent; | 1033 window = parent; |
1038 } | 1034 } |
1039 } | 1035 } |
1040 | 1036 |
1041 bool GetWindowDesktop(XID window, int* desktop) { | 1037 bool GetWindowDesktop(XID window, int* desktop) { |
1042 return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); | 1038 return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); |
1043 } | 1039 } |
1044 | 1040 |
1045 std::string GetX11ErrorString(Display* display, int err) { | 1041 std::string GetX11ErrorString(XDisplay* display, int err) { |
1046 char buffer[256]; | 1042 char buffer[256]; |
1047 XGetErrorText(display, err, buffer, arraysize(buffer)); | 1043 XGetErrorText(display, err, buffer, arraysize(buffer)); |
1048 return buffer; | 1044 return buffer; |
1049 } | 1045 } |
1050 | 1046 |
1051 // Returns true if |window| is a named window. | 1047 // Returns true if |window| is a named window. |
1052 bool IsWindowNamed(XID window) { | 1048 bool IsWindowNamed(XID window) { |
1053 XTextProperty prop; | 1049 XTextProperty prop; |
1054 if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) | 1050 if (!XGetWMName(gfx::GetXDisplay(), window, &prop) || !prop.value) |
1055 return false; | 1051 return false; |
1056 | 1052 |
1057 XFree(prop.value); | 1053 XFree(prop.value); |
1058 return true; | 1054 return true; |
1059 } | 1055 } |
1060 | 1056 |
1061 bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, | 1057 bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, |
1062 const int max_depth, int depth) { | 1058 const int max_depth, int depth) { |
1063 if (depth > max_depth) | 1059 if (depth > max_depth) |
1064 return false; | 1060 return false; |
1065 | 1061 |
1066 XID root, parent, *children; | 1062 XID root, parent, *children; |
1067 unsigned int num_children; | 1063 unsigned int num_children; |
1068 int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, | 1064 int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, |
1069 &num_children); | 1065 &num_children); |
1070 if (status == 0) | 1066 if (status == 0) |
1071 return false; | 1067 return false; |
1072 | 1068 |
1073 std::vector<XID> windows; | 1069 std::vector<XID> windows; |
1074 for (int i = static_cast<int>(num_children) - 1; i >= 0; i--) | 1070 for (int i = static_cast<int>(num_children) - 1; i >= 0; i--) |
1075 windows.push_back(children[i]); | 1071 windows.push_back(children[i]); |
1076 | 1072 |
1077 XFree(children); | 1073 XFree(children); |
1078 | 1074 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 if (data) | 1146 if (data) |
1151 XFree(data); | 1147 XFree(data); |
1152 | 1148 |
1153 return result; | 1149 return result; |
1154 } | 1150 } |
1155 | 1151 |
1156 void RestackWindow(XID window, XID sibling, bool above) { | 1152 void RestackWindow(XID window, XID sibling, bool above) { |
1157 XWindowChanges changes; | 1153 XWindowChanges changes; |
1158 changes.sibling = sibling; | 1154 changes.sibling = sibling; |
1159 changes.stack_mode = above ? Above : Below; | 1155 changes.stack_mode = above ? Above : Below; |
1160 XConfigureWindow(GetXDisplay(), window, CWSibling | CWStackMode, &changes); | 1156 XConfigureWindow(gfx::GetXDisplay(), window, CWSibling | CWStackMode, &changes
); |
1161 } | 1157 } |
1162 | 1158 |
1163 XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) { | 1159 XSharedMemoryId AttachSharedMemory(XDisplay* display, int shared_memory_key) { |
1164 DCHECK(QuerySharedMemorySupport(display)); | 1160 DCHECK(QuerySharedMemorySupport(display)); |
1165 | 1161 |
1166 XShmSegmentInfo shminfo; | 1162 XShmSegmentInfo shminfo; |
1167 memset(&shminfo, 0, sizeof(shminfo)); | 1163 memset(&shminfo, 0, sizeof(shminfo)); |
1168 shminfo.shmid = shared_memory_key; | 1164 shminfo.shmid = shared_memory_key; |
1169 | 1165 |
1170 // This function is only called if QuerySharedMemorySupport returned true. In | 1166 // This function is only called if QuerySharedMemorySupport returned true. In |
1171 // which case we've already succeeded in having the X server attach to one of | 1167 // which case we've already succeeded in having the X server attach to one of |
1172 // our shared memory segments. | 1168 // our shared memory segments. |
1173 if (!XShmAttach(display, &shminfo)) { | 1169 if (!XShmAttach(display, &shminfo)) { |
1174 LOG(WARNING) << "X failed to attach to shared memory segment " | 1170 LOG(WARNING) << "X failed to attach to shared memory segment " |
1175 << shminfo.shmid; | 1171 << shminfo.shmid; |
1176 NOTREACHED(); | 1172 NOTREACHED(); |
1177 } else { | 1173 } else { |
1178 VLOG(1) << "X attached to shared memory segment " << shminfo.shmid; | 1174 VLOG(1) << "X attached to shared memory segment " << shminfo.shmid; |
1179 } | 1175 } |
1180 | 1176 |
1181 return shminfo.shmseg; | 1177 return shminfo.shmseg; |
1182 } | 1178 } |
1183 | 1179 |
1184 void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) { | 1180 void DetachSharedMemory(XDisplay* display, XSharedMemoryId shmseg) { |
1185 DCHECK(QuerySharedMemorySupport(display)); | 1181 DCHECK(QuerySharedMemorySupport(display)); |
1186 | 1182 |
1187 XShmSegmentInfo shminfo; | 1183 XShmSegmentInfo shminfo; |
1188 memset(&shminfo, 0, sizeof(shminfo)); | 1184 memset(&shminfo, 0, sizeof(shminfo)); |
1189 shminfo.shmseg = shmseg; | 1185 shminfo.shmseg = shmseg; |
1190 | 1186 |
1191 if (!XShmDetach(display, &shminfo)) | 1187 if (!XShmDetach(display, &shminfo)) |
1192 NOTREACHED(); | 1188 NOTREACHED(); |
1193 } | 1189 } |
1194 | 1190 |
1195 bool CopyAreaToCanvas(XID drawable, | 1191 bool CopyAreaToCanvas(XID drawable, |
1196 gfx::Rect source_bounds, | 1192 gfx::Rect source_bounds, |
1197 gfx::Point dest_offset, | 1193 gfx::Point dest_offset, |
1198 gfx::Canvas* canvas) { | 1194 gfx::Canvas* canvas) { |
1199 ui::XScopedImage scoped_image( | 1195 ui::XScopedImage scoped_image( |
1200 XGetImage(GetXDisplay(), drawable, | 1196 XGetImage(gfx::GetXDisplay(), drawable, |
1201 source_bounds.x(), source_bounds.y(), | 1197 source_bounds.x(), source_bounds.y(), |
1202 source_bounds.width(), source_bounds.height(), | 1198 source_bounds.width(), source_bounds.height(), |
1203 AllPlanes, ZPixmap)); | 1199 AllPlanes, ZPixmap)); |
1204 XImage* image = scoped_image.get(); | 1200 XImage* image = scoped_image.get(); |
1205 if (!image) { | 1201 if (!image) { |
1206 LOG(ERROR) << "XGetImage failed"; | 1202 LOG(ERROR) << "XGetImage failed"; |
1207 return false; | 1203 return false; |
1208 } | 1204 } |
1209 | 1205 |
1210 if (image->bits_per_pixel == 32) { | 1206 if (image->bits_per_pixel == 32) { |
(...skipping 23 matching lines...) Expand all Loading... |
1234 image_skia.AddRepresentation(image_rep); | 1230 image_skia.AddRepresentation(image_rep); |
1235 canvas->DrawImageInt(image_skia, dest_offset.x(), dest_offset.y()); | 1231 canvas->DrawImageInt(image_skia, dest_offset.x(), dest_offset.y()); |
1236 } else { | 1232 } else { |
1237 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; | 1233 NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; |
1238 return false; | 1234 return false; |
1239 } | 1235 } |
1240 | 1236 |
1241 return true; | 1237 return true; |
1242 } | 1238 } |
1243 | 1239 |
1244 XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { | 1240 XID CreatePictureFromSkiaPixmap(XDisplay* display, XID pixmap) { |
1245 XID picture = XRenderCreatePicture( | 1241 XID picture = XRenderCreatePicture( |
1246 display, pixmap, GetRenderARGB32Format(display), 0, NULL); | 1242 display, pixmap, GetRenderARGB32Format(display), 0, NULL); |
1247 | 1243 |
1248 return picture; | 1244 return picture; |
1249 } | 1245 } |
1250 | 1246 |
1251 void PutARGBImage(Display* display, | 1247 void PutARGBImage(XDisplay* display, |
1252 void* visual, int depth, | 1248 void* visual, int depth, |
1253 XID pixmap, void* pixmap_gc, | 1249 XID pixmap, void* pixmap_gc, |
1254 const uint8* data, | 1250 const uint8* data, |
1255 int width, int height) { | 1251 int width, int height) { |
1256 PutARGBImage(display, | 1252 PutARGBImage(display, |
1257 visual, depth, | 1253 visual, depth, |
1258 pixmap, pixmap_gc, | 1254 pixmap, pixmap_gc, |
1259 data, width, height, | 1255 data, width, height, |
1260 0, 0, // src_x, src_y | 1256 0, 0, // src_x, src_y |
1261 0, 0, // dst_x, dst_y | 1257 0, 0, // dst_x, dst_y |
1262 width, height); | 1258 width, height); |
1263 } | 1259 } |
1264 | 1260 |
1265 void PutARGBImage(Display* display, | 1261 void PutARGBImage(XDisplay* display, |
1266 void* visual, int depth, | 1262 void* visual, int depth, |
1267 XID pixmap, void* pixmap_gc, | 1263 XID pixmap, void* pixmap_gc, |
1268 const uint8* data, | 1264 const uint8* data, |
1269 int data_width, int data_height, | 1265 int data_width, int data_height, |
1270 int src_x, int src_y, | 1266 int src_x, int src_y, |
1271 int dst_x, int dst_y, | 1267 int dst_x, int dst_y, |
1272 int copy_width, int copy_height) { | 1268 int copy_width, int copy_height) { |
1273 // TODO(scherkus): potential performance impact... consider passing in as a | 1269 // TODO(scherkus): potential performance impact... consider passing in as a |
1274 // parameter. | 1270 // parameter. |
1275 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth); | 1271 int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1360 src_x, src_y, dst_x, dst_y, | 1356 src_x, src_y, dst_x, dst_y, |
1361 copy_width, copy_height); | 1357 copy_width, copy_height); |
1362 free(orig_bitmap16); | 1358 free(orig_bitmap16); |
1363 } else { | 1359 } else { |
1364 LOG(FATAL) << "Sorry, we don't support your visual depth without " | 1360 LOG(FATAL) << "Sorry, we don't support your visual depth without " |
1365 "Xrender support (depth:" << depth | 1361 "Xrender support (depth:" << depth |
1366 << " bpp:" << pixmap_bpp << ")"; | 1362 << " bpp:" << pixmap_bpp << ")"; |
1367 } | 1363 } |
1368 } | 1364 } |
1369 | 1365 |
1370 void FreePicture(Display* display, XID picture) { | 1366 void FreePicture(XDisplay* display, XID picture) { |
1371 XRenderFreePicture(display, picture); | 1367 XRenderFreePicture(display, picture); |
1372 } | 1368 } |
1373 | 1369 |
1374 void FreePixmap(Display* display, XID pixmap) { | 1370 void FreePixmap(XDisplay* display, XID pixmap) { |
1375 XFreePixmap(display, pixmap); | 1371 XFreePixmap(display, pixmap); |
1376 } | 1372 } |
1377 | 1373 |
1378 bool GetWindowManagerName(std::string* wm_name) { | 1374 bool GetWindowManagerName(std::string* wm_name) { |
1379 DCHECK(wm_name); | 1375 DCHECK(wm_name); |
1380 int wm_window = 0; | 1376 int wm_window = 0; |
1381 if (!GetIntProperty(GetX11RootWindow(), | 1377 if (!GetIntProperty(GetX11RootWindow(), |
1382 "_NET_SUPPORTING_WM_CHECK", | 1378 "_NET_SUPPORTING_WM_CHECK", |
1383 &wm_window)) { | 1379 &wm_window)) { |
1384 return false; | 1380 return false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 return false; | 1446 return false; |
1451 | 1447 |
1452 XEvent event; | 1448 XEvent event; |
1453 event.xclient.type = ClientMessage; | 1449 event.xclient.type = ClientMessage; |
1454 event.xclient.window = window; | 1450 event.xclient.window = window; |
1455 event.xclient.message_type = GetAtom("_NET_WM_DESKTOP"); | 1451 event.xclient.message_type = GetAtom("_NET_WM_DESKTOP"); |
1456 event.xclient.format = 32; | 1452 event.xclient.format = 32; |
1457 event.xclient.data.l[0] = desktop; | 1453 event.xclient.data.l[0] = desktop; |
1458 event.xclient.data.l[1] = 1; // source indication | 1454 event.xclient.data.l[1] = 1; // source indication |
1459 | 1455 |
1460 int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, | 1456 int result = XSendEvent(gfx::GetXDisplay(), GetX11RootWindow(), False, |
1461 SubstructureNotifyMask, &event); | 1457 SubstructureNotifyMask, &event); |
1462 return result == Success; | 1458 return result == Success; |
1463 } | 1459 } |
1464 | 1460 |
1465 void SetDefaultX11ErrorHandlers() { | 1461 void SetDefaultX11ErrorHandlers() { |
1466 SetX11ErrorHandlers(NULL, NULL); | 1462 SetX11ErrorHandlers(NULL, NULL); |
1467 } | 1463 } |
1468 | 1464 |
1469 bool IsX11WindowFullScreen(XID window) { | 1465 bool IsX11WindowFullScreen(XID window) { |
1470 // If _NET_WM_STATE_FULLSCREEN is in _NET_SUPPORTED, use the presence or | 1466 // If _NET_WM_STATE_FULLSCREEN is in _NET_SUPPORTED, use the presence or |
(...skipping 30 matching lines...) Expand all Loading... |
1501 return monitor_rect.x == window_rect.x() && | 1497 return monitor_rect.x == window_rect.x() && |
1502 monitor_rect.y == window_rect.y() && | 1498 monitor_rect.y == window_rect.y() && |
1503 monitor_rect.width == window_rect.width() && | 1499 monitor_rect.width == window_rect.width() && |
1504 monitor_rect.height == window_rect.height(); | 1500 monitor_rect.height == window_rect.height(); |
1505 #else | 1501 #else |
1506 // We can't use gfx::Screen here because we don't have an aura::Window. So | 1502 // We can't use gfx::Screen here because we don't have an aura::Window. So |
1507 // instead just look at the size of the default display. | 1503 // instead just look at the size of the default display. |
1508 // | 1504 // |
1509 // TODO(erg): Actually doing this correctly would require pulling out xrandr, | 1505 // TODO(erg): Actually doing this correctly would require pulling out xrandr, |
1510 // which we don't even do in the desktop screen yet. | 1506 // which we don't even do in the desktop screen yet. |
1511 ::Display* display = ui::GetXDisplay(); | 1507 ::XDisplay* display = gfx::GetXDisplay(); |
1512 ::Screen* screen = DefaultScreenOfDisplay(display); | 1508 ::Screen* screen = DefaultScreenOfDisplay(display); |
1513 int width = WidthOfScreen(screen); | 1509 int width = WidthOfScreen(screen); |
1514 int height = HeightOfScreen(screen); | 1510 int height = HeightOfScreen(screen); |
1515 return window_rect.size() == gfx::Size(width, height); | 1511 return window_rect.size() == gfx::Size(width, height); |
1516 #endif | 1512 #endif |
1517 } | 1513 } |
1518 | 1514 |
1519 bool IsMotionEvent(XEvent* event) { | 1515 bool IsMotionEvent(XEvent* event) { |
1520 int type = event->type; | 1516 int type = event->type; |
1521 if (type == GenericEvent) | 1517 if (type == GenericEvent) |
1522 type = event->xgeneric.evtype; | 1518 type = event->xgeneric.evtype; |
1523 return type == MotionNotify; | 1519 return type == MotionNotify; |
1524 } | 1520 } |
1525 | 1521 |
1526 int GetMappedButton(int button) { | 1522 int GetMappedButton(int button) { |
1527 return XButtonMap::GetInstance()->GetMappedButton(button); | 1523 return XButtonMap::GetInstance()->GetMappedButton(button); |
1528 } | 1524 } |
1529 | 1525 |
1530 void UpdateButtonMap() { | 1526 void UpdateButtonMap() { |
1531 XButtonMap::GetInstance()->UpdateMapping(); | 1527 XButtonMap::GetInstance()->UpdateMapping(); |
1532 } | 1528 } |
1533 | 1529 |
1534 void InitXKeyEventForTesting(EventType type, | 1530 void InitXKeyEventForTesting(EventType type, |
1535 KeyboardCode key_code, | 1531 KeyboardCode key_code, |
1536 int flags, | 1532 int flags, |
1537 XEvent* event) { | 1533 XEvent* event) { |
1538 CHECK(event); | 1534 CHECK(event); |
1539 Display* display = GetXDisplay(); | 1535 XDisplay* display = gfx::GetXDisplay(); |
1540 XKeyEvent key_event; | 1536 XKeyEvent key_event; |
1541 key_event.type = XKeyEventType(type); | 1537 key_event.type = XKeyEventType(type); |
1542 CHECK_NE(0, key_event.type); | 1538 CHECK_NE(0, key_event.type); |
1543 key_event.serial = 0; | 1539 key_event.serial = 0; |
1544 key_event.send_event = 0; | 1540 key_event.send_event = 0; |
1545 key_event.display = display; | 1541 key_event.display = display; |
1546 key_event.time = 0; | 1542 key_event.time = 0; |
1547 key_event.window = 0; | 1543 key_event.window = 0; |
1548 key_event.root = 0; | 1544 key_event.root = 0; |
1549 key_event.subwindow = 0; | 1545 key_event.subwindow = 0; |
(...skipping 29 matching lines...) Expand all Loading... |
1579 } | 1575 } |
1580 | 1576 |
1581 void XScopedImage::reset(XImage* image) { | 1577 void XScopedImage::reset(XImage* image) { |
1582 if (image_ == image) | 1578 if (image_ == image) |
1583 return; | 1579 return; |
1584 if (image_) | 1580 if (image_) |
1585 XDestroyImage(image_); | 1581 XDestroyImage(image_); |
1586 image_ = image; | 1582 image_ = image; |
1587 } | 1583 } |
1588 | 1584 |
1589 XScopedCursor::XScopedCursor(::Cursor cursor, Display* display) | 1585 XScopedCursor::XScopedCursor(::Cursor cursor, XDisplay* display) |
1590 : cursor_(cursor), | 1586 : cursor_(cursor), |
1591 display_(display) { | 1587 display_(display) { |
1592 } | 1588 } |
1593 | 1589 |
1594 XScopedCursor::~XScopedCursor() { | 1590 XScopedCursor::~XScopedCursor() { |
1595 reset(0U); | 1591 reset(0U); |
1596 } | 1592 } |
1597 | 1593 |
1598 ::Cursor XScopedCursor::get() const { | 1594 ::Cursor XScopedCursor::get() const { |
1599 return cursor_; | 1595 return cursor_; |
1600 } | 1596 } |
1601 | 1597 |
1602 void XScopedCursor::reset(::Cursor cursor) { | 1598 void XScopedCursor::reset(::Cursor cursor) { |
1603 if (cursor_) | 1599 if (cursor_) |
1604 XFreeCursor(display_, cursor_); | 1600 XFreeCursor(display_, cursor_); |
1605 cursor_ = cursor; | 1601 cursor_ = cursor; |
1606 } | 1602 } |
1607 | 1603 |
1608 // ---------------------------------------------------------------------------- | 1604 // ---------------------------------------------------------------------------- |
1609 // These functions are declared in x11_util_internal.h because they require | 1605 // These functions are declared in x11_util_internal.h because they require |
1610 // XLib.h to be included, and it conflicts with many other headers. | 1606 // XLib.h to be included, and it conflicts with many other headers. |
1611 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { | 1607 XRenderPictFormat* GetRenderARGB32Format(XDisplay* dpy) { |
1612 static XRenderPictFormat* pictformat = NULL; | 1608 static XRenderPictFormat* pictformat = NULL; |
1613 if (pictformat) | 1609 if (pictformat) |
1614 return pictformat; | 1610 return pictformat; |
1615 | 1611 |
1616 // First look for a 32-bit format which ignores the alpha value | 1612 // First look for a 32-bit format which ignores the alpha value |
1617 XRenderPictFormat templ; | 1613 XRenderPictFormat templ; |
1618 templ.depth = 32; | 1614 templ.depth = 32; |
1619 templ.type = PictTypeDirect; | 1615 templ.type = PictTypeDirect; |
1620 templ.direct.red = 16; | 1616 templ.direct.red = 16; |
1621 templ.direct.green = 8; | 1617 templ.direct.green = 8; |
(...skipping 15 matching lines...) Expand all Loading... |
1637 if (!pictformat) { | 1633 if (!pictformat) { |
1638 // Not all X servers support xRGB32 formats. However, the XRENDER spec says | 1634 // Not all X servers support xRGB32 formats. However, the XRENDER spec says |
1639 // that they must support an ARGB32 format, so we can always return that. | 1635 // that they must support an ARGB32 format, so we can always return that. |
1640 pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32); | 1636 pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32); |
1641 CHECK(pictformat) << "XRENDER ARGB32 not supported."; | 1637 CHECK(pictformat) << "XRENDER ARGB32 not supported."; |
1642 } | 1638 } |
1643 | 1639 |
1644 return pictformat; | 1640 return pictformat; |
1645 } | 1641 } |
1646 | 1642 |
1647 XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { | 1643 XRenderPictFormat* GetRenderVisualFormat(XDisplay* dpy, Visual* visual) { |
1648 DCHECK(QueryRenderSupport(dpy)); | 1644 DCHECK(QueryRenderSupport(dpy)); |
1649 | 1645 |
1650 CachedPictFormats* formats = get_cached_pict_formats(); | 1646 CachedPictFormats* formats = get_cached_pict_formats(); |
1651 | 1647 |
1652 for (CachedPictFormats::const_iterator i = formats->begin(); | 1648 for (CachedPictFormats::const_iterator i = formats->begin(); |
1653 i != formats->end(); ++i) { | 1649 i != formats->end(); ++i) { |
1654 if (i->equals(dpy, visual)) | 1650 if (i->equals(dpy, visual)) |
1655 return i->format; | 1651 return i->format; |
1656 } | 1652 } |
1657 | 1653 |
(...skipping 23 matching lines...) Expand all Loading... |
1681 return pictformat; | 1677 return pictformat; |
1682 } | 1678 } |
1683 | 1679 |
1684 void SetX11ErrorHandlers(XErrorHandler error_handler, | 1680 void SetX11ErrorHandlers(XErrorHandler error_handler, |
1685 XIOErrorHandler io_error_handler) { | 1681 XIOErrorHandler io_error_handler) { |
1686 XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); | 1682 XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); |
1687 XSetIOErrorHandler( | 1683 XSetIOErrorHandler( |
1688 io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); | 1684 io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); |
1689 } | 1685 } |
1690 | 1686 |
1691 void LogErrorEventDescription(Display* dpy, | 1687 void LogErrorEventDescription(XDisplay* dpy, |
1692 const XErrorEvent& error_event) { | 1688 const XErrorEvent& error_event) { |
1693 char error_str[256]; | 1689 char error_str[256]; |
1694 char request_str[256]; | 1690 char request_str[256]; |
1695 | 1691 |
1696 XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); | 1692 XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); |
1697 | 1693 |
1698 strncpy(request_str, "Unknown", sizeof(request_str)); | 1694 strncpy(request_str, "Unknown", sizeof(request_str)); |
1699 if (error_event.request_code < 128) { | 1695 if (error_event.request_code < 128) { |
1700 std::string num = base::UintToString(error_event.request_code); | 1696 std::string num = base::UintToString(error_event.request_code); |
1701 XGetErrorDatabaseText( | 1697 XGetErrorDatabaseText( |
(...skipping 26 matching lines...) Expand all Loading... |
1728 << "request_code " << static_cast<int>(error_event.request_code) << ", " | 1724 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
1729 << "minor_code " << static_cast<int>(error_event.minor_code) | 1725 << "minor_code " << static_cast<int>(error_event.minor_code) |
1730 << " (" << request_str << ")"; | 1726 << " (" << request_str << ")"; |
1731 } | 1727 } |
1732 | 1728 |
1733 // ---------------------------------------------------------------------------- | 1729 // ---------------------------------------------------------------------------- |
1734 // End of x11_util_internal.h | 1730 // End of x11_util_internal.h |
1735 | 1731 |
1736 | 1732 |
1737 } // namespace ui | 1733 } // namespace ui |
OLD | NEW |