x11_util.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file defines utility functions for X11 (Linux only). This code has been 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ported from XCB since we can't use XCB on Ubuntu while its 32-bit support 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// remains woefully incomplete. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ipc.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/shm.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/XInput2.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/Xrandr.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/randr.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/extensions/shape.h> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_number_conversions.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/events/event_utils.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/keycodes/keyboard_code_conversion_x.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/touch/touch_factory.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/valuators.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util_internal.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point_conversions.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/sysctl.h> 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xcursor/Xcursor.h> 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdk.h> 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdkx.h> 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h> 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gdk_x_compat.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_compat.h" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(sad): Use the new way of handling X errors when 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://codereview.chromium.org/7889040/ lands. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define gdk_error_trap_push() 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define gdk_error_trap_pop() false 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define gdk_flush() 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to cache the XRenderPictFormat for a visual/display pair. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CachedPictFormat { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool equals(Display* display, Visual* visual) const { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return display == this->display && visual == this->visual; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visual* visual; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat* format; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::list<CachedPictFormat> CachedPictFormats; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the cache of pict formats. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CachedPictFormats* get_cached_pict_formats() { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static CachedPictFormats* formats = NULL; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!formats) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats = new CachedPictFormats(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formats; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum number of CachedPictFormats we keep around. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxCacheSize = 5; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MessageLoop::current()) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageLoop::current()->PostTask( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&LogErrorEventDescription, d, *e)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "X error received: " 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "serial " << e->serial << ", " 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "error_code " << static_cast<int>(e->error_code) << ", " 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "request_code " << static_cast<int>(e->request_code) << ", " 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "minor_code " << static_cast<int>(e->minor_code); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DefaultX11IOErrorHandler(Display* d) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there's an IO error it likely means the X server has gone away 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "X IO error received (X server probably went away)"; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _exit(1); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: The caller should free the resulting value data. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProperty(XID window, const std::string& property_name, long max_length, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom* type, int* format, unsigned long* num_items, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char** property) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom property_atom = GetAtom(property_name.c_str()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long remaining_bytes = 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XGetWindowProperty(GetXDisplay(), 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property_atom, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // offset into property data to read 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_length, // max length to get 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) False, // deleted 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnyPropertyType, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_items, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &remaining_bytes, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts ui::EventType to XKeyEvent state. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int XKeyEventState(int flags) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((flags & ui::EF_SHIFT_DOWN) ? ShiftMask : 0) | 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((flags & ui::EF_CONTROL_DOWN) ? ControlMask : 0) | 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((flags & ui::EF_ALT_DOWN) ? Mod1Mask : 0) | 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((flags & ui::EF_CAPS_LOCK_DOWN) ? LockMask : 0); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts EventType to XKeyEvent type. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int XKeyEventType(ui::EventType type) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_KEY_PRESSED: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return KeyPress; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ui::ET_KEY_RELEASED: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return KeyRelease; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts KeyboardCode to XKeyEvent keycode. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int keysym = XKeysymForWindowsKeyCode(key_code, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags & ui::EF_SHIFT_DOWN); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tests assume the keycode for XK_less is equal to the one of XK_comma, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XK_comma. Here we convert the value for XK_less to the value for XK_comma. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A process wide singleton that manages the usage of X cursors. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XCursorCache { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCursorCache() {} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCursorCache() { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Clear(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor GetCursor(int cursor_shape) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lookup cursor by attempting to insert a null value, which avoids 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a second pass through the map after a cache miss. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert( 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::make_pair(cursor_shape, 0)); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it.second) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.first->second = XCreateFontCursor(display, cursor_shape); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it.first->second; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<int, ::Cursor>::iterator it = 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.begin(); it != cache_.end(); ++it) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeCursor(display, it->second); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.clear(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maps X11 font cursor shapes to Cursor IDs. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, ::Cursor> cache_; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCursorCache); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)XCursorCache* cursor_cache = NULL; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A process wide singleton cache for custom X cursors. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XCustomCursorCache { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static XCustomCursorCache* GetInstance() { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<XCustomCursorCache>::get(); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor InstallCustomCursor(XcursorImage* image) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursor* custom_cursor = new XCustomCursor(image); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor xcursor = custom_cursor->cursor(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_[xcursor] = custom_cursor; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return xcursor; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Ref(::Cursor cursor) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_[cursor]->Ref(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Unref(::Cursor cursor) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cache_[cursor]->Unref()) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.erase(cursor); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.clear(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<XCustomCursorCache>; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class XCustomCursor { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This takes ownership of the image. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursor(XcursorImage* image) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : image_(image), 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ref_(1) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor_ = XcursorImageLoadCursor(GetXDisplay(), image); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCustomCursor() { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImageDestroy(image_); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeCursor(GetXDisplay(), cursor_); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor cursor() const { return cursor_; } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Ref() { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ref_; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the cursor was destroyed because of the unref. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Unref() { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--ref_ == 0) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImage* image_; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ref_; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor cursor_; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCustomCursor); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache() {} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCustomCursorCache() { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Clear(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map< ::Cursor, XCustomCursor*> cache_; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCustomCursorCache); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(USE_AURA) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A singleton object that remembers remappings of mouse buttons. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XButtonMap { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static XButtonMap* GetInstance() { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<XButtonMap>::get(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateMapping() { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count_ = XGetPointerMapping(ui::GetXDisplay(), map_, arraysize(map_)); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int GetMappedButton(int button) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return button > 0 && button <= count_ ? map_[button - 1] : button; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<XButtonMap>; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XButtonMap() { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateMapping(); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XButtonMap() {} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char map_[256]; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count_; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XButtonMap); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRandRAvailable() { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int randr_version_major = 0; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int randr_version_minor = 0; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool is_randr_available = XRRQueryVersion( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetXDisplay(), &randr_version_major, &randr_version_minor); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_randr_available; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsShapeAvailable() { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool is_shape_available = 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_shape_available; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Get the EDID data from the |output| and stores to |prop|. |nitem| will store 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// the number of characters |prop| will have. It doesn't take the ownership of 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |prop|, so caller must release it by XFree(). 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if EDID property is successfully obtained. Otherwise returns 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// false and does not touch |prop| and |nitems|. 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetEDIDProperty(XID output, unsigned long* nitems, unsigned char** prop) { 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsRandRAvailable()) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Display* display = GetXDisplay(); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool has_edid_property = false; 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_properties = 0; 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Atom* properties = XRRListOutputProperties(display, output, &num_properties); 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < num_properties; ++i) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (properties[i] == edid_property) { 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) has_edid_property = true; 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFree(properties); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!has_edid_property) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Atom actual_type; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int actual_format; 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned long bytes_after; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XRRGetOutputProperty(display, 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output, 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) edid_property, 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, // offset 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 128, // length 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, // _delete 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) false, // pending 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AnyPropertyType, // req_type 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &actual_type, 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &actual_format, 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nitems, 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &bytes_after, 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prop); 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(XA_INTEGER, actual_type); 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(8, actual_format); 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XDisplayExists() { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (GetXDisplay() != NULL); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Display* GetXDisplay() { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::MessagePumpForUI::GetDefaultXDisplay(); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bool pixmaps_supported; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Query the server's support for XSHM. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On FreeBSD we can't access the shared memory after it was marked for 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deletion, unless this behaviour is explicitly enabled by the user. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case it's not enabled disable shared memory support. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int allow_removed; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length = sizeof(allow_removed); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((sysctlbyname("kern.ipc.shm_allow_removed", &allow_removed, &length, 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0) < 0) || allow_removed < 1) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next we probe to see if shared memory will really work 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shmkey = shmget(IPC_PRIVATE, 1, 0600); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shmkey == -1) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to get shared memory segment."; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Got shared memory segment " << shmkey; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* address = shmat(shmkey, NULL, 0); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the shared memory region for deletion 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shmctl(shmkey, IPC_RMID, NULL); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmid = shmkey; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_error_trap_push(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = XShmAttach(dpy, &shminfo); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X got shared memory segment " << shmkey; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSync(dpy, False); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (gdk_error_trap_pop()) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shmdt(address); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X attached to shared memory segment " << shmkey; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmDetach(dpy, &shminfo); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SharedMemorySupport QuerySharedMemorySupport(Display* dpy) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool shared_memory_support_cached = false; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shared_memory_support_cached) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_memory_support; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_support = DoQuerySharedMemorySupport(dpy); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_support_cached = true; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_memory_support; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool QueryRenderSupport(Display* dpy) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool render_supported = false; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool render_supported_cached = false; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_supported_cached) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_supported; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't care about the version of Xrender since all the features which 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we use are included in every version. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_supported_cached = true; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_supported; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetDefaultScreen(Display* display) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XDefaultScreen(display); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor GetXCursor(int cursor_shape) { 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!cursor_cache) 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cursor_cache = new XCursorCache; 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cursor_cache->GetCursor(cursor_shape); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResetXCursorCache() { 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete cursor_cache; 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cursor_cache = NULL; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor CreateReffedCustomXCursor(XcursorImage* image) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XCustomCursorCache::GetInstance()->InstallCustomCursor(image); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RefCustomXCursor(::Cursor cursor) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache::GetInstance()->Ref(cursor); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnrefCustomXCursor(::Cursor cursor) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache::GetInstance()->Unref(cursor); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XcursorImage* SkBitmapToXcursorImage(const SkBitmap* cursor_image, 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& hotspot) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cursor_image->config() == SkBitmap::kARGB_8888_Config); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point hotspot_point = hotspot; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap scaled; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // X11 seems to have issues with cursors when images get larger than 64 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pixels. So rescale the image if necessary. 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float kMaxPixel = 64.f; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool needs_scale = false; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_image->width() > kMaxPixel || cursor_image->height() > kMaxPixel) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale = 1.f; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_image->width() > cursor_image->height()) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale = kMaxPixel / cursor_image->width(); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale = kMaxPixel / cursor_image->height(); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scaled = skia::ImageOperations::Resize(*cursor_image, 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skia::ImageOperations::RESIZE_BETTER, 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(cursor_image->width() * scale), 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(cursor_image->height() * scale)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hotspot_point = gfx::ToFlooredPoint(gfx::ScalePoint(hotspot, scale)); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_scale = true; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap* bitmap = needs_scale ? &scaled : cursor_image; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImage* image = XcursorImageCreate(bitmap->width(), bitmap->height()); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image->xhot = hotspot_point.x(); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image->yhot = hotspot_point.y(); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap->width() && bitmap->height()) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->lockPixels(); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |bitmap| contains ARGB image, so just copy it. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(image->pixels, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->getPixels(), 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->width() * bitmap->height() * 4); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->unlockPixels(); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CoalescePendingMotionEvents(const XEvent* xev, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent* last_event) { 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_coalesed = 0; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display = xev->xany.display; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int event_type = xev->xgeneric.evtype; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float tracking_id = -1; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_type == XI_TouchUpdate) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::ValuatorTracker::GetInstance()->ExtractValuator(*xev, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ValuatorTracker::VAL_TRACKING_ID, &tracking_id)) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tracking_id = -1; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (XPending(display)) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent next_event; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPeekEvent(display, &next_event); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't get the cookie, abort the check. 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_coalesed; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this isn't from a valid device, throw the event away, as 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that's what the message pump would do. Device events come in pairs 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with one from the master and one from the slave so there will 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always be at least one pending. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XNextEvent(display, &next_event); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_event.type == GenericEvent && 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_event.xgeneric.evtype == event_type && 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !ui::GetScrollOffsets(&next_event, NULL, NULL, NULL, NULL, NULL) && 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !ui::GetFlingData(&next_event, NULL, NULL, NULL, NULL, NULL)) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIDeviceEvent* next_xievent = 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<XIDeviceEvent*>(next_event.xcookie.data); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float next_tracking_id = -1; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_type == XI_TouchUpdate) { 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a touch motion event (as opposed to mouse motion event), 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then make sure the events are from the same touch-point. 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::ValuatorTracker::GetInstance()->ExtractValuator(next_event, 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ValuatorTracker::VAL_TRACKING_ID, &next_tracking_id)) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_tracking_id = -1; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Confirm that the motion event is targeted at the same window 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and that no buttons or modifiers have changed. 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xievent->event == next_xievent->event && 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->child == next_xievent->child && 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_XI2_MT) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (event_type == XI_Motion || tracking_id == next_tracking_id) && 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->buttons.mask_len == next_xievent->buttons.mask_len && 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (memcmp(xievent->buttons.mask, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_xievent->buttons.mask, 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->buttons.mask_len) == 0) && 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.base == next_xievent->mods.base && 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.latched == next_xievent->mods.latched && 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.locked == next_xievent->mods.locked && 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.effective == next_xievent->mods.effective) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free the previous cookie. 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_coalesed > 0) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &last_event->xcookie); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the event and its cookie data. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XNextEvent(display, last_event); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetEventData(display, &last_event->xcookie); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_coalesed; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This isn't an event we want so free its cookie data. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_coalesed; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HideHostCursor() { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (CreateInvisibleCursor(), ui::GetXDisplay())); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()), 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_cursor.get()); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor CreateInvisibleCursor() { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* xdisplay = ui::GetXDisplay(); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor invisible_cursor; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XColor black; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) black.red = black.green = black.blue = 0; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pixmap blank = XCreateBitmapFromData(xdisplay, 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultRootWindow(xdisplay), 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodata, 8, 8); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_cursor = XCreatePixmapCursor(xdisplay, blank, blank, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &black, &black, 0, 0); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreePixmap(xdisplay, blank); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return invisible_cursor; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11RootWindow() { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefaultRootWindow(GetXDisplay()); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCurrentDesktop(int* desktop) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11WindowFromGtkWidget(GtkWidget* widget) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_WINDOW_XID(gtk_widget_get_window(widget)); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11WindowFromGdkWindow(GdkWindow* window) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_WINDOW_XID(window); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GtkWindow* GetGtkWindowFromX11Window(XID xid) { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkWindow* gdk_window = 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_x11_window_lookup_for_display(gdk_display_get_default(), xid); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gdk_window) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWindow* gtk_window = NULL; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_window_get_user_data(gdk_window, 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<gpointer*>(>k_window)); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gtk_window) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gtk_window; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GetVisualFromGtkWidget(GtkWidget* widget) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(TOOLKIT_GTK) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetHideTitlebarWhenMaximizedProperty(XID window, 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HideTitlebarWhenMaximized property) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 hide = property; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XChangeProperty(GetXDisplay(), 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XA_CARDINAL, 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32, // size in bits 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropModeReplace, 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned char*>(&hide), 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearX11DefaultRootWindow() { 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Display* display = GetXDisplay(); 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XID root_window = GetX11RootWindow(); 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect root_bounds; 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetWindowRect(root_window, &root_bounds)) { 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to get the bounds of the X11 root window"; 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XGCValues gc_values = {0}; 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gc_values.foreground = BlackPixel(display, DefaultScreen(display)); 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GC gc = XCreateGC(display, root_window, GCForeground, &gc_values); 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFillRectangle(display, root_window, gc, 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.x(), 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.y(), 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.width(), 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.height()); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFreeGC(display, gc); 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BitsPerPixelForPixmapDepth(Display* dpy, int depth) { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!formats) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bits_per_pixel = -1; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < count; ++i) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (formats[i].depth == depth) { 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bits_per_pixel = formats[i].bits_per_pixel; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(formats); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bits_per_pixel; 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWindowVisible(XID window) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes win_attributes; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWindowAttributes(GetXDisplay(), window, &win_attributes)) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (win_attributes.map_state != IsViewable) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some compositing window managers (notably kwin) do not actually unmap 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows on desktop switch, so we also must check the current desktop. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_desktop, current_desktop; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (!GetWindowDesktop(window, &window_desktop) || 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !GetCurrentDesktop(¤t_desktop) || 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_desktop == kAllDesktops || 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_desktop == current_desktop); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowRect(XID window, gfx::Rect* rect) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window root, child; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, y; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int width, height; 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int border_width, depth; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetGeometry(GetXDisplay(), window, &root, &x, &y, 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &width, &height, &border_width, &depth)) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XTranslateCoordinates(GetXDisplay(), window, root, 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, &x, &y, &child)) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *rect = gfx::Rect(x, y, width, height); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowContainsPoint(XID window, gfx::Point screen_loc) { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_rect; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWindowRect(window, &window_rect)) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window_rect.Contains(screen_loc)) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsShapeAvailable()) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // According to http://www.x.org/releases/X11R7.6/doc/libXext/shapelib.html, 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an X display supports the shape extension the bounds of a window are 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // defined as the intersection of the window bounds and the interior 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rectangles. This means to determine if a point is inside a window for the 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // purpose of input handling we have to check the rectangles in the ShapeInput 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list. 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int input_rects_size = 0; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRectangle* input_rects = XShapeGetRectangles( 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!input_rects) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_in_input_rects = false; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < input_rects_size; ++i) { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The ShapeInput rects appear to be in window space, so we have to 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // translate by the window_rect's offset to map to screen space. 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect input_rect = 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect(input_rects[i].x + window_rect.x(), 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_rects[i].y + window_rect.y(), 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_rects[i].width, input_rects[i].height); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input_rect.Contains(screen_loc)) { 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_in_input_rects = true; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(input_rects); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_in_input_rects; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PropertyExists(XID window, const std::string& property_name) { 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1, 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_items > 0; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetIntProperty(XID window, const std::string& property_name, int* value) { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1, 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 32 || num_items != 1) { 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *value = static_cast<int>(*(reinterpret_cast<long*>(property))); 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetIntArrayProperty(XID window, 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& property_name, 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int>* value) { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* properties = NULL; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (~0L), // (all of them) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &properties); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 32) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long* int_properties = reinterpret_cast<long*>(properties); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->clear(); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned long i = 0; i < num_items; ++i) { 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->push_back(static_cast<int>(int_properties[i])); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAtomArrayProperty(XID window, 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& property_name, 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Atom>* value) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* properties = NULL; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (~0L), // (all of them) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &properties); 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != XA_ATOM) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom* atom_properties = reinterpret_cast<Atom*>(properties); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->clear(); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->insert(value->begin(), atom_properties, atom_properties + num_items); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetStringProperty( 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID window, const std::string& property_name, std::string* value) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1024, 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 8) { 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->assign(reinterpret_cast<char*>(property), num_items); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetIntProperty(XID window, 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& type, 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> values(1, value); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SetIntArrayProperty(window, name, type, values); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetIntArrayProperty(XID window, 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& type, 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<int>& value) { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!value.empty()); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom name_atom = GetAtom(name.c_str()); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type_atom = GetAtom(type.c_str()); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XChangeProperty() expects values of type 32 to be longs. 9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<long[]> data(new long[value.size()]); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < value.size(); ++i) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i] = value[i]; 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_error_trap_push(); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XChangeProperty(ui::GetXDisplay(), 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_atom, 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_atom, 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32, // size in bits of items in 'value' 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropModeReplace, 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const unsigned char*>(data.get()), 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.size()); // num items 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSync(ui::GetXDisplay(), False); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gdk_error_trap_pop() == 0; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Atom GetAtom(const char* name) { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gdk_x11_get_xatom_by_name_for_display( 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_display_get_default(), name); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(derat): Cache atoms to avoid round-trips to the server. 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XInternAtom(GetXDisplay(), name, false); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetParentWindow(XID window) { 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root = None; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID parent = None; 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID* children = NULL; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_children = 0; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XQueryTree(GetXDisplay(), window, &root, &parent, &children, &num_children); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (children) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(children); 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parent; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetHighestAncestorWindow(XID window, XID root) { 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID parent = GetParentWindow(window); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent == None) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent == root) 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window = parent; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowDesktop(XID window, int* desktop) { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetX11ErrorString(Display* display, int err) { 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[256]; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorText(display, err, buffer, arraysize(buffer)); 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |window| is a named window. 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWindowNamed(XID window) { 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XTextProperty prop; 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(prop.value); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_depth, int depth) { 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (depth > max_depth) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root, parent, *children; 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_children; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children, 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_children); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == 0) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID> windows; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = static_cast<int>(num_children) - 1; i >= 0; i--) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows.push_back(children[i]); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(children); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XQueryTree returns the children of |window| in bottom-to-top order, so 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reverse-iterate the list to check the windows from top-to-bottom. 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID>::iterator iter; 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = windows.begin(); iter != windows.end(); iter++) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter)) 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're at this point, we didn't find the window we're looking for at the 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current level, so we need to recurse to the next level. We use a second 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop because the recursion and call to XQueryTree are expensive and is only 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // needed for a small number of cases. 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++depth <= max_depth) { 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = windows.begin(); iter != windows.end(); iter++) { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EnumerateChildren(delegate, *iter, max_depth, depth)) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root = GetX11RootWindow(); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumerateChildren(delegate, root, max_depth, 0); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) { 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID> stack; 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) { 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to old school enumeration of all X windows. Some WMs parent 'top-level' 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows in unnamed actual top-level windows (ion WM), so extend the 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // search depth to all children of top-level windows. 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxSearchDepth = 1; 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::EnumerateAllWindows(delegate, kMaxSearchDepth); 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID>::iterator iter; 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = stack.begin(); iter != stack.end(); iter++) { 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate->ShouldStopIterating(*iter)) 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetXWindowStack(Window window, std::vector<XID>* windows) { 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows->clear(); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long count; 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char *data = NULL; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetProperty(window, 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_NET_CLIENT_LIST_STACKING", 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~0L, 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &format, 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count, 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &data) != Success) { 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == XA_WINDOW && format == 32 && data && count > 0) { 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID* stack = reinterpret_cast<XID*>(data); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (long i = static_cast<long>(count) - 1; i >= 0; i--) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows->push_back(stack[i]); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data) 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(data); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RestackWindow(XID window, XID sibling, bool above) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowChanges changes; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes.sibling = sibling; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes.stack_mode = above ? Above : Below; 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XConfigureWindow(GetXDisplay(), window, CWSibling | CWStackMode, &changes); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) { 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QuerySharedMemorySupport(display)); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmid = shared_memory_key; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function is only called if QuerySharedMemorySupport returned true. In 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which case we've already succeeded in having the X server attach to one of 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our shared memory segments. 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmAttach(display, &shminfo)) { 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << shminfo.shmid; 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X attached to shared memory segment " << shminfo.shmid; 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shminfo.shmseg; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) { 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QuerySharedMemorySupport(display)); 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmseg = shmseg; 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmDetach(display, &shminfo)) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) { 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID picture = XRenderCreatePicture( 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display, pixmap, GetRenderARGB32Format(display), 0, NULL); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return picture; 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PutARGBImage(Display* display, 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* visual, int depth, 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID pixmap, void* pixmap_gc, 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* data, 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width, int height) { 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PutARGBImage(display, 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visual, depth, 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pixmap, pixmap_gc, 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data, width, height, 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, // src_x, src_y 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, // dst_x, dst_y 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width, height); 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PutARGBImage(Display* display, 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* visual, int depth, 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID pixmap, void* pixmap_gc, 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* data, 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_width, int data_height, 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int src_x, int src_y, 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dst_x, int dst_y, 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int copy_width, int copy_height) { 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scherkus): potential performance impact... consider passing in as a 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parameter. 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth); 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XImage image; 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&image, 0, sizeof(image)); 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.width = data_width; 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.height = data_height; 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.format = ZPixmap; 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.byte_order = LSBFirst; 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.bitmap_unit = 8; 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.bitmap_bit_order = LSBFirst; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.depth = depth; 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.bits_per_pixel = pixmap_bpp; 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.bytes_per_line = data_width * pixmap_bpp / 8; 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pixmap_bpp == 32) { 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.red_mask = 0xff0000; 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.green_mask = 0xff00; 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.blue_mask = 0xff; 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the X server depth is already 32-bits and the color masks match, 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then our job is easy. 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visual* vis = static_cast<Visual*>(visual); 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image.red_mask == vis->red_mask && 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.green_mask == vis->green_mask && 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.blue_mask == vis->blue_mask) { 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.data = const_cast<char*>(reinterpret_cast<const char*>(data)); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src_x, src_y, dst_x, dst_y, 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_width, copy_height); 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, we need to shuffle the colors around. Assume red and blue 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to be swapped. 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible to use some fancy SSE tricks here, but since this is the 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // slow path anyway, we do it slowly. 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* bitmap32 = 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint8_t*>(malloc(4 * data_width * data_height)); 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bitmap32) 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const orig_bitmap32 = bitmap32; 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data); 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < data_height; ++y) { 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = 0; x < data_width; ++x) { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32_t pixel = *(bitmap_in++); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap32[0] = (pixel >> 16) & 0xff; // Red 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap32[1] = (pixel >> 8) & 0xff; // Green 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap32[2] = pixel & 0xff; // Blue 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap32[3] = (pixel >> 24) & 0xff; // Alpha 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap32 += 4; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.data = reinterpret_cast<char*>(orig_bitmap32); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src_x, src_y, dst_x, dst_y, 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_width, copy_height); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(orig_bitmap32); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (pixmap_bpp == 16) { 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some folks have VNC setups which still use 16-bit visuals and VNC 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doesn't include Xrender. 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t* bitmap16 = 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint16_t*>(malloc(2 * data_width * data_height)); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bitmap16) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t* const orig_bitmap16 = bitmap16; 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data); 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < data_height; ++y) { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = 0; x < data_width; ++x) { 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32_t pixel = *(bitmap_in++); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16_t out_pixel = ((pixel >> 8) & 0xf800) | 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((pixel >> 5) & 0x07e0) | 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((pixel >> 3) & 0x001f); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(bitmap16++) = out_pixel; 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.data = reinterpret_cast<char*>(orig_bitmap16); 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.red_mask = 0xf800; 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.green_mask = 0x07e0; 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.blue_mask = 0x001f; 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image, 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src_x, src_y, dst_x, dst_y, 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_width, copy_height); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(orig_bitmap16); 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << "Sorry, we don't support your visual depth without " 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Xrender support (depth:" << depth 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " bpp:" << pixmap_bpp << ")"; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FreePicture(Display* display, XID picture) { 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderFreePicture(display, picture); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FreePixmap(Display* display, XID pixmap) { 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreePixmap(display, pixmap); 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetOutputDeviceData(XID output, 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16* manufacturer_id, 12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16* product_code, 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* human_readable_name) { 12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned long nitems = 0; 12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char *prop = NULL; 12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetEDIDProperty(output, &nitems, &prop)) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool result = ParseOutputDeviceData( 12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prop, nitems, manufacturer_id, product_code, human_readable_name); 12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFree(prop); 12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ParseOutputDeviceData(const unsigned char* prop, 13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned long nitems, 13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16* manufacturer_id, 13032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16* product_code, 13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* human_readable_name) { 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://en.wikipedia.org/wiki/Extended_display_identification_data 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the details of EDID data format. We use the following data: 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes 8-9: manufacturer EISA ID, in big-endian 13082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bytes 10-11: represents product code, in little-endian 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes 54-125: four descriptors (18-bytes each) which may contain 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the display name. 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int kManufacturerOffset = 8; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int kManufacturerLength = 2; 13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kProductCodeOffset = 10; 13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kProductCodeLength = 2; 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int kDescriptorOffset = 54; 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int kNumDescriptors = 4; 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int kDescriptorLength = 18; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The specifier types. 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char kMonitorNameDescriptor = 0xfc; 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (manufacturer_id) { 13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nitems < kManufacturerOffset + kManufacturerLength) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *manufacturer_id = 13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *reinterpret_cast<const uint16*>(prop + kManufacturerOffset); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN) 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *manufacturer_id = base::ByteSwap(*manufacturer_id); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (product_code) { 13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nitems < kProductCodeOffset + kProductCodeLength) 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *product_code = base::ByteSwapToLE16( 13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *reinterpret_cast<const uint16*>(prop + kProductCodeOffset)); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!human_readable_name) 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) human_readable_name->clear(); 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < kNumDescriptors; ++i) { 13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char* desc_buf = 13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prop + kDescriptorOffset + i * kDescriptorLength; 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the descriptor contains the display name, it has the following 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // structure: 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes 0-2, 4: \0 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // byte 3: descriptor type, defined above. 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes 5-17: text data, ending with \r, padding with spaces 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we should check bytes 0-2 and 4, since it may have other values in 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // case that the descriptor contains other type of data. 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 && 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desc_buf[4] == 0) { 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desc_buf[3] == kMonitorNameDescriptor) { 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string found_name( 13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const char*>(desc_buf + 5), kDescriptorLength - 5); 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (human_readable_name->empty()) 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify if the |human_readable_name| consists of printable characters only. 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < human_readable_name->size(); ++i) { 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = (*human_readable_name)[i]; 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isascii(c) || !isprint(c)) { 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) human_readable_name->clear(); 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetOutputOverscanFlag(XID output, bool* flag) { 13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned long nitems = 0; 13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char *prop = NULL; 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetEDIDProperty(output, &nitems, &prop)) 13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool found = ParseOutputOverscanFlag(prop, nitems, flag); 13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFree(prop); 13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return found; 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ParseOutputOverscanFlag(const unsigned char* prop, 13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned long nitems, 13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool *flag) { 13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // See http://en.wikipedia.org/wiki/Extended_display_identification_data 13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for the extension format of EDID. Also see EIA/CEA-861 spec for 13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the format of the extensions and how video capability is encoded. 14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 0: tag. should be 02h. 14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 1: revision. only cares revision 3 (03h). 14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 4-: data block. 14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kExtensionBase = 128; 14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kExtensionSize = 128; 14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kNumExtensionsOffset = 126; 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kDataBlockOffset = 4; 14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char kCEAExtensionTag = '\x02'; 14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char kExpectedExtensionRevision = '\x03'; 14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char kExtendedTag = 7; 14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char kExtendedVideoCapabilityTag = 0; 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kPTOverscan = 4; 14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kITOverscan = 2; 14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned int kCEOverscan = 0; 14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nitems <= kNumExtensionsOffset) 14162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char num_extensions = prop[kNumExtensionsOffset]; 14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < num_extensions; ++i) { 14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Skip parsing the whole extension if size is not enough. 14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nitems < kExtensionBase + (i + 1) * kExtensionSize) 14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char* extension = prop + kExtensionBase + i * kExtensionSize; 14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char tag = extension[0]; 14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char revision = extension[1]; 14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision) 14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char timing_descriptors_start = 14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(extension[2], static_cast<unsigned char>(kExtensionSize)); 14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char* data_block = extension + kDataBlockOffset; 14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (data_block < extension + timing_descriptors_start) { 14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A data block is encoded as: 14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 1 high 3 bits: tag. '07' for extended tags. 14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 1 remaining bits: the length of data block. 14382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 2: the extended tag. '0' for video capability. 14392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // - byte 3: the capability. 14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char tag = data_block[0] >> 5; 14412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char payload_length = data_block[0] & 0x1f; 14422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (static_cast<unsigned long>(data_block + payload_length - prop) > 14432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nitems) 14442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 14452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tag != kExtendedTag && payload_length < 2) { 14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_block += payload_length + 1; 14482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 14492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char extended_tag_code = data_block[1]; 14522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (extended_tag_code != kExtendedVideoCapabilityTag) { 14532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data_block += payload_length; 14542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 14552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The difference between preferred, IT, and CE video formats 14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // doesn't matter. Sets |flag| to true if any of these flags are true. 14592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((data_block[2] & (1 << kPTOverscan)) || 14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (data_block[2] & (1 << kITOverscan)) || 14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (data_block[2] & (1 << kCEOverscan))) { 14622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *flag = true; 14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 14642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *flag = false; 14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 14672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowManagerName(std::string* wm_name) { 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(wm_name); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wm_window = 0; 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetIntProperty(GetX11RootWindow(), 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_NET_SUPPORTING_WM_CHECK", 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wm_window)) { 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible that a window manager started earlier in this X session left 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a stale _NET_SUPPORTING_WM_CHECK property when it was replaced by a 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // non-EWMH window manager, so we trap errors in the following requests to 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avoid crashes (issue 23860). 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EWMH requires the supporting-WM window to also have a 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // _NET_SUPPORTING_WM_CHECK property pointing to itself (to avoid a stale 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // property referencing an ID that's been recycled for another window), so we 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check that too. 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_error_trap_push(); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wm_window_property = 0; 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = GetIntProperty( 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wm_window, "_NET_SUPPORTING_WM_CHECK", &wm_window_property); 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_flush(); 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool got_error = gdk_error_trap_pop(); 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (got_error || !result || wm_window_property != wm_window) 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_error_trap_push(); 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = GetStringProperty( 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name); 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_flush(); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) got_error = gdk_error_trap_pop(); 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !got_error && result; 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowManagerName GuessWindowManager() { 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetWindowManagerName(&name)) { 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These names are taken from the WMs' source code. 15122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Blackbox") 15132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_BLACKBOX; 15142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "chromeos-wm") 15152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_CHROME_OS; 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Compiz" || name == "compiz") 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_COMPIZ; 15182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "e16") 15192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_ENLIGHTENMENT; 15202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (StartsWithASCII(name, "IceWM", true)) 15212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_ICE_WM; 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "KWin") 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_KWIN; 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Metacity") 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_METACITY; 15262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Mutter (Muffin)") 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_MUFFIN; 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Mutter") 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_MUTTER; 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Openbox") 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_OPENBOX; 15322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Xfwm4") 15332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_XFWM4; 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_UNKNOWN; 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChangeWindowDesktop(XID window, XID destination) { 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desktop; 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWindowDesktop(destination, &desktop)) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |window| is sticky, use the current desktop. 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desktop == kAllDesktops && 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !GetCurrentDesktop(&desktop)) 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent event; 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.type = ClientMessage; 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.window = window; 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.message_type = GetAtom("_NET_WM_DESKTOP"); 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.format = 32; 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.data.l[0] = desktop; 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.data.l[1] = 1; // source indication 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False, 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SubstructureNotifyMask, &event); 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result == Success; 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetDefaultX11ErrorHandlers() { 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetX11ErrorHandlers(NULL, NULL); 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsX11WindowFullScreen(XID window) { 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check if _NET_WM_STATE property contains _NET_WM_STATE_FULLSCREEN. 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN"); 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Atom> atom_properties; 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetAtomArrayProperty(window, 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_NET_WM_STATE", 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &atom_properties) && 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(atom_properties.begin(), atom_properties.end(), atom) 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != atom_properties.end()) 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As the last resort, check if the window size is as large as the main 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // screen. 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkRectangle monitor_rect; 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect); 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_rect; 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::GetWindowRect(window, &window_rect)) 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return monitor_rect.x == window_rect.x() && 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.y == window_rect.y() && 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.width == window_rect.width() && 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.height == window_rect.height(); 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsMotionEvent(XEvent* event) { 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type = event->type; 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == GenericEvent) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type = event->xgeneric.evtype; 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type == MotionNotify; 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetMappedButton(int button) { 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XButtonMap::GetInstance()->GetMappedButton(button); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateButtonMap() { 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XButtonMap::GetInstance()->UpdateMapping(); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitXKeyEventForTesting(EventType type, 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeyboardCode key_code, 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent* event) { 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(event); 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Display* display = GetXDisplay(); 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XKeyEvent key_event; 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.type = XKeyEventType(type); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_NE(0, key_event.type); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.serial = 0; 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.send_event = 0; 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.display = display; 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.time = 0; 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.window = 0; 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.root = 0; 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.subwindow = 0; 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.x = 0; 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.y = 0; 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.x_root = 0; 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.y_root = 0; 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.state = XKeyEventState(flags); 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.keycode = XKeyEventKeyCode(key_code, flags, display); 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_event.same_screen = 1; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->type = key_event.type; 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->xkey = key_event; 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedString::~XScopedString() { 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(string_); 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedImage::~XScopedImage() { 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset(NULL); 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void XScopedImage::reset(XImage* image) { 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_ == image) 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_) 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XDestroyImage(image_); 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_ = image; 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedCursor::XScopedCursor(::Cursor cursor, Display* display) 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : cursor_(cursor), 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_(display) { 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedCursor::~XScopedCursor() { 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset(0U); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor XScopedCursor::get() const { 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cursor_; 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void XScopedCursor::reset(::Cursor cursor) { 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_) 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeCursor(display_, cursor_); 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor_ = cursor; 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are declared in x11_util_internal.h because they require 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XLib.h to be included, and it conflicts with many other headers. 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static XRenderPictFormat* pictformat = NULL; 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pictformat) 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First look for a 32-bit format which ignores the alpha value 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat templ; 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.depth = 32; 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.type = PictTypeDirect; 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.red = 16; 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.green = 8; 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.blue = 0; 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.redMask = 0xff; 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.greenMask = 0xff; 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.blueMask = 0xff; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.alphaMask = 0; 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const unsigned long kMask = 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatType | PictFormatDepth | 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatRed | PictFormatRedMask | 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatGreen | PictFormatGreenMask | 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatBlue | PictFormatBlueMask | 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatAlphaMask; 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */); 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pictformat) { 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not all X servers support xRGB32 formats. However, the XRENDER spec says 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that they must support an ARGB32 format, so we can always return that. 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32); 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pictformat) << "XRENDER ARGB32 not supported."; 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QueryRenderSupport(dpy)); 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedPictFormats* formats = get_cached_pict_formats(); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CachedPictFormats::const_iterator i = formats->begin(); 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != formats->end(); ++i) { 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->equals(dpy, visual)) 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->format; 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not cached, look up the value. 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat* pictformat = XRenderFindVisualFormat(dpy, visual); 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pictformat) << "XRENDER does not support default visual"; 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And store it in the cache. 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedPictFormat cached_value; 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.visual = visual; 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.display = dpy; 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.format = pictformat; 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats->push_front(cached_value); 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (formats->size() == kMaxCacheSize) { 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats->pop_back(); 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should really only have at most 2 display/visual combinations: 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one for normal browser windows, and possibly another for an argb window 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created to display a menu. 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get here it's not fatal, we just need to make sure we aren't 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always blowing away the cache. If we are, then we should figure out why 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and make it bigger. 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetX11ErrorHandlers(XErrorHandler error_handler, 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIOErrorHandler io_error_handler) { 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSetIOErrorHandler( 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogErrorEventDescription(Display* dpy, 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XErrorEvent& error_event) { 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char error_str[256]; 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char request_str[256]; 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(request_str, "Unknown", sizeof(request_str)); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_event.request_code < 128) { 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string num = base::UintToString(error_event.request_code); 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorDatabaseText( 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpy, "XRequest", num.c_str(), "Unknown", request_str, 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(request_str)); 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_ext; 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char** ext_list = XListExtensions(dpy, &num_ext); 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_ext; i++) { 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ext_code, first_event, first_error; 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_event.request_code == ext_code) { 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string msg = base::StringPrintf( 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s.%d", ext_list[i], error_event.minor_code); 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorDatabaseText( 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpy, "XRequest", msg.c_str(), "Unknown", request_str, 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(request_str)); 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeExtensionList(ext_list); 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "X error received: " 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "serial " << error_event.serial << ", " 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "error_code " << static_cast<int>(error_event.error_code) 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" << error_str << "), " 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "request_code " << static_cast<int>(error_event.request_code) << ", " 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "minor_code " << static_cast<int>(error_event.minor_code) 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" << request_str << ")"; 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// End of x11_util_internal.h 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 1804