Home | History | Annotate | Download | only in desktop_aura
      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 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
      6 
      7 #include <X11/extensions/shape.h>
      8 #include <X11/extensions/XInput2.h>
      9 #include <X11/Xatom.h>
     10 #include <X11/Xregion.h>
     11 #include <X11/Xutil.h>
     12 
     13 #include "base/basictypes.h"
     14 #include "base/command_line.h"
     15 #include "base/debug/trace_event.h"
     16 #include "base/strings/stringprintf.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "third_party/skia/include/core/SkPath.h"
     19 #include "ui/aura/client/cursor_client.h"
     20 #include "ui/aura/client/focus_client.h"
     21 #include "ui/aura/window.h"
     22 #include "ui/aura/window_event_dispatcher.h"
     23 #include "ui/aura/window_property.h"
     24 #include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
     25 #include "ui/base/hit_test.h"
     26 #include "ui/base/x/x11_util.h"
     27 #include "ui/events/event_utils.h"
     28 #include "ui/events/platform/platform_event_source.h"
     29 #include "ui/events/platform/x11/x11_event_source.h"
     30 #include "ui/events/x/device_data_manager.h"
     31 #include "ui/events/x/device_list_cache_x.h"
     32 #include "ui/events/x/touch_factory_x11.h"
     33 #include "ui/gfx/image/image_skia.h"
     34 #include "ui/gfx/image/image_skia_rep.h"
     35 #include "ui/gfx/insets.h"
     36 #include "ui/gfx/path.h"
     37 #include "ui/gfx/path_x11.h"
     38 #include "ui/gfx/screen.h"
     39 #include "ui/native_theme/native_theme.h"
     40 #include "ui/views/corewm/tooltip_aura.h"
     41 #include "ui/views/ime/input_method.h"
     42 #include "ui/views/linux_ui/linux_ui.h"
     43 #include "ui/views/views_delegate.h"
     44 #include "ui/views/views_switches.h"
     45 #include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
     46 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
     47 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
     48 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
     49 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h"
     50 #include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
     51 #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h"
     52 #include "ui/views/widget/desktop_aura/x11_scoped_capture.h"
     53 #include "ui/views/widget/desktop_aura/x11_window_event_filter.h"
     54 #include "ui/wm/core/compound_event_filter.h"
     55 #include "ui/wm/core/window_util.h"
     56 
     57 namespace views {
     58 
     59 DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture =
     60     NULL;
     61 std::list<XID>* DesktopWindowTreeHostX11::open_windows_ = NULL;
     62 
     63 DEFINE_WINDOW_PROPERTY_KEY(
     64     aura::Window*, kViewsWindowForRootWindow, NULL);
     65 
     66 DEFINE_WINDOW_PROPERTY_KEY(
     67     DesktopWindowTreeHostX11*, kHostForRootWindow, NULL);
     68 
     69 namespace {
     70 
     71 // Constants that are part of EWMH.
     72 const int k_NET_WM_STATE_ADD = 1;
     73 const int k_NET_WM_STATE_REMOVE = 0;
     74 
     75 // Special value of the _NET_WM_DESKTOP property which indicates that the window
     76 // should appear on all desktops.
     77 const int kAllDesktops = 0xFFFFFFFF;
     78 
     79 const char* kAtomsToCache[] = {
     80   "UTF8_STRING",
     81   "WM_DELETE_WINDOW",
     82   "WM_PROTOCOLS",
     83   "_NET_FRAME_EXTENTS",
     84   "_NET_WM_CM_S0",
     85   "_NET_WM_DESKTOP",
     86   "_NET_WM_ICON",
     87   "_NET_WM_NAME",
     88   "_NET_WM_PID",
     89   "_NET_WM_PING",
     90   "_NET_WM_STATE",
     91   "_NET_WM_STATE_ABOVE",
     92   "_NET_WM_STATE_FULLSCREEN",
     93   "_NET_WM_STATE_HIDDEN",
     94   "_NET_WM_STATE_MAXIMIZED_HORZ",
     95   "_NET_WM_STATE_MAXIMIZED_VERT",
     96   "_NET_WM_STATE_SKIP_TASKBAR",
     97   "_NET_WM_STATE_STICKY",
     98   "_NET_WM_USER_TIME",
     99   "_NET_WM_WINDOW_OPACITY",
    100   "_NET_WM_WINDOW_TYPE",
    101   "_NET_WM_WINDOW_TYPE_DND",
    102   "_NET_WM_WINDOW_TYPE_MENU",
    103   "_NET_WM_WINDOW_TYPE_NORMAL",
    104   "_NET_WM_WINDOW_TYPE_NOTIFICATION",
    105   "_NET_WM_WINDOW_TYPE_TOOLTIP",
    106   "XdndActionAsk",
    107   "XdndActionCopy"
    108   "XdndActionLink",
    109   "XdndActionList",
    110   "XdndActionMove",
    111   "XdndActionPrivate",
    112   "XdndAware",
    113   "XdndDrop",
    114   "XdndEnter",
    115   "XdndFinished",
    116   "XdndLeave",
    117   "XdndPosition",
    118   "XdndProxy",  // Proxy windows?
    119   "XdndSelection",
    120   "XdndStatus",
    121   "XdndTypeList",
    122   NULL
    123 };
    124 
    125 }  // namespace
    126 
    127 ////////////////////////////////////////////////////////////////////////////////
    128 // DesktopWindowTreeHostX11, public:
    129 
    130 DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
    131     internal::NativeWidgetDelegate* native_widget_delegate,
    132     DesktopNativeWidgetAura* desktop_native_widget_aura)
    133     : close_widget_factory_(this),
    134       xdisplay_(gfx::GetXDisplay()),
    135       xwindow_(0),
    136       x_root_window_(DefaultRootWindow(xdisplay_)),
    137       atom_cache_(xdisplay_, kAtomsToCache),
    138       window_mapped_(false),
    139       is_fullscreen_(false),
    140       is_always_on_top_(false),
    141       use_native_frame_(false),
    142       use_argb_visual_(false),
    143       drag_drop_client_(NULL),
    144       current_cursor_(ui::kCursorNull),
    145       native_widget_delegate_(native_widget_delegate),
    146       desktop_native_widget_aura_(desktop_native_widget_aura),
    147       content_window_(NULL),
    148       window_parent_(NULL),
    149       window_shape_(NULL),
    150       custom_window_shape_(false),
    151       urgency_hint_set_(false) {
    152 }
    153 
    154 DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
    155   window()->ClearProperty(kHostForRootWindow);
    156   aura::client::SetWindowMoveClient(window(), NULL);
    157   desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
    158   if (window_shape_)
    159     XDestroyRegion(window_shape_);
    160   DestroyDispatcher();
    161 }
    162 
    163 // static
    164 aura::Window* DesktopWindowTreeHostX11::GetContentWindowForXID(XID xid) {
    165   aura::WindowTreeHost* host =
    166       aura::WindowTreeHost::GetForAcceleratedWidget(xid);
    167   return host ? host->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
    168 }
    169 
    170 // static
    171 DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::GetHostForXID(XID xid) {
    172   aura::WindowTreeHost* host =
    173       aura::WindowTreeHost::GetForAcceleratedWidget(xid);
    174   return host ? host->window()->GetProperty(kHostForRootWindow) : NULL;
    175 }
    176 
    177 // static
    178 std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() {
    179   std::vector<aura::Window*> windows(open_windows().size());
    180   std::transform(open_windows().begin(),
    181                  open_windows().end(),
    182                  windows.begin(),
    183                  GetContentWindowForXID);
    184   return windows;
    185 }
    186 
    187 gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const {
    188   return bounds_;
    189 }
    190 
    191 gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const {
    192   gfx::Rect outer_bounds(bounds_);
    193   outer_bounds.Inset(-native_window_frame_borders_);
    194   return outer_bounds;
    195 }
    196 
    197 ::Region DesktopWindowTreeHostX11::GetWindowShape() const {
    198   return window_shape_;
    199 }
    200 
    201 void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged(
    202     bool active) {
    203   if (active) {
    204     FlashFrame(false);
    205     OnHostActivated();
    206     open_windows().remove(xwindow_);
    207     open_windows().insert(open_windows().begin(), xwindow_);
    208   }
    209 
    210   desktop_native_widget_aura_->HandleActivationChanged(active);
    211 
    212   native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
    213 }
    214 
    215 void DesktopWindowTreeHostX11::AddObserver(
    216     views::DesktopWindowTreeHostObserverX11* observer) {
    217   observer_list_.AddObserver(observer);
    218 }
    219 
    220 void DesktopWindowTreeHostX11::RemoveObserver(
    221     views::DesktopWindowTreeHostObserverX11* observer) {
    222   observer_list_.RemoveObserver(observer);
    223 }
    224 
    225 void DesktopWindowTreeHostX11::SwapNonClientEventHandler(
    226     scoped_ptr<ui::EventHandler> handler) {
    227   wm::CompoundEventFilter* compound_event_filter =
    228       desktop_native_widget_aura_->root_window_event_filter();
    229   if (x11_non_client_event_filter_)
    230     compound_event_filter->RemoveHandler(x11_non_client_event_filter_.get());
    231   compound_event_filter->AddHandler(handler.get());
    232   x11_non_client_event_filter_ = handler.Pass();
    233 }
    234 
    235 void DesktopWindowTreeHostX11::CleanUpWindowList() {
    236   delete open_windows_;
    237   open_windows_ = NULL;
    238 }
    239 
    240 ////////////////////////////////////////////////////////////////////////////////
    241 // DesktopWindowTreeHostX11, DesktopWindowTreeHost implementation:
    242 
    243 void DesktopWindowTreeHostX11::Init(aura::Window* content_window,
    244                                     const Widget::InitParams& params) {
    245   content_window_ = content_window;
    246 
    247   // TODO(erg): Check whether we *should* be building a WindowTreeHost here, or
    248   // whether we should be proxying requests to another DRWHL.
    249 
    250   // In some situations, views tries to make a zero sized window, and that
    251   // makes us crash. Make sure we have valid sizes.
    252   Widget::InitParams sanitized_params = params;
    253   if (sanitized_params.bounds.width() == 0)
    254     sanitized_params.bounds.set_width(100);
    255   if (sanitized_params.bounds.height() == 0)
    256     sanitized_params.bounds.set_height(100);
    257 
    258   InitX11Window(sanitized_params);
    259 }
    260 
    261 void DesktopWindowTreeHostX11::OnNativeWidgetCreated(
    262     const Widget::InitParams& params) {
    263   window()->SetProperty(kViewsWindowForRootWindow, content_window_);
    264   window()->SetProperty(kHostForRootWindow, this);
    265 
    266   // Ensure that the X11DesktopHandler exists so that it dispatches activation
    267   // messages to us.
    268   X11DesktopHandler::get();
    269 
    270   // TODO(erg): Unify this code once the other consumer goes away.
    271   SwapNonClientEventHandler(
    272       scoped_ptr<ui::EventHandler>(new X11WindowEventFilter(this)).Pass());
    273   SetUseNativeFrame(params.type == Widget::InitParams::TYPE_WINDOW &&
    274                     !params.remove_standard_frame);
    275 
    276   x11_window_move_client_.reset(new X11DesktopWindowMoveClient);
    277   aura::client::SetWindowMoveClient(window(), x11_window_move_client_.get());
    278 
    279   SetWindowTransparency();
    280 
    281   native_widget_delegate_->OnNativeWidgetCreated(true);
    282 }
    283 
    284 scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostX11::CreateTooltip() {
    285   return scoped_ptr<corewm::Tooltip>(
    286       new corewm::TooltipAura(gfx::SCREEN_TYPE_NATIVE));
    287 }
    288 
    289 scoped_ptr<aura::client::DragDropClient>
    290 DesktopWindowTreeHostX11::CreateDragDropClient(
    291     DesktopNativeCursorManager* cursor_manager) {
    292   drag_drop_client_ = new DesktopDragDropClientAuraX11(
    293       window(), cursor_manager, xdisplay_, xwindow_);
    294   return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
    295 }
    296 
    297 void DesktopWindowTreeHostX11::Close() {
    298   // TODO(erg): Might need to do additional hiding tasks here.
    299   delayed_resize_task_.Cancel();
    300 
    301   if (!close_widget_factory_.HasWeakPtrs()) {
    302     // And we delay the close so that if we are called from an ATL callback,
    303     // we don't destroy the window before the callback returned (as the caller
    304     // may delete ourselves on destroy and the ATL callback would still
    305     // dereference us when the callback returns).
    306     base::MessageLoop::current()->PostTask(
    307         FROM_HERE,
    308         base::Bind(&DesktopWindowTreeHostX11::CloseNow,
    309                    close_widget_factory_.GetWeakPtr()));
    310   }
    311 }
    312 
    313 void DesktopWindowTreeHostX11::CloseNow() {
    314   if (xwindow_ == None)
    315     return;
    316 
    317   x11_capture_.reset();
    318   native_widget_delegate_->OnNativeWidgetDestroying();
    319 
    320   // If we have children, close them. Use a copy for iteration because they'll
    321   // remove themselves.
    322   std::set<DesktopWindowTreeHostX11*> window_children_copy = window_children_;
    323   for (std::set<DesktopWindowTreeHostX11*>::iterator it =
    324            window_children_copy.begin(); it != window_children_copy.end();
    325        ++it) {
    326     (*it)->CloseNow();
    327   }
    328   DCHECK(window_children_.empty());
    329 
    330   // If we have a parent, remove ourselves from its children list.
    331   if (window_parent_) {
    332     window_parent_->window_children_.erase(this);
    333     window_parent_ = NULL;
    334   }
    335 
    336   // Remove the event listeners we've installed. We need to remove these
    337   // because otherwise we get assert during ~WindowEventDispatcher().
    338   desktop_native_widget_aura_->root_window_event_filter()->RemoveHandler(
    339       x11_non_client_event_filter_.get());
    340   x11_non_client_event_filter_.reset();
    341 
    342   // Destroy the compositor before destroying the |xwindow_| since shutdown
    343   // may try to swap, and the swap without a window causes an X error, which
    344   // causes a crash with in-process renderer.
    345   DestroyCompositor();
    346 
    347   open_windows().remove(xwindow_);
    348   // Actually free our native resources.
    349   if (ui::PlatformEventSource::GetInstance())
    350     ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
    351   XDestroyWindow(xdisplay_, xwindow_);
    352   xwindow_ = None;
    353 
    354   desktop_native_widget_aura_->OnHostClosed();
    355 }
    356 
    357 aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() {
    358   return this;
    359 }
    360 
    361 void DesktopWindowTreeHostX11::ShowWindowWithState(
    362     ui::WindowShowState show_state) {
    363   if (!window_mapped_)
    364     MapWindow(show_state);
    365 
    366   if (show_state == ui::SHOW_STATE_NORMAL ||
    367       show_state == ui::SHOW_STATE_MAXIMIZED) {
    368     // Note: XFCE ignores a maximize hint given before mapping the window.
    369     if (show_state == ui::SHOW_STATE_MAXIMIZED)
    370       Maximize();
    371     Activate();
    372   }
    373 
    374   native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
    375 }
    376 
    377 void DesktopWindowTreeHostX11::ShowMaximizedWithBounds(
    378     const gfx::Rect& restored_bounds) {
    379   ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED);
    380   // Enforce |restored_bounds_| since calling Maximize() could have reset it.
    381   restored_bounds_ = restored_bounds;
    382 }
    383 
    384 bool DesktopWindowTreeHostX11::IsVisible() const {
    385   return window_mapped_;
    386 }
    387 
    388 void DesktopWindowTreeHostX11::SetSize(const gfx::Size& size) {
    389   bool size_changed = bounds_.size() != size;
    390   XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
    391   bounds_.set_size(size);
    392   if (size_changed) {
    393     OnHostResized(size);
    394     ResetWindowRegion();
    395   }
    396 }
    397 
    398 void DesktopWindowTreeHostX11::StackAtTop() {
    399   XRaiseWindow(xdisplay_, xwindow_);
    400 }
    401 
    402 void DesktopWindowTreeHostX11::CenterWindow(const gfx::Size& size) {
    403   gfx::Rect parent_bounds = GetWorkAreaBoundsInScreen();
    404 
    405   // If |window_|'s transient parent bounds are big enough to contain |size|,
    406   // use them instead.
    407   if (wm::GetTransientParent(content_window_)) {
    408     gfx::Rect transient_parent_rect =
    409         wm::GetTransientParent(content_window_)->GetBoundsInScreen();
    410     if (transient_parent_rect.height() >= size.height() &&
    411         transient_parent_rect.width() >= size.width()) {
    412       parent_bounds = transient_parent_rect;
    413     }
    414   }
    415 
    416   gfx::Rect window_bounds(
    417       parent_bounds.x() + (parent_bounds.width() - size.width()) / 2,
    418       parent_bounds.y() + (parent_bounds.height() - size.height()) / 2,
    419       size.width(),
    420       size.height());
    421   // Don't size the window bigger than the parent, otherwise the user may not be
    422   // able to close or move it.
    423   window_bounds.AdjustToFit(parent_bounds);
    424 
    425   SetBounds(window_bounds);
    426 }
    427 
    428 void DesktopWindowTreeHostX11::GetWindowPlacement(
    429     gfx::Rect* bounds,
    430     ui::WindowShowState* show_state) const {
    431   *bounds = GetRestoredBounds();
    432 
    433   if (IsFullscreen()) {
    434     *show_state = ui::SHOW_STATE_FULLSCREEN;
    435   } else if (IsMinimized()) {
    436     *show_state = ui::SHOW_STATE_MINIMIZED;
    437   } else if (IsMaximized()) {
    438     *show_state = ui::SHOW_STATE_MAXIMIZED;
    439   } else if (!IsActive()) {
    440     *show_state = ui::SHOW_STATE_INACTIVE;
    441   } else {
    442     *show_state = ui::SHOW_STATE_NORMAL;
    443   }
    444 }
    445 
    446 gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
    447   return bounds_;
    448 }
    449 
    450 gfx::Rect DesktopWindowTreeHostX11::GetClientAreaBoundsInScreen() const {
    451   // TODO(erg): The NativeWidgetAura version returns |bounds_|, claiming its
    452   // needed for View::ConvertPointToScreen() to work
    453   // correctly. DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() just
    454   // asks windows what it thinks the client rect is.
    455   //
    456   // Attempts to calculate the rect by asking the NonClientFrameView what it
    457   // thought its GetBoundsForClientView() were broke combobox drop down
    458   // placement.
    459   return bounds_;
    460 }
    461 
    462 gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const {
    463   // We can't reliably track the restored bounds of a window, but we can get
    464   // the 90% case down. When *chrome* is the process that requests maximizing
    465   // or restoring bounds, we can record the current bounds before we request
    466   // maximization, and clear it when we detect a state change.
    467   if (!restored_bounds_.IsEmpty())
    468     return restored_bounds_;
    469 
    470   return GetWindowBoundsInScreen();
    471 }
    472 
    473 gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
    474   std::vector<int> value;
    475   if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
    476       value.size() >= 4) {
    477     return gfx::Rect(value[0], value[1], value[2], value[3]);
    478   }
    479 
    480   // Fetch the geometry of the root window.
    481   Window root;
    482   int x, y;
    483   unsigned int width, height;
    484   unsigned int border_width, depth;
    485   if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y,
    486                     &width, &height, &border_width, &depth)) {
    487     NOTIMPLEMENTED();
    488     return gfx::Rect(0, 0, 10, 10);
    489   }
    490 
    491   return gfx::Rect(x, y, width, height);
    492 }
    493 
    494 void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) {
    495   if (window_shape_)
    496     XDestroyRegion(window_shape_);
    497   custom_window_shape_ = true;
    498   window_shape_ = gfx::CreateRegionFromSkRegion(*native_region);
    499   ResetWindowRegion();
    500   delete native_region;
    501 }
    502 
    503 void DesktopWindowTreeHostX11::Activate() {
    504   if (!window_mapped_)
    505     return;
    506 
    507   X11DesktopHandler::get()->ActivateWindow(xwindow_);
    508 }
    509 
    510 void DesktopWindowTreeHostX11::Deactivate() {
    511   if (!IsActive())
    512     return;
    513 
    514   x11_capture_.reset();
    515   XLowerWindow(xdisplay_, xwindow_);
    516 }
    517 
    518 bool DesktopWindowTreeHostX11::IsActive() const {
    519   return X11DesktopHandler::get()->IsActiveWindow(xwindow_);
    520 }
    521 
    522 void DesktopWindowTreeHostX11::Maximize() {
    523   // When we are in the process of requesting to maximize a window, we can
    524   // accurately keep track of our restored bounds instead of relying on the
    525   // heuristics that are in the PropertyNotify and ConfigureNotify handlers.
    526   restored_bounds_ = bounds_;
    527 
    528   SetWMSpecState(true,
    529                  atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
    530                  atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
    531   if (IsMinimized())
    532     ShowWindowWithState(ui::SHOW_STATE_NORMAL);
    533 }
    534 
    535 void DesktopWindowTreeHostX11::Minimize() {
    536   x11_capture_.reset();
    537   XIconifyWindow(xdisplay_, xwindow_, 0);
    538 }
    539 
    540 void DesktopWindowTreeHostX11::Restore() {
    541   SetWMSpecState(false,
    542                  atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
    543                  atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
    544   if (IsMinimized())
    545     ShowWindowWithState(ui::SHOW_STATE_NORMAL);
    546 }
    547 
    548 bool DesktopWindowTreeHostX11::IsMaximized() const {
    549   return (HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_VERT") &&
    550           HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_HORZ"));
    551 }
    552 
    553 bool DesktopWindowTreeHostX11::IsMinimized() const {
    554   return HasWMSpecProperty("_NET_WM_STATE_HIDDEN");
    555 }
    556 
    557 bool DesktopWindowTreeHostX11::HasCapture() const {
    558   return g_current_capture == this;
    559 }
    560 
    561 void DesktopWindowTreeHostX11::SetAlwaysOnTop(bool always_on_top) {
    562   is_always_on_top_ = always_on_top;
    563   SetWMSpecState(always_on_top,
    564                  atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"),
    565                  None);
    566 }
    567 
    568 bool DesktopWindowTreeHostX11::IsAlwaysOnTop() const {
    569   return is_always_on_top_;
    570 }
    571 
    572 void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) {
    573   SetWMSpecState(always_visible,
    574                  atom_cache_.GetAtom("_NET_WM_STATE_STICKY"),
    575                  None);
    576 
    577   int new_desktop = 0;
    578   if (always_visible) {
    579     new_desktop = kAllDesktops;
    580   } else {
    581     if (!ui::GetCurrentDesktop(&new_desktop))
    582       return;
    583   }
    584 
    585   XEvent xevent;
    586   memset (&xevent, 0, sizeof (xevent));
    587   xevent.type = ClientMessage;
    588   xevent.xclient.window = xwindow_;
    589   xevent.xclient.message_type = atom_cache_.GetAtom("_NET_WM_DESKTOP");
    590   xevent.xclient.format = 32;
    591   xevent.xclient.data.l[0] = new_desktop;
    592   xevent.xclient.data.l[1] = 0;
    593   xevent.xclient.data.l[2] = 0;
    594   xevent.xclient.data.l[3] = 0;
    595   xevent.xclient.data.l[4] = 0;
    596   XSendEvent(xdisplay_, x_root_window_, False,
    597              SubstructureRedirectMask | SubstructureNotifyMask,
    598              &xevent);
    599 }
    600 
    601 bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) {
    602   if (window_title_ == title)
    603     return false;
    604   window_title_ = title;
    605   std::string utf8str = base::UTF16ToUTF8(title);
    606   XChangeProperty(xdisplay_,
    607                   xwindow_,
    608                   atom_cache_.GetAtom("_NET_WM_NAME"),
    609                   atom_cache_.GetAtom("UTF8_STRING"),
    610                   8,
    611                   PropModeReplace,
    612                   reinterpret_cast<const unsigned char*>(utf8str.c_str()),
    613                   utf8str.size());
    614   // TODO(erg): This is technically wrong. So XStoreName and friends expect
    615   // this in Host Portable Character Encoding instead of UTF-8, which I believe
    616   // is Compound Text. This shouldn't matter 90% of the time since this is the
    617   // fallback to the UTF8 property above.
    618   XStoreName(xdisplay_, xwindow_, utf8str.c_str());
    619   return true;
    620 }
    621 
    622 void DesktopWindowTreeHostX11::ClearNativeFocus() {
    623   // This method is weird and misnamed. Instead of clearing the native focus,
    624   // it sets the focus to our |content_window_|, which will trigger a cascade
    625   // of focus changes into views.
    626   if (content_window_ && aura::client::GetFocusClient(content_window_) &&
    627       content_window_->Contains(
    628           aura::client::GetFocusClient(content_window_)->GetFocusedWindow())) {
    629     aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
    630   }
    631 }
    632 
    633 Widget::MoveLoopResult DesktopWindowTreeHostX11::RunMoveLoop(
    634     const gfx::Vector2d& drag_offset,
    635     Widget::MoveLoopSource source,
    636     Widget::MoveLoopEscapeBehavior escape_behavior) {
    637   aura::client::WindowMoveSource window_move_source =
    638       source == Widget::MOVE_LOOP_SOURCE_MOUSE ?
    639       aura::client::WINDOW_MOVE_SOURCE_MOUSE :
    640       aura::client::WINDOW_MOVE_SOURCE_TOUCH;
    641   if (x11_window_move_client_->RunMoveLoop(content_window_, drag_offset,
    642       window_move_source) == aura::client::MOVE_SUCCESSFUL)
    643     return Widget::MOVE_LOOP_SUCCESSFUL;
    644 
    645   return Widget::MOVE_LOOP_CANCELED;
    646 }
    647 
    648 void DesktopWindowTreeHostX11::EndMoveLoop() {
    649   x11_window_move_client_->EndMoveLoop();
    650 }
    651 
    652 void DesktopWindowTreeHostX11::SetVisibilityChangedAnimationsEnabled(
    653     bool value) {
    654   // Much like the previous NativeWidgetGtk, we don't have anything to do here.
    655 }
    656 
    657 bool DesktopWindowTreeHostX11::ShouldUseNativeFrame() const {
    658   return use_native_frame_;
    659 }
    660 
    661 bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const {
    662   return false;
    663 }
    664 
    665 void DesktopWindowTreeHostX11::FrameTypeChanged() {
    666   Widget::FrameType new_type =
    667       native_widget_delegate_->AsWidget()->frame_type();
    668   if (new_type == Widget::FRAME_TYPE_DEFAULT) {
    669     // The default is determined by Widget::InitParams::remove_standard_frame
    670     // and does not change.
    671     return;
    672   }
    673 
    674   SetUseNativeFrame(new_type == Widget::FRAME_TYPE_FORCE_NATIVE);
    675   // Replace the frame and layout the contents. Even though we don't have a
    676   // swapable glass frame like on Windows, we still replace the frame because
    677   // the button assets don't update otherwise.
    678   native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame();
    679 }
    680 
    681 void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
    682   if (is_fullscreen_ == fullscreen)
    683     return;
    684   is_fullscreen_ = fullscreen;
    685   SetWMSpecState(fullscreen,
    686                  atom_cache_.GetAtom("_NET_WM_STATE_FULLSCREEN"),
    687                  None);
    688   // Try to guess the size we will have after the switch to/from fullscreen:
    689   // - (may) avoid transient states
    690   // - works around Flash content which expects to have the size updated
    691   //   synchronously.
    692   // See https://crbug.com/361408
    693   if (fullscreen) {
    694     restored_bounds_ = bounds_;
    695     const gfx::Display display =
    696         gfx::Screen::GetScreenFor(NULL)->GetDisplayNearestWindow(window());
    697     bounds_ = display.bounds();
    698   } else {
    699     bounds_ = restored_bounds_;
    700   }
    701   OnHostMoved(bounds_.origin());
    702   OnHostResized(bounds_.size());
    703 
    704   if (HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN") == fullscreen) {
    705     Relayout();
    706     ResetWindowRegion();
    707   }
    708   // Else: the widget will be relaid out either when the window bounds change or
    709   // when |xwindow_|'s fullscreen state changes.
    710 }
    711 
    712 bool DesktopWindowTreeHostX11::IsFullscreen() const {
    713   return is_fullscreen_;
    714 }
    715 
    716 void DesktopWindowTreeHostX11::SetOpacity(unsigned char opacity) {
    717   // X server opacity is in terms of 32 bit unsigned int space, and counts from
    718   // the opposite direction.
    719   // XChangeProperty() expects "cardinality" to be long.
    720   unsigned long cardinality = opacity * 0x1010101;
    721 
    722   if (cardinality == 0xffffffff) {
    723     XDeleteProperty(xdisplay_, xwindow_,
    724                     atom_cache_.GetAtom("_NET_WM_WINDOW_OPACITY"));
    725   } else {
    726     XChangeProperty(xdisplay_, xwindow_,
    727                     atom_cache_.GetAtom("_NET_WM_WINDOW_OPACITY"),
    728                     XA_CARDINAL, 32,
    729                     PropModeReplace,
    730                     reinterpret_cast<unsigned char*>(&cardinality), 1);
    731   }
    732 }
    733 
    734 void DesktopWindowTreeHostX11::SetWindowIcons(
    735     const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
    736   // TODO(erg): The way we handle icons across different versions of chrome
    737   // could be substantially improved. The Windows version does its own thing
    738   // and only sometimes comes down this code path. The icon stuff in
    739   // ChromeViewsDelegate is hard coded to use HICONs. Likewise, we're hard
    740   // coded to be given two images instead of an arbitrary collection of images
    741   // so that we can pass to the WM.
    742   //
    743   // All of this could be made much, much better.
    744   std::vector<unsigned long> data;
    745 
    746   if (window_icon.HasRepresentation(1.0f))
    747     SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data);
    748 
    749   if (app_icon.HasRepresentation(1.0f))
    750     SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data);
    751 
    752   if (data.empty())
    753     XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_ICON"));
    754   else
    755     ui::SetAtomArrayProperty(xwindow_, "_NET_WM_ICON", "CARDINAL", data);
    756 }
    757 
    758 void DesktopWindowTreeHostX11::InitModalType(ui::ModalType modal_type) {
    759   switch (modal_type) {
    760     case ui::MODAL_TYPE_NONE:
    761       break;
    762     default:
    763       // TODO(erg): Figure out under what situations |modal_type| isn't
    764       // none. The comment in desktop_native_widget_aura.cc suggests that this
    765       // is rare.
    766       NOTIMPLEMENTED();
    767   }
    768 }
    769 
    770 void DesktopWindowTreeHostX11::FlashFrame(bool flash_frame) {
    771   if (urgency_hint_set_ == flash_frame)
    772     return;
    773 
    774   XWMHints* hints = XGetWMHints(xdisplay_, xwindow_);
    775   if (!hints) {
    776     // The window hasn't had its hints set yet.
    777     hints = XAllocWMHints();
    778   }
    779 
    780   if (flash_frame)
    781     hints->flags |= XUrgencyHint;
    782   else
    783     hints->flags &= ~XUrgencyHint;
    784 
    785   XSetWMHints(xdisplay_, xwindow_, hints);
    786   XFree(hints);
    787 
    788   urgency_hint_set_ = flash_frame;
    789 }
    790 
    791 void DesktopWindowTreeHostX11::OnRootViewLayout() const {
    792   if (!window_mapped_)
    793     return;
    794 
    795   XSizeHints hints;
    796   long supplied_return;
    797   XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return);
    798 
    799   gfx::Size minimum = native_widget_delegate_->GetMinimumSize();
    800   if (minimum.IsEmpty()) {
    801     hints.flags &= ~PMinSize;
    802   } else {
    803     hints.flags |= PMinSize;
    804     hints.min_width = minimum.width();
    805     hints.min_height = minimum.height();
    806   }
    807 
    808   gfx::Size maximum = native_widget_delegate_->GetMaximumSize();
    809   if (maximum.IsEmpty()) {
    810     hints.flags &= ~PMaxSize;
    811   } else {
    812     hints.flags |= PMaxSize;
    813     hints.max_width = maximum.width();
    814     hints.max_height = maximum.height();
    815   }
    816 
    817   XSetWMNormalHints(xdisplay_, xwindow_, &hints);
    818 }
    819 
    820 void DesktopWindowTreeHostX11::OnNativeWidgetFocus() {
    821   native_widget_delegate_->AsWidget()->GetInputMethod()->OnFocus();
    822 }
    823 
    824 void DesktopWindowTreeHostX11::OnNativeWidgetBlur() {
    825   if (xwindow_) {
    826     x11_capture_.reset();
    827     native_widget_delegate_->AsWidget()->GetInputMethod()->OnBlur();
    828   }
    829 }
    830 
    831 bool DesktopWindowTreeHostX11::IsAnimatingClosed() const {
    832   return false;
    833 }
    834 
    835 bool DesktopWindowTreeHostX11::IsTranslucentWindowOpacitySupported() const {
    836   return false;
    837 }
    838 
    839 ////////////////////////////////////////////////////////////////////////////////
    840 // DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
    841 
    842 ui::EventSource* DesktopWindowTreeHostX11::GetEventSource() {
    843   return this;
    844 }
    845 
    846 gfx::AcceleratedWidget DesktopWindowTreeHostX11::GetAcceleratedWidget() {
    847   return xwindow_;
    848 }
    849 
    850 void DesktopWindowTreeHostX11::Show() {
    851   ShowWindowWithState(ui::SHOW_STATE_NORMAL);
    852   native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);
    853 }
    854 
    855 void DesktopWindowTreeHostX11::Hide() {
    856   if (window_mapped_) {
    857     XWithdrawWindow(xdisplay_, xwindow_, 0);
    858     window_mapped_ = false;
    859   }
    860   native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);
    861 }
    862 
    863 gfx::Rect DesktopWindowTreeHostX11::GetBounds() const {
    864   return bounds_;
    865 }
    866 
    867 void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
    868   bool origin_changed = bounds_.origin() != bounds.origin();
    869   bool size_changed = bounds_.size() != bounds.size();
    870   XWindowChanges changes = {0};
    871   unsigned value_mask = 0;
    872 
    873   if (size_changed) {
    874     // X11 will send an XError at our process if have a 0 sized window.
    875     DCHECK_GT(bounds.width(), 0);
    876     DCHECK_GT(bounds.height(), 0);
    877 
    878     changes.width = bounds.width();
    879     changes.height = bounds.height();
    880     value_mask |= CWHeight | CWWidth;
    881   }
    882 
    883   if (origin_changed) {
    884     changes.x = bounds.x();
    885     changes.y = bounds.y();
    886     value_mask |= CWX | CWY;
    887   }
    888   if (value_mask)
    889     XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
    890 
    891   // Assume that the resize will go through as requested, which should be the
    892   // case if we're running without a window manager.  If there's a window
    893   // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
    894   // (possibly synthetic) ConfigureNotify about the actual size and correct
    895   // |bounds_| later.
    896   bounds_ = bounds;
    897 
    898   if (origin_changed)
    899     native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
    900   if (size_changed) {
    901     OnHostResized(bounds.size());
    902     ResetWindowRegion();
    903   }
    904 }
    905 
    906 gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
    907   return bounds_.origin();
    908 }
    909 
    910 void DesktopWindowTreeHostX11::SetCapture() {
    911   // This is vaguely based on the old NativeWidgetGtk implementation.
    912   //
    913   // X11's XPointerGrab() shouldn't be used for everything; it doesn't map
    914   // cleanly to Windows' SetCapture(). GTK only provides a separate concept of
    915   // a grab that wasn't the X11 pointer grab, but was instead a manual
    916   // redirection of the event. (You need to drop into GDK if you want to
    917   // perform a raw X11 grab).
    918 
    919   if (g_current_capture)
    920     g_current_capture->OnCaptureReleased();
    921 
    922   g_current_capture = this;
    923   x11_capture_.reset(new X11ScopedCapture(xwindow_));
    924 }
    925 
    926 void DesktopWindowTreeHostX11::ReleaseCapture() {
    927   if (g_current_capture == this)
    928     g_current_capture->OnCaptureReleased();
    929 }
    930 
    931 void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
    932   XDefineCursor(xdisplay_, xwindow_, cursor.platform());
    933 }
    934 
    935 void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
    936   XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
    937                bounds_.x() + location.x(), bounds_.y() + location.y());
    938 }
    939 
    940 void DesktopWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
    941   // TODO(erg): Conditional on us enabling touch on desktop linux builds, do
    942   // the same tap-to-click disabling here that chromeos does.
    943 }
    944 
    945 void DesktopWindowTreeHostX11::PostNativeEvent(
    946     const base::NativeEvent& native_event) {
    947   DCHECK(xwindow_);
    948   DCHECK(xdisplay_);
    949   XEvent xevent = *native_event;
    950   xevent.xany.display = xdisplay_;
    951   xevent.xany.window = xwindow_;
    952 
    953   switch (xevent.type) {
    954     case EnterNotify:
    955     case LeaveNotify:
    956     case MotionNotify:
    957     case KeyPress:
    958     case KeyRelease:
    959     case ButtonPress:
    960     case ButtonRelease: {
    961       // The fields used below are in the same place for all of events
    962       // above. Using xmotion from XEvent's unions to avoid repeating
    963       // the code.
    964       xevent.xmotion.root = x_root_window_;
    965       xevent.xmotion.time = CurrentTime;
    966 
    967       gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
    968       ConvertPointToNativeScreen(&point);
    969       xevent.xmotion.x_root = point.x();
    970       xevent.xmotion.y_root = point.y();
    971     }
    972     default:
    973       break;
    974   }
    975   XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
    976 }
    977 
    978 void DesktopWindowTreeHostX11::OnDeviceScaleFactorChanged(
    979     float device_scale_factor) {
    980 }
    981 
    982 ////////////////////////////////////////////////////////////////////////////////
    983 // DesktopWindowTreeHostX11, ui::EventSource implementation:
    984 
    985 ui::EventProcessor* DesktopWindowTreeHostX11::GetEventProcessor() {
    986   return dispatcher();
    987 }
    988 
    989 ////////////////////////////////////////////////////////////////////////////////
    990 // DesktopWindowTreeHostX11, private:
    991 
    992 void DesktopWindowTreeHostX11::InitX11Window(
    993     const Widget::InitParams& params) {
    994   unsigned long attribute_mask = CWBackPixmap;
    995   XSetWindowAttributes swa;
    996   memset(&swa, 0, sizeof(swa));
    997   swa.background_pixmap = None;
    998 
    999   ::Atom window_type;
   1000   switch (params.type) {
   1001     case Widget::InitParams::TYPE_MENU:
   1002       swa.override_redirect = True;
   1003       window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU");
   1004       break;
   1005     case Widget::InitParams::TYPE_TOOLTIP:
   1006       swa.override_redirect = True;
   1007       window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP");
   1008       break;
   1009     case Widget::InitParams::TYPE_POPUP:
   1010       swa.override_redirect = True;
   1011       window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION");
   1012       break;
   1013     case Widget::InitParams::TYPE_DRAG:
   1014       swa.override_redirect = True;
   1015       window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_DND");
   1016       break;
   1017     default:
   1018       window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NORMAL");
   1019       break;
   1020   }
   1021   if (swa.override_redirect)
   1022     attribute_mask |= CWOverrideRedirect;
   1023 
   1024   // Detect whether we're running inside a compositing manager. If so, try to
   1025   // use the ARGB visual. Otherwise, just use our parent's visual.
   1026   Visual* visual = CopyFromParent;
   1027   int depth = CopyFromParent;
   1028   if (CommandLine::ForCurrentProcess()->HasSwitch(
   1029           switches::kEnableTransparentVisuals) &&
   1030       XGetSelectionOwner(xdisplay_,
   1031                          atom_cache_.GetAtom("_NET_WM_CM_S0")) != None) {
   1032     Visual* rgba_visual = GetARGBVisual();
   1033     if (rgba_visual) {
   1034       visual = rgba_visual;
   1035       depth = 32;
   1036 
   1037       attribute_mask |= CWColormap;
   1038       swa.colormap = XCreateColormap(xdisplay_, x_root_window_, visual,
   1039                                      AllocNone);
   1040 
   1041       // x.org will BadMatch if we don't set a border when the depth isn't the
   1042       // same as the parent depth.
   1043       attribute_mask |= CWBorderPixel;
   1044       swa.border_pixel = 0;
   1045 
   1046       use_argb_visual_ = true;
   1047     }
   1048   }
   1049 
   1050   bounds_ = params.bounds;
   1051   xwindow_ = XCreateWindow(
   1052       xdisplay_, x_root_window_,
   1053       bounds_.x(), bounds_.y(),
   1054       bounds_.width(), bounds_.height(),
   1055       0,               // border width
   1056       depth,
   1057       InputOutput,
   1058       visual,
   1059       attribute_mask,
   1060       &swa);
   1061   if (ui::PlatformEventSource::GetInstance())
   1062     ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
   1063   open_windows().push_back(xwindow_);
   1064 
   1065   // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL().
   1066 
   1067   long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
   1068                     KeyPressMask | KeyReleaseMask |
   1069                     EnterWindowMask | LeaveWindowMask |
   1070                     ExposureMask | VisibilityChangeMask |
   1071                     StructureNotifyMask | PropertyChangeMask |
   1072                     PointerMotionMask;
   1073   XSelectInput(xdisplay_, xwindow_, event_mask);
   1074   XFlush(xdisplay_);
   1075 
   1076   if (ui::IsXInput2Available())
   1077     ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
   1078 
   1079   // TODO(erg): We currently only request window deletion events. We also
   1080   // should listen for activation events and anything else that GTK+ listens
   1081   // for, and do something useful.
   1082   ::Atom protocols[2];
   1083   protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
   1084   protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
   1085   XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
   1086 
   1087   // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
   1088   // the desktop environment.
   1089   XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
   1090 
   1091   // Likewise, the X server needs to know this window's pid so it knows which
   1092   // program to kill if the window hangs.
   1093   // XChangeProperty() expects "pid" to be long.
   1094   COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long);
   1095   long pid = getpid();
   1096   XChangeProperty(xdisplay_,
   1097                   xwindow_,
   1098                   atom_cache_.GetAtom("_NET_WM_PID"),
   1099                   XA_CARDINAL,
   1100                   32,
   1101                   PropModeReplace,
   1102                   reinterpret_cast<unsigned char*>(&pid), 1);
   1103 
   1104   XChangeProperty(xdisplay_,
   1105                   xwindow_,
   1106                   atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE"),
   1107                   XA_ATOM,
   1108                   32,
   1109                   PropModeReplace,
   1110                   reinterpret_cast<unsigned char*>(&window_type), 1);
   1111 
   1112   // List of window state properties (_NET_WM_STATE) to set, if any.
   1113   std::vector< ::Atom> state_atom_list;
   1114 
   1115   // Remove popup windows from taskbar unless overridden.
   1116   if ((params.type == Widget::InitParams::TYPE_POPUP ||
   1117        params.type == Widget::InitParams::TYPE_BUBBLE) &&
   1118       !params.force_show_in_taskbar) {
   1119     state_atom_list.push_back(
   1120         atom_cache_.GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
   1121   }
   1122 
   1123   // If the window should stay on top of other windows, add the
   1124   // _NET_WM_STATE_ABOVE property.
   1125   is_always_on_top_ = params.keep_on_top;
   1126   if (is_always_on_top_)
   1127     state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"));
   1128 
   1129   if (params.visible_on_all_workspaces) {
   1130     state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_STICKY"));
   1131     ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", kAllDesktops);
   1132   }
   1133 
   1134   // Setting _NET_WM_STATE by sending a message to the root_window (with
   1135   // SetWMSpecState) has no effect here since the window has not yet been
   1136   // mapped. So we manually change the state.
   1137   if (!state_atom_list.empty()) {
   1138     ui::SetAtomArrayProperty(xwindow_,
   1139                              "_NET_WM_STATE",
   1140                              "ATOM",
   1141                              state_atom_list);
   1142   }
   1143 
   1144   if (!params.wm_class_name.empty() || !params.wm_class_class.empty()) {
   1145     ui::SetWindowClassHint(
   1146         xdisplay_, xwindow_, params.wm_class_name, params.wm_class_class);
   1147   }
   1148   if (!params.wm_role_name.empty() ||
   1149       params.type == Widget::InitParams::TYPE_POPUP) {
   1150     const char kX11WindowRolePopup[] = "popup";
   1151     ui::SetWindowRole(xdisplay_, xwindow_, params.wm_role_name.empty() ?
   1152                       std::string(kX11WindowRolePopup) : params.wm_role_name);
   1153   }
   1154 
   1155   if (params.remove_standard_frame) {
   1156     // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force
   1157     // fullscreen on the window when it matches the desktop size.
   1158     ui::SetHideTitlebarWhenMaximizedProperty(xwindow_,
   1159                                              ui::HIDE_TITLEBAR_WHEN_MAXIMIZED);
   1160   }
   1161 
   1162   // If we have a parent, record the parent/child relationship. We use this
   1163   // data during destruction to make sure that when we try to close a parent
   1164   // window, we also destroy all child windows.
   1165   if (params.parent && params.parent->GetHost()) {
   1166     XID parent_xid =
   1167         params.parent->GetHost()->GetAcceleratedWidget();
   1168     window_parent_ = GetHostForXID(parent_xid);
   1169     DCHECK(window_parent_);
   1170     window_parent_->window_children_.insert(this);
   1171   }
   1172 
   1173   // If we have a delegate which is providing a default window icon, use that
   1174   // icon.
   1175   gfx::ImageSkia* window_icon = ViewsDelegate::views_delegate ?
   1176       ViewsDelegate::views_delegate->GetDefaultWindowIcon() : NULL;
   1177   if (window_icon) {
   1178     SetWindowIcons(gfx::ImageSkia(), *window_icon);
   1179   }
   1180   CreateCompositor(GetAcceleratedWidget());
   1181 }
   1182 
   1183 void DesktopWindowTreeHostX11::OnWMStateUpdated() {
   1184   std::vector< ::Atom> atom_list;
   1185   if (!ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list))
   1186     return;
   1187 
   1188   bool was_minimized = IsMinimized();
   1189 
   1190   window_properties_.clear();
   1191   std::copy(atom_list.begin(), atom_list.end(),
   1192             inserter(window_properties_, window_properties_.begin()));
   1193 
   1194   // Propagate the window minimization information to the content window, so
   1195   // the render side can update its visibility properly. OnWMStateUpdated() is
   1196   // called by PropertyNofify event from DispatchEvent() when the browser is
   1197   // minimized or shown from minimized state. On Windows, this is realized by
   1198   // calling OnHostResized() with an empty size. In particular,
   1199   // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the
   1200   // window is minimized. On Linux, returning empty size in GetBounds() or
   1201   // SetBounds() does not work.
   1202   bool is_minimized = IsMinimized();
   1203   if (is_minimized != was_minimized) {
   1204     if (is_minimized)
   1205       content_window_->Hide();
   1206     else
   1207       content_window_->Show();
   1208   }
   1209 
   1210   if (restored_bounds_.IsEmpty()) {
   1211     DCHECK(!IsFullscreen());
   1212     if (IsMaximized()) {
   1213       // The request that we become maximized originated from a different
   1214       // process. |bounds_| already contains our maximized bounds. Do a best
   1215       // effort attempt to get restored bounds by setting it to our previously
   1216       // set bounds (and if we get this wrong, we aren't any worse off since
   1217       // we'd otherwise be returning our maximized bounds).
   1218       restored_bounds_ = previous_bounds_;
   1219     }
   1220   } else if (!IsMaximized() && !IsFullscreen()) {
   1221     // If we have restored bounds, but WM_STATE no longer claims to be
   1222     // maximized or fullscreen, we should clear our restored bounds.
   1223     restored_bounds_ = gfx::Rect();
   1224   }
   1225 
   1226   // Ignore requests by the window manager to enter or exit fullscreen (e.g. as
   1227   // a result of pressing a window manager accelerator key). Chrome does not
   1228   // handle window manager initiated fullscreen. In particular, Chrome needs to
   1229   // do preprocessing before the x window's fullscreen state is toggled.
   1230 
   1231   is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE");
   1232 
   1233   // Now that we have different window properties, we may need to relayout the
   1234   // window. (The windows code doesn't need this because their window change is
   1235   // synchronous.)
   1236   Relayout();
   1237   ResetWindowRegion();
   1238 }
   1239 
   1240 void DesktopWindowTreeHostX11::OnFrameExtentsUpdated() {
   1241   std::vector<int> insets;
   1242   if (ui::GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) &&
   1243       insets.size() == 4) {
   1244     // |insets| are returned in the order: [left, right, top, bottom].
   1245     native_window_frame_borders_ = gfx::Insets(
   1246         insets[2],
   1247         insets[0],
   1248         insets[3],
   1249         insets[1]);
   1250   } else {
   1251     native_window_frame_borders_ = gfx::Insets();
   1252   }
   1253 }
   1254 
   1255 void DesktopWindowTreeHostX11::UpdateWMUserTime(
   1256     const ui::PlatformEvent& event) {
   1257   if (!IsActive())
   1258     return;
   1259 
   1260   ui::EventType type = ui::EventTypeFromNative(event);
   1261   if (type == ui::ET_MOUSE_PRESSED ||
   1262       type == ui::ET_KEY_PRESSED ||
   1263       type == ui::ET_TOUCH_PRESSED) {
   1264     unsigned long wm_user_time_ms = static_cast<unsigned long>(
   1265         ui::EventTimeFromNative(event).InMilliseconds());
   1266     XChangeProperty(xdisplay_,
   1267                     xwindow_,
   1268                     atom_cache_.GetAtom("_NET_WM_USER_TIME"),
   1269                     XA_CARDINAL,
   1270                     32,
   1271                     PropModeReplace,
   1272                     reinterpret_cast<const unsigned char *>(&wm_user_time_ms),
   1273                     1);
   1274     X11DesktopHandler::get()->set_wm_user_time_ms(wm_user_time_ms);
   1275   }
   1276 }
   1277 
   1278 void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled,
   1279                                                 ::Atom state1,
   1280                                                 ::Atom state2) {
   1281   XEvent xclient;
   1282   memset(&xclient, 0, sizeof(xclient));
   1283   xclient.type = ClientMessage;
   1284   xclient.xclient.window = xwindow_;
   1285   xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE");
   1286   xclient.xclient.format = 32;
   1287   xclient.xclient.data.l[0] =
   1288       enabled ? k_NET_WM_STATE_ADD : k_NET_WM_STATE_REMOVE;
   1289   xclient.xclient.data.l[1] = state1;
   1290   xclient.xclient.data.l[2] = state2;
   1291   xclient.xclient.data.l[3] = 1;
   1292   xclient.xclient.data.l[4] = 0;
   1293 
   1294   XSendEvent(xdisplay_, x_root_window_, False,
   1295              SubstructureRedirectMask | SubstructureNotifyMask,
   1296              &xclient);
   1297 }
   1298 
   1299 bool DesktopWindowTreeHostX11::HasWMSpecProperty(const char* property) const {
   1300   return window_properties_.find(atom_cache_.GetAtom(property)) !=
   1301       window_properties_.end();
   1302 }
   1303 
   1304 void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
   1305   use_native_frame_ = use_native_frame;
   1306   ui::SetUseOSWindowFrame(xwindow_, use_native_frame);
   1307   ResetWindowRegion();
   1308 }
   1309 
   1310 void DesktopWindowTreeHostX11::OnCaptureReleased() {
   1311   x11_capture_.reset();
   1312   g_current_capture = NULL;
   1313   OnHostLostWindowCapture();
   1314   native_widget_delegate_->OnMouseCaptureLost();
   1315 }
   1316 
   1317 void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
   1318   // In Windows, the native events sent to chrome are separated into client
   1319   // and non-client versions of events, which we record on our LocatedEvent
   1320   // structures. On X11, we emulate the concept of non-client. Before we pass
   1321   // this event to the cross platform event handling framework, we need to
   1322   // make sure it is appropriately marked as non-client if it's in the non
   1323   // client area, or otherwise, we can get into a state where the a window is
   1324   // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc
   1325   // despite the mouse button being released.
   1326   //
   1327   // We can't do this later in the dispatch process because we share that
   1328   // with ash, and ash gets confused about event IS_NON_CLIENT-ness on
   1329   // events, since ash doesn't expect this bit to be set, because it's never
   1330   // been set before. (This works on ash on Windows because none of the mouse
   1331   // events on the ash desktop are clicking in what Windows considers to be a
   1332   // non client area.) Likewise, we won't want to do the following in any
   1333   // WindowTreeHost that hosts ash.
   1334   if (content_window_ && content_window_->delegate()) {
   1335     int flags = event->flags();
   1336     int hit_test_code =
   1337         content_window_->delegate()->GetNonClientComponent(event->location());
   1338     if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE)
   1339       flags |= ui::EF_IS_NON_CLIENT;
   1340     event->set_flags(flags);
   1341   }
   1342 
   1343   // While we unset the urgency hint when we gain focus, we also must remove it
   1344   // on mouse clicks because we can call FlashFrame() on an active window.
   1345   if (event->IsAnyButton() || event->IsMouseWheelEvent())
   1346     FlashFrame(false);
   1347 
   1348   if (!g_current_capture || g_current_capture == this) {
   1349     SendEventToProcessor(event);
   1350   } else {
   1351     // Another DesktopWindowTreeHostX11 has installed itself as
   1352     // capture. Translate the event's location and dispatch to the other.
   1353     event->ConvertLocationToTarget(window(), g_current_capture->window());
   1354     g_current_capture->SendEventToProcessor(event);
   1355   }
   1356 }
   1357 
   1358 void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) {
   1359   if (g_current_capture && g_current_capture != this &&
   1360       event->type() == ui::ET_TOUCH_PRESSED) {
   1361     event->ConvertLocationToTarget(window(), g_current_capture->window());
   1362     g_current_capture->SendEventToProcessor(event);
   1363   } else {
   1364     SendEventToProcessor(event);
   1365   }
   1366 }
   1367 
   1368 void DesktopWindowTreeHostX11::ResetWindowRegion() {
   1369   // If a custom window shape was supplied then apply it.
   1370   if (custom_window_shape_) {
   1371     XShapeCombineRegion(
   1372         xdisplay_, xwindow_, ShapeBounding, 0, 0, window_shape_, false);
   1373     return;
   1374   }
   1375 
   1376   if (window_shape_)
   1377     XDestroyRegion(window_shape_);
   1378   window_shape_ = NULL;
   1379 
   1380   if (!IsMaximized() && !IsFullscreen()) {
   1381     gfx::Path window_mask;
   1382     views::Widget* widget = native_widget_delegate_->AsWidget();
   1383     if (widget->non_client_view()) {
   1384       // Some frame views define a custom (non-rectangular) window mask. If
   1385       // so, use it to define the window shape. If not, fall through.
   1386       widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask);
   1387       if (window_mask.countPoints() > 0) {
   1388         window_shape_ = gfx::CreateRegionFromSkPath(window_mask);
   1389         XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding,
   1390                             0, 0, window_shape_, false);
   1391         return;
   1392       }
   1393     }
   1394   }
   1395 
   1396   // If we didn't set the shape for any reason, reset the shaping information.
   1397   // How this is done depends on the border style, due to quirks and bugs in
   1398   // various window managers.
   1399   if (ShouldUseNativeFrame()) {
   1400     // If the window has system borders, the mask must be set to null (not a
   1401     // rectangle), because several window managers (eg, KDE, XFCE, XMonad) will
   1402     // not put borders on a window with a custom shape.
   1403     XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, None, ShapeSet);
   1404   } else {
   1405     // Conversely, if the window does not have system borders, the mask must be
   1406     // manually set to a rectangle that covers the whole window (not null). This
   1407     // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null
   1408     // shape causes the hint to disable system borders to be ignored (resulting
   1409     // in a double border).
   1410     XRectangle r = {0, 0, static_cast<unsigned short>(bounds_.width()),
   1411                     static_cast<unsigned short>(bounds_.height())};
   1412     XShapeCombineRectangles(
   1413         xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, ShapeSet, YXBanded);
   1414   }
   1415 }
   1416 
   1417 void DesktopWindowTreeHostX11::SerializeImageRepresentation(
   1418     const gfx::ImageSkiaRep& rep,
   1419     std::vector<unsigned long>* data) {
   1420   int width = rep.GetWidth();
   1421   data->push_back(width);
   1422 
   1423   int height = rep.GetHeight();
   1424   data->push_back(height);
   1425 
   1426   const SkBitmap& bitmap = rep.sk_bitmap();
   1427   SkAutoLockPixels locker(bitmap);
   1428 
   1429   for (int y = 0; y < height; ++y)
   1430     for (int x = 0; x < width; ++x)
   1431       data->push_back(bitmap.getColor(x, y));
   1432 }
   1433 
   1434 Visual* DesktopWindowTreeHostX11::GetARGBVisual() {
   1435   XVisualInfo visual_template;
   1436   visual_template.screen = 0;
   1437   Visual* to_return = NULL;
   1438 
   1439   int visuals_len;
   1440   XVisualInfo* visual_list = XGetVisualInfo(xdisplay_,
   1441                                             VisualScreenMask,
   1442                                             &visual_template, &visuals_len);
   1443   for (int i = 0; i < visuals_len; ++i) {
   1444     // Why support only 8888 ARGB? Because it's all that GTK+ supports. In
   1445     // gdkvisual-x11.cc, they look for this specific visual and use it for all
   1446     // their alpha channel using needs.
   1447     //
   1448     // TODO(erg): While the following does find a valid visual, some GL drivers
   1449     // don't believe that this has an alpha channel. According to marcheu@,
   1450     // this should work on open source driver though. (It doesn't work with
   1451     // NVidia's binaries currently.) http://crbug.com/369209
   1452     if (visual_list[i].depth == 32 &&
   1453         visual_list[i].visual->red_mask == 0xff0000 &&
   1454         visual_list[i].visual->green_mask == 0x00ff00 &&
   1455         visual_list[i].visual->blue_mask == 0x0000ff) {
   1456       to_return = visual_list[i].visual;
   1457       break;
   1458     }
   1459   }
   1460 
   1461   if (visual_list)
   1462     XFree(visual_list);
   1463 
   1464   return to_return;
   1465 }
   1466 
   1467 std::list<XID>& DesktopWindowTreeHostX11::open_windows() {
   1468   if (!open_windows_)
   1469     open_windows_ = new std::list<XID>();
   1470   return *open_windows_;
   1471 }
   1472 
   1473 void DesktopWindowTreeHostX11::MapWindow(ui::WindowShowState show_state) {
   1474   if (show_state != ui::SHOW_STATE_DEFAULT &&
   1475       show_state != ui::SHOW_STATE_NORMAL &&
   1476       show_state != ui::SHOW_STATE_INACTIVE) {
   1477     // It will behave like SHOW_STATE_NORMAL.
   1478     NOTIMPLEMENTED();
   1479   }
   1480 
   1481   // Before we map the window, set size hints. Otherwise, some window managers
   1482   // will ignore toplevel XMoveWindow commands.
   1483   XSizeHints size_hints;
   1484   size_hints.flags = PPosition;
   1485   size_hints.x = bounds_.x();
   1486   size_hints.y = bounds_.y();
   1487   XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
   1488 
   1489   // If SHOW_STATE_INACTIVE, tell the window manager not to focus the window
   1490   // when mapping. This is done by setting the _NET_WM_USER_TIME to 0. See e.g.
   1491   // http://standards.freedesktop.org/wm-spec/latest/ar01s05.html
   1492   unsigned long wm_user_time_ms = (show_state == ui::SHOW_STATE_INACTIVE) ?
   1493       0 : X11DesktopHandler::get()->wm_user_time_ms();
   1494   if (show_state == ui::SHOW_STATE_INACTIVE || wm_user_time_ms != 0) {
   1495     XChangeProperty(xdisplay_,
   1496                     xwindow_,
   1497                     atom_cache_.GetAtom("_NET_WM_USER_TIME"),
   1498                     XA_CARDINAL,
   1499                     32,
   1500                     PropModeReplace,
   1501                     reinterpret_cast<const unsigned char *>(&wm_user_time_ms),
   1502                     1);
   1503   }
   1504 
   1505   XMapWindow(xdisplay_, xwindow_);
   1506 
   1507   // We now block until our window is mapped. Some X11 APIs will crash and
   1508   // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
   1509   // asynchronous.
   1510   if (ui::X11EventSource::GetInstance())
   1511     ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
   1512   window_mapped_ = true;
   1513 }
   1514 
   1515 void DesktopWindowTreeHostX11::SetWindowTransparency() {
   1516   compositor()->SetHostHasTransparentBackground(use_argb_visual_);
   1517   window()->SetTransparent(use_argb_visual_);
   1518   content_window_->SetTransparent(use_argb_visual_);
   1519 }
   1520 
   1521 void DesktopWindowTreeHostX11::Relayout() {
   1522   Widget* widget = native_widget_delegate_->AsWidget();
   1523   NonClientView* non_client_view = widget->non_client_view();
   1524   // non_client_view may be NULL, especially during creation.
   1525   if (non_client_view) {
   1526     non_client_view->client_view()->InvalidateLayout();
   1527     non_client_view->InvalidateLayout();
   1528   }
   1529   widget->GetRootView()->Layout();
   1530 }
   1531 
   1532 ////////////////////////////////////////////////////////////////////////////////
   1533 // DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation:
   1534 
   1535 bool DesktopWindowTreeHostX11::CanDispatchEvent(
   1536     const ui::PlatformEvent& event) {
   1537   return event->xany.window == xwindow_ ||
   1538          (event->type == GenericEvent &&
   1539           static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_);
   1540 }
   1541 
   1542 uint32_t DesktopWindowTreeHostX11::DispatchEvent(
   1543     const ui::PlatformEvent& event) {
   1544   XEvent* xev = event;
   1545 
   1546   TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch",
   1547                "event->type", event->type);
   1548 
   1549   UpdateWMUserTime(event);
   1550 
   1551   // May want to factor CheckXEventForConsistency(xev); into a common location
   1552   // since it is called here.
   1553   switch (xev->type) {
   1554     case EnterNotify:
   1555     case LeaveNotify: {
   1556       // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
   1557       // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
   1558       // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
   1559       // necessary. crbug.com/385716
   1560       if (xev->xcrossing.detail == NotifyInferior)
   1561         break;
   1562 
   1563       ui::MouseEvent mouse_event(xev);
   1564       DispatchMouseEvent(&mouse_event);
   1565       break;
   1566     }
   1567     case Expose: {
   1568       gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
   1569                             xev->xexpose.width, xev->xexpose.height);
   1570       compositor()->ScheduleRedrawRect(damage_rect);
   1571       break;
   1572     }
   1573     case KeyPress: {
   1574       ui::KeyEvent keydown_event(xev, false);
   1575       SendEventToProcessor(&keydown_event);
   1576       break;
   1577     }
   1578     case KeyRelease: {
   1579       ui::KeyEvent keyup_event(xev, false);
   1580       SendEventToProcessor(&keyup_event);
   1581       break;
   1582     }
   1583     case ButtonPress:
   1584     case ButtonRelease: {
   1585       ui::EventType event_type = ui::EventTypeFromNative(xev);
   1586       switch (event_type) {
   1587         case ui::ET_MOUSEWHEEL: {
   1588           ui::MouseWheelEvent mouseev(xev);
   1589           DispatchMouseEvent(&mouseev);
   1590           break;
   1591         }
   1592         case ui::ET_MOUSE_PRESSED:
   1593         case ui::ET_MOUSE_RELEASED: {
   1594           ui::MouseEvent mouseev(xev);
   1595           DispatchMouseEvent(&mouseev);
   1596           break;
   1597         }
   1598         case ui::ET_UNKNOWN:
   1599           // No event is created for X11-release events for mouse-wheel buttons.
   1600           break;
   1601         default:
   1602           NOTREACHED() << event_type;
   1603       }
   1604       break;
   1605     }
   1606     case FocusOut:
   1607       if (xev->xfocus.mode != NotifyGrab) {
   1608         ReleaseCapture();
   1609         OnHostLostWindowCapture();
   1610         X11DesktopHandler::get()->ProcessXEvent(xev);
   1611       } else {
   1612         dispatcher()->OnHostLostMouseGrab();
   1613       }
   1614       break;
   1615     case FocusIn:
   1616       X11DesktopHandler::get()->ProcessXEvent(xev);
   1617       break;
   1618     case ConfigureNotify: {
   1619       DCHECK_EQ(xwindow_, xev->xconfigure.window);
   1620       DCHECK_EQ(xwindow_, xev->xconfigure.event);
   1621       // It's possible that the X window may be resized by some other means than
   1622       // from within aura (e.g. the X window manager can change the size). Make
   1623       // sure the root window size is maintained properly.
   1624       int translated_x = xev->xconfigure.x;
   1625       int translated_y = xev->xconfigure.y;
   1626       if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) {
   1627         Window unused;
   1628         XTranslateCoordinates(xdisplay_, xwindow_, x_root_window_,
   1629             0, 0, &translated_x, &translated_y, &unused);
   1630       }
   1631       gfx::Rect bounds(translated_x, translated_y,
   1632                        xev->xconfigure.width, xev->xconfigure.height);
   1633       bool size_changed = bounds_.size() != bounds.size();
   1634       bool origin_changed = bounds_.origin() != bounds.origin();
   1635       previous_bounds_ = bounds_;
   1636       bounds_ = bounds;
   1637 
   1638       if (origin_changed)
   1639         OnHostMoved(bounds_.origin());
   1640 
   1641       if (size_changed) {
   1642         delayed_resize_task_.Reset(base::Bind(
   1643             &DesktopWindowTreeHostX11::DelayedResize,
   1644             close_widget_factory_.GetWeakPtr(),
   1645             bounds.size()));
   1646         base::MessageLoop::current()->PostTask(
   1647             FROM_HERE, delayed_resize_task_.callback());
   1648       }
   1649       break;
   1650     }
   1651     case GenericEvent: {
   1652       ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
   1653       if (!factory->ShouldProcessXI2Event(xev))
   1654         break;
   1655 
   1656       ui::EventType type = ui::EventTypeFromNative(xev);
   1657       XEvent last_event;
   1658       int num_coalesced = 0;
   1659 
   1660       switch (type) {
   1661         case ui::ET_TOUCH_MOVED:
   1662           num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
   1663           if (num_coalesced > 0)
   1664             xev = &last_event;
   1665           // fallthrough
   1666         case ui::ET_TOUCH_PRESSED:
   1667         case ui::ET_TOUCH_RELEASED: {
   1668           ui::TouchEvent touchev(xev);
   1669           DispatchTouchEvent(&touchev);
   1670           break;
   1671         }
   1672         case ui::ET_MOUSE_MOVED:
   1673         case ui::ET_MOUSE_DRAGGED:
   1674         case ui::ET_MOUSE_PRESSED:
   1675         case ui::ET_MOUSE_RELEASED:
   1676         case ui::ET_MOUSE_ENTERED:
   1677         case ui::ET_MOUSE_EXITED: {
   1678           if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
   1679             // If this is a motion event, we want to coalesce all pending motion
   1680             // events that are at the top of the queue.
   1681             num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
   1682             if (num_coalesced > 0)
   1683               xev = &last_event;
   1684           }
   1685           ui::MouseEvent mouseev(xev);
   1686           DispatchMouseEvent(&mouseev);
   1687           break;
   1688         }
   1689         case ui::ET_MOUSEWHEEL: {
   1690           ui::MouseWheelEvent mouseev(xev);
   1691           DispatchMouseEvent(&mouseev);
   1692           break;
   1693         }
   1694         case ui::ET_SCROLL_FLING_START:
   1695         case ui::ET_SCROLL_FLING_CANCEL:
   1696         case ui::ET_SCROLL: {
   1697           ui::ScrollEvent scrollev(xev);
   1698           SendEventToProcessor(&scrollev);
   1699           break;
   1700         }
   1701         case ui::ET_UNKNOWN:
   1702           break;
   1703         default:
   1704           NOTREACHED();
   1705       }
   1706 
   1707       // If we coalesced an event we need to free its cookie.
   1708       if (num_coalesced > 0)
   1709         XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
   1710       break;
   1711     }
   1712     case MapNotify: {
   1713       FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
   1714                         observer_list_,
   1715                         OnWindowMapped(xwindow_));
   1716       break;
   1717     }
   1718     case UnmapNotify: {
   1719       FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
   1720                         observer_list_,
   1721                         OnWindowUnmapped(xwindow_));
   1722       break;
   1723     }
   1724     case ClientMessage: {
   1725       Atom message_type = xev->xclient.message_type;
   1726       if (message_type == atom_cache_.GetAtom("WM_PROTOCOLS")) {
   1727         Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
   1728         if (protocol == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
   1729           // We have received a close message from the window manager.
   1730           OnHostCloseRequested();
   1731         } else if (protocol == atom_cache_.GetAtom("_NET_WM_PING")) {
   1732           XEvent reply_event = *xev;
   1733           reply_event.xclient.window = x_root_window_;
   1734 
   1735           XSendEvent(xdisplay_,
   1736                      reply_event.xclient.window,
   1737                      False,
   1738                      SubstructureRedirectMask | SubstructureNotifyMask,
   1739                      &reply_event);
   1740         }
   1741       } else if (message_type == atom_cache_.GetAtom("XdndEnter")) {
   1742         drag_drop_client_->OnXdndEnter(xev->xclient);
   1743       } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
   1744         drag_drop_client_->OnXdndLeave(xev->xclient);
   1745       } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
   1746         drag_drop_client_->OnXdndPosition(xev->xclient);
   1747       } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
   1748         drag_drop_client_->OnXdndStatus(xev->xclient);
   1749       } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
   1750         drag_drop_client_->OnXdndFinished(xev->xclient);
   1751       } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
   1752         drag_drop_client_->OnXdndDrop(xev->xclient);
   1753       }
   1754       break;
   1755     }
   1756     case MappingNotify: {
   1757       switch (xev->xmapping.request) {
   1758         case MappingModifier:
   1759         case MappingKeyboard:
   1760           XRefreshKeyboardMapping(&xev->xmapping);
   1761           break;
   1762         case MappingPointer:
   1763           ui::DeviceDataManager::GetInstance()->UpdateButtonMap();
   1764           break;
   1765         default:
   1766           NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
   1767           break;
   1768       }
   1769       break;
   1770     }
   1771     case MotionNotify: {
   1772       // Discard all but the most recent motion event that targets the same
   1773       // window with unchanged state.
   1774       XEvent last_event;
   1775       while (XPending(xev->xany.display)) {
   1776         XEvent next_event;
   1777         XPeekEvent(xev->xany.display, &next_event);
   1778         if (next_event.type == MotionNotify &&
   1779             next_event.xmotion.window == xev->xmotion.window &&
   1780             next_event.xmotion.subwindow == xev->xmotion.subwindow &&
   1781             next_event.xmotion.state == xev->xmotion.state) {
   1782           XNextEvent(xev->xany.display, &last_event);
   1783           xev = &last_event;
   1784         } else {
   1785           break;
   1786         }
   1787       }
   1788 
   1789       ui::MouseEvent mouseev(xev);
   1790       DispatchMouseEvent(&mouseev);
   1791       break;
   1792     }
   1793     case PropertyNotify: {
   1794       ::Atom changed_atom = xev->xproperty.atom;
   1795       if (changed_atom == atom_cache_.GetAtom("_NET_WM_STATE"))
   1796         OnWMStateUpdated();
   1797       else if (changed_atom == atom_cache_.GetAtom("_NET_FRAME_EXTENTS"))
   1798         OnFrameExtentsUpdated();
   1799       break;
   1800     }
   1801     case SelectionNotify: {
   1802       drag_drop_client_->OnSelectionNotify(xev->xselection);
   1803       break;
   1804     }
   1805   }
   1806   return ui::POST_DISPATCH_STOP_PROPAGATION;
   1807 }
   1808 
   1809 void DesktopWindowTreeHostX11::DelayedResize(const gfx::Size& size) {
   1810   OnHostResized(size);
   1811   ResetWindowRegion();
   1812   delayed_resize_task_.Cancel();
   1813 }
   1814 
   1815 ////////////////////////////////////////////////////////////////////////////////
   1816 // DesktopWindowTreeHost, public:
   1817 
   1818 // static
   1819 DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
   1820     internal::NativeWidgetDelegate* native_widget_delegate,
   1821     DesktopNativeWidgetAura* desktop_native_widget_aura) {
   1822   return new DesktopWindowTreeHostX11(native_widget_delegate,
   1823                                       desktop_native_widget_aura);
   1824 }
   1825 
   1826 // static
   1827 ui::NativeTheme* DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
   1828   const views::LinuxUI* linux_ui = views::LinuxUI::instance();
   1829   if (linux_ui) {
   1830     ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window);
   1831     if (native_theme)
   1832       return native_theme;
   1833   }
   1834 
   1835   return ui::NativeTheme::instance();
   1836 }
   1837 
   1838 }  // namespace views
   1839