Home | History | Annotate | Download | only in x
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file defines utility functions for X11 (Linux only). This code has been
      6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support
      7 // remains woefully incomplete.
      8 
      9 #include "ui/base/x/x11_util.h"
     10 
     11 #include <ctype.h>
     12 #include <sys/ipc.h>
     13 #include <sys/shm.h>
     14 
     15 #include <list>
     16 #include <map>
     17 #include <utility>
     18 #include <vector>
     19 
     20 #include <X11/extensions/shape.h>
     21 #include <X11/extensions/XInput2.h>
     22 
     23 #include "base/bind.h"
     24 #include "base/command_line.h"
     25 #include "base/logging.h"
     26 #include "base/memory/scoped_ptr.h"
     27 #include "base/memory/singleton.h"
     28 #include "base/message_loop/message_loop.h"
     29 #include "base/metrics/histogram.h"
     30 #include "base/strings/string_number_conversions.h"
     31 #include "base/strings/string_util.h"
     32 #include "base/strings/stringprintf.h"
     33 #include "base/sys_byteorder.h"
     34 #include "base/threading/thread.h"
     35 #include "ui/base/events/event_utils.h"
     36 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
     37 #include "ui/base/touch/touch_factory_x11.h"
     38 #include "ui/base/x/device_data_manager.h"
     39 #include "ui/base/x/x11_util_internal.h"
     40 #include "ui/gfx/point_conversions.h"
     41 #include "ui/gfx/rect.h"
     42 #include "ui/gfx/size.h"
     43 
     44 #if defined(OS_FREEBSD)
     45 #include <sys/sysctl.h>
     46 #include <sys/types.h>
     47 #endif
     48 
     49 #if defined(USE_AURA)
     50 #include <X11/Xcursor/Xcursor.h>
     51 #include "skia/ext/image_operations.h"
     52 #include "third_party/skia/include/core/SkBitmap.h"
     53 #include "ui/gfx/skia_util.h"
     54 #endif
     55 
     56 #if defined(TOOLKIT_GTK)
     57 #include <gdk/gdk.h>
     58 #include <gdk/gdkx.h>
     59 #include <gtk/gtk.h>
     60 #include "ui/base/gtk/gdk_x_compat.h"
     61 #include "ui/base/gtk/gtk_compat.h"
     62 #else
     63 // TODO(sad): Use the new way of handling X errors when
     64 // http://codereview.chromium.org/7889040/ lands.
     65 #define gdk_error_trap_push()
     66 #define gdk_error_trap_pop() false
     67 #define gdk_flush()
     68 #endif
     69 
     70 namespace ui {
     71 
     72 namespace {
     73 
     74 // Used to cache the XRenderPictFormat for a visual/display pair.
     75 struct CachedPictFormat {
     76   bool equals(Display* display, Visual* visual) const {
     77     return display == this->display && visual == this->visual;
     78   }
     79 
     80   Display* display;
     81   Visual* visual;
     82   XRenderPictFormat* format;
     83 };
     84 
     85 typedef std::list<CachedPictFormat> CachedPictFormats;
     86 
     87 // Returns the cache of pict formats.
     88 CachedPictFormats* get_cached_pict_formats() {
     89   static CachedPictFormats* formats = NULL;
     90   if (!formats)
     91     formats = new CachedPictFormats();
     92   return formats;
     93 }
     94 
     95 // Maximum number of CachedPictFormats we keep around.
     96 const size_t kMaxCacheSize = 5;
     97 
     98 int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) {
     99   if (base::MessageLoop::current()) {
    100     base::MessageLoop::current()->PostTask(
    101         FROM_HERE, base::Bind(&LogErrorEventDescription, d, *e));
    102   } else {
    103     LOG(ERROR)
    104         << "X error received: "
    105         << "serial " << e->serial << ", "
    106         << "error_code " << static_cast<int>(e->error_code) << ", "
    107         << "request_code " << static_cast<int>(e->request_code) << ", "
    108         << "minor_code " << static_cast<int>(e->minor_code);
    109   }
    110   return 0;
    111 }
    112 
    113 int DefaultX11IOErrorHandler(Display* d) {
    114   // If there's an IO error it likely means the X server has gone away
    115   LOG(ERROR) << "X IO error received (X server probably went away)";
    116   _exit(1);
    117 }
    118 
    119 // Note: The caller should free the resulting value data.
    120 bool GetProperty(XID window, const std::string& property_name, long max_length,
    121                  Atom* type, int* format, unsigned long* num_items,
    122                  unsigned char** property) {
    123   Atom property_atom = GetAtom(property_name.c_str());
    124   unsigned long remaining_bytes = 0;
    125   return XGetWindowProperty(GetXDisplay(),
    126                             window,
    127                             property_atom,
    128                             0,          // offset into property data to read
    129                             max_length, // max length to get
    130                             False,      // deleted
    131                             AnyPropertyType,
    132                             type,
    133                             format,
    134                             num_items,
    135                             &remaining_bytes,
    136                             property);
    137 }
    138 
    139 // Converts ui::EventType to XKeyEvent state.
    140 unsigned int XKeyEventState(int flags) {
    141   return
    142       ((flags & ui::EF_SHIFT_DOWN) ? ShiftMask : 0) |
    143       ((flags & ui::EF_CONTROL_DOWN) ? ControlMask : 0) |
    144       ((flags & ui::EF_ALT_DOWN) ? Mod1Mask : 0) |
    145       ((flags & ui::EF_CAPS_LOCK_DOWN) ? LockMask : 0);
    146 }
    147 
    148 // Converts EventType to XKeyEvent type.
    149 int XKeyEventType(ui::EventType type) {
    150   switch (type) {
    151     case ui::ET_KEY_PRESSED:
    152       return KeyPress;
    153     case ui::ET_KEY_RELEASED:
    154       return KeyRelease;
    155     default:
    156       return 0;
    157   }
    158 }
    159 
    160 // Converts KeyboardCode to XKeyEvent keycode.
    161 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code,
    162                               int flags,
    163                               Display* display) {
    164   const int keysym = XKeysymForWindowsKeyCode(key_code,
    165                                               flags & ui::EF_SHIFT_DOWN);
    166   // Tests assume the keycode for XK_less is equal to the one of XK_comma,
    167   // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for
    168   // XK_comma. Here we convert the value for XK_less to the value for XK_comma.
    169   return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym);
    170 }
    171 
    172 // A process wide singleton that manages the usage of X cursors.
    173 class XCursorCache {
    174  public:
    175   XCursorCache() {}
    176   ~XCursorCache() {
    177     Clear();
    178   }
    179 
    180   ::Cursor GetCursor(int cursor_shape) {
    181     // Lookup cursor by attempting to insert a null value, which avoids
    182     // a second pass through the map after a cache miss.
    183     std::pair<std::map<int, ::Cursor>::iterator, bool> it = cache_.insert(
    184         std::make_pair(cursor_shape, 0));
    185     if (it.second) {
    186       Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
    187       it.first->second = XCreateFontCursor(display, cursor_shape);
    188     }
    189     return it.first->second;
    190   }
    191 
    192   void Clear() {
    193     Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
    194     for (std::map<int, ::Cursor>::iterator it =
    195         cache_.begin(); it != cache_.end(); ++it) {
    196       XFreeCursor(display, it->second);
    197     }
    198     cache_.clear();
    199   }
    200 
    201  private:
    202   // Maps X11 font cursor shapes to Cursor IDs.
    203   std::map<int, ::Cursor> cache_;
    204 
    205   DISALLOW_COPY_AND_ASSIGN(XCursorCache);
    206 };
    207 
    208 XCursorCache* cursor_cache = NULL;
    209 
    210 #if defined(USE_AURA)
    211 // A process wide singleton cache for custom X cursors.
    212 class XCustomCursorCache {
    213  public:
    214   static XCustomCursorCache* GetInstance() {
    215     return Singleton<XCustomCursorCache>::get();
    216   }
    217 
    218   ::Cursor InstallCustomCursor(XcursorImage* image) {
    219     XCustomCursor* custom_cursor = new XCustomCursor(image);
    220     ::Cursor xcursor = custom_cursor->cursor();
    221     cache_[xcursor] = custom_cursor;
    222     return xcursor;
    223   }
    224 
    225   void Ref(::Cursor cursor) {
    226     cache_[cursor]->Ref();
    227   }
    228 
    229   void Unref(::Cursor cursor) {
    230     if (cache_[cursor]->Unref())
    231       cache_.erase(cursor);
    232   }
    233 
    234   void Clear() {
    235     cache_.clear();
    236   }
    237 
    238  private:
    239   friend struct DefaultSingletonTraits<XCustomCursorCache>;
    240 
    241   class XCustomCursor {
    242    public:
    243     // This takes ownership of the image.
    244     XCustomCursor(XcursorImage* image)
    245         : image_(image),
    246           ref_(1) {
    247       cursor_ = XcursorImageLoadCursor(GetXDisplay(), image);
    248     }
    249 
    250     ~XCustomCursor() {
    251       XcursorImageDestroy(image_);
    252       XFreeCursor(GetXDisplay(), cursor_);
    253     }
    254 
    255     ::Cursor cursor() const { return cursor_; }
    256 
    257     void Ref() {
    258       ++ref_;
    259     }
    260 
    261     // Returns true if the cursor was destroyed because of the unref.
    262     bool Unref() {
    263       if (--ref_ == 0) {
    264         delete this;
    265         return true;
    266       }
    267       return false;
    268     }
    269 
    270    private:
    271     XcursorImage* image_;
    272     int ref_;
    273     ::Cursor cursor_;
    274 
    275     DISALLOW_COPY_AND_ASSIGN(XCustomCursor);
    276   };
    277 
    278   XCustomCursorCache() {}
    279   ~XCustomCursorCache() {
    280     Clear();
    281   }
    282 
    283   std::map< ::Cursor, XCustomCursor*> cache_;
    284   DISALLOW_COPY_AND_ASSIGN(XCustomCursorCache);
    285 };
    286 #endif  // defined(USE_AURA)
    287 
    288 // A singleton object that remembers remappings of mouse buttons.
    289 class XButtonMap {
    290  public:
    291   static XButtonMap* GetInstance() {
    292     return Singleton<XButtonMap>::get();
    293   }
    294 
    295   void UpdateMapping() {
    296     count_ = XGetPointerMapping(ui::GetXDisplay(), map_, arraysize(map_));
    297   }
    298 
    299   int GetMappedButton(int button) {
    300     return button > 0 && button <= count_ ? map_[button - 1] : button;
    301   }
    302 
    303  private:
    304   friend struct DefaultSingletonTraits<XButtonMap>;
    305 
    306   XButtonMap() {
    307     UpdateMapping();
    308   }
    309 
    310   ~XButtonMap() {}
    311 
    312   unsigned char map_[256];
    313   int count_;
    314 
    315   DISALLOW_COPY_AND_ASSIGN(XButtonMap);
    316 };
    317 
    318 bool IsShapeAvailable() {
    319   int dummy;
    320   static bool is_shape_available =
    321     XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy);
    322   return is_shape_available;
    323 
    324 }
    325 
    326 }  // namespace
    327 
    328 bool XDisplayExists() {
    329   return (GetXDisplay() != NULL);
    330 }
    331 
    332 Display* GetXDisplay() {
    333   return base::MessagePumpForUI::GetDefaultXDisplay();
    334 }
    335 
    336 static SharedMemorySupport DoQuerySharedMemorySupport(Display* dpy) {
    337   int dummy;
    338   Bool pixmaps_supported;
    339   // Query the server's support for XSHM.
    340   if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported))
    341     return SHARED_MEMORY_NONE;
    342 
    343 #if defined(OS_FREEBSD)
    344   // On FreeBSD we can't access the shared memory after it was marked for
    345   // deletion, unless this behaviour is explicitly enabled by the user.
    346   // In case it's not enabled disable shared memory support.
    347   int allow_removed;
    348   size_t length = sizeof(allow_removed);
    349 
    350   if ((sysctlbyname("kern.ipc.shm_allow_removed", &allow_removed, &length,
    351       NULL, 0) < 0) || allow_removed < 1) {
    352     return SHARED_MEMORY_NONE;
    353   }
    354 #endif
    355 
    356   // Next we probe to see if shared memory will really work
    357   int shmkey = shmget(IPC_PRIVATE, 1, 0600);
    358   if (shmkey == -1) {
    359     LOG(WARNING) << "Failed to get shared memory segment.";
    360     return SHARED_MEMORY_NONE;
    361   } else {
    362     VLOG(1) << "Got shared memory segment " << shmkey;
    363   }
    364 
    365   void* address = shmat(shmkey, NULL, 0);
    366   // Mark the shared memory region for deletion
    367   shmctl(shmkey, IPC_RMID, NULL);
    368 
    369   XShmSegmentInfo shminfo;
    370   memset(&shminfo, 0, sizeof(shminfo));
    371   shminfo.shmid = shmkey;
    372 
    373   gdk_error_trap_push();
    374   bool result = XShmAttach(dpy, &shminfo);
    375   if (result)
    376     VLOG(1) << "X got shared memory segment " << shmkey;
    377   else
    378     LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey;
    379   XSync(dpy, False);
    380   if (gdk_error_trap_pop())
    381     result = false;
    382   shmdt(address);
    383   if (!result) {
    384     LOG(WARNING) << "X failed to attach to shared memory segment " << shmkey;
    385     return SHARED_MEMORY_NONE;
    386   }
    387 
    388   VLOG(1) << "X attached to shared memory segment " << shmkey;
    389 
    390   XShmDetach(dpy, &shminfo);
    391   return pixmaps_supported ? SHARED_MEMORY_PIXMAP : SHARED_MEMORY_PUTIMAGE;
    392 }
    393 
    394 SharedMemorySupport QuerySharedMemorySupport(Display* dpy) {
    395   static SharedMemorySupport shared_memory_support = SHARED_MEMORY_NONE;
    396   static bool shared_memory_support_cached = false;
    397 
    398   if (shared_memory_support_cached)
    399     return shared_memory_support;
    400 
    401   shared_memory_support = DoQuerySharedMemorySupport(dpy);
    402   shared_memory_support_cached = true;
    403 
    404   return shared_memory_support;
    405 }
    406 
    407 bool QueryRenderSupport(Display* dpy) {
    408   static bool render_supported = false;
    409   static bool render_supported_cached = false;
    410 
    411   if (render_supported_cached)
    412     return render_supported;
    413 
    414   // We don't care about the version of Xrender since all the features which
    415   // we use are included in every version.
    416   int dummy;
    417   render_supported = XRenderQueryExtension(dpy, &dummy, &dummy);
    418   render_supported_cached = true;
    419 
    420   return render_supported;
    421 }
    422 
    423 int GetDefaultScreen(Display* display) {
    424   return XDefaultScreen(display);
    425 }
    426 
    427 ::Cursor GetXCursor(int cursor_shape) {
    428   if (!cursor_cache)
    429     cursor_cache = new XCursorCache;
    430   return cursor_cache->GetCursor(cursor_shape);
    431 }
    432 
    433 void ResetXCursorCache() {
    434   delete cursor_cache;
    435   cursor_cache = NULL;
    436 }
    437 
    438 #if defined(USE_AURA)
    439 ::Cursor CreateReffedCustomXCursor(XcursorImage* image) {
    440   return XCustomCursorCache::GetInstance()->InstallCustomCursor(image);
    441 }
    442 
    443 void RefCustomXCursor(::Cursor cursor) {
    444   XCustomCursorCache::GetInstance()->Ref(cursor);
    445 }
    446 
    447 void UnrefCustomXCursor(::Cursor cursor) {
    448   XCustomCursorCache::GetInstance()->Unref(cursor);
    449 }
    450 
    451 XcursorImage* SkBitmapToXcursorImage(const SkBitmap* cursor_image,
    452                                      const gfx::Point& hotspot) {
    453   DCHECK(cursor_image->config() == SkBitmap::kARGB_8888_Config);
    454   gfx::Point hotspot_point = hotspot;
    455   SkBitmap scaled;
    456 
    457   // X11 seems to have issues with cursors when images get larger than 64
    458   // pixels. So rescale the image if necessary.
    459   const float kMaxPixel = 64.f;
    460   bool needs_scale = false;
    461   if (cursor_image->width() > kMaxPixel || cursor_image->height() > kMaxPixel) {
    462     float scale = 1.f;
    463     if (cursor_image->width() > cursor_image->height())
    464       scale = kMaxPixel / cursor_image->width();
    465     else
    466       scale = kMaxPixel / cursor_image->height();
    467 
    468     scaled = skia::ImageOperations::Resize(*cursor_image,
    469         skia::ImageOperations::RESIZE_BETTER,
    470         static_cast<int>(cursor_image->width() * scale),
    471         static_cast<int>(cursor_image->height() * scale));
    472     hotspot_point = gfx::ToFlooredPoint(gfx::ScalePoint(hotspot, scale));
    473     needs_scale = true;
    474   }
    475 
    476   const SkBitmap* bitmap = needs_scale ? &scaled : cursor_image;
    477   XcursorImage* image = XcursorImageCreate(bitmap->width(), bitmap->height());
    478   image->xhot = std::min(bitmap->width() - 1, hotspot_point.x());
    479   image->yhot = std::min(bitmap->height() - 1, hotspot_point.y());
    480 
    481   if (bitmap->width() && bitmap->height()) {
    482     bitmap->lockPixels();
    483     // The |bitmap| contains ARGB image, so just copy it.
    484     memcpy(image->pixels,
    485            bitmap->getPixels(),
    486            bitmap->width() * bitmap->height() * 4);
    487     bitmap->unlockPixels();
    488   }
    489 
    490   return image;
    491 }
    492 
    493 
    494 int CoalescePendingMotionEvents(const XEvent* xev,
    495                                 XEvent* last_event) {
    496   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
    497   int num_coalesced = 0;
    498   Display* display = xev->xany.display;
    499   int event_type = xev->xgeneric.evtype;
    500 
    501   DCHECK_EQ(event_type, XI_Motion);
    502 
    503   while (XPending(display)) {
    504     XEvent next_event;
    505     XPeekEvent(display, &next_event);
    506 
    507     // If we can't get the cookie, abort the check.
    508     if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie))
    509       return num_coalesced;
    510 
    511     // If this isn't from a valid device, throw the event away, as
    512     // that's what the message pump would do. Device events come in pairs
    513     // with one from the master and one from the slave so there will
    514     // always be at least one pending.
    515     if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(&next_event)) {
    516       XFreeEventData(display, &next_event.xcookie);
    517       XNextEvent(display, &next_event);
    518       continue;
    519     }
    520 
    521     if (next_event.type == GenericEvent &&
    522         next_event.xgeneric.evtype == event_type &&
    523         !ui::DeviceDataManager::GetInstance()->IsCMTGestureEvent(
    524             &next_event)) {
    525       XIDeviceEvent* next_xievent =
    526           static_cast<XIDeviceEvent*>(next_event.xcookie.data);
    527       // Confirm that the motion event is targeted at the same window
    528       // and that no buttons or modifiers have changed.
    529       if (xievent->event == next_xievent->event &&
    530           xievent->child == next_xievent->child &&
    531           xievent->buttons.mask_len == next_xievent->buttons.mask_len &&
    532           (memcmp(xievent->buttons.mask,
    533                   next_xievent->buttons.mask,
    534                   xievent->buttons.mask_len) == 0) &&
    535           xievent->mods.base == next_xievent->mods.base &&
    536           xievent->mods.latched == next_xievent->mods.latched &&
    537           xievent->mods.locked == next_xievent->mods.locked &&
    538           xievent->mods.effective == next_xievent->mods.effective) {
    539         XFreeEventData(display, &next_event.xcookie);
    540         // Free the previous cookie.
    541         if (num_coalesced > 0)
    542           XFreeEventData(display, &last_event->xcookie);
    543         // Get the event and its cookie data.
    544         XNextEvent(display, last_event);
    545         XGetEventData(display, &last_event->xcookie);
    546         ++num_coalesced;
    547         continue;
    548       } else {
    549         // This isn't an event we want so free its cookie data.
    550         XFreeEventData(display, &next_event.xcookie);
    551       }
    552     }
    553     break;
    554   }
    555 
    556   if (num_coalesced > 0) {
    557     base::TimeDelta delta = ui::EventTimeFromNative(last_event) -
    558         ui::EventTimeFromNative(const_cast<XEvent*>(xev));
    559     UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced);
    560     UMA_HISTOGRAM_TIMES("Event.CoalescedLatency.Mouse", delta);
    561   }
    562   return num_coalesced;
    563 }
    564 #endif
    565 
    566 void HideHostCursor() {
    567   CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor,
    568                          (CreateInvisibleCursor(), ui::GetXDisplay()));
    569   XDefineCursor(ui::GetXDisplay(), DefaultRootWindow(ui::GetXDisplay()),
    570                 invisible_cursor.get());
    571 }
    572 
    573 ::Cursor CreateInvisibleCursor() {
    574   Display* xdisplay = ui::GetXDisplay();
    575   ::Cursor invisible_cursor;
    576   char nodata[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    577   XColor black;
    578   black.red = black.green = black.blue = 0;
    579   Pixmap blank = XCreateBitmapFromData(xdisplay,
    580                                        DefaultRootWindow(xdisplay),
    581                                        nodata, 8, 8);
    582   invisible_cursor = XCreatePixmapCursor(xdisplay, blank, blank,
    583                                          &black, &black, 0, 0);
    584   XFreePixmap(xdisplay, blank);
    585   return invisible_cursor;
    586 }
    587 
    588 XID GetX11RootWindow() {
    589   return DefaultRootWindow(GetXDisplay());
    590 }
    591 
    592 bool GetCurrentDesktop(int* desktop) {
    593   return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop);
    594 }
    595 
    596 #if defined(TOOLKIT_GTK)
    597 XID GetX11WindowFromGtkWidget(GtkWidget* widget) {
    598   return GDK_WINDOW_XID(gtk_widget_get_window(widget));
    599 }
    600 
    601 XID GetX11WindowFromGdkWindow(GdkWindow* window) {
    602   return GDK_WINDOW_XID(window);
    603 }
    604 
    605 GtkWindow* GetGtkWindowFromX11Window(XID xid) {
    606   GdkWindow* gdk_window =
    607       gdk_x11_window_lookup_for_display(gdk_display_get_default(), xid);
    608   if (!gdk_window)
    609     return NULL;
    610   GtkWindow* gtk_window = NULL;
    611   gdk_window_get_user_data(gdk_window,
    612                            reinterpret_cast<gpointer*>(&gtk_window));
    613   if (!gtk_window)
    614     return NULL;
    615   return gtk_window;
    616 }
    617 
    618 void* GetVisualFromGtkWidget(GtkWidget* widget) {
    619   return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget));
    620 }
    621 #endif  // defined(TOOLKIT_GTK)
    622 
    623 void SetHideTitlebarWhenMaximizedProperty(XID window,
    624                                           HideTitlebarWhenMaximized property) {
    625   uint32 hide = property;
    626   XChangeProperty(GetXDisplay(),
    627       window,
    628       GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
    629       XA_CARDINAL,
    630       32,  // size in bits
    631       PropModeReplace,
    632       reinterpret_cast<unsigned char*>(&hide),
    633       1);
    634 }
    635 
    636 void ClearX11DefaultRootWindow() {
    637   Display* display = GetXDisplay();
    638   XID root_window = GetX11RootWindow();
    639   gfx::Rect root_bounds;
    640   if (!GetWindowRect(root_window, &root_bounds)) {
    641     LOG(ERROR) << "Failed to get the bounds of the X11 root window";
    642     return;
    643   }
    644 
    645   XGCValues gc_values = {0};
    646   gc_values.foreground = BlackPixel(display, DefaultScreen(display));
    647   GC gc = XCreateGC(display, root_window, GCForeground, &gc_values);
    648   XFillRectangle(display, root_window, gc,
    649                  root_bounds.x(),
    650                  root_bounds.y(),
    651                  root_bounds.width(),
    652                  root_bounds.height());
    653   XFreeGC(display, gc);
    654 }
    655 
    656 int BitsPerPixelForPixmapDepth(Display* dpy, int depth) {
    657   int count;
    658   XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count);
    659   if (!formats)
    660     return -1;
    661 
    662   int bits_per_pixel = -1;
    663   for (int i = 0; i < count; ++i) {
    664     if (formats[i].depth == depth) {
    665       bits_per_pixel = formats[i].bits_per_pixel;
    666       break;
    667     }
    668   }
    669 
    670   XFree(formats);
    671   return bits_per_pixel;
    672 }
    673 
    674 bool IsWindowVisible(XID window) {
    675   XWindowAttributes win_attributes;
    676   if (!XGetWindowAttributes(GetXDisplay(), window, &win_attributes))
    677     return false;
    678   if (win_attributes.map_state != IsViewable)
    679     return false;
    680   // Some compositing window managers (notably kwin) do not actually unmap
    681   // windows on desktop switch, so we also must check the current desktop.
    682   int window_desktop, current_desktop;
    683   return (!GetWindowDesktop(window, &window_desktop) ||
    684           !GetCurrentDesktop(&current_desktop) ||
    685           window_desktop == kAllDesktops ||
    686           window_desktop == current_desktop);
    687 }
    688 
    689 bool GetWindowRect(XID window, gfx::Rect* rect) {
    690   Window root, child;
    691   int x, y;
    692   unsigned int width, height;
    693   unsigned int border_width, depth;
    694 
    695   if (!XGetGeometry(GetXDisplay(), window, &root, &x, &y,
    696                     &width, &height, &border_width, &depth))
    697     return false;
    698 
    699   if (!XTranslateCoordinates(GetXDisplay(), window, root,
    700                              0, 0, &x, &y, &child))
    701     return false;
    702 
    703   *rect = gfx::Rect(x, y, width, height);
    704   return true;
    705 }
    706 
    707 
    708 bool WindowContainsPoint(XID window, gfx::Point screen_loc) {
    709   gfx::Rect window_rect;
    710   if (!GetWindowRect(window, &window_rect))
    711     return false;
    712 
    713   if (!window_rect.Contains(screen_loc))
    714     return false;
    715 
    716   if (!IsShapeAvailable())
    717     return true;
    718 
    719   // According to http://www.x.org/releases/X11R7.6/doc/libXext/shapelib.html,
    720   // if an X display supports the shape extension the bounds of a window are
    721   // defined as the intersection of the window bounds and the interior
    722   // rectangles. This means to determine if a point is inside a window for the
    723   // purpose of input handling we have to check the rectangles in the ShapeInput
    724   // list.
    725   int dummy;
    726   int input_rects_size = 0;
    727   XRectangle* input_rects = XShapeGetRectangles(
    728       ui::GetXDisplay(), window, ShapeInput, &input_rects_size, &dummy);
    729   if (!input_rects)
    730     return true;
    731   bool is_in_input_rects = false;
    732   for (int i = 0; i < input_rects_size; ++i) {
    733     // The ShapeInput rects appear to be in window space, so we have to
    734     // translate by the window_rect's offset to map to screen space.
    735     gfx::Rect input_rect =
    736         gfx::Rect(input_rects[i].x + window_rect.x(),
    737                   input_rects[i].y + window_rect.y(),
    738                   input_rects[i].width, input_rects[i].height);
    739     if (input_rect.Contains(screen_loc)) {
    740       is_in_input_rects = true;
    741       break;
    742     }
    743   }
    744   XFree(input_rects);
    745   return is_in_input_rects;
    746 }
    747 
    748 
    749 bool PropertyExists(XID window, const std::string& property_name) {
    750   Atom type = None;
    751   int format = 0;  // size in bits of each item in 'property'
    752   unsigned long num_items = 0;
    753   unsigned char* property = NULL;
    754 
    755   int result = GetProperty(window, property_name, 1,
    756                            &type, &format, &num_items, &property);
    757   if (result != Success)
    758     return false;
    759 
    760   XFree(property);
    761   return num_items > 0;
    762 }
    763 
    764 bool GetRawBytesOfProperty(XID window,
    765                            Atom property,
    766                            scoped_refptr<base::RefCountedMemory>* out_data,
    767                            size_t* out_data_bytes,
    768                            size_t* out_data_items,
    769                            Atom* out_type) {
    770   // Retrieve the data from our window.
    771   unsigned long nitems = 0;
    772   unsigned long nbytes = 0;
    773   Atom prop_type = None;
    774   int prop_format = 0;
    775   unsigned char* property_data = NULL;
    776   if (XGetWindowProperty(GetXDisplay(), window, property,
    777                          0, 0x1FFFFFFF /* MAXINT32 / 4 */, False,
    778                          AnyPropertyType, &prop_type, &prop_format,
    779                          &nitems, &nbytes, &property_data) != Success) {
    780     return false;
    781   }
    782 
    783   if (prop_type == None)
    784     return false;
    785 
    786   size_t bytes = 0;
    787   // So even though we should theoretically have nbytes (and we can't
    788   // pass NULL there), we need to manually calculate the byte length here
    789   // because nbytes always returns zero.
    790   switch (prop_format) {
    791     case 8:
    792       bytes = nitems;
    793       break;
    794     case 16:
    795       bytes = sizeof(short) * nitems;
    796       break;
    797     case 32:
    798       bytes = sizeof(long) * nitems;
    799       break;
    800     default:
    801       NOTREACHED();
    802       break;
    803   }
    804 
    805   if (out_data_bytes)
    806     *out_data_bytes = bytes;
    807 
    808   if (out_data)
    809     *out_data = new XRefcountedMemory(property_data, bytes);
    810   else
    811     XFree(property_data);
    812 
    813   if (out_data_items)
    814     *out_data_items = nitems;
    815 
    816   if (out_type)
    817     *out_type = prop_type;
    818 
    819   return true;
    820 }
    821 
    822 bool GetIntProperty(XID window, const std::string& property_name, int* value) {
    823   Atom type = None;
    824   int format = 0;  // size in bits of each item in 'property'
    825   unsigned long num_items = 0;
    826   unsigned char* property = NULL;
    827 
    828   int result = GetProperty(window, property_name, 1,
    829                            &type, &format, &num_items, &property);
    830   if (result != Success)
    831     return false;
    832 
    833   if (format != 32 || num_items != 1) {
    834     XFree(property);
    835     return false;
    836   }
    837 
    838   *value = static_cast<int>(*(reinterpret_cast<long*>(property)));
    839   XFree(property);
    840   return true;
    841 }
    842 
    843 bool GetXIDProperty(XID window, const std::string& property_name, XID* value) {
    844   Atom type = None;
    845   int format = 0;  // size in bits of each item in 'property'
    846   unsigned long num_items = 0;
    847   unsigned char* property = NULL;
    848 
    849   int result = GetProperty(window, property_name, 1,
    850                            &type, &format, &num_items, &property);
    851   if (result != Success)
    852     return false;
    853 
    854   if (format != 32 || num_items != 1) {
    855     XFree(property);
    856     return false;
    857   }
    858 
    859   *value = *(reinterpret_cast<XID*>(property));
    860   XFree(property);
    861   return true;
    862 }
    863 
    864 bool GetIntArrayProperty(XID window,
    865                          const std::string& property_name,
    866                          std::vector<int>* value) {
    867   Atom type = None;
    868   int format = 0;  // size in bits of each item in 'property'
    869   unsigned long num_items = 0;
    870   unsigned char* properties = NULL;
    871 
    872   int result = GetProperty(window, property_name,
    873                            (~0L), // (all of them)
    874                            &type, &format, &num_items, &properties);
    875   if (result != Success)
    876     return false;
    877 
    878   if (format != 32) {
    879     XFree(properties);
    880     return false;
    881   }
    882 
    883   long* int_properties = reinterpret_cast<long*>(properties);
    884   value->clear();
    885   for (unsigned long i = 0; i < num_items; ++i) {
    886     value->push_back(static_cast<int>(int_properties[i]));
    887   }
    888   XFree(properties);
    889   return true;
    890 }
    891 
    892 bool GetAtomArrayProperty(XID window,
    893                           const std::string& property_name,
    894                           std::vector<Atom>* value) {
    895   Atom type = None;
    896   int format = 0;  // size in bits of each item in 'property'
    897   unsigned long num_items = 0;
    898   unsigned char* properties = NULL;
    899 
    900   int result = GetProperty(window, property_name,
    901                            (~0L), // (all of them)
    902                            &type, &format, &num_items, &properties);
    903   if (result != Success)
    904     return false;
    905 
    906   if (type != XA_ATOM) {
    907     XFree(properties);
    908     return false;
    909   }
    910 
    911   Atom* atom_properties = reinterpret_cast<Atom*>(properties);
    912   value->clear();
    913   value->insert(value->begin(), atom_properties, atom_properties + num_items);
    914   XFree(properties);
    915   return true;
    916 }
    917 
    918 bool GetStringProperty(
    919     XID window, const std::string& property_name, std::string* value) {
    920   Atom type = None;
    921   int format = 0;  // size in bits of each item in 'property'
    922   unsigned long num_items = 0;
    923   unsigned char* property = NULL;
    924 
    925   int result = GetProperty(window, property_name, 1024,
    926                            &type, &format, &num_items, &property);
    927   if (result != Success)
    928     return false;
    929 
    930   if (format != 8) {
    931     XFree(property);
    932     return false;
    933   }
    934 
    935   value->assign(reinterpret_cast<char*>(property), num_items);
    936   XFree(property);
    937   return true;
    938 }
    939 
    940 bool SetIntProperty(XID window,
    941                     const std::string& name,
    942                     const std::string& type,
    943                     int value) {
    944   std::vector<int> values(1, value);
    945   return SetIntArrayProperty(window, name, type, values);
    946 }
    947 
    948 bool SetIntArrayProperty(XID window,
    949                          const std::string& name,
    950                          const std::string& type,
    951                          const std::vector<int>& value) {
    952   DCHECK(!value.empty());
    953   Atom name_atom = GetAtom(name.c_str());
    954   Atom type_atom = GetAtom(type.c_str());
    955 
    956   // XChangeProperty() expects values of type 32 to be longs.
    957   scoped_ptr<long[]> data(new long[value.size()]);
    958   for (size_t i = 0; i < value.size(); ++i)
    959     data[i] = value[i];
    960 
    961   gdk_error_trap_push();
    962   XChangeProperty(ui::GetXDisplay(),
    963                   window,
    964                   name_atom,
    965                   type_atom,
    966                   32,  // size in bits of items in 'value'
    967                   PropModeReplace,
    968                   reinterpret_cast<const unsigned char*>(data.get()),
    969                   value.size());  // num items
    970   XSync(ui::GetXDisplay(), False);
    971   return gdk_error_trap_pop() == 0;
    972 }
    973 
    974 bool SetAtomArrayProperty(XID window,
    975                           const std::string& name,
    976                           const std::string& type,
    977                           const std::vector<Atom>& value) {
    978   DCHECK(!value.empty());
    979   Atom name_atom = GetAtom(name.c_str());
    980   Atom type_atom = GetAtom(type.c_str());
    981 
    982   // XChangeProperty() expects values of type 32 to be longs.
    983   scoped_ptr<Atom[]> data(new Atom[value.size()]);
    984   for (size_t i = 0; i < value.size(); ++i)
    985     data[i] = value[i];
    986 
    987   gdk_error_trap_push();
    988   XChangeProperty(ui::GetXDisplay(),
    989                   window,
    990                   name_atom,
    991                   type_atom,
    992                   32,  // size in bits of items in 'value'
    993                   PropModeReplace,
    994                   reinterpret_cast<const unsigned char*>(data.get()),
    995                   value.size());  // num items
    996   XSync(ui::GetXDisplay(), False);
    997   return gdk_error_trap_pop() == 0;
    998 }
    999 
   1000 Atom GetAtom(const char* name) {
   1001 #if defined(TOOLKIT_GTK)
   1002   return gdk_x11_get_xatom_by_name_for_display(
   1003       gdk_display_get_default(), name);
   1004 #else
   1005   // TODO(derat): Cache atoms to avoid round-trips to the server.
   1006   return XInternAtom(GetXDisplay(), name, false);
   1007 #endif
   1008 }
   1009 
   1010 XID GetParentWindow(XID window) {
   1011   XID root = None;
   1012   XID parent = None;
   1013   XID* children = NULL;
   1014   unsigned int num_children = 0;
   1015   XQueryTree(GetXDisplay(), window, &root, &parent, &children, &num_children);
   1016   if (children)
   1017     XFree(children);
   1018   return parent;
   1019 }
   1020 
   1021 XID GetHighestAncestorWindow(XID window, XID root) {
   1022   while (true) {
   1023     XID parent = GetParentWindow(window);
   1024     if (parent == None)
   1025       return None;
   1026     if (parent == root)
   1027       return window;
   1028     window = parent;
   1029   }
   1030 }
   1031 
   1032 bool GetWindowDesktop(XID window, int* desktop) {
   1033   return GetIntProperty(window, "_NET_WM_DESKTOP", desktop);
   1034 }
   1035 
   1036 std::string GetX11ErrorString(Display* display, int err) {
   1037   char buffer[256];
   1038   XGetErrorText(display, err, buffer, arraysize(buffer));
   1039   return buffer;
   1040 }
   1041 
   1042 // Returns true if |window| is a named window.
   1043 bool IsWindowNamed(XID window) {
   1044   XTextProperty prop;
   1045   if (!XGetWMName(GetXDisplay(), window, &prop) || !prop.value)
   1046     return false;
   1047 
   1048   XFree(prop.value);
   1049   return true;
   1050 }
   1051 
   1052 bool EnumerateChildren(EnumerateWindowsDelegate* delegate, XID window,
   1053                        const int max_depth, int depth) {
   1054   if (depth > max_depth)
   1055     return false;
   1056 
   1057   XID root, parent, *children;
   1058   unsigned int num_children;
   1059   int status = XQueryTree(GetXDisplay(), window, &root, &parent, &children,
   1060                           &num_children);
   1061   if (status == 0)
   1062     return false;
   1063 
   1064   std::vector<XID> windows;
   1065   for (int i = static_cast<int>(num_children) - 1; i >= 0; i--)
   1066     windows.push_back(children[i]);
   1067 
   1068   XFree(children);
   1069 
   1070   // XQueryTree returns the children of |window| in bottom-to-top order, so
   1071   // reverse-iterate the list to check the windows from top-to-bottom.
   1072   std::vector<XID>::iterator iter;
   1073   for (iter = windows.begin(); iter != windows.end(); iter++) {
   1074     if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter))
   1075       return true;
   1076   }
   1077 
   1078   // If we're at this point, we didn't find the window we're looking for at the
   1079   // current level, so we need to recurse to the next level.  We use a second
   1080   // loop because the recursion and call to XQueryTree are expensive and is only
   1081   // needed for a small number of cases.
   1082   if (++depth <= max_depth) {
   1083     for (iter = windows.begin(); iter != windows.end(); iter++) {
   1084       if (EnumerateChildren(delegate, *iter, max_depth, depth))
   1085         return true;
   1086     }
   1087   }
   1088 
   1089   return false;
   1090 }
   1091 
   1092 bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) {
   1093   XID root = GetX11RootWindow();
   1094   return EnumerateChildren(delegate, root, max_depth, 0);
   1095 }
   1096 
   1097 void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) {
   1098   std::vector<XID> stack;
   1099   if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) {
   1100     // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back
   1101     // to old school enumeration of all X windows.  Some WMs parent 'top-level'
   1102     // windows in unnamed actual top-level windows (ion WM), so extend the
   1103     // search depth to all children of top-level windows.
   1104     const int kMaxSearchDepth = 1;
   1105     ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
   1106     return;
   1107   }
   1108 
   1109   std::vector<XID>::iterator iter;
   1110   for (iter = stack.begin(); iter != stack.end(); iter++) {
   1111     if (delegate->ShouldStopIterating(*iter))
   1112       return;
   1113   }
   1114 }
   1115 
   1116 bool GetXWindowStack(Window window, std::vector<XID>* windows) {
   1117   windows->clear();
   1118 
   1119   Atom type;
   1120   int format;
   1121   unsigned long count;
   1122   unsigned char *data = NULL;
   1123   if (GetProperty(window,
   1124                   "_NET_CLIENT_LIST_STACKING",
   1125                   ~0L,
   1126                   &type,
   1127                   &format,
   1128                   &count,
   1129                   &data) != Success) {
   1130     return false;
   1131   }
   1132 
   1133   bool result = false;
   1134   if (type == XA_WINDOW && format == 32 && data && count > 0) {
   1135     result = true;
   1136     XID* stack = reinterpret_cast<XID*>(data);
   1137     for (long i = static_cast<long>(count) - 1; i >= 0; i--)
   1138       windows->push_back(stack[i]);
   1139   }
   1140 
   1141   if (data)
   1142     XFree(data);
   1143 
   1144   return result;
   1145 }
   1146 
   1147 void RestackWindow(XID window, XID sibling, bool above) {
   1148   XWindowChanges changes;
   1149   changes.sibling = sibling;
   1150   changes.stack_mode = above ? Above : Below;
   1151   XConfigureWindow(GetXDisplay(), window, CWSibling | CWStackMode, &changes);
   1152 }
   1153 
   1154 XSharedMemoryId AttachSharedMemory(Display* display, int shared_memory_key) {
   1155   DCHECK(QuerySharedMemorySupport(display));
   1156 
   1157   XShmSegmentInfo shminfo;
   1158   memset(&shminfo, 0, sizeof(shminfo));
   1159   shminfo.shmid = shared_memory_key;
   1160 
   1161   // This function is only called if QuerySharedMemorySupport returned true. In
   1162   // which case we've already succeeded in having the X server attach to one of
   1163   // our shared memory segments.
   1164   if (!XShmAttach(display, &shminfo)) {
   1165     LOG(WARNING) << "X failed to attach to shared memory segment "
   1166                  << shminfo.shmid;
   1167     NOTREACHED();
   1168   } else {
   1169     VLOG(1) << "X attached to shared memory segment " << shminfo.shmid;
   1170   }
   1171 
   1172   return shminfo.shmseg;
   1173 }
   1174 
   1175 void DetachSharedMemory(Display* display, XSharedMemoryId shmseg) {
   1176   DCHECK(QuerySharedMemorySupport(display));
   1177 
   1178   XShmSegmentInfo shminfo;
   1179   memset(&shminfo, 0, sizeof(shminfo));
   1180   shminfo.shmseg = shmseg;
   1181 
   1182   if (!XShmDetach(display, &shminfo))
   1183     NOTREACHED();
   1184 }
   1185 
   1186 XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) {
   1187   XID picture = XRenderCreatePicture(
   1188       display, pixmap, GetRenderARGB32Format(display), 0, NULL);
   1189 
   1190   return picture;
   1191 }
   1192 
   1193 void PutARGBImage(Display* display,
   1194                   void* visual, int depth,
   1195                   XID pixmap, void* pixmap_gc,
   1196                   const uint8* data,
   1197                   int width, int height) {
   1198   PutARGBImage(display,
   1199                visual, depth,
   1200                pixmap, pixmap_gc,
   1201                data, width, height,
   1202                0, 0, // src_x, src_y
   1203                0, 0, // dst_x, dst_y
   1204                width, height);
   1205 }
   1206 
   1207 void PutARGBImage(Display* display,
   1208                   void* visual, int depth,
   1209                   XID pixmap, void* pixmap_gc,
   1210                   const uint8* data,
   1211                   int data_width, int data_height,
   1212                   int src_x, int src_y,
   1213                   int dst_x, int dst_y,
   1214                   int copy_width, int copy_height) {
   1215   // TODO(scherkus): potential performance impact... consider passing in as a
   1216   // parameter.
   1217   int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
   1218 
   1219   XImage image;
   1220   memset(&image, 0, sizeof(image));
   1221 
   1222   image.width = data_width;
   1223   image.height = data_height;
   1224   image.format = ZPixmap;
   1225   image.byte_order = LSBFirst;
   1226   image.bitmap_unit = 8;
   1227   image.bitmap_bit_order = LSBFirst;
   1228   image.depth = depth;
   1229   image.bits_per_pixel = pixmap_bpp;
   1230   image.bytes_per_line = data_width * pixmap_bpp / 8;
   1231 
   1232   if (pixmap_bpp == 32) {
   1233     image.red_mask = 0xff0000;
   1234     image.green_mask = 0xff00;
   1235     image.blue_mask = 0xff;
   1236 
   1237     // If the X server depth is already 32-bits and the color masks match,
   1238     // then our job is easy.
   1239     Visual* vis = static_cast<Visual*>(visual);
   1240     if (image.red_mask == vis->red_mask &&
   1241         image.green_mask == vis->green_mask &&
   1242         image.blue_mask == vis->blue_mask) {
   1243       image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
   1244       XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
   1245                 src_x, src_y, dst_x, dst_y,
   1246                 copy_width, copy_height);
   1247     } else {
   1248       // Otherwise, we need to shuffle the colors around. Assume red and blue
   1249       // need to be swapped.
   1250       //
   1251       // It's possible to use some fancy SSE tricks here, but since this is the
   1252       // slow path anyway, we do it slowly.
   1253 
   1254       uint8_t* bitmap32 =
   1255           static_cast<uint8_t*>(malloc(4 * data_width * data_height));
   1256       if (!bitmap32)
   1257         return;
   1258       uint8_t* const orig_bitmap32 = bitmap32;
   1259       const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
   1260       for (int y = 0; y < data_height; ++y) {
   1261         for (int x = 0; x < data_width; ++x) {
   1262           const uint32_t pixel = *(bitmap_in++);
   1263           bitmap32[0] = (pixel >> 16) & 0xff;  // Red
   1264           bitmap32[1] = (pixel >> 8) & 0xff;   // Green
   1265           bitmap32[2] = pixel & 0xff;          // Blue
   1266           bitmap32[3] = (pixel >> 24) & 0xff;  // Alpha
   1267           bitmap32 += 4;
   1268         }
   1269       }
   1270       image.data = reinterpret_cast<char*>(orig_bitmap32);
   1271       XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
   1272                 src_x, src_y, dst_x, dst_y,
   1273                 copy_width, copy_height);
   1274       free(orig_bitmap32);
   1275     }
   1276   } else if (pixmap_bpp == 16) {
   1277     // Some folks have VNC setups which still use 16-bit visuals and VNC
   1278     // doesn't include Xrender.
   1279 
   1280     uint16_t* bitmap16 =
   1281         static_cast<uint16_t*>(malloc(2 * data_width * data_height));
   1282     if (!bitmap16)
   1283       return;
   1284     uint16_t* const orig_bitmap16 = bitmap16;
   1285     const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
   1286     for (int y = 0; y < data_height; ++y) {
   1287       for (int x = 0; x < data_width; ++x) {
   1288         const uint32_t pixel = *(bitmap_in++);
   1289         uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
   1290                              ((pixel >> 5) & 0x07e0) |
   1291                              ((pixel >> 3) & 0x001f);
   1292         *(bitmap16++) = out_pixel;
   1293       }
   1294     }
   1295 
   1296     image.data = reinterpret_cast<char*>(orig_bitmap16);
   1297     image.red_mask = 0xf800;
   1298     image.green_mask = 0x07e0;
   1299     image.blue_mask = 0x001f;
   1300 
   1301     XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
   1302               src_x, src_y, dst_x, dst_y,
   1303               copy_width, copy_height);
   1304     free(orig_bitmap16);
   1305   } else {
   1306     LOG(FATAL) << "Sorry, we don't support your visual depth without "
   1307                   "Xrender support (depth:" << depth
   1308                << " bpp:" << pixmap_bpp << ")";
   1309   }
   1310 }
   1311 
   1312 void FreePicture(Display* display, XID picture) {
   1313   XRenderFreePicture(display, picture);
   1314 }
   1315 
   1316 void FreePixmap(Display* display, XID pixmap) {
   1317   XFreePixmap(display, pixmap);
   1318 }
   1319 
   1320 bool GetWindowManagerName(std::string* wm_name) {
   1321   DCHECK(wm_name);
   1322   int wm_window = 0;
   1323   if (!GetIntProperty(GetX11RootWindow(),
   1324                       "_NET_SUPPORTING_WM_CHECK",
   1325                       &wm_window)) {
   1326     return false;
   1327   }
   1328 
   1329   // It's possible that a window manager started earlier in this X session left
   1330   // a stale _NET_SUPPORTING_WM_CHECK property when it was replaced by a
   1331   // non-EWMH window manager, so we trap errors in the following requests to
   1332   // avoid crashes (issue 23860).
   1333 
   1334   // EWMH requires the supporting-WM window to also have a
   1335   // _NET_SUPPORTING_WM_CHECK property pointing to itself (to avoid a stale
   1336   // property referencing an ID that's been recycled for another window), so we
   1337   // check that too.
   1338   gdk_error_trap_push();
   1339   int wm_window_property = 0;
   1340   bool result = GetIntProperty(
   1341       wm_window, "_NET_SUPPORTING_WM_CHECK", &wm_window_property);
   1342   gdk_flush();
   1343   bool got_error = gdk_error_trap_pop();
   1344   if (got_error || !result || wm_window_property != wm_window)
   1345     return false;
   1346 
   1347   gdk_error_trap_push();
   1348   result = GetStringProperty(
   1349       static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name);
   1350   gdk_flush();
   1351   got_error = gdk_error_trap_pop();
   1352   return !got_error && result;
   1353 }
   1354 
   1355 WindowManagerName GuessWindowManager() {
   1356   std::string name;
   1357   if (GetWindowManagerName(&name)) {
   1358     // These names are taken from the WMs' source code.
   1359     if (name == "Blackbox")
   1360       return WM_BLACKBOX;
   1361     if (name == "chromeos-wm")
   1362       return WM_CHROME_OS;
   1363     if (name == "Compiz" || name == "compiz")
   1364       return WM_COMPIZ;
   1365     if (name == "e16")
   1366       return WM_ENLIGHTENMENT;
   1367     if (StartsWithASCII(name, "IceWM", true))
   1368       return WM_ICE_WM;
   1369     if (name == "KWin")
   1370       return WM_KWIN;
   1371     if (name == "Metacity")
   1372       return WM_METACITY;
   1373     if (name == "Mutter (Muffin)")
   1374       return WM_MUFFIN;
   1375     if (name == "GNOME Shell")
   1376       return WM_MUTTER; // GNOME Shell uses Mutter
   1377     if (name == "Mutter")
   1378       return WM_MUTTER;
   1379     if (name == "Openbox")
   1380       return WM_OPENBOX;
   1381     if (name == "Xfwm4")
   1382       return WM_XFWM4;
   1383   }
   1384   return WM_UNKNOWN;
   1385 }
   1386 
   1387 bool ChangeWindowDesktop(XID window, XID destination) {
   1388   int desktop;
   1389   if (!GetWindowDesktop(destination, &desktop))
   1390     return false;
   1391 
   1392   // If |window| is sticky, use the current desktop.
   1393   if (desktop == kAllDesktops &&
   1394       !GetCurrentDesktop(&desktop))
   1395     return false;
   1396 
   1397   XEvent event;
   1398   event.xclient.type = ClientMessage;
   1399   event.xclient.window = window;
   1400   event.xclient.message_type = GetAtom("_NET_WM_DESKTOP");
   1401   event.xclient.format = 32;
   1402   event.xclient.data.l[0] = desktop;
   1403   event.xclient.data.l[1] = 1;  // source indication
   1404 
   1405   int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False,
   1406                           SubstructureNotifyMask, &event);
   1407   return result == Success;
   1408 }
   1409 
   1410 void SetDefaultX11ErrorHandlers() {
   1411   SetX11ErrorHandlers(NULL, NULL);
   1412 }
   1413 
   1414 bool IsX11WindowFullScreen(XID window) {
   1415   // If _NET_WM_STATE_FULLSCREEN is in _NET_SUPPORTED, use the presence or
   1416   // absence of _NET_WM_STATE_FULLSCREEN in _NET_WM_STATE to determine
   1417   // whether we're fullscreen.
   1418   std::vector<Atom> supported_atoms;
   1419   if (GetAtomArrayProperty(GetX11RootWindow(),
   1420                            "_NET_SUPPORTED",
   1421                            &supported_atoms)) {
   1422     Atom atom = GetAtom("_NET_WM_STATE_FULLSCREEN");
   1423 
   1424     if (std::find(supported_atoms.begin(), supported_atoms.end(), atom)
   1425         != supported_atoms.end()) {
   1426       std::vector<Atom> atom_properties;
   1427       if (GetAtomArrayProperty(window,
   1428                                "_NET_WM_STATE",
   1429                                &atom_properties)) {
   1430         return std::find(atom_properties.begin(), atom_properties.end(), atom)
   1431             != atom_properties.end();
   1432       }
   1433     }
   1434   }
   1435 
   1436   gfx::Rect window_rect;
   1437   if (!ui::GetWindowRect(window, &window_rect))
   1438     return false;
   1439 
   1440 #if defined(TOOLKIT_GTK)
   1441   // As the last resort, check if the window size is as large as the main
   1442   // screen.
   1443   GdkRectangle monitor_rect;
   1444   gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &monitor_rect);
   1445 
   1446   return monitor_rect.x == window_rect.x() &&
   1447          monitor_rect.y == window_rect.y() &&
   1448          monitor_rect.width == window_rect.width() &&
   1449          monitor_rect.height == window_rect.height();
   1450 #else
   1451   // We can't use gfx::Screen here because we don't have an aura::Window. So
   1452   // instead just look at the size of the default display.
   1453   //
   1454   // TODO(erg): Actually doing this correctly would require pulling out xrandr,
   1455   // which we don't even do in the desktop screen yet.
   1456   ::Display* display = ui::GetXDisplay();
   1457   ::Screen* screen = DefaultScreenOfDisplay(display);
   1458   int width = WidthOfScreen(screen);
   1459   int height = HeightOfScreen(screen);
   1460   return window_rect.size() == gfx::Size(width, height);
   1461 #endif
   1462 }
   1463 
   1464 bool IsMotionEvent(XEvent* event) {
   1465   int type = event->type;
   1466   if (type == GenericEvent)
   1467     type = event->xgeneric.evtype;
   1468   return type == MotionNotify;
   1469 }
   1470 
   1471 int GetMappedButton(int button) {
   1472   return XButtonMap::GetInstance()->GetMappedButton(button);
   1473 }
   1474 
   1475 void UpdateButtonMap() {
   1476   XButtonMap::GetInstance()->UpdateMapping();
   1477 }
   1478 
   1479 void InitXKeyEventForTesting(EventType type,
   1480                              KeyboardCode key_code,
   1481                              int flags,
   1482                              XEvent* event) {
   1483   CHECK(event);
   1484   Display* display = GetXDisplay();
   1485   XKeyEvent key_event;
   1486   key_event.type = XKeyEventType(type);
   1487   CHECK_NE(0, key_event.type);
   1488   key_event.serial = 0;
   1489   key_event.send_event = 0;
   1490   key_event.display = display;
   1491   key_event.time = 0;
   1492   key_event.window = 0;
   1493   key_event.root = 0;
   1494   key_event.subwindow = 0;
   1495   key_event.x = 0;
   1496   key_event.y = 0;
   1497   key_event.x_root = 0;
   1498   key_event.y_root = 0;
   1499   key_event.state = XKeyEventState(flags);
   1500   key_event.keycode = XKeyEventKeyCode(key_code, flags, display);
   1501   key_event.same_screen = 1;
   1502   event->type = key_event.type;
   1503   event->xkey = key_event;
   1504 }
   1505 
   1506 const unsigned char* XRefcountedMemory::front() const {
   1507   return x11_data_;
   1508 }
   1509 
   1510 size_t XRefcountedMemory::size() const {
   1511   return length_;
   1512 }
   1513 
   1514 XRefcountedMemory::~XRefcountedMemory() {
   1515   XFree(x11_data_);
   1516 }
   1517 
   1518 XScopedString::~XScopedString() {
   1519   XFree(string_);
   1520 }
   1521 
   1522 XScopedImage::~XScopedImage() {
   1523   reset(NULL);
   1524 }
   1525 
   1526 void XScopedImage::reset(XImage* image) {
   1527   if (image_ == image)
   1528     return;
   1529   if (image_)
   1530     XDestroyImage(image_);
   1531   image_ = image;
   1532 }
   1533 
   1534 XScopedCursor::XScopedCursor(::Cursor cursor, Display* display)
   1535     : cursor_(cursor),
   1536       display_(display) {
   1537 }
   1538 
   1539 XScopedCursor::~XScopedCursor() {
   1540   reset(0U);
   1541 }
   1542 
   1543 ::Cursor XScopedCursor::get() const {
   1544   return cursor_;
   1545 }
   1546 
   1547 void XScopedCursor::reset(::Cursor cursor) {
   1548   if (cursor_)
   1549     XFreeCursor(display_, cursor_);
   1550   cursor_ = cursor;
   1551 }
   1552 
   1553 // ----------------------------------------------------------------------------
   1554 // These functions are declared in x11_util_internal.h because they require
   1555 // XLib.h to be included, and it conflicts with many other headers.
   1556 XRenderPictFormat* GetRenderARGB32Format(Display* dpy) {
   1557   static XRenderPictFormat* pictformat = NULL;
   1558   if (pictformat)
   1559     return pictformat;
   1560 
   1561   // First look for a 32-bit format which ignores the alpha value
   1562   XRenderPictFormat templ;
   1563   templ.depth = 32;
   1564   templ.type = PictTypeDirect;
   1565   templ.direct.red = 16;
   1566   templ.direct.green = 8;
   1567   templ.direct.blue = 0;
   1568   templ.direct.redMask = 0xff;
   1569   templ.direct.greenMask = 0xff;
   1570   templ.direct.blueMask = 0xff;
   1571   templ.direct.alphaMask = 0;
   1572 
   1573   static const unsigned long kMask =
   1574     PictFormatType | PictFormatDepth |
   1575     PictFormatRed | PictFormatRedMask |
   1576     PictFormatGreen | PictFormatGreenMask |
   1577     PictFormatBlue | PictFormatBlueMask |
   1578     PictFormatAlphaMask;
   1579 
   1580   pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */);
   1581 
   1582   if (!pictformat) {
   1583     // Not all X servers support xRGB32 formats. However, the XRENDER spec says
   1584     // that they must support an ARGB32 format, so we can always return that.
   1585     pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32);
   1586     CHECK(pictformat) << "XRENDER ARGB32 not supported.";
   1587   }
   1588 
   1589   return pictformat;
   1590 }
   1591 
   1592 XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) {
   1593   DCHECK(QueryRenderSupport(dpy));
   1594 
   1595   CachedPictFormats* formats = get_cached_pict_formats();
   1596 
   1597   for (CachedPictFormats::const_iterator i = formats->begin();
   1598        i != formats->end(); ++i) {
   1599     if (i->equals(dpy, visual))
   1600       return i->format;
   1601   }
   1602 
   1603   // Not cached, look up the value.
   1604   XRenderPictFormat* pictformat = XRenderFindVisualFormat(dpy, visual);
   1605   CHECK(pictformat) << "XRENDER does not support default visual";
   1606 
   1607   // And store it in the cache.
   1608   CachedPictFormat cached_value;
   1609   cached_value.visual = visual;
   1610   cached_value.display = dpy;
   1611   cached_value.format = pictformat;
   1612   formats->push_front(cached_value);
   1613 
   1614   if (formats->size() == kMaxCacheSize) {
   1615     formats->pop_back();
   1616     // We should really only have at most 2 display/visual combinations:
   1617     // one for normal browser windows, and possibly another for an argb window
   1618     // created to display a menu.
   1619     //
   1620     // If we get here it's not fatal, we just need to make sure we aren't
   1621     // always blowing away the cache. If we are, then we should figure out why
   1622     // and make it bigger.
   1623     NOTREACHED();
   1624   }
   1625 
   1626   return pictformat;
   1627 }
   1628 
   1629 void SetX11ErrorHandlers(XErrorHandler error_handler,
   1630                          XIOErrorHandler io_error_handler) {
   1631   XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler);
   1632   XSetIOErrorHandler(
   1633       io_error_handler ? io_error_handler : DefaultX11IOErrorHandler);
   1634 }
   1635 
   1636 void LogErrorEventDescription(Display* dpy,
   1637                               const XErrorEvent& error_event) {
   1638   char error_str[256];
   1639   char request_str[256];
   1640 
   1641   XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str));
   1642 
   1643   strncpy(request_str, "Unknown", sizeof(request_str));
   1644   if (error_event.request_code < 128) {
   1645     std::string num = base::UintToString(error_event.request_code);
   1646     XGetErrorDatabaseText(
   1647         dpy, "XRequest", num.c_str(), "Unknown", request_str,
   1648         sizeof(request_str));
   1649   } else {
   1650     int num_ext;
   1651     char** ext_list = XListExtensions(dpy, &num_ext);
   1652 
   1653     for (int i = 0; i < num_ext; i++) {
   1654       int ext_code, first_event, first_error;
   1655       XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error);
   1656       if (error_event.request_code == ext_code) {
   1657         std::string msg = base::StringPrintf(
   1658             "%s.%d", ext_list[i], error_event.minor_code);
   1659         XGetErrorDatabaseText(
   1660             dpy, "XRequest", msg.c_str(), "Unknown", request_str,
   1661             sizeof(request_str));
   1662         break;
   1663       }
   1664     }
   1665     XFreeExtensionList(ext_list);
   1666   }
   1667 
   1668   LOG(ERROR)
   1669       << "X error received: "
   1670       << "serial " << error_event.serial << ", "
   1671       << "error_code " << static_cast<int>(error_event.error_code)
   1672       << " (" << error_str << "), "
   1673       << "request_code " << static_cast<int>(error_event.request_code) << ", "
   1674       << "minor_code " << static_cast<int>(error_event.minor_code)
   1675       << " (" << request_str << ")";
   1676 }
   1677 
   1678 // ----------------------------------------------------------------------------
   1679 // End of x11_util_internal.h
   1680 
   1681 
   1682 }  // namespace ui
   1683