This source file includes following definitions.
- urgency_hint_set_
- GetContentWindowForXID
- GetHostForXID
- GetAllOpenWindows
- GetX11RootWindowBounds
- HandleNativeWidgetActivationChanged
- AddObserver
- RemoveObserver
- CleanUpWindowList
- Init
- OnNativeWidgetCreated
- CreateTooltip
- CreateDragDropClient
- Close
- CloseNow
- AsWindowTreeHost
- ShowWindowWithState
- ShowMaximizedWithBounds
- IsVisible
- SetSize
- StackAtTop
- CenterWindow
- GetWindowPlacement
- GetWindowBoundsInScreen
- GetClientAreaBoundsInScreen
- GetRestoredBounds
- GetWorkAreaBoundsInScreen
- SetShape
- Activate
- Deactivate
- IsActive
- Maximize
- Minimize
- Restore
- IsMaximized
- IsMinimized
- HasCapture
- SetAlwaysOnTop
- IsAlwaysOnTop
- SetVisibleOnAllWorkspaces
- SetWindowTitle
- ClearNativeFocus
- RunMoveLoop
- EndMoveLoop
- SetVisibilityChangedAnimationsEnabled
- ShouldUseNativeFrame
- ShouldWindowContentsBeTransparent
- FrameTypeChanged
- CreateNonClientFrameView
- SetFullscreen
- IsFullscreen
- SetOpacity
- SetWindowIcons
- InitModalType
- FlashFrame
- OnRootViewLayout
- OnNativeWidgetFocus
- OnNativeWidgetBlur
- IsAnimatingClosed
- GetAcceleratedWidget
- Show
- Hide
- ToggleFullScreen
- GetBounds
- SetBounds
- GetInsets
- SetInsets
- GetLocationOnNativeScreen
- SetCapture
- ReleaseCapture
- QueryMouseLocation
- ConfineCursorToRootWindow
- UnConfineCursor
- SetCursorNative
- MoveCursorToNative
- OnCursorVisibilityChangedNative
- PostNativeEvent
- OnDeviceScaleFactorChanged
- GetEventProcessor
- InitX11Window
- IsWindowManagerPresent
- SetWMSpecState
- HasWMSpecProperty
- SetUseNativeFrame
- OnCaptureReleased
- DispatchMouseEvent
- DispatchTouchEvent
- ResetWindowRegion
- SerializeImageRepresentation
- open_windows
- MapWindow
- Dispatch
- Create
- GetNativeTheme
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xatom.h>
#include <X11/Xregion.h>
#include <X11/Xutil.h>
#include "base/basictypes.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_pump_x11.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#include "ui/base/hit_test.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/event_utils.h"
#include "ui/events/x/device_data_manager.h"
#include "ui/events/x/device_list_cache_x.h"
#include "ui/events/x/touch_factory_x11.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/path.h"
#include "ui/gfx/path_x11.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/ime/input_method.h"
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h"
#include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
#include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h"
#include "ui/views/widget/desktop_aura/x11_scoped_capture.h"
#include "ui/views/widget/desktop_aura/x11_window_event_filter.h"
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/window_util.h"
namespace views {
DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture =
    NULL;
std::list<XID>* DesktopWindowTreeHostX11::open_windows_ = NULL;
DEFINE_WINDOW_PROPERTY_KEY(
    aura::Window*, kViewsWindowForRootWindow, NULL);
DEFINE_WINDOW_PROPERTY_KEY(
    DesktopWindowTreeHostX11*, kHostForRootWindow, NULL);
namespace {
const int k_NET_WM_STATE_ADD = 1;
const int k_NET_WM_STATE_REMOVE = 0;
const char* kAtomsToCache[] = {
  "UTF8_STRING",
  "WM_DELETE_WINDOW",
  "WM_PROTOCOLS",
  "WM_S0",
  "_NET_WM_ICON",
  "_NET_WM_NAME",
  "_NET_WM_PID",
  "_NET_WM_PING",
  "_NET_WM_STATE",
  "_NET_WM_STATE_ABOVE",
  "_NET_WM_STATE_FULLSCREEN",
  "_NET_WM_STATE_HIDDEN",
  "_NET_WM_STATE_MAXIMIZED_HORZ",
  "_NET_WM_STATE_MAXIMIZED_VERT",
  "_NET_WM_STATE_SKIP_TASKBAR",
  "_NET_WM_STATE_STICKY",
  "_NET_WM_USER_TIME",
  "_NET_WM_WINDOW_OPACITY",
  "_NET_WM_WINDOW_TYPE",
  "_NET_WM_WINDOW_TYPE_DND",
  "_NET_WM_WINDOW_TYPE_MENU",
  "_NET_WM_WINDOW_TYPE_NORMAL",
  "_NET_WM_WINDOW_TYPE_NOTIFICATION",
  "_NET_WM_WINDOW_TYPE_TOOLTIP",
  "XdndActionAsk",
  "XdndActionCopy"
  "XdndActionLink",
  "XdndActionList",
  "XdndActionMove",
  "XdndActionPrivate",
  "XdndAware",
  "XdndDrop",
  "XdndEnter",
  "XdndFinished",
  "XdndLeave",
  "XdndPosition",
  "XdndProxy",  
  "XdndSelection",
  "XdndStatus",
  "XdndTypeList",
  NULL
};
}  
DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
    internal::NativeWidgetDelegate* native_widget_delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura)
    : close_widget_factory_(this),
      xdisplay_(gfx::GetXDisplay()),
      xwindow_(0),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      atom_cache_(xdisplay_, kAtomsToCache),
      window_mapped_(false),
      is_fullscreen_(false),
      is_always_on_top_(false),
      use_native_frame_(false),
      drag_drop_client_(NULL),
      current_cursor_(ui::kCursorNull),
      native_widget_delegate_(native_widget_delegate),
      desktop_native_widget_aura_(desktop_native_widget_aura),
      content_window_(NULL),
      window_parent_(NULL),
      custom_window_shape_(NULL),
      urgency_hint_set_(false) {
}
DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
  window()->ClearProperty(kHostForRootWindow);
  aura::client::SetWindowMoveClient(window(), NULL);
  desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
  if (custom_window_shape_)
    XDestroyRegion(custom_window_shape_);
  DestroyDispatcher();
}
aura::Window* DesktopWindowTreeHostX11::GetContentWindowForXID(XID xid) {
  aura::WindowTreeHost* host =
      aura::WindowTreeHost::GetForAcceleratedWidget(xid);
  return host ? host->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
}
DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::GetHostForXID(XID xid) {
  aura::WindowTreeHost* host =
      aura::WindowTreeHost::GetForAcceleratedWidget(xid);
  return host ? host->window()->GetProperty(kHostForRootWindow) : NULL;
}
std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() {
  std::vector<aura::Window*> windows(open_windows().size());
  std::transform(open_windows().begin(),
                 open_windows().end(),
                 windows.begin(),
                 GetContentWindowForXID);
  return windows;
}
gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const {
  return bounds_;
}
void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged(
    bool active) {
  if (active) {
    FlashFrame(false);
    OnHostActivated();
    open_windows().remove(xwindow_);
    open_windows().insert(open_windows().begin(), xwindow_);
  }
  desktop_native_widget_aura_->HandleActivationChanged(active);
  native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
}
void DesktopWindowTreeHostX11::AddObserver(
    views::DesktopWindowTreeHostObserverX11* observer) {
  observer_list_.AddObserver(observer);
}
void DesktopWindowTreeHostX11::RemoveObserver(
    views::DesktopWindowTreeHostObserverX11* observer) {
  observer_list_.RemoveObserver(observer);
}
void DesktopWindowTreeHostX11::CleanUpWindowList() {
  delete open_windows_;
  open_windows_ = NULL;
}
void DesktopWindowTreeHostX11::Init(aura::Window* content_window,
                                    const Widget::InitParams& params) {
  content_window_ = content_window;
  
  
  
  
  Widget::InitParams sanitized_params = params;
  if (sanitized_params.bounds.width() == 0)
    sanitized_params.bounds.set_width(100);
  if (sanitized_params.bounds.height() == 0)
    sanitized_params.bounds.set_height(100);
  InitX11Window(sanitized_params);
}
void DesktopWindowTreeHostX11::OnNativeWidgetCreated(
    const Widget::InitParams& params) {
  window()->SetProperty(kViewsWindowForRootWindow, content_window_);
  window()->SetProperty(kHostForRootWindow, this);
  
  
  X11DesktopHandler::get();
  
  x11_window_event_filter_.reset(new X11WindowEventFilter(this));
  SetUseNativeFrame(params.type == Widget::InitParams::TYPE_WINDOW &&
                    !params.remove_standard_frame);
  desktop_native_widget_aura_->root_window_event_filter()->AddHandler(
      x11_window_event_filter_.get());
  x11_window_move_client_.reset(new X11DesktopWindowMoveClient);
  aura::client::SetWindowMoveClient(window(), x11_window_move_client_.get());
  native_widget_delegate_->OnNativeWidgetCreated(true);
}
scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostX11::CreateTooltip() {
  return scoped_ptr<corewm::Tooltip>(
      new corewm::TooltipAura(gfx::SCREEN_TYPE_NATIVE));
}
scoped_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostX11::CreateDragDropClient(
    DesktopNativeCursorManager* cursor_manager) {
  drag_drop_client_ = new DesktopDragDropClientAuraX11(
      window(), cursor_manager, xdisplay_, xwindow_);
  return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
}
void DesktopWindowTreeHostX11::Close() {
  
  if (!close_widget_factory_.HasWeakPtrs()) {
    
    
    
    
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&DesktopWindowTreeHostX11::CloseNow,
                   close_widget_factory_.GetWeakPtr()));
  }
}
void DesktopWindowTreeHostX11::CloseNow() {
  if (xwindow_ == None)
    return;
  x11_capture_.reset();
  native_widget_delegate_->OnNativeWidgetDestroying();
  
  
  std::set<DesktopWindowTreeHostX11*> window_children_copy = window_children_;
  for (std::set<DesktopWindowTreeHostX11*>::iterator it =
           window_children_copy.begin(); it != window_children_copy.end();
       ++it) {
    (*it)->CloseNow();
  }
  DCHECK(window_children_.empty());
  
  if (window_parent_) {
    window_parent_->window_children_.erase(this);
    window_parent_ = NULL;
  }
  
  
  desktop_native_widget_aura_->root_window_event_filter()->RemoveHandler(
      x11_window_event_filter_.get());
  
  
  
  DestroyCompositor();
  open_windows().remove(xwindow_);
  
  base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_);
  XDestroyWindow(xdisplay_, xwindow_);
  xwindow_ = None;
  desktop_native_widget_aura_->OnHostClosed();
}
aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() {
  return this;
}
void DesktopWindowTreeHostX11::ShowWindowWithState(
    ui::WindowShowState show_state) {
  if (!window_mapped_)
    MapWindow(show_state);
  if (show_state == ui::SHOW_STATE_NORMAL ||
      show_state == ui::SHOW_STATE_MAXIMIZED) {
    
    if (show_state == ui::SHOW_STATE_MAXIMIZED)
      Maximize();
    Activate();
  }
  native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
}
void DesktopWindowTreeHostX11::ShowMaximizedWithBounds(
    const gfx::Rect& restored_bounds) {
  restored_bounds_ = restored_bounds;
  ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED);
}
bool DesktopWindowTreeHostX11::IsVisible() const {
  return window_mapped_;
}
void DesktopWindowTreeHostX11::SetSize(const gfx::Size& size) {
  bool size_changed = bounds_.size() != size;
  XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
  bounds_.set_size(size);
  if (size_changed)
    OnHostResized(size);
}
void DesktopWindowTreeHostX11::StackAtTop() {
  XRaiseWindow(xdisplay_, xwindow_);
}
void DesktopWindowTreeHostX11::CenterWindow(const gfx::Size& size) {
  gfx::Rect parent_bounds = GetWorkAreaBoundsInScreen();
  
  
  if (wm::GetTransientParent(content_window_)) {
    gfx::Rect transient_parent_rect =
        wm::GetTransientParent(content_window_)->GetBoundsInScreen();
    if (transient_parent_rect.height() >= size.height() &&
        transient_parent_rect.width() >= size.width()) {
      parent_bounds = transient_parent_rect;
    }
  }
  gfx::Rect window_bounds(
      parent_bounds.x() + (parent_bounds.width() - size.width()) / 2,
      parent_bounds.y() + (parent_bounds.height() - size.height()) / 2,
      size.width(),
      size.height());
  
  
  window_bounds.AdjustToFit(parent_bounds);
  SetBounds(window_bounds);
}
void DesktopWindowTreeHostX11::GetWindowPlacement(
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  *bounds = GetRestoredBounds();
  if (IsFullscreen()) {
    *show_state = ui::SHOW_STATE_FULLSCREEN;
  } else if (IsMinimized()) {
    *show_state = ui::SHOW_STATE_MINIMIZED;
  } else if (IsMaximized()) {
    *show_state = ui::SHOW_STATE_MAXIMIZED;
  } else if (!IsActive()) {
    *show_state = ui::SHOW_STATE_INACTIVE;
  } else {
    *show_state = ui::SHOW_STATE_NORMAL;
  }
}
gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
  return bounds_;
}
gfx::Rect DesktopWindowTreeHostX11::GetClientAreaBoundsInScreen() const {
  
  
  
  
  
  
  
  
  return bounds_;
}
gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const {
  
  
  
  
  if (!restored_bounds_.IsEmpty())
    return restored_bounds_;
  return GetWindowBoundsInScreen();
}
gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
  std::vector<int> value;
  if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
      value.size() >= 4) {
    return gfx::Rect(value[0], value[1], value[2], value[3]);
  }
  
  Window root;
  int x, y;
  unsigned int width, height;
  unsigned int border_width, depth;
  if (!XGetGeometry(xdisplay_, x_root_window_, &root, &x, &y,
                    &width, &height, &border_width, &depth)) {
    NOTIMPLEMENTED();
    return gfx::Rect(0, 0, 10, 10);
  }
  return gfx::Rect(x, y, width, height);
}
void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) {
  if (custom_window_shape_)
    XDestroyRegion(custom_window_shape_);
  custom_window_shape_ = gfx::CreateRegionFromSkRegion(*native_region);
  ResetWindowRegion();
  delete native_region;
}
void DesktopWindowTreeHostX11::Activate() {
  if (!window_mapped_)
    return;
  X11DesktopHandler::get()->ActivateWindow(xwindow_);
}
void DesktopWindowTreeHostX11::Deactivate() {
  if (!IsActive())
    return;
  x11_capture_.reset();
  XLowerWindow(xdisplay_, xwindow_);
}
bool DesktopWindowTreeHostX11::IsActive() const {
  return X11DesktopHandler::get()->IsActiveWindow(xwindow_);
}
void DesktopWindowTreeHostX11::Maximize() {
  
  
  
  restored_bounds_ = bounds_;
  SetWMSpecState(true,
                 atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
                 atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
}
void DesktopWindowTreeHostX11::Minimize() {
  x11_capture_.reset();
  XIconifyWindow(xdisplay_, xwindow_, 0);
}
void DesktopWindowTreeHostX11::Restore() {
  SetWMSpecState(false,
                 atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
                 atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
}
bool DesktopWindowTreeHostX11::IsMaximized() const {
  return (HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_VERT") &&
          HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_HORZ"));
}
bool DesktopWindowTreeHostX11::IsMinimized() const {
  return HasWMSpecProperty("_NET_WM_STATE_HIDDEN");
}
bool DesktopWindowTreeHostX11::HasCapture() const {
  return g_current_capture == this;
}
void DesktopWindowTreeHostX11::SetAlwaysOnTop(bool always_on_top) {
  is_always_on_top_ = always_on_top;
  SetWMSpecState(always_on_top,
                 atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"),
                 None);
}
bool DesktopWindowTreeHostX11::IsAlwaysOnTop() const {
  return is_always_on_top_;
}
void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) {
  SetWMSpecState(always_visible,
                 atom_cache_.GetAtom("_NET_WM_STATE_STICKY"),
                 None);
}
bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) {
  if (window_title_ == title)
    return false;
  window_title_ = title;
  std::string utf8str = base::UTF16ToUTF8(title);
  XChangeProperty(xdisplay_,
                  xwindow_,
                  atom_cache_.GetAtom("_NET_WM_NAME"),
                  atom_cache_.GetAtom("UTF8_STRING"),
                  8,
                  PropModeReplace,
                  reinterpret_cast<const unsigned char*>(utf8str.c_str()),
                  utf8str.size());
  
  
  
  
  XStoreName(xdisplay_, xwindow_, utf8str.c_str());
  return true;
}
void DesktopWindowTreeHostX11::ClearNativeFocus() {
  
  
  
  if (content_window_ && aura::client::GetFocusClient(content_window_) &&
      content_window_->Contains(
          aura::client::GetFocusClient(content_window_)->GetFocusedWindow())) {
    aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
  }
}
Widget::MoveLoopResult DesktopWindowTreeHostX11::RunMoveLoop(
    const gfx::Vector2d& drag_offset,
    Widget::MoveLoopSource source,
    Widget::MoveLoopEscapeBehavior escape_behavior) {
  aura::client::WindowMoveSource window_move_source =
      source == Widget::MOVE_LOOP_SOURCE_MOUSE ?
      aura::client::WINDOW_MOVE_SOURCE_MOUSE :
      aura::client::WINDOW_MOVE_SOURCE_TOUCH;
  if (x11_window_move_client_->RunMoveLoop(content_window_, drag_offset,
      window_move_source) == aura::client::MOVE_SUCCESSFUL)
    return Widget::MOVE_LOOP_SUCCESSFUL;
  return Widget::MOVE_LOOP_CANCELED;
}
void DesktopWindowTreeHostX11::EndMoveLoop() {
  x11_window_move_client_->EndMoveLoop();
}
void DesktopWindowTreeHostX11::SetVisibilityChangedAnimationsEnabled(
    bool value) {
  
}
bool DesktopWindowTreeHostX11::ShouldUseNativeFrame() const {
  return use_native_frame_;
}
bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const {
  return false;
}
void DesktopWindowTreeHostX11::FrameTypeChanged() {
  Widget::FrameType new_type =
      native_widget_delegate_->AsWidget()->frame_type();
  SetUseNativeFrame(new_type == Widget::FRAME_TYPE_FORCE_NATIVE);
  
  
  
  native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame();
}
NonClientFrameView* DesktopWindowTreeHostX11::CreateNonClientFrameView() {
  return NULL;
}
void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
  is_fullscreen_ = fullscreen;
  SetWMSpecState(fullscreen,
                 atom_cache_.GetAtom("_NET_WM_STATE_FULLSCREEN"),
                 None);
}
bool DesktopWindowTreeHostX11::IsFullscreen() const {
  return is_fullscreen_;
}
void DesktopWindowTreeHostX11::SetOpacity(unsigned char opacity) {
  
  
  
  unsigned long cardinality = opacity * 0x1010101;
  if (cardinality == 0xffffffff) {
    XDeleteProperty(xdisplay_, xwindow_,
                    atom_cache_.GetAtom("_NET_WM_WINDOW_OPACITY"));
  } else {
    XChangeProperty(xdisplay_, xwindow_,
                    atom_cache_.GetAtom("_NET_WM_WINDOW_OPACITY"),
                    XA_CARDINAL, 32,
                    PropModeReplace,
                    reinterpret_cast<unsigned char*>(&cardinality), 1);
  }
}
void DesktopWindowTreeHostX11::SetWindowIcons(
    const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
  
  
  
  
  
  
  
  
  std::vector<unsigned long> data;
  if (window_icon.HasRepresentation(1.0f))
    SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data);
  if (app_icon.HasRepresentation(1.0f))
    SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data);
  if (data.empty())
    XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_ICON"));
  else
    ui::SetAtomArrayProperty(xwindow_, "_NET_WM_ICON", "CARDINAL", data);
}
void DesktopWindowTreeHostX11::InitModalType(ui::ModalType modal_type) {
  switch (modal_type) {
    case ui::MODAL_TYPE_NONE:
      break;
    default:
      
      
      
      NOTIMPLEMENTED();
  }
}
void DesktopWindowTreeHostX11::FlashFrame(bool flash_frame) {
  if (urgency_hint_set_ == flash_frame)
    return;
  XWMHints* hints = XGetWMHints(xdisplay_, xwindow_);
  if (!hints) {
    
    hints = XAllocWMHints();
  }
  if (flash_frame)
    hints->flags |= XUrgencyHint;
  else
    hints->flags &= ~XUrgencyHint;
  XSetWMHints(xdisplay_, xwindow_, hints);
  XFree(hints);
  urgency_hint_set_ = flash_frame;
}
void DesktopWindowTreeHostX11::OnRootViewLayout() const {
  if (!window_mapped_)
    return;
  XSizeHints hints;
  long supplied_return;
  XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return);
  gfx::Size minimum = native_widget_delegate_->GetMinimumSize();
  if (minimum.IsEmpty()) {
    hints.flags &= ~PMinSize;
  } else {
    hints.flags |= PMinSize;
    hints.min_width = minimum.width();
    hints.min_height = minimum.height();
  }
  gfx::Size maximum = native_widget_delegate_->GetMaximumSize();
  if (maximum.IsEmpty()) {
    hints.flags &= ~PMaxSize;
  } else {
    hints.flags |= PMaxSize;
    hints.max_width = maximum.width();
    hints.max_height = maximum.height();
  }
  XSetWMNormalHints(xdisplay_, xwindow_, &hints);
}
void DesktopWindowTreeHostX11::OnNativeWidgetFocus() {
  native_widget_delegate_->AsWidget()->GetInputMethod()->OnFocus();
}
void DesktopWindowTreeHostX11::OnNativeWidgetBlur() {
  if (xwindow_) {
    x11_capture_.reset();
    native_widget_delegate_->AsWidget()->GetInputMethod()->OnBlur();
  }
}
bool DesktopWindowTreeHostX11::IsAnimatingClosed() const {
  return false;
}
gfx::AcceleratedWidget DesktopWindowTreeHostX11::GetAcceleratedWidget() {
  return xwindow_;
}
void DesktopWindowTreeHostX11::Show() {
  ShowWindowWithState(ui::SHOW_STATE_NORMAL);
  native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);
}
void DesktopWindowTreeHostX11::Hide() {
  if (window_mapped_) {
    XWithdrawWindow(xdisplay_, xwindow_, 0);
    window_mapped_ = false;
  }
  native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);
}
void DesktopWindowTreeHostX11::ToggleFullScreen() {
  NOTIMPLEMENTED();
}
gfx::Rect DesktopWindowTreeHostX11::GetBounds() const {
  return bounds_;
}
void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
  bool origin_changed = bounds_.origin() != bounds.origin();
  bool size_changed = bounds_.size() != bounds.size();
  XWindowChanges changes = {0};
  unsigned value_mask = 0;
  if (size_changed) {
    
    DCHECK_GT(bounds.width(), 0);
    DCHECK_GT(bounds.height(), 0);
    changes.width = bounds.width();
    changes.height = bounds.height();
    value_mask |= CWHeight | CWWidth;
  }
  if (origin_changed) {
    changes.x = bounds.x();
    changes.y = bounds.y();
    value_mask |= CWX | CWY;
  }
  if (value_mask)
    XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
  
  
  
  
  
  bounds_ = bounds;
  if (origin_changed)
    native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
  if (size_changed)
    OnHostResized(bounds.size());
  else
    compositor()->ScheduleRedrawRect(gfx::Rect(bounds.size()));
}
gfx::Insets DesktopWindowTreeHostX11::GetInsets() const {
  return gfx::Insets();
}
void DesktopWindowTreeHostX11::SetInsets(const gfx::Insets& insets) {
}
gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
  return bounds_.origin();
}
void DesktopWindowTreeHostX11::SetCapture() {
  
  
  
  
  
  
  
  if (g_current_capture)
    g_current_capture->OnCaptureReleased();
  g_current_capture = this;
  x11_capture_.reset(new X11ScopedCapture(xwindow_));
}
void DesktopWindowTreeHostX11::ReleaseCapture() {
  if (g_current_capture == this)
    g_current_capture->OnCaptureReleased();
}
bool DesktopWindowTreeHostX11::QueryMouseLocation(
    gfx::Point* location_return) {
  aura::client::CursorClient* cursor_client =
      aura::client::GetCursorClient(window());
  if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
    *location_return = gfx::Point(0, 0);
    return false;
  }
  ::Window root_return, child_return;
  int root_x_return, root_y_return, win_x_return, win_y_return;
  unsigned int mask_return;
  XQueryPointer(xdisplay_,
                xwindow_,
                &root_return,
                &child_return,
                &root_x_return, &root_y_return,
                &win_x_return, &win_y_return,
                &mask_return);
  *location_return = gfx::Point(
      std::max(0, std::min(bounds_.width(), win_x_return)),
      std::max(0, std::min(bounds_.height(), win_y_return)));
  return (win_x_return >= 0 && win_x_return < bounds_.width() &&
          win_y_return >= 0 && win_y_return < bounds_.height());
}
bool DesktopWindowTreeHostX11::ConfineCursorToRootWindow() {
  NOTIMPLEMENTED();
  return false;
}
void DesktopWindowTreeHostX11::UnConfineCursor() {
  NOTIMPLEMENTED();
}
void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
  XDefineCursor(xdisplay_, xwindow_, cursor.platform());
}
void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
  XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
               bounds_.x() + location.x(), bounds_.y() + location.y());
}
void DesktopWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
  
  
}
void DesktopWindowTreeHostX11::PostNativeEvent(
    const base::NativeEvent& native_event) {
  DCHECK(xwindow_);
  DCHECK(xdisplay_);
  XEvent xevent = *native_event;
  xevent.xany.display = xdisplay_;
  xevent.xany.window = xwindow_;
  switch (xevent.type) {
    case EnterNotify:
    case LeaveNotify:
    case MotionNotify:
    case KeyPress:
    case KeyRelease:
    case ButtonPress:
    case ButtonRelease: {
      
      
      
      xevent.xmotion.root = x_root_window_;
      xevent.xmotion.time = CurrentTime;
      gfx::Point point(xevent.xmotion.x, xevent.xmotion.y);
      ConvertPointToNativeScreen(&point);
      xevent.xmotion.x_root = point.x();
      xevent.xmotion.y_root = point.y();
    }
    default:
      break;
  }
  XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
}
void DesktopWindowTreeHostX11::OnDeviceScaleFactorChanged(
    float device_scale_factor) {
}
ui::EventProcessor* DesktopWindowTreeHostX11::GetEventProcessor() {
  return dispatcher();
}
void DesktopWindowTreeHostX11::InitX11Window(
    const Widget::InitParams& params) {
  unsigned long attribute_mask = CWBackPixmap;
  XSetWindowAttributes swa;
  memset(&swa, 0, sizeof(swa));
  swa.background_pixmap = None;
  ::Atom window_type;
  switch (params.type) {
    case Widget::InitParams::TYPE_MENU:
      swa.override_redirect = True;
      window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU");
      break;
    case Widget::InitParams::TYPE_TOOLTIP:
      window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP");
      break;
    case Widget::InitParams::TYPE_POPUP:
      swa.override_redirect = True;
      window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION");
      break;
    case Widget::InitParams::TYPE_DRAG:
      swa.override_redirect = True;
      window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_DND");
      break;
    default:
      window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_NORMAL");
      break;
  }
  if (swa.override_redirect)
    attribute_mask |= CWOverrideRedirect;
  bounds_ = params.bounds;
  xwindow_ = XCreateWindow(
      xdisplay_, x_root_window_,
      bounds_.x(), bounds_.y(),
      bounds_.width(), bounds_.height(),
      0,               
      CopyFromParent,  
      InputOutput,
      CopyFromParent,  
      attribute_mask,
      &swa);
  base::MessagePumpX11::Current()->AddDispatcherForWindow(this, xwindow_);
  open_windows().push_back(xwindow_);
  
  long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
                    KeyPressMask | KeyReleaseMask |
                    EnterWindowMask | LeaveWindowMask |
                    ExposureMask | VisibilityChangeMask |
                    StructureNotifyMask | PropertyChangeMask |
                    PointerMotionMask;
  XSelectInput(xdisplay_, xwindow_, event_mask);
  XFlush(xdisplay_);
  if (ui::IsXInput2Available())
    ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
  
  
  
  ::Atom protocols[2];
  protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
  protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
  XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
  
  
  XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
  
  
  
  COMPILE_ASSERT(sizeof(long) >= sizeof(pid_t), pid_t_bigger_than_long);
  long pid = getpid();
  XChangeProperty(xdisplay_,
                  xwindow_,
                  atom_cache_.GetAtom("_NET_WM_PID"),
                  XA_CARDINAL,
                  32,
                  PropModeReplace,
                  reinterpret_cast<unsigned char*>(&pid), 1);
  XChangeProperty(xdisplay_,
                  xwindow_,
                  atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE"),
                  XA_ATOM,
                  32,
                  PropModeReplace,
                  reinterpret_cast<unsigned char*>(&window_type), 1);
  
  std::vector< ::Atom> state_atom_list;
  
  if ((params.type == Widget::InitParams::TYPE_POPUP ||
       params.type == Widget::InitParams::TYPE_BUBBLE) &&
      !params.force_show_in_taskbar) {
    state_atom_list.push_back(
        atom_cache_.GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
  }
  
  
  is_always_on_top_ = params.keep_on_top;
  if (is_always_on_top_)
    state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"));
  if (params.visible_on_all_workspaces)
    state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_STICKY"));
  
  
  
  if (!state_atom_list.empty()) {
    ui::SetAtomArrayProperty(xwindow_,
                             "_NET_WM_STATE",
                             "ATOM",
                             state_atom_list);
  }
  if (!params.wm_class_name.empty() || !params.wm_class_class.empty()) {
    ui::SetWindowClassHint(
        xdisplay_, xwindow_, params.wm_class_name, params.wm_class_class);
  }
  if (!params.wm_role_name.empty() ||
      params.type == Widget::InitParams::TYPE_POPUP) {
    const char kX11WindowRolePopup[] = "popup";
    ui::SetWindowRole(xdisplay_, xwindow_, params.wm_role_name.empty() ?
                      std::string(kX11WindowRolePopup) : params.wm_role_name);
  }
  if (params.remove_standard_frame) {
    
    
    ui::SetHideTitlebarWhenMaximizedProperty(xwindow_,
                                             ui::HIDE_TITLEBAR_WHEN_MAXIMIZED);
  }
  
  
  
  if (params.parent && params.parent->GetHost()) {
    XID parent_xid =
        params.parent->GetHost()->GetAcceleratedWidget();
    window_parent_ = GetHostForXID(parent_xid);
    DCHECK(window_parent_);
    window_parent_->window_children_.insert(this);
  }
  
  
  gfx::ImageSkia* window_icon = ViewsDelegate::views_delegate ?
      ViewsDelegate::views_delegate->GetDefaultWindowIcon() : NULL;
  if (window_icon) {
    SetWindowIcons(gfx::ImageSkia(), *window_icon);
  }
  CreateCompositor(GetAcceleratedWidget());
}
bool DesktopWindowTreeHostX11::IsWindowManagerPresent() {
  
  
  return XGetSelectionOwner(
      xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
}
void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled,
                                                ::Atom state1,
                                                ::Atom state2) {
  XEvent xclient;
  memset(&xclient, 0, sizeof(xclient));
  xclient.type = ClientMessage;
  xclient.xclient.window = xwindow_;
  xclient.xclient.message_type = atom_cache_.GetAtom("_NET_WM_STATE");
  xclient.xclient.format = 32;
  xclient.xclient.data.l[0] =
      enabled ? k_NET_WM_STATE_ADD : k_NET_WM_STATE_REMOVE;
  xclient.xclient.data.l[1] = state1;
  xclient.xclient.data.l[2] = state2;
  xclient.xclient.data.l[3] = 1;
  xclient.xclient.data.l[4] = 0;
  XSendEvent(xdisplay_, x_root_window_, False,
             SubstructureRedirectMask | SubstructureNotifyMask,
             &xclient);
}
bool DesktopWindowTreeHostX11::HasWMSpecProperty(const char* property) const {
  return window_properties_.find(atom_cache_.GetAtom(property)) !=
      window_properties_.end();
}
void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
  use_native_frame_ = use_native_frame;
  x11_window_event_filter_->SetUseHostWindowBorders(use_native_frame);
}
void DesktopWindowTreeHostX11::OnCaptureReleased() {
  x11_capture_.reset();
  g_current_capture = NULL;
  OnHostLostWindowCapture();
  native_widget_delegate_->OnMouseCaptureLost();
}
void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  if (content_window_ && content_window_->delegate()) {
    int flags = event->flags();
    int hit_test_code =
        content_window_->delegate()->GetNonClientComponent(event->location());
    if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE)
      flags |= ui::EF_IS_NON_CLIENT;
    event->set_flags(flags);
  }
  
  
  if (event->IsAnyButton() || event->IsMouseWheelEvent())
    FlashFrame(false);
  if (!g_current_capture || g_current_capture == this) {
    SendEventToProcessor(event);
  } else {
    
    
    event->ConvertLocationToTarget(window(), g_current_capture->window());
    g_current_capture->SendEventToProcessor(event);
  }
}
void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) {
  if (g_current_capture && g_current_capture != this &&
      event->type() == ui::ET_TOUCH_PRESSED) {
    event->ConvertLocationToTarget(window(), g_current_capture->window());
    g_current_capture->SendEventToProcessor(event);
  } else {
    SendEventToProcessor(event);
  }
}
void DesktopWindowTreeHostX11::ResetWindowRegion() {
  
  if (custom_window_shape_) {
    XShapeCombineRegion(
        xdisplay_, xwindow_, ShapeBounding, 0, 0, custom_window_shape_, false);
    return;
  }
  if (!IsMaximized()) {
    gfx::Path window_mask;
    views::Widget* widget = native_widget_delegate_->AsWidget();
    if (widget->non_client_view()) {
      
      
      widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask);
      if (window_mask.countPoints() > 0) {
        Region region = gfx::CreateRegionFromSkPath(window_mask);
        XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding,
                            0, 0, region, false);
        XDestroyRegion(region);
        return;
      }
    }
  }
  
  
  
  if (ShouldUseNativeFrame()) {
    
    
    
    XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, None, ShapeSet);
  } else {
    
    
    
    
    
    XRectangle r = {0, 0, static_cast<unsigned short>(bounds_.width()),
                    static_cast<unsigned short>(bounds_.height())};
    XShapeCombineRectangles(
        xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, ShapeSet, YXBanded);
  }
}
void DesktopWindowTreeHostX11::SerializeImageRepresentation(
    const gfx::ImageSkiaRep& rep,
    std::vector<unsigned long>* data) {
  int width = rep.GetWidth();
  data->push_back(width);
  int height = rep.GetHeight();
  data->push_back(height);
  const SkBitmap& bitmap = rep.sk_bitmap();
  SkAutoLockPixels locker(bitmap);
  for (int y = 0; y < height; ++y)
    for (int x = 0; x < width; ++x)
      data->push_back(bitmap.getColor(x, y));
}
std::list<XID>& DesktopWindowTreeHostX11::open_windows() {
  if (!open_windows_)
    open_windows_ = new std::list<XID>();
  return *open_windows_;
}
void DesktopWindowTreeHostX11::MapWindow(ui::WindowShowState show_state) {
  if (show_state != ui::SHOW_STATE_DEFAULT &&
      show_state != ui::SHOW_STATE_NORMAL &&
      show_state != ui::SHOW_STATE_INACTIVE) {
    
    NOTIMPLEMENTED();
  }
  
  
  XSizeHints size_hints;
  size_hints.flags = PPosition;
  size_hints.x = bounds_.x();
  size_hints.y = bounds_.y();
  XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
  
  
  
  if (show_state == ui::SHOW_STATE_INACTIVE) {
    unsigned long value = 0;
    XChangeProperty(xdisplay_,
                    xwindow_,
                    atom_cache_.GetAtom("_NET_WM_USER_TIME"),
                    XA_CARDINAL,
                    32,
                    PropModeReplace,
                    reinterpret_cast<const unsigned char *>(&value),
                    1);
  } else {
    
    
    
    XDeleteProperty(
        xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_USER_TIME"));
  }
  XMapWindow(xdisplay_, xwindow_);
  
  
  
  base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_);
  window_mapped_ = true;
}
uint32_t DesktopWindowTreeHostX11::Dispatch(const base::NativeEvent& event) {
  XEvent* xev = event;
  TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch",
               "event->type", event->type);
  
  
  switch (xev->type) {
    case EnterNotify:
    case LeaveNotify: {
      if (!g_current_capture)
        X11DesktopHandler::get()->ProcessXEvent(xev);
      ui::MouseEvent mouse_event(xev);
      DispatchMouseEvent(&mouse_event);
      break;
    }
    case Expose: {
      gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
                            xev->xexpose.width, xev->xexpose.height);
      compositor()->ScheduleRedrawRect(damage_rect);
      break;
    }
    case KeyPress: {
      ui::KeyEvent keydown_event(xev, false);
      SendEventToProcessor(&keydown_event);
      break;
    }
    case KeyRelease: {
      ui::KeyEvent keyup_event(xev, false);
      SendEventToProcessor(&keyup_event);
      break;
    }
    case ButtonPress:
    case ButtonRelease: {
      ui::EventType event_type = ui::EventTypeFromNative(xev);
      switch (event_type) {
        case ui::ET_MOUSEWHEEL: {
          ui::MouseWheelEvent mouseev(xev);
          DispatchMouseEvent(&mouseev);
          break;
        }
        case ui::ET_MOUSE_PRESSED:
        case ui::ET_MOUSE_RELEASED: {
          ui::MouseEvent mouseev(xev);
          DispatchMouseEvent(&mouseev);
          break;
        }
        case ui::ET_UNKNOWN:
          
          break;
        default:
          NOTREACHED() << event_type;
      }
      break;
    }
    case FocusOut:
      if (xev->xfocus.mode != NotifyGrab) {
        ReleaseCapture();
        OnHostLostWindowCapture();
      } else {
        dispatcher()->OnHostLostMouseGrab();
      }
      break;
    case FocusIn:
      X11DesktopHandler::get()->ProcessXEvent(xev);
      break;
    case ConfigureNotify: {
      DCHECK_EQ(xwindow_, xev->xconfigure.window);
      DCHECK_EQ(xwindow_, xev->xconfigure.event);
      
      
      
      int translated_x = xev->xconfigure.x;
      int translated_y = xev->xconfigure.y;
      if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) {
        Window unused;
        XTranslateCoordinates(xdisplay_, xwindow_, x_root_window_,
            0, 0, &translated_x, &translated_y, &unused);
      }
      gfx::Rect bounds(translated_x, translated_y,
                       xev->xconfigure.width, xev->xconfigure.height);
      bool size_changed = bounds_.size() != bounds.size();
      bool origin_changed = bounds_.origin() != bounds.origin();
      previous_bounds_ = bounds_;
      bounds_ = bounds;
      if (size_changed)
        OnHostResized(bounds.size());
      if (origin_changed)
        OnHostMoved(bounds_.origin());
      ResetWindowRegion();
      break;
    }
    case GenericEvent: {
      ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
      if (!factory->ShouldProcessXI2Event(xev))
        break;
      ui::EventType type = ui::EventTypeFromNative(xev);
      XEvent last_event;
      int num_coalesced = 0;
      switch (type) {
        case ui::ET_TOUCH_MOVED:
          num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
          if (num_coalesced > 0)
            xev = &last_event;
          
        case ui::ET_TOUCH_PRESSED:
        case ui::ET_TOUCH_RELEASED: {
          ui::TouchEvent touchev(xev);
          DispatchTouchEvent(&touchev);
          break;
        }
        case ui::ET_MOUSE_MOVED:
        case ui::ET_MOUSE_DRAGGED:
        case ui::ET_MOUSE_PRESSED:
        case ui::ET_MOUSE_RELEASED:
        case ui::ET_MOUSE_ENTERED:
        case ui::ET_MOUSE_EXITED: {
          if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
            
            
            num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
            if (num_coalesced > 0)
              xev = &last_event;
          }
          ui::MouseEvent mouseev(xev);
          DispatchMouseEvent(&mouseev);
          break;
        }
        case ui::ET_MOUSEWHEEL: {
          ui::MouseWheelEvent mouseev(xev);
          DispatchMouseEvent(&mouseev);
          break;
        }
        case ui::ET_SCROLL_FLING_START:
        case ui::ET_SCROLL_FLING_CANCEL:
        case ui::ET_SCROLL: {
          ui::ScrollEvent scrollev(xev);
          SendEventToProcessor(&scrollev);
          break;
        }
        case ui::ET_UNKNOWN:
          break;
        default:
          NOTREACHED();
      }
      
      if (num_coalesced > 0)
        XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
      break;
    }
    case MapNotify: {
      FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
                        observer_list_,
                        OnWindowMapped(xwindow_));
      break;
    }
    case UnmapNotify: {
      FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
                        observer_list_,
                        OnWindowUnmapped(xwindow_));
      break;
    }
    case ClientMessage: {
      Atom message_type = xev->xclient.message_type;
      if (message_type == atom_cache_.GetAtom("WM_PROTOCOLS")) {
        Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
        if (protocol == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
          
          OnHostCloseRequested();
        } else if (protocol == atom_cache_.GetAtom("_NET_WM_PING")) {
          XEvent reply_event = *xev;
          reply_event.xclient.window = x_root_window_;
          XSendEvent(xdisplay_,
                     reply_event.xclient.window,
                     False,
                     SubstructureRedirectMask | SubstructureNotifyMask,
                     &reply_event);
        }
      } else if (message_type == atom_cache_.GetAtom("XdndEnter")) {
        drag_drop_client_->OnXdndEnter(xev->xclient);
      } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
        drag_drop_client_->OnXdndLeave(xev->xclient);
      } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
        drag_drop_client_->OnXdndPosition(xev->xclient);
      } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
        drag_drop_client_->OnXdndStatus(xev->xclient);
      } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
        drag_drop_client_->OnXdndFinished(xev->xclient);
      } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
        drag_drop_client_->OnXdndDrop(xev->xclient);
      }
      break;
    }
    case MappingNotify: {
      switch (xev->xmapping.request) {
        case MappingModifier:
        case MappingKeyboard:
          XRefreshKeyboardMapping(&xev->xmapping);
          break;
        case MappingPointer:
          ui::DeviceDataManager::GetInstance()->UpdateButtonMap();
          break;
        default:
          NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
          break;
      }
      break;
    }
    case MotionNotify: {
      
      
      XEvent last_event;
      while (XPending(xev->xany.display)) {
        XEvent next_event;
        XPeekEvent(xev->xany.display, &next_event);
        if (next_event.type == MotionNotify &&
            next_event.xmotion.window == xev->xmotion.window &&
            next_event.xmotion.subwindow == xev->xmotion.subwindow &&
            next_event.xmotion.state == xev->xmotion.state) {
          XNextEvent(xev->xany.display, &last_event);
          xev = &last_event;
        } else {
          break;
        }
      }
      ui::MouseEvent mouseev(xev);
      DispatchMouseEvent(&mouseev);
      break;
    }
    case PropertyNotify: {
      
      ::Atom state = atom_cache_.GetAtom("_NET_WM_STATE");
      std::vector< ::Atom> atom_list;
      if (xev->xproperty.atom == state &&
          ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list)) {
        window_properties_.clear();
        std::copy(atom_list.begin(), atom_list.end(),
                  inserter(window_properties_, window_properties_.begin()));
        if (!restored_bounds_.IsEmpty() && !IsMaximized()) {
          
          
          restored_bounds_ = gfx::Rect();
        } else if (IsMaximized() && restored_bounds_.IsEmpty()) {
          
          
          
          
          
          restored_bounds_ = previous_bounds_;
        }
        is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN");
        is_always_on_top_ = HasWMSpecProperty("_NET_WM_STATE_ABOVE");
        
        
        
        
        
        
        
        
        
        Widget* widget = native_widget_delegate_->AsWidget();
        NonClientView* non_client_view = widget->non_client_view();
        
        if (non_client_view) {
          non_client_view->client_view()->InvalidateLayout();
          non_client_view->InvalidateLayout();
        }
        widget->GetRootView()->Layout();
        
        
        ResetWindowRegion();
      }
      break;
    }
    case SelectionNotify: {
      drag_drop_client_->OnSelectionNotify(xev->xselection);
      break;
    }
  }
  return POST_DISPATCH_NONE;
}
DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
    internal::NativeWidgetDelegate* native_widget_delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura) {
  return new DesktopWindowTreeHostX11(native_widget_delegate,
                                      desktop_native_widget_aura);
}
ui::NativeTheme* DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
  const views::LinuxUI* linux_ui = views::LinuxUI::instance();
  if (linux_ui) {
    ui::NativeTheme* native_theme = linux_ui->GetNativeTheme();
    if (native_theme)
      return native_theme;
  }
  return ui::NativeTheme::instance();
}
}