// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/ui/public/cpp/window_tree_client.h"

#include <stddef.h>

#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/map.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/common/util.h"
#include "services/ui/public/cpp/in_flight_change.h"
#include "services/ui/public/cpp/input_event_handler.h"
#include "services/ui/public/cpp/window_drop_target.h"
#include "services/ui/public/cpp/window_manager_delegate.h"
#include "services/ui/public/cpp/window_observer.h"
#include "services/ui/public/cpp/window_private.h"
#include "services/ui/public/cpp/window_tracker.h"
#include "services/ui/public/cpp/window_tree_client_delegate.h"
#include "services/ui/public/cpp/window_tree_client_observer.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"

namespace ui {

Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) {
  return (client_id << 16) | local_id;
}

// Helper function to get the device_scale_factor() of the display::Display
// with |display_id|.
float ScaleFactorForDisplay(int64_t display_id) {
  // TODO(jonross): Remove this once aura-mus is complete. Currently the screen
  // is not being set properly for mus-in-renderer. (http://crbug.com/659155)
  if (!display::Screen::GetScreen())
    return 1.f;

  // TODO(riajiang): Change to use display::GetDisplayWithDisplayId() after
  // https://codereview.chromium.org/2361283002/ is landed.
  std::vector<display::Display> displays =
      display::Screen::GetScreen()->GetAllDisplays();
  auto iter = std::find_if(displays.begin(), displays.end(),
                           [display_id](const display::Display& display) {
                             return display.id() == display_id;
                           });
  if (iter != displays.end())
    return iter->device_scale_factor();
  return 1.f;
}

// Helper called to construct a local window object from transport data.
Window* AddWindowToClient(WindowTreeClient* client,
                          Window* parent,
                          const mojom::WindowDataPtr& window_data) {
  // We don't use the ctor that takes a WindowTreeClient here, since it will
  // call back to the service and attempt to create a new window.
  Window* window = WindowPrivate::LocalCreate();
  WindowPrivate private_window(window);
  private_window.set_client(client);
  private_window.set_server_id(window_data->window_id);
  private_window.set_visible(window_data->visible);
  private_window.set_properties(
      mojo::UnorderedMapToMap(window_data->properties));
  client->AddWindow(window);
  private_window.LocalSetBounds(
      gfx::Rect(),
      gfx::ConvertRectToDIP(ScaleFactorForDisplay(window->display_id()),
                            window_data->bounds));
  if (parent)
    WindowPrivate(parent).LocalAddChild(window);
  return window;
}

struct WindowTreeClient::CurrentDragState {
  // The current change id of the current drag an drop ipc.
  uint32_t change_id;

  // The effect to return when we send our finish signal.
  uint32_t completed_action;

  // Callback executed when a drag initiated by PerformDragDrop() is completed.
  base::Callback<void(bool, uint32_t)> on_finished;
};

WindowTreeClient::WindowTreeClient(
    WindowTreeClientDelegate* delegate,
    WindowManagerDelegate* window_manager_delegate,
    mojo::InterfaceRequest<mojom::WindowTreeClient> request)
    : client_id_(0),
      next_window_id_(1),
      next_change_id_(1),
      delegate_(delegate),
      window_manager_delegate_(window_manager_delegate),
      capture_window_(nullptr),
      focused_window_(nullptr),
      binding_(this),
      tree_(nullptr),
      in_destructor_(false),
      weak_factory_(this) {
  // Allow for a null request in tests.
  if (request.is_pending())
    binding_.Bind(std::move(request));
  if (window_manager_delegate)
    window_manager_delegate->SetWindowManagerClient(this);
}

WindowTreeClient::~WindowTreeClient() {
  in_destructor_ = true;

  for (auto& observer : observers_)
    observer.OnWillDestroyClient(this);

  std::vector<Window*> non_owned;
  WindowTracker tracker;
  while (!windows_.empty()) {
    IdToWindowMap::iterator it = windows_.begin();
    if (it->second->WasCreatedByThisClient()) {
      it->second->Destroy();
    } else {
      tracker.Add(it->second);
      windows_.erase(it);
    }
  }

  // Delete the non-owned windows last. In the typical case these are roots. The
  // exception is the window manager and embed roots, which may know about
  // other random windows that it doesn't own.
  // NOTE: we manually delete as we're a friend.
  while (!tracker.windows().empty())
    delete tracker.windows().front();

  for (auto& observer : observers_)
    observer.OnDidDestroyClient(this);
}

void WindowTreeClient::ConnectViaWindowTreeFactory(
    service_manager::Connector* connector) {
  // The client id doesn't really matter, we use 101 purely for debugging.
  client_id_ = 101;

  mojom::WindowTreeFactoryPtr factory;
  connector->BindInterface(ui::mojom::kServiceName, &factory);
  mojom::WindowTreePtr window_tree;
  factory->CreateWindowTree(MakeRequest(&window_tree),
                            binding_.CreateInterfacePtrAndBind());
  SetWindowTree(std::move(window_tree));
}

void WindowTreeClient::ConnectAsWindowManager(
    service_manager::Connector* connector) {
  DCHECK(window_manager_delegate_);

  mojom::WindowManagerWindowTreeFactoryPtr factory;
  connector->BindInterface(ui::mojom::kServiceName, &factory);
  mojom::WindowTreePtr window_tree;
  factory->CreateWindowTree(MakeRequest(&window_tree),
                            binding_.CreateInterfacePtrAndBind());
  SetWindowTree(std::move(window_tree));
}

void WindowTreeClient::WaitForEmbed() {
  DCHECK(roots_.empty());
  // OnEmbed() is the first function called.
  binding_.WaitForIncomingMethodCall();
  // TODO(sky): deal with pipe being closed before we get OnEmbed().
}

void WindowTreeClient::DestroyWindow(Window* window) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<CrashInFlightChange>(window, ChangeType::DELETE_WINDOW));
  tree_->DeleteWindow(change_id, server_id(window));
}

void WindowTreeClient::AddChild(Window* parent, Id child_id) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<CrashInFlightChange>(parent, ChangeType::ADD_CHILD));
  tree_->AddWindow(change_id, parent->server_id(), child_id);
}

void WindowTreeClient::RemoveChild(Window* parent, Id child_id) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<CrashInFlightChange>(parent, ChangeType::REMOVE_CHILD));
  tree_->RemoveWindowFromParent(change_id, child_id);
}

void WindowTreeClient::AddTransientWindow(Window* window,
                                              Id transient_window_id) {
  DCHECK(tree_);
  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
          window, ChangeType::ADD_TRANSIENT_WINDOW));
  tree_->AddTransientWindow(change_id, server_id(window), transient_window_id);
}

void WindowTreeClient::RemoveTransientWindowFromParent(Window* window) {
  DCHECK(tree_);
  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
          window, ChangeType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT));
  tree_->RemoveTransientWindowFromParent(change_id, server_id(window));
}

void WindowTreeClient::SetModal(Window* window) {
  DCHECK(tree_);
  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<InFlightSetModalChange>(window));
  tree_->SetModal(change_id, server_id(window));
}

void WindowTreeClient::Reorder(Window* window,
                                   Id relative_window_id,
                                   mojom::OrderDirection direction) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<CrashInFlightChange>(window, ChangeType::REORDER));
  tree_->ReorderWindow(change_id, server_id(window), relative_window_id,
                       direction);
}

bool WindowTreeClient::WasCreatedByThisClient(const Window* window) const {
  // Windows created via CreateTopLevelWindow() are not owned by us, but have
  // our client id. const_cast is required by set.
  return HiWord(server_id(window)) == client_id_ &&
         roots_.count(const_cast<Window*>(window)) == 0;
}

void WindowTreeClient::SetBounds(Window* window,
                                 const gfx::Rect& old_bounds,
                                 const gfx::Rect& bounds) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightBoundsChange>(window, old_bounds));
  tree_->SetWindowBounds(
      change_id, server_id(window),
      gfx::ConvertRectToPixel(ScaleFactorForDisplay(window->display_id()),
                              bounds));
}

void WindowTreeClient::SetCapture(Window* window) {
  // In order for us to get here we had to have exposed a window, which implies
  // we got a client.
  DCHECK(tree_);
  if (capture_window_ == window)
    return;
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightCaptureChange>(this, capture_window_));
  tree_->SetCapture(change_id, server_id(window));
  LocalSetCapture(window);
}

void WindowTreeClient::ReleaseCapture(Window* window) {
  // In order for us to get here we had to have exposed a window, which implies
  // we got a client.
  DCHECK(tree_);
  if (capture_window_ != window)
    return;
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightCaptureChange>(this, window));
  tree_->ReleaseCapture(change_id, server_id(window));
  LocalSetCapture(nullptr);
}

void WindowTreeClient::SetClientArea(
    Id window_id,
    const gfx::Insets& client_area,
    const std::vector<gfx::Rect>& additional_client_areas) {
  DCHECK(tree_);
  float device_scale_factor =
      ScaleFactorForDisplay(GetWindowByServerId(window_id)->display_id());
  std::vector<gfx::Rect> additional_client_areas_in_pixel;
  for (const gfx::Rect& area : additional_client_areas) {
    additional_client_areas_in_pixel.push_back(
        gfx::ConvertRectToPixel(device_scale_factor, area));
  }
  tree_->SetClientArea(
      window_id, gfx::ConvertInsetsToPixel(device_scale_factor, client_area),
      additional_client_areas_in_pixel);
}

void WindowTreeClient::SetHitTestMask(Id window_id, const gfx::Rect& mask) {
  DCHECK(tree_);
  tree_->SetHitTestMask(
      window_id,
      gfx::ConvertRectToPixel(
          ScaleFactorForDisplay(GetWindowByServerId(window_id)->display_id()),
          mask));
}

void WindowTreeClient::ClearHitTestMask(Id window_id) {
  DCHECK(tree_);
  tree_->SetHitTestMask(window_id, base::nullopt);
}

void WindowTreeClient::SetFocus(Window* window) {
  // In order for us to get here we had to have exposed a window, which implies
  // we got a client.
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightFocusChange>(this, focused_window_));
  tree_->SetFocus(change_id, window ? server_id(window) : 0);
  LocalSetFocus(window);
}

void WindowTreeClient::SetCanFocus(Id window_id, bool can_focus) {
  DCHECK(tree_);
  tree_->SetCanFocus(window_id, can_focus);
}

void WindowTreeClient::SetPredefinedCursor(Id window_id,
                                           ui::mojom::Cursor cursor_id) {
  DCHECK(tree_);

  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  // We make an inflight change thing here.
  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<InFlightPredefinedCursorChange>(
          window, window->predefined_cursor()));
  tree_->SetPredefinedCursor(change_id, window_id, cursor_id);
}

void WindowTreeClient::SetVisible(Window* window, bool visible) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightVisibleChange>(window, !visible));
  tree_->SetWindowVisibility(change_id, server_id(window), visible);
}

void WindowTreeClient::SetOpacity(Window* window, float opacity) {
  DCHECK(tree_);
  const uint32_t change_id = ScheduleInFlightChange(
      base::MakeUnique<InFlightOpacityChange>(window, window->opacity()));
  tree_->SetWindowOpacity(change_id, server_id(window), opacity);
}

void WindowTreeClient::SetProperty(
    Window* window,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& data) {
  DCHECK(tree_);

  base::Optional<std::vector<uint8_t>> old_value;
  if (window->HasSharedProperty(name))
    old_value.emplace(window->properties_[name]);

  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<InFlightPropertyChange>(
          window, name, std::move(old_value)));
  tree_->SetWindowProperty(change_id, server_id(window), name, data);
}

void WindowTreeClient::SetWindowTextInputState(
    Id window_id,
    mojo::TextInputStatePtr state) {
  DCHECK(tree_);
  tree_->SetWindowTextInputState(window_id, std::move(state));
}

void WindowTreeClient::SetImeVisibility(Id window_id,
                                            bool visible,
                                            mojo::TextInputStatePtr state) {
  DCHECK(tree_);
  tree_->SetImeVisibility(window_id, visible, std::move(state));
}

void WindowTreeClient::Embed(Id window_id,
                             mojom::WindowTreeClientPtr client,
                             uint32_t flags,
                             const mojom::WindowTree::EmbedCallback& callback) {
  DCHECK(tree_);
  tree_->Embed(window_id, std::move(client), flags, callback);
}

void WindowTreeClient::RequestClose(Window* window) {
  if (window_manager_internal_client_)
    window_manager_internal_client_->WmRequestClose(server_id(window));
}

void WindowTreeClient::AttachCompositorFrameSink(
    Id window_id,
    cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink,
    cc::mojom::MojoCompositorFrameSinkClientPtr client) {
  DCHECK(tree_);
  tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink),
                                   std::move(client));
}

void WindowTreeClient::LocalSetCapture(Window* window) {
  if (capture_window_ == window)
    return;
  Window* lost_capture = capture_window_;
  capture_window_ = window;
  if (lost_capture) {
    for (auto& observer : *WindowPrivate(lost_capture).observers())
      observer.OnWindowLostCapture(lost_capture);
  }
  for (auto& observer : observers_)
    observer.OnWindowTreeCaptureChanged(window, lost_capture);
}

void WindowTreeClient::LocalSetFocus(Window* focused) {
  Window* blurred = focused_window_;
  // Update |focused_window_| before calling any of the observers, so that the
  // observers get the correct result from calling |Window::HasFocus()|,
  // |WindowTreeClient::GetFocusedWindow()| etc.
  focused_window_ = focused;
  if (blurred) {
    for (auto& observer : *WindowPrivate(blurred).observers())
      observer.OnWindowFocusChanged(focused, blurred);
  }
  if (focused) {
    for (auto& observer : *WindowPrivate(focused).observers())
      observer.OnWindowFocusChanged(focused, blurred);
  }
  for (auto& observer : observers_)
    observer.OnWindowTreeFocusChanged(focused, blurred);
}

void WindowTreeClient::AddWindow(Window* window) {
  DCHECK(windows_.find(server_id(window)) == windows_.end());
  windows_[server_id(window)] = window;
}

void WindowTreeClient::OnWindowDestroying(Window* window) {
  if (window == capture_window_) {
    // Normally the queue updates itself upon window destruction. However since
    // |window| is being destroyed, it will not be possible to notify its
    // observers of the lost capture. Update local state now.
    LocalSetCapture(nullptr);
  }
  // For |focused_window_| window destruction clears the entire focus state.
}

void WindowTreeClient::OnWindowDestroyed(Window* window) {
  windows_.erase(server_id(window));

  for (auto& entry : embedded_windows_) {
    auto it = entry.second.find(window);
    if (it != entry.second.end()) {
      entry.second.erase(it);
      break;
    }
  }

  // Remove any InFlightChanges associated with the window.
  std::set<uint32_t> in_flight_change_ids_to_remove;
  for (const auto& pair : in_flight_map_) {
    if (pair.second->window() == window)
      in_flight_change_ids_to_remove.insert(pair.first);
  }
  for (auto change_id : in_flight_change_ids_to_remove)
    in_flight_map_.erase(change_id);

  const bool was_root = roots_.erase(window) > 0;
  if (!in_destructor_ && was_root && roots_.empty() && is_from_embed_)
    delegate_->OnEmbedRootDestroyed(window);
}

Window* WindowTreeClient::GetWindowByServerId(Id id) {
  IdToWindowMap::const_iterator it = windows_.find(id);
  return it != windows_.end() ? it->second : NULL;
}

InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching(
    const InFlightChange& change) {
  for (const auto& pair : in_flight_map_) {
    if (pair.second->window() == change.window() &&
        pair.second->change_type() == change.change_type() &&
        pair.second->Matches(change)) {
      return pair.second.get();
    }
  }
  return nullptr;
}

uint32_t WindowTreeClient::ScheduleInFlightChange(
    std::unique_ptr<InFlightChange> change) {
  DCHECK(!change->window() ||
         windows_.count(change->window()->server_id()) > 0);
  const uint32_t change_id = next_change_id_++;
  in_flight_map_[change_id] = std::move(change);
  return change_id;
}

bool WindowTreeClient::ApplyServerChangeToExistingInFlightChange(
    const InFlightChange& change) {
  InFlightChange* existing_change = GetOldestInFlightChangeMatching(change);
  if (!existing_change)
    return false;

  existing_change->SetRevertValueFrom(change);
  return true;
}

void WindowTreeClient::BuildWindowTree(
    const std::vector<mojom::WindowDataPtr>& windows,
    Window* initial_parent) {
  for (const auto& window_data : windows) {
    Window* parent = window_data->parent_id == 0
                         ? nullptr
                         : GetWindowByServerId(window_data->parent_id);
    Window* existing_window = GetWindowByServerId(window_data->window_id);
    if (!existing_window)
      AddWindowToClient(this, parent, window_data);
    else if (parent)
      WindowPrivate(parent).LocalAddChild(existing_window);
  }
}

Window* WindowTreeClient::NewWindowImpl(
    NewWindowType type,
    const Window::SharedProperties* properties) {
  DCHECK(tree_);
  Window* window =
      new Window(this, MakeTransportId(client_id_, next_window_id_++));
  if (properties)
    window->properties_ = *properties;
  AddWindow(window);

  const uint32_t change_id =
      ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
          window, type == NewWindowType::CHILD
                      ? ChangeType::NEW_WINDOW
                      : ChangeType::NEW_TOP_LEVEL_WINDOW));
  std::unordered_map<std::string, std::vector<uint8_t>> transport_properties;
  if (properties)
    transport_properties = mojo::MapToUnorderedMap(*properties);

  if (type == NewWindowType::CHILD) {
    tree_->NewWindow(change_id, server_id(window),
                     std::move(transport_properties));
  } else {
    roots_.insert(window);
    tree_->NewTopLevelWindow(change_id, server_id(window),
                             transport_properties);
  }
  return window;
}

void WindowTreeClient::SetWindowTree(mojom::WindowTreePtr window_tree_ptr) {
  tree_ptr_ = std::move(window_tree_ptr);
  tree_ = tree_ptr_.get();

  tree_ptr_->GetCursorLocationMemory(
      base::Bind(&WindowTreeClient::OnReceivedCursorLocationMemory,
                 weak_factory_.GetWeakPtr()));

  tree_ptr_.set_connection_error_handler(base::Bind(
      &WindowTreeClient::OnConnectionLost, weak_factory_.GetWeakPtr()));

  if (window_manager_delegate_) {
    tree_ptr_->GetWindowManagerClient(MakeRequest(
        &window_manager_internal_client_, tree_ptr_.associated_group()));
  }
}

void WindowTreeClient::OnConnectionLost() {
  delegate_->OnLostConnection(this);
}

void WindowTreeClient::OnEmbedImpl(mojom::WindowTree* window_tree,
                                       ClientSpecificId client_id,
                                       mojom::WindowDataPtr root_data,
                                       int64_t display_id,
                                       Id focused_window_id,
                                       bool drawn) {
  // WARNING: this is only called if WindowTreeClient was created as the
  // result of an embedding.
  tree_ = window_tree;
  client_id_ = client_id;

  DCHECK(roots_.empty());
  Window* root = AddWindowToClient(this, nullptr, root_data);
  WindowPrivate(root).LocalSetDisplay(display_id);
  roots_.insert(root);

  focused_window_ = GetWindowByServerId(focused_window_id);

  WindowPrivate(root).LocalSetParentDrawn(drawn);

  delegate_->OnEmbed(root);

  if (focused_window_) {
    for (auto& observer : observers_)
      observer.OnWindowTreeFocusChanged(focused_window_, nullptr);
  }
}

void WindowTreeClient::WmNewDisplayAddedImpl(const display::Display& display,
                                             mojom::WindowDataPtr root_data,
                                             bool parent_drawn) {
  DCHECK(window_manager_delegate_);

  Window* root = AddWindowToClient(this, nullptr, root_data);
  WindowPrivate(root).LocalSetDisplay(display.id());
  WindowPrivate(root).LocalSetParentDrawn(parent_drawn);
  roots_.insert(root);

  window_manager_delegate_->OnWmNewDisplay(root, display);
}

void WindowTreeClient::OnReceivedCursorLocationMemory(
    mojo::ScopedSharedBufferHandle handle) {
  cursor_location_mapping_ = handle->Map(sizeof(base::subtle::Atomic32));
  DCHECK(cursor_location_mapping_);
}

void WindowTreeClient::OnWmMoveLoopCompleted(uint32_t change_id,
                                             bool completed) {
  if (window_manager_internal_client_)
    window_manager_internal_client_->WmResponse(change_id, completed);

  if (change_id == current_wm_move_loop_change_) {
    current_wm_move_loop_change_ = 0;
    current_wm_move_loop_window_id_ = 0;
  }
}

////////////////////////////////////////////////////////////////////////////////
// WindowTreeClient, WindowTreeClient implementation:

const std::set<Window*>& WindowTreeClient::GetRoots() {
  return roots_;
}

Window* WindowTreeClient::GetFocusedWindow() {
  return focused_window_;
}

void WindowTreeClient::ClearFocus() {
  if (!focused_window_)
    return;

  SetFocus(nullptr);
}

gfx::Point WindowTreeClient::GetCursorScreenPoint() {
  // We raced initialization. Return (0, 0).
  if (!cursor_location_memory())
    return gfx::Point();

  base::subtle::Atomic32 location =
      base::subtle::NoBarrier_Load(cursor_location_memory());
  return gfx::Point(static_cast<int16_t>(location >> 16),
                    static_cast<int16_t>(location & 0xFFFF));
}

void WindowTreeClient::StartPointerWatcher(bool want_moves) {
  if (has_pointer_watcher_)
    StopPointerWatcher();
  has_pointer_watcher_ = true;
  tree_->StartPointerWatcher(want_moves);
}

void WindowTreeClient::StopPointerWatcher() {
  DCHECK(has_pointer_watcher_);
  tree_->StopPointerWatcher();
  has_pointer_watcher_ = false;
}

void WindowTreeClient::PerformDragDrop(
    Window* window,
    const std::map<std::string, std::vector<uint8_t>>& drag_data,
    int drag_operation,
    const gfx::Point& cursor_location,
    const SkBitmap& bitmap,
    const base::Callback<void(bool, uint32_t)>& callback) {
  DCHECK(!current_drag_state_);

  // TODO(erg): Pass |cursor_location| and |bitmap| in PerformDragDrop() when
  // we start showing an image representation of the drag under the cursor.

  auto unordered_drag_data = mojo::MapToUnorderedMap(drag_data);

  if (window->drop_target()) {
    // To minimize the number of round trips, copy the drag drop data to our
    // handler here, instead of forcing mus to send this same data back.
    OnDragDropStart(unordered_drag_data);
  }

  uint32_t current_drag_change = ScheduleInFlightChange(
      base::MakeUnique<InFlightDragChange>(window, ChangeType::DRAG_LOOP));
  current_drag_state_.reset(new CurrentDragState{
      current_drag_change, ui::mojom::kDropEffectNone, callback});

  tree_->PerformDragDrop(current_drag_change, window->server_id(),
                         unordered_drag_data, drag_operation);
}

void WindowTreeClient::CancelDragDrop(Window* window) {
  // Server will clean up drag and fail the in-flight change.
  tree_->CancelDragDrop(window->server_id());
}

void WindowTreeClient::PerformWindowMove(
    Window* window,
    ui::mojom::MoveLoopSource source,
    const gfx::Point& cursor_location,
    const base::Callback<void(bool)>& callback) {
  DCHECK(on_current_move_finished_.is_null());
  on_current_move_finished_ = callback;

  current_move_loop_change_ = ScheduleInFlightChange(
      base::MakeUnique<InFlightDragChange>(window, ChangeType::MOVE_LOOP));
  // Tell the window manager to take over moving us.
  tree_->PerformWindowMove(current_move_loop_change_, window->server_id(),
                           source, cursor_location);
}

void WindowTreeClient::CancelWindowMove(Window* window) {
  tree_->CancelWindowMove(window->server_id());
}

Window* WindowTreeClient::NewWindow(
    const Window::SharedProperties* properties) {
  return NewWindowImpl(NewWindowType::CHILD, properties);
}

Window* WindowTreeClient::NewTopLevelWindow(
    const Window::SharedProperties* properties) {
  Window* window = NewWindowImpl(NewWindowType::TOP_LEVEL, properties);
  // Assume newly created top level windows are drawn by default, otherwise
  // requests to focus will fail. We will get the real value in
  // OnTopLevelCreated().
  window->LocalSetParentDrawn(true);
  return window;
}

#if !defined(NDEBUG)
std::string WindowTreeClient::GetDebugWindowHierarchy() const {
  std::string result;
  for (Window* root : roots_)
    BuildDebugInfo(std::string(), root, &result);
  return result;
}

void WindowTreeClient::BuildDebugInfo(const std::string& depth,
                                      Window* window,
                                      std::string* result) const {
  std::string name = window->GetName();
  *result += base::StringPrintf(
      "%sid=%d visible=%s bounds=%d,%d %dx%d %s\n", depth.c_str(),
      window->server_id(), window->visible() ? "true" : "false",
      window->bounds().x(), window->bounds().y(), window->bounds().width(),
      window->bounds().height(), !name.empty() ? name.c_str() : "(no name)");
  for (Window* child : window->children())
    BuildDebugInfo(depth + "  ", child, result);
}
#endif  // !defined(NDEBUG)

////////////////////////////////////////////////////////////////////////////////
// WindowTreeClient, WindowTreeClient implementation:

void WindowTreeClient::AddObserver(WindowTreeClientObserver* observer) {
  observers_.AddObserver(observer);
}

void WindowTreeClient::RemoveObserver(WindowTreeClientObserver* observer) {
  observers_.RemoveObserver(observer);
}

void WindowTreeClient::SetCanAcceptDrops(Id window_id, bool can_accept_drops) {
  DCHECK(tree_);
  tree_->SetCanAcceptDrops(window_id, can_accept_drops);
}

void WindowTreeClient::SetCanAcceptEvents(Id window_id,
                                          bool can_accept_events) {
  DCHECK(tree_);
  tree_->SetCanAcceptEvents(window_id, can_accept_events);
}

void WindowTreeClient::OnEmbed(ClientSpecificId client_id,
                               mojom::WindowDataPtr root_data,
                               mojom::WindowTreePtr tree,
                               int64_t display_id,
                               Id focused_window_id,
                               bool drawn) {
  DCHECK(!tree_ptr_);
  tree_ptr_ = std::move(tree);

  is_from_embed_ = true;

  if (window_manager_delegate_) {
    tree_ptr_->GetWindowManagerClient(MakeRequest(
        &window_manager_internal_client_, tree_ptr_.associated_group()));
  }

  OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data), display_id,
              focused_window_id, drawn);
}

void WindowTreeClient::OnEmbeddedAppDisconnected(Id window_id) {
  Window* window = GetWindowByServerId(window_id);
  if (window) {
    for (auto& observer : *WindowPrivate(window).observers())
      observer.OnWindowEmbeddedAppDisconnected(window);
  }
}

void WindowTreeClient::OnUnembed(Id window_id) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  delegate_->OnUnembed(window);
  WindowPrivate(window).LocalDestroy();
}

void WindowTreeClient::OnCaptureChanged(Id new_capture_window_id,
                                        Id old_capture_window_id) {
  Window* new_capture_window = GetWindowByServerId(new_capture_window_id);
  Window* lost_capture_window = GetWindowByServerId(old_capture_window_id);
  if (!new_capture_window && !lost_capture_window)
    return;

  InFlightCaptureChange change(this, new_capture_window);
  if (ApplyServerChangeToExistingInFlightChange(change))
    return;

  LocalSetCapture(new_capture_window);
}

void WindowTreeClient::OnTopLevelCreated(uint32_t change_id,
                                             mojom::WindowDataPtr data,
                                             int64_t display_id,
                                             bool drawn) {
  // The server ack'd the top level window we created and supplied the state
  // of the window at the time the server created it. For properties we do not
  // have changes in flight for we can update them immediately. For properties
  // with changes in flight we set the revert value from the server.

  if (!in_flight_map_.count(change_id)) {
    // The window may have been destroyed locally before the server could finish
    // creating the window, and before the server received the notification that
    // the window has been destroyed.
    return;
  }
  std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
  in_flight_map_.erase(change_id);

  Window* window = change->window();
  WindowPrivate window_private(window);

  // Drawn state and display-id always come from the server (they can't be
  // modified locally).
  window_private.LocalSetParentDrawn(drawn);
  window_private.LocalSetDisplay(display_id);

  // The default visibilty is false, we only need update visibility if it
  // differs from that.
  if (data->visible) {
    InFlightVisibleChange visible_change(window, data->visible);
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(visible_change);
    if (current_change)
      current_change->SetRevertValueFrom(visible_change);
    else
      window_private.LocalSetVisible(true);
  }

  const gfx::Rect bounds(data->bounds);
  {
    InFlightBoundsChange bounds_change(window, bounds);
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(bounds_change);
    if (current_change)
      current_change->SetRevertValueFrom(bounds_change);
    else if (window->bounds() != bounds)
      window_private.LocalSetBounds(window->bounds(), bounds);
  }

  // There is currently no API to bulk set properties, so we iterate over each
  // property individually.
  Window::SharedProperties properties =
      mojo::UnorderedMapToMap(data->properties);
  for (const auto& pair : properties) {
    InFlightPropertyChange property_change(window, pair.first, pair.second);
    InFlightChange* current_change =
        GetOldestInFlightChangeMatching(property_change);
    if (current_change)
      current_change->SetRevertValueFrom(property_change);
    else
      window_private.LocalSetSharedProperty(pair.first, &(pair.second));
  }

  // Top level windows should not have a parent.
  DCHECK_EQ(0u, data->parent_id);
}

void WindowTreeClient::OnWindowBoundsChanged(Id window_id,
                                             const gfx::Rect& old_bounds,
                                             const gfx::Rect& new_bounds) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  float device_scale_factor = ScaleFactorForDisplay(window->display_id());
  gfx::Rect old_bounds_in_dip =
      gfx::ConvertRectToDIP(device_scale_factor, old_bounds);
  gfx::Rect new_bounds_in_dip =
      gfx::ConvertRectToDIP(device_scale_factor, new_bounds);

  InFlightBoundsChange new_change(window, new_bounds_in_dip);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;
  WindowPrivate(window).LocalSetBounds(old_bounds_in_dip, new_bounds_in_dip);
}

void WindowTreeClient::OnClientAreaChanged(
    uint32_t window_id,
    const gfx::Insets& new_client_area,
    const std::vector<gfx::Rect>& new_additional_client_areas) {
  Window* window = GetWindowByServerId(window_id);
  if (window) {
    float device_scale_factor = ScaleFactorForDisplay(window->display_id());
    std::vector<gfx::Rect> new_additional_client_areas_in_dip;
    for (const gfx::Rect& area : new_additional_client_areas) {
      new_additional_client_areas_in_dip.push_back(
          gfx::ConvertRectToDIP(device_scale_factor, area));
    }
    WindowPrivate(window).LocalSetClientArea(
        gfx::ConvertInsetsToDIP(device_scale_factor, new_client_area),
        new_additional_client_areas_in_dip);
  }
}

void WindowTreeClient::OnTransientWindowAdded(
    uint32_t window_id,
    uint32_t transient_window_id) {
  Window* window = GetWindowByServerId(window_id);
  Window* transient_window = GetWindowByServerId(transient_window_id);
  // window or transient_window or both may be null if a local delete occurs
  // with an in flight add from the server.
  if (window && transient_window)
    WindowPrivate(window).LocalAddTransientWindow(transient_window);
}

void WindowTreeClient::OnTransientWindowRemoved(
    uint32_t window_id,
    uint32_t transient_window_id) {
  Window* window = GetWindowByServerId(window_id);
  Window* transient_window = GetWindowByServerId(transient_window_id);
  // window or transient_window or both may be null if a local delete occurs
  // with an in flight delete from the server.
  if (window && transient_window)
    WindowPrivate(window).LocalRemoveTransientWindow(transient_window);
}

void WindowTreeClient::OnWindowHierarchyChanged(
    Id window_id,
    Id old_parent_id,
    Id new_parent_id,
    std::vector<mojom::WindowDataPtr> windows) {
  Window* initial_parent =
      windows.size() ? GetWindowByServerId(windows[0]->parent_id) : NULL;

  const bool was_window_known = GetWindowByServerId(window_id) != nullptr;

  BuildWindowTree(windows, initial_parent);

  // If the window was not known, then BuildWindowTree() will have created it
  // and parented the window.
  if (!was_window_known)
    return;

  Window* new_parent = GetWindowByServerId(new_parent_id);
  Window* old_parent = GetWindowByServerId(old_parent_id);
  Window* window = GetWindowByServerId(window_id);
  if (new_parent)
    WindowPrivate(new_parent).LocalAddChild(window);
  else
    WindowPrivate(old_parent).LocalRemoveChild(window);
}

void WindowTreeClient::OnWindowReordered(Id window_id,
                                             Id relative_window_id,
                                             mojom::OrderDirection direction) {
  Window* window = GetWindowByServerId(window_id);
  Window* relative_window = GetWindowByServerId(relative_window_id);
  if (window && relative_window)
    WindowPrivate(window).LocalReorder(relative_window, direction);
}

void WindowTreeClient::OnWindowDeleted(Id window_id) {
  Window* window = GetWindowByServerId(window_id);
  if (window)
    WindowPrivate(window).LocalDestroy();
}

Window* WindowTreeClient::GetCaptureWindow() {
  return capture_window_;
}

void WindowTreeClient::OnWindowVisibilityChanged(Id window_id,
                                                     bool visible) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightVisibleChange new_change(window, visible);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  WindowPrivate(window).LocalSetVisible(visible);
}

void WindowTreeClient::OnWindowOpacityChanged(Id window_id,
                                                  float old_opacity,
                                                  float new_opacity) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightOpacityChange new_change(window, new_opacity);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  WindowPrivate(window).LocalSetOpacity(new_opacity);
}

void WindowTreeClient::OnWindowParentDrawnStateChanged(Id window_id,
                                                           bool drawn) {
  Window* window = GetWindowByServerId(window_id);
  if (window)
    WindowPrivate(window).LocalSetParentDrawn(drawn);
}

void WindowTreeClient::OnWindowSharedPropertyChanged(
    Id window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& new_data) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightPropertyChange new_change(window, name, new_data);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  WindowPrivate(window).LocalSetSharedProperty(
      name, new_data ? &new_data.value() : nullptr);
}

void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
                                          Id window_id,
                                          std::unique_ptr<ui::Event> event,
                                          bool matches_pointer_watcher) {
  DCHECK(event);
  Window* window = GetWindowByServerId(window_id);  // May be null.

  if (matches_pointer_watcher && has_pointer_watcher_) {
    DCHECK(event->IsPointerEvent());
    delegate_->OnPointerEventObserved(*event->AsPointerEvent(), window);
  }

  if (!window || !window->input_event_handler_) {
    tree_->OnWindowInputEventAck(event_id, mojom::EventResult::UNHANDLED);
    return;
  }

  std::unique_ptr<base::Callback<void(mojom::EventResult)>> ack_callback(
      new base::Callback<void(mojom::EventResult)>(
          base::Bind(&mojom::WindowTree::OnWindowInputEventAck,
                     base::Unretained(tree_), event_id)));

  // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
  // ui::TouchEvent once we have proper support for pointer events.
  if (event->IsMousePointerEvent()) {
    if (event->type() == ui::ET_POINTER_WHEEL_CHANGED) {
      window->input_event_handler_->OnWindowInputEvent(
          window, ui::MouseWheelEvent(*event->AsPointerEvent()), &ack_callback);
    } else {
      window->input_event_handler_->OnWindowInputEvent(
          window, ui::MouseEvent(*event->AsPointerEvent()), &ack_callback);
    }
  } else if (event->IsTouchPointerEvent()) {
    window->input_event_handler_->OnWindowInputEvent(
        window, ui::TouchEvent(*event->AsPointerEvent()), &ack_callback);
  } else {
    window->input_event_handler_->OnWindowInputEvent(window, *event.get(),
                                                     &ack_callback);
  }

  // The handler did not take ownership of the callback, so we send the ack,
  // marking the event as not consumed.
  if (ack_callback)
    ack_callback->Run(mojom::EventResult::UNHANDLED);
}

void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
                                              uint32_t window_id) {
  DCHECK(event);
  DCHECK(event->IsPointerEvent());
  if (has_pointer_watcher_) {
    Window* target_window = GetWindowByServerId(window_id);
    delegate_->OnPointerEventObserved(*event->AsPointerEvent(), target_window);
  }
}

void WindowTreeClient::OnWindowFocused(Id focused_window_id) {
  Window* focused_window = GetWindowByServerId(focused_window_id);
  InFlightFocusChange new_change(this, focused_window);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  LocalSetFocus(focused_window);
}

void WindowTreeClient::OnWindowPredefinedCursorChanged(
    Id window_id,
    mojom::Cursor cursor) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;

  InFlightPredefinedCursorChange new_change(window, cursor);
  if (ApplyServerChangeToExistingInFlightChange(new_change))
    return;

  WindowPrivate(window).LocalSetPredefinedCursor(cursor);
}

void WindowTreeClient::OnWindowSurfaceChanged(
    Id window_id,
    const cc::SurfaceInfo& surface_info) {
  Window* window = GetWindowByServerId(window_id);
  if (!window)
    return;
  WindowPrivate(window).LocalSetSurfaceInfo(surface_info);
}

void WindowTreeClient::OnDragDropStart(
    const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) {
  mime_drag_data_ = mojo::UnorderedMapToMap(mime_data);
}

void WindowTreeClient::OnDragEnter(Id window_id,
                                   uint32_t key_state,
                                   const gfx::Point& position,
                                   uint32_t effect_bitmask,
                                   const OnDragEnterCallback& callback) {
  Window* window = GetWindowByServerId(window_id);
  if (!window || !window->drop_target()) {
    callback.Run(mojom::kDropEffectNone);
    return;
  }

  if (!base::ContainsKey(drag_entered_windows_, window_id)) {
    window->drop_target()->OnDragDropStart(mime_drag_data_);
    drag_entered_windows_.insert(window_id);
  }

  uint32_t ret =
      window->drop_target()->OnDragEnter(key_state, position, effect_bitmask);
  callback.Run(ret);
}

void WindowTreeClient::OnDragOver(Id window_id,
                                  uint32_t key_state,
                                  const gfx::Point& position,
                                  uint32_t effect_bitmask,
                                  const OnDragOverCallback& callback) {
  Window* window = GetWindowByServerId(window_id);
  if (!window || !window->drop_target()) {
    callback.Run(mojom::kDropEffectNone);
    return;
  }

  uint32_t ret =
      window->drop_target()->OnDragOver(key_state, position, effect_bitmask);
  callback.Run(ret);
}

void WindowTreeClient::OnDragLeave(Id window_id) {
  Window* window = GetWindowByServerId(window_id);
  if (!window || !window->drop_target())
    return;

  window->drop_target()->OnDragLeave();
}

void WindowTreeClient::OnDragDropDone() {
  for (Id id : drag_entered_windows_) {
    Window* window = GetWindowByServerId(id);
    if (!window || !window->drop_target())
      continue;
    window->drop_target()->OnDragDropDone();
  }
  drag_entered_windows_.clear();
}

void WindowTreeClient::OnCompleteDrop(Id window_id,
                                      uint32_t key_state,
                                      const gfx::Point& position,
                                      uint32_t effect_bitmask,
                                      const OnCompleteDropCallback& callback) {
  Window* window = GetWindowByServerId(window_id);
  if (!window || !window->drop_target()) {
    callback.Run(mojom::kDropEffectNone);
    return;
  }

  uint32_t ret = window->drop_target()->OnCompleteDrop(key_state, position,
                                                       effect_bitmask);
  callback.Run(ret);
}

void WindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id,
                                                  bool success,
                                                  uint32_t action_taken) {
  if (current_drag_state_ && change_id == current_drag_state_->change_id) {
    current_drag_state_->completed_action = action_taken;
    OnChangeCompleted(change_id, success);
  }
}

void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) {
  std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
  in_flight_map_.erase(change_id);
  if (!change)
    return;

  if (!success)
    change->ChangeFailed();

  InFlightChange* next_change = GetOldestInFlightChangeMatching(*change);
  if (next_change) {
    if (!success)
      next_change->SetRevertValueFrom(*change);
  } else if (!success) {
    change->Revert();
  }

  if (change_id == current_move_loop_change_) {
    current_move_loop_change_ = 0;
    on_current_move_finished_.Run(success);
    on_current_move_finished_.Reset();
  }

  if (current_drag_state_ && change_id == current_drag_state_->change_id) {
    OnDragDropDone();

    current_drag_state_->on_finished.Run(success,
                                         current_drag_state_->completed_action);
    current_drag_state_.reset();
  }
}

void WindowTreeClient::GetWindowManager(
    mojo::AssociatedInterfaceRequest<WindowManager> internal) {
  window_manager_internal_.reset(
      new mojo::AssociatedBinding<mojom::WindowManager>(this,
                                                        std::move(internal)));
}

void WindowTreeClient::RequestClose(uint32_t window_id) {
  Window* window = GetWindowByServerId(window_id);
  if (!window || !IsRoot(window))
    return;

  for (auto& observer : *WindowPrivate(window).observers())
    observer.OnRequestClose(window);
}

void WindowTreeClient::OnConnect(ClientSpecificId client_id) {
  client_id_ = client_id;
}

void WindowTreeClient::WmNewDisplayAdded(const display::Display& display,
                                         mojom::WindowDataPtr root_data,
                                         bool parent_drawn) {
  WmNewDisplayAddedImpl(display, std::move(root_data), parent_drawn);
}

void WindowTreeClient::WmDisplayRemoved(int64_t display_id) {
  DCHECK(window_manager_delegate_);

  for (Window* root : roots_) {
    if (root->display_id() == display_id) {
      window_manager_delegate_->OnWmDisplayRemoved(root);
      return;
    }
  }
}

void WindowTreeClient::WmDisplayModified(const display::Display& display) {
  DCHECK(window_manager_delegate_);
  window_manager_delegate_->OnWmDisplayModified(display);
}

void WindowTreeClient::WmSetBounds(uint32_t change_id,
                                       Id window_id,
                                       const gfx::Rect& transit_bounds) {
  Window* window = GetWindowByServerId(window_id);
  bool result = false;
  if (window) {
    DCHECK(window_manager_delegate_);
    gfx::Rect transit_bounds_in_dip = gfx::ConvertRectToDIP(
        ScaleFactorForDisplay(window->display_id()), transit_bounds);
    gfx::Rect bounds = transit_bounds_in_dip;
    result = window_manager_delegate_->OnWmSetBounds(window, &bounds);
    if (result) {
      // If the resulting bounds differ return false. Returning false ensures
      // the client applies the bounds we set below.
      result = bounds == transit_bounds_in_dip;
      window->SetBounds(bounds);
    }
  }
  if (window_manager_internal_client_)
    window_manager_internal_client_->WmResponse(change_id, result);
}

void WindowTreeClient::WmSetProperty(
    uint32_t change_id,
    Id window_id,
    const std::string& name,
    const base::Optional<std::vector<uint8_t>>& transit_data) {
  Window* window = GetWindowByServerId(window_id);
  bool result = false;
  if (window) {
    DCHECK(window_manager_delegate_);
    std::unique_ptr<std::vector<uint8_t>> data;
    if (transit_data.has_value())
      data.reset(new std::vector<uint8_t>(transit_data.value()));

    result = window_manager_delegate_->OnWmSetProperty(window, name, &data);
    if (result) {
      // If the resulting bounds differ return false. Returning false ensures
      // the client applies the bounds we set below.
      window->SetSharedPropertyInternal(name, data.get());
    }
  }
  if (window_manager_internal_client_)
    window_manager_internal_client_->WmResponse(change_id, result);
}

void WindowTreeClient::WmCreateTopLevelWindow(
    uint32_t change_id,
    ClientSpecificId requesting_client_id,
    const std::unordered_map<std::string, std::vector<uint8_t>>&
        transport_properties) {
  std::map<std::string, std::vector<uint8_t>> properties =
      mojo::UnorderedMapToMap(transport_properties);
  Window* window =
      window_manager_delegate_->OnWmCreateTopLevelWindow(&properties);
  embedded_windows_[requesting_client_id].insert(window);
  if (window_manager_internal_client_) {
    window_manager_internal_client_->OnWmCreatedTopLevelWindow(
        change_id, server_id(window));
  }
}

void WindowTreeClient::WmClientJankinessChanged(ClientSpecificId client_id,
                                                bool janky) {
  if (window_manager_delegate_) {
    auto it = embedded_windows_.find(client_id);
    CHECK(it != embedded_windows_.end());
    window_manager_delegate_->OnWmClientJankinessChanged(
        embedded_windows_[client_id], janky);
  }
}

void WindowTreeClient::WmPerformMoveLoop(uint32_t change_id,
                                         Id window_id,
                                         mojom::MoveLoopSource source,
                                         const gfx::Point& cursor_location) {
  if (!window_manager_delegate_ || current_wm_move_loop_change_ != 0) {
    OnWmMoveLoopCompleted(change_id, false);
    return;
  }

  current_wm_move_loop_change_ = change_id;
  current_wm_move_loop_window_id_ = window_id;
  Window* window = GetWindowByServerId(window_id);
  if (window) {
    window_manager_delegate_->OnWmPerformMoveLoop(
        window, source, cursor_location,
        base::Bind(&WindowTreeClient::OnWmMoveLoopCompleted,
                   weak_factory_.GetWeakPtr(), change_id));
  } else {
    OnWmMoveLoopCompleted(change_id, false);
  }
}

void WindowTreeClient::WmCancelMoveLoop(uint32_t change_id) {
  if (!window_manager_delegate_ || change_id != current_wm_move_loop_change_)
    return;

  Window* window = GetWindowByServerId(current_wm_move_loop_window_id_);
  if (window)
    window_manager_delegate_->OnWmCancelMoveLoop(window);
}

void WindowTreeClient::WmDeactivateWindow(uint32_t window_id) {}

void WindowTreeClient::OnAccelerator(uint32_t ack_id,
                                     uint32_t accelerator_id,
                                     std::unique_ptr<ui::Event> event) {
  DCHECK(event);
  const mojom::EventResult result =
      window_manager_delegate_->OnAccelerator(accelerator_id, *event.get());
  if (ack_id && window_manager_internal_client_)
    window_manager_internal_client_->OnAcceleratorAck(ack_id, result);
}

void WindowTreeClient::SetFrameDecorationValues(
    mojom::FrameDecorationValuesPtr values) {
  if (window_manager_internal_client_) {
    window_manager_internal_client_->WmSetFrameDecorationValues(
        std::move(values));
  }
}

void WindowTreeClient::SetNonClientCursor(Window* window,
                                          ui::mojom::Cursor cursor_id) {
  window_manager_internal_client_->WmSetNonClientCursor(server_id(window),
                                                        cursor_id);
}

void WindowTreeClient::AddAccelerators(
    std::vector<mojom::AcceleratorPtr> accelerators,
    const base::Callback<void(bool)>& callback) {
  if (window_manager_internal_client_) {
    window_manager_internal_client_->AddAccelerators(std::move(accelerators),
                                                     callback);
  }
}

void WindowTreeClient::RemoveAccelerator(uint32_t id) {
  if (window_manager_internal_client_) {
    window_manager_internal_client_->RemoveAccelerator(id);
  }
}

void WindowTreeClient::AddActivationParent(Window* window) {
  if (window_manager_internal_client_)
    window_manager_internal_client_->AddActivationParent(server_id(window));
}

void WindowTreeClient::RemoveActivationParent(Window* window) {
  if (window_manager_internal_client_)
    window_manager_internal_client_->RemoveActivationParent(server_id(window));
}

void WindowTreeClient::ActivateNextWindow() {
  if (window_manager_internal_client_)
    window_manager_internal_client_->ActivateNextWindow();
}

void WindowTreeClient::SetUnderlaySurfaceOffsetAndExtendedHitArea(
    Window* window,
    const gfx::Vector2d& offset,
    const gfx::Insets& hit_area) {
  if (window_manager_internal_client_) {
    // TODO(riajiang): Figure out if |offset| needs to be converted.
    // (http://crbugs.com/646932)
    window_manager_internal_client_->SetUnderlaySurfaceOffsetAndExtendedHitArea(
        server_id(window), offset.x(), offset.y(),
        gfx::ConvertInsetsToDIP(ScaleFactorForDisplay(window->display_id()),
                                hit_area));
  }
}

}  // namespace ui
