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/shape.h> 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/extensions/XInput2.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/debug/trace_event.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/metrics/histogram.h" 317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/x11/x11_error_tracker.h" 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "third_party/skia/include/core/SkPostConfig.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/x/x11_util_internal.h" 40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_utils.h" 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/keycodes/keyboard_code_conversion_x.h" 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/x/device_data_manager.h" 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/x/touch_factory_x11.h" 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/canvas.h" 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/image/image_skia_rep.h" 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/point.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point_conversions.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/sysctl.h> 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xcursor/Xcursor.h> 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gdk/gdk.h> 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h> 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gdk_compat.h" 6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gtk_compat.h" 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to cache the XRenderPictFormat for a visual/display pair. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CachedPictFormat { 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool equals(XDisplay* display, Visual* visual) const { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return display == this->display && visual == this->visual; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Visual* visual; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat* format; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::list<CachedPictFormat> CachedPictFormats; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the cache of pict formats. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CachedPictFormats* get_cached_pict_formats() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static CachedPictFormats* formats = NULL; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!formats) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats = new CachedPictFormats(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formats; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum number of CachedPictFormats we keep around. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxCacheSize = 5; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int DefaultX11ErrorHandler(XDisplay* d, XErrorEvent* e) { 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (base::MessageLoop::current()) { 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostTask( 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, base::Bind(&LogErrorEventDescription, d, *e)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "X error received: " 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "serial " << e->serial << ", " 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "error_code " << static_cast<int>(e->error_code) << ", " 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "request_code " << static_cast<int>(e->request_code) << ", " 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "minor_code " << static_cast<int>(e->minor_code); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int DefaultX11IOErrorHandler(XDisplay* d) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there's an IO error it likely means the X server has gone away 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "X IO error received (X server probably went away)"; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _exit(1); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: The caller should free the resulting value data. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProperty(XID window, const std::string& property_name, long max_length, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom* type, int* format, unsigned long* num_items, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char** property) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom property_atom = GetAtom(property_name.c_str()); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long remaining_bytes = 0; 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return XGetWindowProperty(gfx::GetXDisplay(), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property_atom, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // offset into property data to read 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_length, // max length to get 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) False, // deleted 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnyPropertyType, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_items, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &remaining_bytes, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A process wide singleton that manages the usage of X cursors. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XCursorCache { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCursorCache() {} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCursorCache() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Clear(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor GetCursor(int cursor_shape) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lookup cursor by attempting to insert a null value, which avoids 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a second pass through the map after a cache miss. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::make_pair(cursor_shape, 0)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it.second) { 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.first->second = XCreateFontCursor(display, cursor_shape); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it.first->second; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = base::MessagePumpForUI::GetDefaultXDisplay(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<int, ::Cursor>::iterator it = 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.begin(); it != cache_.end(); ++it) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeCursor(display, it->second); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.clear(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maps X11 font cursor shapes to Cursor IDs. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, ::Cursor> cache_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCursorCache); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)XCursorCache* cursor_cache = NULL; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A process wide singleton cache for custom X cursors. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class XCustomCursorCache { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static XCustomCursorCache* GetInstance() { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<XCustomCursorCache>::get(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor InstallCustomCursor(XcursorImage* image) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursor* custom_cursor = new XCustomCursor(image); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor xcursor = custom_cursor->cursor(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_[xcursor] = custom_cursor; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return xcursor; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Ref(::Cursor cursor) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_[cursor]->Ref(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Unref(::Cursor cursor) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cache_[cursor]->Unref()) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.erase(cursor); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_.clear(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<XCustomCursorCache>; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class XCustomCursor { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This takes ownership of the image. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursor(XcursorImage* image) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : image_(image), 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ref_(1) { 21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCustomCursor() { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImageDestroy(image_); 21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XFreeCursor(gfx::GetXDisplay(), cursor_); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor cursor() const { return cursor_; } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Ref() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ref_; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the cursor was destroyed because of the unref. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Unref() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (--ref_ == 0) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImage* image_; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ref_; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor cursor_; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCustomCursor); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache() {} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~XCustomCursorCache() { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Clear(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map< ::Cursor, XCustomCursor*> cache_; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(XCustomCursorCache); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(USE_AURA) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsShapeAvailable() { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool is_shape_available = 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XShapeQueryExtension(gfx::GetXDisplay(), &dummy, &dummy); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_shape_available; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// A list of bogus sizes in mm that X detects that should be ignored. 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// See crbug.com/136533. The first element maintains the minimum 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// size required to be valid size. 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const unsigned long kInvalidDisplaySizeList[][2] = { 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {40, 30}, 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {50, 40}, 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {160, 90}, 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {160, 100}, 271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XDisplayExists() { 27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (gfx::GetXDisplay() != NULL); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsXInput2Available() { 280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return DeviceDataManager::GetInstance()->IsXInput2Available(); 281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)static SharedMemorySupport DoQuerySharedMemorySupport(XDisplay* dpy) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bool pixmaps_supported; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Query the server's support for XSHM. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported)) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_FREEBSD) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On FreeBSD we can't access the shared memory after it was marked for 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deletion, unless this behaviour is explicitly enabled by the user. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case it's not enabled disable shared memory support. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int allow_removed; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length = sizeof(allow_removed); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((sysctlbyname("kern.ipc.shm_allow_removed", &allow_removed, &length, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 0) < 0) || allow_removed < 1) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next we probe to see if shared memory will really work 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shmkey = shmget(IPC_PRIVATE, 1, 0600); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shmkey == -1) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to get shared memory segment."; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Got shared memory segment " << shmkey; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* address = shmat(shmkey, NULL, 0); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the shared memory region for deletion 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shmctl(shmkey, IPC_RMID, NULL); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmid = shmkey; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::X11ErrorTracker err_tracker; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = XShmAttach(dpy, &shminfo); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X got shared memory segment " << shmkey; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; 326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (err_tracker.FoundNewError()) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shmdt(address); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SHARED_MEMORY_NONE; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X attached to shared memory segment " << shmkey; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmDetach(dpy, &shminfo); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)SharedMemorySupport QuerySharedMemorySupport(XDisplay* dpy) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool shared_memory_support_cached = false; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shared_memory_support_cached) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_memory_support; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_support = DoQuerySharedMemorySupport(dpy); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_memory_support_cached = true; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shared_memory_support; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool QueryRenderSupport(XDisplay* dpy) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool render_supported = false; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool render_supported_cached = false; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_supported_cached) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_supported; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't care about the version of Xrender since all the features which 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we use are included in every version. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_supported = XRenderQueryExtension(dpy, &dummy, &dummy); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_supported_cached = true; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_supported; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int GetDefaultScreen(XDisplay* display) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XDefaultScreen(display); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor GetXCursor(int cursor_shape) { 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!cursor_cache) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cursor_cache = new XCursorCache; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cursor_cache->GetCursor(cursor_shape); 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResetXCursorCache() { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete cursor_cache; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cursor_cache = NULL; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor CreateReffedCustomXCursor(XcursorImage* image) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return XCustomCursorCache::GetInstance()->InstallCustomCursor(image); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RefCustomXCursor(::Cursor cursor) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache::GetInstance()->Ref(cursor); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UnrefCustomXCursor(::Cursor cursor) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCustomCursorCache::GetInstance()->Unref(cursor); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XcursorImage* SkBitmapToXcursorImage(const SkBitmap* cursor_image, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& hotspot) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cursor_image->config() == SkBitmap::kARGB_8888_Config); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point hotspot_point = hotspot; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap scaled; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // X11 seems to have issues with cursors when images get larger than 64 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pixels. So rescale the image if necessary. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float kMaxPixel = 64.f; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool needs_scale = false; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_image->width() > kMaxPixel || cursor_image->height() > kMaxPixel) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale = 1.f; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_image->width() > cursor_image->height()) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale = kMaxPixel / cursor_image->width(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale = kMaxPixel / cursor_image->height(); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scaled = skia::ImageOperations::Resize(*cursor_image, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skia::ImageOperations::RESIZE_BETTER, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(cursor_image->width() * scale), 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(cursor_image->height() * scale)); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hotspot_point = gfx::ToFlooredPoint(gfx::ScalePoint(hotspot, scale)); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_scale = true; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SkBitmap* bitmap = needs_scale ? &scaled : cursor_image; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XcursorImage* image = XcursorImageCreate(bitmap->width(), bitmap->height()); 424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) image->xhot = std::min(bitmap->width() - 1, hotspot_point.x()); 425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) image->yhot = std::min(bitmap->height() - 1, hotspot_point.y()); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bitmap->width() && bitmap->height()) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->lockPixels(); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |bitmap| contains ARGB image, so just copy it. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(image->pixels, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->getPixels(), 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->width() * bitmap->height() * 4); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap->unlockPixels(); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return image; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CoalescePendingMotionEvents(const XEvent* xev, 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent* last_event) { 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); 44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int num_coalesced = 0; 44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = xev->xany.display; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int event_type = xev->xgeneric.evtype; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(event_type == XI_Motion || event_type == XI_TouchUpdate); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (XPending(display)) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent next_event; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XPeekEvent(display, &next_event); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't get the cookie, abort the check. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) 45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return num_coalesced; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this isn't from a valid device, throw the event away, as 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that's what the message pump would do. Device events come in pairs 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with one from the master and one from the slave so there will 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always be at least one pending. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XNextEvent(display, &next_event); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_event.type == GenericEvent && 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_event.xgeneric.evtype == event_type && 4697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !ui::DeviceDataManager::GetInstance()->IsCMTGestureEvent( 4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) &next_event)) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIDeviceEvent* next_xievent = 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<XIDeviceEvent*>(next_event.xcookie.data); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Confirm that the motion event is targeted at the same window 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and that no buttons or modifiers have changed. 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xievent->event == next_xievent->event && 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->child == next_xievent->child && 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) xievent->detail == next_xievent->detail && 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->buttons.mask_len == next_xievent->buttons.mask_len && 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (memcmp(xievent->buttons.mask, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_xievent->buttons.mask, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->buttons.mask_len) == 0) && 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.base == next_xievent->mods.base && 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.latched == next_xievent->mods.latched && 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.locked == next_xievent->mods.locked && 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xievent->mods.effective == next_xievent->mods.effective) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free the previous cookie. 48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (num_coalesced > 0) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeEventData(display, &last_event->xcookie); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the event and its cookie data. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XNextEvent(display, last_event); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetEventData(display, &last_event->xcookie); 49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ++num_coalesced; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This isn't an event we want so free its cookie data. 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) XFreeEventData(display, &next_event.xcookie); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (event_type == XI_Motion && num_coalesced > 0) { 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::TimeDelta delta = ui::EventTimeFromNative(last_event) - 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ui::EventTimeFromNative(const_cast<XEvent*>(xev)); 50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced); 50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UMA_HISTOGRAM_TIMES("Event.CoalescedLatency.Mouse", delta); 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return num_coalesced; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HideHostCursor() { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor, 51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (CreateInvisibleCursor(), gfx::GetXDisplay())); 51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDefineCursor(gfx::GetXDisplay(), DefaultRootWindow(gfx::GetXDisplay()), 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_cursor.get()); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor CreateInvisibleCursor() { 52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* xdisplay = gfx::GetXDisplay(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Cursor invisible_cursor; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XColor black; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) black.red = black.green = black.blue = 0; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Pixmap blank = XCreateBitmapFromData(xdisplay, 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultRootWindow(xdisplay), 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodata, 8, 8); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invisible_cursor = XCreatePixmapCursor(xdisplay, blank, blank, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &black, &black, 0, 0); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreePixmap(xdisplay, blank); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return invisible_cursor; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11RootWindow() { 53568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return DefaultRootWindow(gfx::GetXDisplay()); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetCurrentDesktop(int* desktop) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11WindowFromGtkWidget(GtkWidget* widget) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_WINDOW_XID(gtk_widget_get_window(widget)); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetX11WindowFromGdkWindow(GdkWindow* window) { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_WINDOW_XID(window); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GtkWindow* GetGtkWindowFromX11Window(XID xid) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkWindow* gdk_window = 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_x11_window_lookup_for_display(gdk_display_get_default(), xid); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gdk_window) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWindow* gtk_window = NULL; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_window_get_user_data(gdk_window, 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<gpointer*>(>k_window)); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gtk_window) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gtk_window; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GetVisualFromGtkWidget(GtkWidget* widget) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget)); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(TOOLKIT_GTK) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetHideTitlebarWhenMaximizedProperty(XID window, 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HideTitlebarWhenMaximized property) { 5714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // XChangeProperty() expects "hide" to be long. 5724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned long hide = property; 57368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XChangeProperty(gfx::GetXDisplay(), 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XA_CARDINAL, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32, // size in bits 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropModeReplace, 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned char*>(&hide), 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearX11DefaultRootWindow() { 58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XID root_window = GetX11RootWindow(); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect root_bounds; 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetWindowRect(root_window, &root_bounds)) { 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Failed to get the bounds of the X11 root window"; 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XGCValues gc_values = {0}; 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gc_values.foreground = BlackPixel(display, DefaultScreen(display)); 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GC gc = XCreateGC(display, root_window, GCForeground, &gc_values); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFillRectangle(display, root_window, gc, 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.x(), 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.y(), 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.width(), 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_bounds.height()); 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) XFreeGC(display, gc); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWindowVisible(XID window) { 604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("ui", "IsWindowVisible"); 605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes win_attributes; 60768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes)) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (win_attributes.map_state != IsViewable) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some compositing window managers (notably kwin) do not actually unmap 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows on desktop switch, so we also must check the current desktop. 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_desktop, current_desktop; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (!GetWindowDesktop(window, &window_desktop) || 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !GetCurrentDesktop(¤t_desktop) || 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_desktop == kAllDesktops || 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_desktop == current_desktop); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowRect(XID window, gfx::Rect* rect) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window root, child; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, y; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int width, height; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int border_width, depth; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!XGetGeometry(gfx::GetXDisplay(), window, &root, &x, &y, 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &width, &height, &border_width, &depth)) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!XTranslateCoordinates(gfx::GetXDisplay(), window, root, 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, &x, &y, &child)) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *rect = gfx::Rect(x, y, width, height); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowContainsPoint(XID window, gfx::Point screen_loc) { 640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("ui", "WindowContainsPoint"); 641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect window_rect; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWindowRect(window, &window_rect)) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window_rect.Contains(screen_loc)) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsShapeAvailable()) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // According to http://www.x.org/releases/X11R7.6/doc/libXext/shapelib.html, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if an X display supports the shape extension the bounds of a window are 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // defined as the intersection of the window bounds and the interior 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // rectangles. This means to determine if a point is inside a window for the 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // purpose of input handling we have to check the rectangles in the ShapeInput 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list. 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dummy; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int input_rects_size = 0; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRectangle* input_rects = XShapeGetRectangles( 66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!input_rects) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_in_input_rects = false; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < input_rects_size; ++i) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The ShapeInput rects appear to be in window space, so we have to 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // translate by the window_rect's offset to map to screen space. 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect input_rect = 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect(input_rects[i].x + window_rect.x(), 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_rects[i].y + window_rect.y(), 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_rects[i].width, input_rects[i].height); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input_rect.Contains(screen_loc)) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_in_input_rects = true; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(input_rects); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_in_input_rects; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PropertyExists(XID window, const std::string& property_name) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1, 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_items > 0; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool GetRawBytesOfProperty(XID window, 698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom property, 699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<base::RefCountedMemory>* out_data, 700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t* out_data_bytes, 701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t* out_data_items, 702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom* out_type) { 703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Retrieve the data from our window. 704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned long nitems = 0; 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned long nbytes = 0; 706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom prop_type = None; 707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int prop_format = 0; 708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char* property_data = NULL; 70968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (XGetWindowProperty(gfx::GetXDisplay(), window, property, 710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, 0x1FFFFFFF /* MAXINT32 / 4 */, False, 711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AnyPropertyType, &prop_type, &prop_format, 712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &nitems, &nbytes, &property_data) != Success) { 713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (prop_type == None) 717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t bytes = 0; 720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // So even though we should theoretically have nbytes (and we can't 721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // pass NULL there), we need to manually calculate the byte length here 722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // because nbytes always returns zero. 723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch switch (prop_format) { 724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case 8: 725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bytes = nitems; 726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case 16: 728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bytes = sizeof(short) * nitems; 729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case 32: 731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bytes = sizeof(long) * nitems; 732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: 734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (out_data_bytes) 739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *out_data_bytes = bytes; 740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (out_data) 742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *out_data = new XRefcountedMemory(property_data, bytes); 743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch XFree(property_data); 745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (out_data_items) 747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *out_data_items = nitems; 748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (out_type) 750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *out_type = prop_type; 751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetIntProperty(XID window, const std::string& property_name, int* value) { 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1, 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 32 || num_items != 1) { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *value = static_cast<int>(*(reinterpret_cast<long*>(property))); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool GetXIDProperty(XID window, const std::string& property_name, XID* value) { 777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom type = None; 778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int format = 0; // size in bits of each item in 'property' 779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned long num_items = 0; 780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unsigned char* property = NULL; 781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int result = GetProperty(window, property_name, 1, 783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &type, &format, &num_items, &property); 784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (result != Success) 785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (format != 32 || num_items != 1) { 788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch XFree(property); 789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *value = *(reinterpret_cast<XID*>(property)); 793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch XFree(property); 794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetIntArrayProperty(XID window, 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& property_name, 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int>* value) { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* properties = NULL; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (~0L), // (all of them) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &properties); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 32) { 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long* int_properties = reinterpret_cast<long*>(properties); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->clear(); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned long i = 0; i < num_items; ++i) { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->push_back(static_cast<int>(int_properties[i])); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAtomArrayProperty(XID window, 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& property_name, 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Atom>* value) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* properties = NULL; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (~0L), // (all of them) 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &properties); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != XA_ATOM) { 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom* atom_properties = reinterpret_cast<Atom*>(properties); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->clear(); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->insert(value->begin(), atom_properties, atom_properties + num_items); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(properties); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetStringProperty( 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID window, const std::string& property_name, std::string* value) { 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type = None; 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format = 0; // size in bits of each item in 'property' 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long num_items = 0; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* property = NULL; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GetProperty(window, property_name, 1024, 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, &format, &num_items, &property); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != Success) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (format != 8) { 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value->assign(reinterpret_cast<char*>(property), num_items); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(property); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetIntProperty(XID window, 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& type, 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value) { 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> values(1, value); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SetIntArrayProperty(window, name, type, values); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetIntArrayProperty(XID window, 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& type, 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<int>& value) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!value.empty()); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom name_atom = GetAtom(name.c_str()); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type_atom = GetAtom(type.c_str()); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XChangeProperty() expects values of type 32 to be longs. 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<long[]> data(new long[value.size()]); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < value.size(); ++i) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i] = value[i]; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::X11ErrorTracker err_tracker; 89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XChangeProperty(gfx::GetXDisplay(), 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_atom, 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_atom, 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32, // size in bits of items in 'value' 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PropModeReplace, 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const unsigned char*>(data.get()), 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.size()); // num items 903d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return !err_tracker.FoundNewError(); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool SetAtomArrayProperty(XID window, 907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& name, 908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& type, 909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::vector<Atom>& value) { 910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!value.empty()); 911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom name_atom = GetAtom(name.c_str()); 912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Atom type_atom = GetAtom(type.c_str()); 913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // XChangeProperty() expects values of type 32 to be longs. 915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<Atom[]> data(new Atom[value.size()]); 916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < value.size(); ++i) 917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data[i] = value[i]; 918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::X11ErrorTracker err_tracker; 92068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XChangeProperty(gfx::GetXDisplay(), 921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch window, 922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch name_atom, 923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch type_atom, 924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32, // size in bits of items in 'value' 925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch PropModeReplace, 926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reinterpret_cast<const unsigned char*>(data.get()), 927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch value.size()); // num items 928d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return !err_tracker.FoundNewError(); 929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Atom GetAtom(const char* name) { 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gdk_x11_get_xatom_by_name_for_display( 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_display_get_default(), name); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(derat): Cache atoms to avoid round-trips to the server. 93768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return XInternAtom(gfx::GetXDisplay(), name, false); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 94168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SetWindowClassHint(XDisplay* display, 94258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) XID window, 943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& res_name, 944f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& res_class) { 94558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) XClassHint class_hints; 94658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // const_cast is safe because XSetClassHint does not modify the strings. 94758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Just to be safe, the res_name and res_class parameters are local copies, 94858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // not const references. 94958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class_hints.res_name = const_cast<char*>(res_name.c_str()); 95058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) class_hints.res_class = const_cast<char*>(res_class.c_str()); 95158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) XSetClassHint(display, window, &class_hints); 95258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 95358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SetWindowRole(XDisplay* display, XID window, const std::string& role) { 955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (role.empty()) { 956f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) XDeleteProperty(display, window, GetAtom("WM_WINDOW_ROLE")); 957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) char* role_c = const_cast<char*>(role.c_str()); 959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) XChangeProperty(display, window, GetAtom("WM_WINDOW_ROLE"), XA_STRING, 8, 960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PropModeReplace, 961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reinterpret_cast<unsigned char*>(role_c), 962f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) role.size()); 963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 964f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetParentWindow(XID window) { 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root = None; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID parent = None; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID* children = NULL; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_children = 0; 97168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, &num_children); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (children) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(children); 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return parent; 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XID GetHighestAncestorWindow(XID window, XID root) { 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID parent = GetParentWindow(window); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent == None) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent == root) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window = parent; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowDesktop(XID window, int* desktop) { 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string GetX11ErrorString(XDisplay* display, int err) { 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[256]; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorText(display, err, buffer, arraysize(buffer)); 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |window| is a named window. 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWindowNamed(XID window) { 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XTextProperty prop; 100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!XGetWMName(gfx::GetXDisplay(), window, &prop) || !prop.value) 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(prop.value); 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window, 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_depth, int depth) { 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (depth > max_depth) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root, parent, *children; 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int num_children; 101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &num_children); 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == 0) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID> windows; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = static_cast<int>(num_children) - 1; i >= 0; i--) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows.push_back(children[i]); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(children); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // XQueryTree returns the children of |window| in bottom-to-top order, so 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reverse-iterate the list to check the windows from top-to-bottom. 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID>::iterator iter; 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = windows.begin(); iter != windows.end(); iter++) { 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter)) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're at this point, we didn't find the window we're looking for at the 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current level, so we need to recurse to the next level. We use a second 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop because the recursion and call to XQueryTree are expensive and is only 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // needed for a small number of cases. 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++depth <= max_depth) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = windows.begin(); iter != windows.end(); iter++) { 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EnumerateChildren(delegate, *iter, max_depth, depth)) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID root = GetX11RootWindow(); 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EnumerateChildren(delegate, root, max_depth, 0); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) { 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID> stack; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) { 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to old school enumeration of all X windows. Some WMs parent 'top-level' 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows in unnamed actual top-level windows (ion WM), so extend the 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // search depth to all children of top-level windows. 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxSearchDepth = 1; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::EnumerateAllWindows(delegate, kMaxSearchDepth); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<XID>::iterator iter; 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (iter = stack.begin(); iter != stack.end(); iter++) { 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate->ShouldStopIterating(*iter)) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetXWindowStack(Window window, std::vector<XID>* windows) { 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows->clear(); 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Atom type; 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int format; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long count; 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char *data = NULL; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetProperty(window, 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_NET_CLIENT_LIST_STACKING", 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~0L, 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &format, 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &count, 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &data) != Success) { 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == XA_WINDOW && format == 32 && data && count > 0) { 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID* stack = reinterpret_cast<XID*>(data); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (long i = static_cast<long>(count) - 1; i >= 0; i--) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows->push_back(stack[i]); 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(data); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RestackWindow(XID window, XID sibling, bool above) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowChanges changes; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes.sibling = sibling; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) changes.stack_mode = above ? Above : Below; 110768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XConfigureWindow(gfx::GetXDisplay(), window, CWSibling | CWStackMode, &changes); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 111068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XSharedMemoryId AttachSharedMemory(XDisplay* display, int shared_memory_key) { 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QuerySharedMemorySupport(display)); 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmid = shared_memory_key; 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function is only called if QuerySharedMemorySupport returned true. In 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which case we've already succeeded in having the X server attach to one of 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // our shared memory segments. 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmAttach(display, &shminfo)) { 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "X failed to attach to shared memory segment " 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << shminfo.shmid; 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "X attached to shared memory segment " << shminfo.shmid; 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shminfo.shmseg; 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 113168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DetachSharedMemory(XDisplay* display, XSharedMemoryId shmseg) { 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QuerySharedMemorySupport(display)); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XShmSegmentInfo shminfo; 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&shminfo, 0, sizeof(shminfo)); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shminfo.shmseg = shmseg; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XShmDetach(display, &shminfo)) 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool CopyAreaToCanvas(XID drawable, 11433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) gfx::Rect source_bounds, 11443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) gfx::Point dest_offset, 11453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) gfx::Canvas* canvas) { 11463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ui::XScopedImage scoped_image( 114768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XGetImage(gfx::GetXDisplay(), drawable, 11483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) source_bounds.x(), source_bounds.y(), 11493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) source_bounds.width(), source_bounds.height(), 11503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) AllPlanes, ZPixmap)); 11513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) XImage* image = scoped_image.get(); 11523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!image) { 11533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "XGetImage failed"; 11543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 11553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 11563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 11573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (image->bits_per_pixel == 32) { 11583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if ((0xff << SK_R32_SHIFT) != image->red_mask || 11593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (0xff << SK_G32_SHIFT) != image->green_mask || 11603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (0xff << SK_B32_SHIFT) != image->blue_mask) { 11613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(WARNING) << "XImage and Skia byte orders differ"; 11623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 11633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 11643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 11653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Set the alpha channel before copying to the canvas. Otherwise, areas of 11663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the framebuffer that were cleared by ply-image rather than being obscured 11673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // by an image during boot may end up transparent. 11683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(derat|marcheu): Remove this if/when ply-image has been updated to 11693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // set the framebuffer's alpha channel regardless of whether the device 11703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // claims to support alpha or not. 11713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (int i = 0; i < image->width * image->height * 4; i += 4) 11723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) image->data[i + 3] = 0xff; 11733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 11743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SkBitmap bitmap; 11753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bitmap.setConfig(SkBitmap::kARGB_8888_Config, 11763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) image->width, image->height, 11773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) image->bytes_per_line); 11783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bitmap.setPixels(image->data); 11793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) gfx::ImageSkia image_skia; 118068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkiaRep image_rep(bitmap, canvas->image_scale()); 11813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) image_skia.AddRepresentation(image_rep); 11823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) canvas->DrawImageInt(image_skia, dest_offset.x(), dest_offset.y()); 11833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 11843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NOTIMPLEMENTED() << "Unsupported bits-per-pixel " << image->bits_per_pixel; 11853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 11863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 11873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 11883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 11893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 11903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 119168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XID CreatePictureFromSkiaPixmap(XDisplay* display, XID pixmap) { 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XID picture = XRenderCreatePicture( 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display, pixmap, GetRenderARGB32Format(display), 0, NULL); 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return picture; 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 119868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void FreePicture(XDisplay* display, XID picture) { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderFreePicture(display, picture); 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 120268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void FreePixmap(XDisplay* display, XID pixmap) { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreePixmap(display, pixmap); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetWindowManagerName(std::string* wm_name) { 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(wm_name); 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wm_window = 0; 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetIntProperty(GetX11RootWindow(), 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_NET_SUPPORTING_WM_CHECK", 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wm_window)) { 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's possible that a window manager started earlier in this X session left 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a stale _NET_SUPPORTING_WM_CHECK property when it was replaced by a 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // non-EWMH window manager, so we trap errors in the following requests to 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avoid crashes (issue 23860). 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EWMH requires the supporting-WM window to also have a 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // _NET_SUPPORTING_WM_CHECK property pointing to itself (to avoid a stale 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // property referencing an ID that's been recycled for another window), so we 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // check that too. 12244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::X11ErrorTracker err_tracker; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wm_window_property = 0; 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = GetIntProperty( 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wm_window, "_NET_SUPPORTING_WM_CHECK", &wm_window_property); 1228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (err_tracker.FoundNewError() || !result || 1229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) wm_window_property != wm_window) { 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = GetStringProperty( 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name); 1235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return !err_tracker.FoundNewError() && result; 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowManagerName GuessWindowManager() { 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetWindowManagerName(&name)) { 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These names are taken from the WMs' source code. 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Blackbox") 12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_BLACKBOX; 12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "chromeos-wm") 12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_CHROME_OS; 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Compiz" || name == "compiz") 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_COMPIZ; 12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "e16") 12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_ENLIGHTENMENT; 12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (StartsWithASCII(name, "IceWM", true)) 12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_ICE_WM; 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "KWin") 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_KWIN; 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Metacity") 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_METACITY; 12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Mutter (Muffin)") 12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_MUFFIN; 1258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (name == "GNOME Shell") 1259a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return WM_MUTTER; // GNOME Shell uses Mutter 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Mutter") 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_MUTTER; 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name == "Openbox") 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_OPENBOX; 12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name == "Xfwm4") 12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return WM_XFWM4; 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WM_UNKNOWN; 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChangeWindowDesktop(XID window, XID destination) { 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int desktop; 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetWindowDesktop(destination, &desktop)) 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |window| is sticky, use the current desktop. 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desktop == kAllDesktops && 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !GetCurrentDesktop(&desktop)) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent event; 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.type = ClientMessage; 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.window = window; 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.message_type = GetAtom("_NET_WM_DESKTOP"); 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.format = 32; 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.data.l[0] = desktop; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.xclient.data.l[1] = 1; // source indication 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 128868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int result = XSendEvent(gfx::GetXDisplay(), GetX11RootWindow(), False, 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SubstructureNotifyMask, &event); 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result == Success; 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetDefaultX11ErrorHandlers() { 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetX11ErrorHandlers(NULL, NULL); 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsX11WindowFullScreen(XID window) { 1298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If _NET_WM_STATE_FULLSCREEN is in _NET_SUPPORTED, use the presence or 1299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // absence of _NET_WM_STATE_FULLSCREEN in _NET_WM_STATE to determine 1300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // whether we're fullscreen. 1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<Atom> supported_atoms; 1302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (GetAtomArrayProperty(GetX11RootWindow(), 1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "_NET_SUPPORTED", 1304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &supported_atoms)) { 1305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN"); 1306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (std::find(supported_atoms.begin(), supported_atoms.end(), atom) 1308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) != supported_atoms.end()) { 1309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<Atom> atom_properties; 1310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (GetAtomArrayProperty(window, 1311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "_NET_WM_STATE", 1312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &atom_properties)) { 1313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return std::find(atom_properties.begin(), atom_properties.end(), atom) 1314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) != atom_properties.end(); 1315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect window_rect; 1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!ui::GetWindowRect(window, &window_rect)) 1321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_GTK) 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As the last resort, check if the window size is as large as the main 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // screen. 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkRectangle monitor_rect; 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect); 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return monitor_rect.x == window_rect.x() && 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.y == window_rect.y() && 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.width == window_rect.width() && 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) monitor_rect.height == window_rect.height(); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // We can't use gfx::Screen here because we don't have an aura::Window. So 1335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // instead just look at the size of the default display. 1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // 1337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(erg): Actually doing this correctly would require pulling out xrandr, 1338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // which we don't even do in the desktop screen yet. 133968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ::XDisplay* display = gfx::GetXDisplay(); 1340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::Screen* screen = DefaultScreenOfDisplay(display); 1341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int width = WidthOfScreen(screen); 1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int height = HeightOfScreen(screen); 1343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return window_rect.size() == gfx::Size(width, height); 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsXDisplaySizeBlackListed(unsigned long mm_width, 1348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsigned long mm_height) { 1349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Ignore if the reported display is smaller than minimum size. 1350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mm_width <= kInvalidDisplaySizeList[0][0] || 1351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mm_height <= kInvalidDisplaySizeList[0][1]) { 1352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(WARNING) << "Smaller than minimum display size"; 1353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 1354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (unsigned long i = 1 ; i < arraysize(kInvalidDisplaySizeList); ++i) { 1356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const unsigned long* size = kInvalidDisplaySizeList[i]; 1357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mm_width == size[0] && mm_height == size[1]) { 1358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(WARNING) << "Black listed display size detected:" 1359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << size[0] << "x" << size[1]; 1360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 1361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 1364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst unsigned char* XRefcountedMemory::front() const { 1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return x11_data_; 1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochsize_t XRefcountedMemory::size() const { 1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return length_; 1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochXRefcountedMemory::~XRefcountedMemory() { 1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch XFree(x11_data_); 1376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 1377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedString::~XScopedString() { 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(string_); 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedImage::~XScopedImage() { 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset(NULL); 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void XScopedImage::reset(XImage* image) { 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_ == image) 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (image_) 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XDestroyImage(image_); 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_ = image; 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 139468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XScopedCursor::XScopedCursor(::Cursor cursor, XDisplay* display) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : cursor_(cursor), 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_(display) { 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XScopedCursor::~XScopedCursor() { 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset(0U); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::Cursor XScopedCursor::get() const { 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cursor_; 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void XScopedCursor::reset(::Cursor cursor) { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cursor_) 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeCursor(display_, cursor_); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cursor_ = cursor; 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are declared in x11_util_internal.h because they require 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// XLib.h to be included, and it conflicts with many other headers. 141668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XRenderPictFormat* GetRenderARGB32Format(XDisplay* dpy) { 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static XRenderPictFormat* pictformat = NULL; 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pictformat) 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First look for a 32-bit format which ignores the alpha value 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat templ; 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.depth = 32; 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.type = PictTypeDirect; 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.red = 16; 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.green = 8; 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.blue = 0; 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.redMask = 0xff; 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.greenMask = 0xff; 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.blueMask = 0xff; 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) templ.direct.alphaMask = 0; 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const unsigned long kMask = 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatType | PictFormatDepth | 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatRed | PictFormatRedMask | 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatGreen | PictFormatGreenMask | 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatBlue | PictFormatBlueMask | 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictFormatAlphaMask; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pictformat) { 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not all X servers support xRGB32 formats. However, the XRENDER spec says 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that they must support an ARGB32 format, so we can always return that. 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32); 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pictformat) << "XRENDER ARGB32 not supported."; 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)XRenderPictFormat* GetRenderVisualFormat(XDisplay* dpy, Visual* visual) { 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(QueryRenderSupport(dpy)); 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedPictFormats* formats = get_cached_pict_formats(); 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CachedPictFormats::const_iterator i = formats->begin(); 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != formats->end(); ++i) { 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->equals(dpy, visual)) 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->format; 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not cached, look up the value. 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XRenderPictFormat* pictformat = XRenderFindVisualFormat(dpy, visual); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(pictformat) << "XRENDER does not support default visual"; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And store it in the cache. 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedPictFormat cached_value; 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.visual = visual; 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.display = dpy; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cached_value.format = pictformat; 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats->push_front(cached_value); 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (formats->size() == kMaxCacheSize) { 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formats->pop_back(); 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should really only have at most 2 display/visual combinations: 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one for normal browser windows, and possibly another for an argb window 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created to display a menu. 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get here it's not fatal, we just need to make sure we aren't 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always blowing away the cache. If we are, then we should figure out why 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and make it bigger. 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pictformat; 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetX11ErrorHandlers(XErrorHandler error_handler, 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XIOErrorHandler io_error_handler) { 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSetIOErrorHandler( 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void LogErrorEventDescription(XDisplay* dpy, 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XErrorEvent& error_event) { 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char error_str[256]; 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char request_str[256]; 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(request_str, "Unknown", sizeof(request_str)); 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_event.request_code < 128) { 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string num = base::UintToString(error_event.request_code); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorDatabaseText( 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpy, "XRequest", num.c_str(), "Unknown", request_str, 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(request_str)); 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_ext; 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char** ext_list = XListExtensions(dpy, &num_ext); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_ext; i++) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ext_code, first_event, first_error; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_event.request_code == ext_code) { 15172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string msg = base::StringPrintf( 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s.%d", ext_list[i], error_event.minor_code); 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetErrorDatabaseText( 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dpy, "XRequest", msg.c_str(), "Unknown", request_str, 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(request_str)); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFreeExtensionList(ext_list); 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LOG(WARNING) 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "X error received: " 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "serial " << error_event.serial << ", " 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "error_code " << static_cast<int>(error_event.error_code) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" << error_str << "), " 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "request_code " << static_cast<int>(error_event.request_code) << ", " 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "minor_code " << static_cast<int>(error_event.minor_code) 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" << request_str << ")"; 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// End of x11_util_internal.h 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 1543