// Copyright 2015 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 "ash/window_manager.h"

#include <stdint.h>

#include <limits>
#include <memory>
#include <utility>

#include "ash/accelerators/accelerator_handler.h"
#include "ash/accelerators/accelerator_ids.h"
#include "ash/drag_drop/drag_image_view.h"
#include "ash/event_matcher_util.h"
#include "ash/public/cpp/config.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/window_pin_type.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/public/cpp/window_state_type.h"
#include "ash/public/interfaces/window_actions.mojom.h"
#include "ash/public/interfaces/window_pin_type.mojom.h"
#include "ash/public/interfaces/window_properties.mojom.h"
#include "ash/public/interfaces/window_state_type.mojom.h"
#include "ash/root_window_controller.h"
#include "ash/root_window_settings.h"
#include "ash/session/session_controller.h"
#include "ash/shell.h"
#include "ash/shell_delegate_mus.h"
#include "ash/shell_init_params.h"
#include "ash/shell_port_mash.h"
#include "ash/shell_port_mus.h"
#include "ash/wayland/wayland_server_controller.h"
#include "ash/wm/ash_focus_rules.h"
#include "ash/wm/move_event_handler.h"
#include "ash/wm/non_client_frame_controller.h"
#include "ash/wm/property_util.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/top_level_window_factory.h"
#include "ash/wm/window_properties.h"
#include "ash/wm/window_state.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/common/accelerator_util.h"
#include "services/ui/common/types.h"
#include "services/ui/public/cpp/input_devices/input_device_client.h"
#include "services/ui/public/cpp/property_type_converters.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/capture_synchronizer.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/window.h"
#include "ui/base/class_property.h"
#include "ui/base/hit_test.h"
#include "ui/display/display_observer.h"
#include "ui/events/mojo/event.mojom.h"
#include "ui/views/mus/pointer_watcher_event_router.h"
#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_animations.h"
#include "ui/wm/core/wm_state.h"
#include "ui/wm/public/activation_client.h"

namespace ash {

struct WindowManager::DragState {
  // An image representation of the contents of the current drag and drop
  // clipboard.
  std::unique_ptr<ash::DragImageView> view;

  // The cursor offset of the dragged item.
  gfx::Vector2d image_offset;
};

// TODO: need to register OSExchangeDataProviderMus. http://crbug.com/665077.
WindowManager::WindowManager(service_manager::Connector* connector,
                             Config config,
                             bool show_primary_host_on_connect)
    : connector_(connector),
      config_(config),
      show_primary_host_on_connect_(show_primary_host_on_connect),
      wm_state_(std::make_unique<::wm::WMState>()),
      property_converter_(std::make_unique<aura::PropertyConverter>()) {
  property_converter_->RegisterPrimitiveProperty(
      kCanConsumeSystemKeysKey, ash::mojom::kCanConsumeSystemKeys_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());
  property_converter_->RegisterPrimitiveProperty(
      aura::client::kDrawAttentionKey,
      ui::mojom::WindowManager::kDrawAttention_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());
  property_converter_->RegisterPrimitiveProperty(
      kPanelAttachedKey, ui::mojom::WindowManager::kPanelAttached_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());
  property_converter_->RegisterPrimitiveProperty(
      kRenderTitleAreaProperty,
      ui::mojom::WindowManager::kRenderParentTitleArea_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());
  property_converter_->RegisterPrimitiveProperty(
      kShelfItemTypeKey, ui::mojom::WindowManager::kShelfItemType_Property,
      base::Bind(&IsValidShelfItemType));
  property_converter_->RegisterPrimitiveProperty(
      ::wm::kShadowElevationKey,
      ui::mojom::WindowManager::kShadowElevation_Property,
      base::Bind(&::wm::IsValidShadowElevation));
  property_converter_->RegisterPrimitiveProperty(
      kWindowStateTypeKey, mojom::kWindowStateType_Property,
      base::Bind(&ash::IsValidWindowStateType));
  property_converter_->RegisterPrimitiveProperty(
      kWindowPinTypeKey, ash::mojom::kWindowPinType_Property,
      base::Bind(&ash::IsValidWindowPinType));
  property_converter_->RegisterPrimitiveProperty(
      kWindowPositionManagedTypeKey,
      ash::mojom::kWindowPositionManaged_Property,
      aura::PropertyConverter::CreateAcceptAnyValueCallback());
  property_converter_->RegisterStringProperty(
      kShelfIDKey, ui::mojom::WindowManager::kShelfID_Property);
}

WindowManager::~WindowManager() {
  Shutdown();
  ash::Shell::set_window_tree_client(nullptr);
  ash::Shell::set_window_manager_client(nullptr);
}

void WindowManager::Init(
    std::unique_ptr<aura::WindowTreeClient> window_tree_client,
    std::unique_ptr<ShellDelegate> shell_delegate) {
  // Only create InputDeviceClient in MASH mode. For MUS mode WindowManager is
  // created by chrome, which creates InputDeviceClient.
  if (config_ == Config::MASH) {
    input_device_client_ = std::make_unique<ui::InputDeviceClient>();

    // |connector_| can be nullptr in tests.
    if (connector_) {
      ui::mojom::InputDeviceServerPtr server;
      connector_->BindInterface(ui::mojom::kServiceName, &server);
      input_device_client_->Connect(std::move(server));
    }
  } else {
    // In Config::MUS ash handles all drag and drop.
    window_tree_client->DisableDragDropClient();
  }

  DCHECK(window_manager_client_);
  DCHECK(!window_tree_client_);
  window_tree_client_ = std::move(window_tree_client);

  DCHECK_EQ(nullptr, ash::Shell::window_tree_client());
  ash::Shell::set_window_tree_client(window_tree_client_.get());

  // TODO(jamescook): Maybe not needed in Config::MUS?
  pointer_watcher_event_router_ =
      std::make_unique<views::PointerWatcherEventRouter>(
          window_tree_client_.get());

  // Notify PointerWatcherEventRouter and CaptureSynchronizer that the capture
  // client has been set.
  aura::client::CaptureClient* capture_client = wm_state_->capture_controller();
  pointer_watcher_event_router_->AttachToCaptureClient(capture_client);
  window_tree_client_->capture_synchronizer()->AttachToCaptureClient(
      capture_client);

  if (shell_delegate)
    shell_delegate_ = std::move(shell_delegate);

  InitCursorOnKeyList();
}

void WindowManager::SetLostConnectionCallback(base::OnceClosure closure) {
  lost_connection_callback_ = std::move(closure);
}

bool WindowManager::WaitForInitialDisplays() {
  return window_manager_client_->WaitForInitialDisplays();
}

bool WindowManager::GetNextAcceleratorNamespaceId(uint16_t* id) {
  if (accelerator_handlers_.size() == std::numeric_limits<uint16_t>::max())
    return false;
  while (accelerator_handlers_.count(next_accelerator_namespace_id_) > 0)
    ++next_accelerator_namespace_id_;
  *id = next_accelerator_namespace_id_;
  ++next_accelerator_namespace_id_;
  return true;
}

void WindowManager::AddAcceleratorHandler(uint16_t id_namespace,
                                          AcceleratorHandler* handler) {
  DCHECK_EQ(0u, accelerator_handlers_.count(id_namespace));
  accelerator_handlers_[id_namespace] = handler;
}

void WindowManager::RemoveAcceleratorHandler(uint16_t id_namespace) {
  accelerator_handlers_.erase(id_namespace);
}

display::mojom::DisplayController* WindowManager::GetDisplayController() {
  return display_controller_ ? display_controller_.get() : nullptr;
}

void WindowManager::CreateShell() {
  DCHECK(!created_shell_);
  created_shell_ = true;
  ShellInitParams init_params;
  // Shell::CreateInstance() takes ownership of ShellDelegate.
  init_params.delegate = shell_delegate_ ? shell_delegate_.release()
                                         : new ShellDelegateMus(connector_);
  if (config_ == Config::MUS) {
    init_params.shell_port = new ShellPortMus(this);
  } else {
    init_params.shell_port =
        new ShellPortMash(this, pointer_watcher_event_router_.get());
  }
  Shell::CreateInstance(init_params);
}

void WindowManager::InitCursorOnKeyList() {
  DCHECK(window_manager_client_);
  if (config_ == Config::MASH) {
    // In Mash, we build a list of keys and send them to the window
    // server. This controls which keys *don't* hide the cursors.

    // TODO(erg): This needs to also check the case of the accessibility
    // keyboard being shown, since clicking a key on the keyboard shouldn't
    // hide the cursor.
    std::vector<ui::mojom::EventMatcherPtr> cursor_key_list;
    cursor_key_list.push_back(BuildKeyReleaseMatcher());
    cursor_key_list.push_back(BuildAltMatcher());
    cursor_key_list.push_back(BuildControlMatcher());

    BuildKeyMatcherRange(ui::mojom::KeyboardCode::F1,
                         ui::mojom::KeyboardCode::F24, &cursor_key_list);
    BuildKeyMatcherRange(ui::mojom::KeyboardCode::BROWSER_BACK,
                         ui::mojom::KeyboardCode::MEDIA_LAUNCH_APP2,
                         &cursor_key_list);
    BuildKeyMatcherList(
        {ui::mojom::KeyboardCode::SHIFT, ui::mojom::KeyboardCode::CONTROL,
         ui::mojom::KeyboardCode::MENU,
         ui::mojom::KeyboardCode::LWIN,  // Search key == VKEY_LWIN.
         ui::mojom::KeyboardCode::WLAN, ui::mojom::KeyboardCode::POWER,
         ui::mojom::KeyboardCode::BRIGHTNESS_DOWN,
         ui::mojom::KeyboardCode::BRIGHTNESS_UP,
         ui::mojom::KeyboardCode::KBD_BRIGHTNESS_DOWN,
         ui::mojom::KeyboardCode::KBD_BRIGHTNESS_UP},
        &cursor_key_list);

    window_manager_client_->SetKeyEventsThatDontHideCursor(
        std::move(cursor_key_list));
  }
}

void WindowManager::InstallFrameDecorationValues() {
  ui::mojom::FrameDecorationValuesPtr frame_decoration_values =
      ui::mojom::FrameDecorationValues::New();
  const gfx::Insets client_area_insets =
      NonClientFrameController::GetPreferredClientAreaInsets();
  frame_decoration_values->normal_client_area_insets = client_area_insets;
  frame_decoration_values->maximized_client_area_insets = client_area_insets;
  frame_decoration_values->max_title_bar_button_width =
      NonClientFrameController::GetMaxTitleBarButtonWidth();
  window_manager_client_->SetFrameDecorationValues(
      std::move(frame_decoration_values));
}

void WindowManager::Shutdown() {
  if (!window_tree_client_)
    return;

  aura::client::CaptureClient* capture_client = wm_state_->capture_controller();
  pointer_watcher_event_router_->DetachFromCaptureClient(capture_client);
  window_tree_client_->capture_synchronizer()->DetachFromCaptureClient(
      capture_client);

  Shell::DeleteInstance();

  pointer_watcher_event_router_.reset();

  window_tree_client_.reset();
  window_manager_client_ = nullptr;
}

void WindowManager::OnEmbed(
    std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
  // WindowManager should never see this, instead OnWmNewDisplay() is called.
  NOTREACHED();
}

void WindowManager::OnEmbedRootDestroyed(
    aura::WindowTreeHostMus* window_tree_host) {
  // WindowManager should never see this.
  NOTREACHED();
}

void WindowManager::OnLostConnection(aura::WindowTreeClient* client) {
  DCHECK_EQ(client, window_tree_client_.get());
  if (!lost_connection_callback_.is_null()) {
    base::ResetAndReturn(&lost_connection_callback_).Run();
    return;
  }
  Shutdown();
  // TODO(sky): this case should trigger shutting down WindowManagerService too.
}

void WindowManager::OnPointerEventObserved(const ui::PointerEvent& event,
                                           aura::Window* target) {
  pointer_watcher_event_router_->OnPointerEventObserved(event, target);
}

aura::PropertyConverter* WindowManager::GetPropertyConverter() {
  return property_converter_.get();
}

void WindowManager::SetWindowManagerClient(aura::WindowManagerClient* client) {
  window_manager_client_ = client;
  ash::Shell::set_window_manager_client(client);
}

void WindowManager::OnWmConnected() {
  // InstallFrameDecorationValues() must be called before the shell is created,
  // otherwise Mus attempts to notify clients with no frame decorations, which
  // triggers validation errors.
  InstallFrameDecorationValues();
  CreateShell();
  if (show_primary_host_on_connect_)
    Shell::GetPrimaryRootWindow()->GetHost()->Show();

  // We only create controller in the ash process for mash.
  if (Shell::GetAshConfig() == Config::MASH)
    wayland_server_controller_ = WaylandServerController::CreateIfNecessary();
}

void WindowManager::OnWmAcceleratedWidgetAvailableForDisplay(
    int64_t display_id,
    gfx::AcceleratedWidget widget) {
  auto* window = Shell::GetRootWindowForDisplayId(display_id);
  if (window) {
    auto* host = static_cast<aura::WindowTreeHostMus*>(window->GetHost());
    host->OverrideAcceleratedWidget(widget);
  }
}

void WindowManager::OnWmSetBounds(aura::Window* window,
                                  const gfx::Rect& bounds) {
  // TODO(sky): this indirectly sets bounds, which is against what
  // OnWmSetBounds() recommends doing. Remove that restriction, or fix this.
  window->SetBounds(bounds);
}

bool WindowManager::OnWmSetProperty(
    aura::Window* window,
    const std::string& name,
    std::unique_ptr<std::vector<uint8_t>>* new_data) {
  if (property_converter_->IsTransportNameRegistered(name))
    return true;
  DVLOG(1) << "unknown property changed, ignoring " << name;
  return false;
}

void WindowManager::OnWmSetModalType(aura::Window* window, ui::ModalType type) {
  ui::ModalType old_type = window->GetProperty(aura::client::kModalKey);
  if (type == old_type)
    return;

  window->SetProperty(aura::client::kModalKey, type);
  // Assume the client has positioned the window in the right container and
  // don't attempt to change the parent. This is currently true for Chrome
  // code, but likely there should be checks. Adding checks is complicated by
  // the fact that assumptions in GetSystemModalContainer() are not always
  // valid for Chrome code. In particular Chrome code may create system modal
  // dialogs without a transient parent that Chrome wants shown on the lock
  // screen.
}

void WindowManager::OnWmSetCanFocus(aura::Window* window, bool can_focus) {
  NonClientFrameController* non_client_frame_controller =
      NonClientFrameController::Get(window);
  if (non_client_frame_controller)
    non_client_frame_controller->set_can_activate(can_focus);
}

aura::Window* WindowManager::OnWmCreateTopLevelWindow(
    ui::mojom::WindowType window_type,
    std::map<std::string, std::vector<uint8_t>>* properties) {
  if (window_type == ui::mojom::WindowType::UNKNOWN) {
    LOG(WARNING) << "Request to create top level of unknown type, failing";
    return nullptr;
  }

  return CreateAndParentTopLevelWindow(this, window_type, properties);
}

void WindowManager::OnWmClientJankinessChanged(
    const std::set<aura::Window*>& client_windows,
    bool janky) {
  for (auto* window : client_windows)
    window->SetProperty(kWindowIsJanky, janky);
}

void WindowManager::OnWmBuildDragImage(const gfx::Point& screen_location,
                                       const SkBitmap& drag_image,
                                       const gfx::Vector2d& drag_image_offset,
                                       ui::mojom::PointerKind source) {
  if (drag_image.isNull())
    return;

  // TODO(erg): Get the right display for this drag image. Right now, none of
  // the drag drop code is multidisplay aware.
  aura::Window* root_window = Shell::GetPrimaryRootWindow();

  // TODO(erg): SkBitmap is the wrong data type for the drag image; we should
  // be passing ImageSkias once http://crbug.com/655874 is implemented.

  ui::DragDropTypes::DragEventSource ui_source =
      source == ui::mojom::PointerKind::MOUSE
          ? ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
          : ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
  std::unique_ptr<DragImageView> drag_view =
      std::make_unique<DragImageView>(root_window, ui_source);
  drag_view->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(drag_image));
  gfx::Size size = drag_view->GetPreferredSize();
  gfx::Rect drag_image_bounds(screen_location - drag_image_offset, size);
  drag_view->SetBoundsInScreen(drag_image_bounds);
  drag_view->SetWidgetVisible(true);

  drag_state_ = std::make_unique<DragState>();
  drag_state_->view = std::move(drag_view);
  drag_state_->image_offset = drag_image_offset;
}

void WindowManager::OnWmMoveDragImage(const gfx::Point& screen_location) {
  if (drag_state_) {
    drag_state_->view->SetScreenPosition(screen_location -
                                         drag_state_->image_offset);
  }
}

void WindowManager::OnWmDestroyDragImage() {
  drag_state_.reset();
}

void WindowManager::OnWmWillCreateDisplay(const display::Display& display) {
  // Ash connects such that |automatically_create_display_roots| is false, which
  // means this should never be hit.
  NOTREACHED();
}

void WindowManager::OnWmNewDisplay(
    std::unique_ptr<aura::WindowTreeHostMus> window_tree_host,
    const display::Display& display) {
  // Ash connects such that |automatically_create_display_roots| is false, which
  // means this should never be hit.
  NOTREACHED();
}

void WindowManager::OnWmDisplayRemoved(
    aura::WindowTreeHostMus* window_tree_host) {
  // Ash connects such that |automatically_create_display_roots| is false, which
  // means this should never be hit.
  NOTREACHED();
}

void WindowManager::OnWmDisplayModified(const display::Display& display) {
  // TODO(sky): this shouldn't be called as we're passing false for
  // |automatically_create_display_roots|, but it currently is. Update mus.
}

void WindowManager::OnWmPerformMoveLoop(
    aura::Window* window,
    ui::mojom::MoveLoopSource source,
    const gfx::Point& cursor_location,
    const base::Callback<void(bool)>& on_done) {
  MoveEventHandler* handler = MoveEventHandler::GetForWindow(window);
  if (!handler) {
    on_done.Run(false);
    return;
  }

  DCHECK(!handler->IsDragInProgress());
  ::wm::WindowMoveSource aura_source =
      source == ui::mojom::MoveLoopSource::MOUSE
          ? ::wm::WINDOW_MOVE_SOURCE_MOUSE
          : ::wm::WINDOW_MOVE_SOURCE_TOUCH;
  handler->AttemptToStartDrag(cursor_location, HTCAPTION, aura_source, on_done);
}

void WindowManager::OnWmCancelMoveLoop(aura::Window* window) {
  MoveEventHandler* handler = MoveEventHandler::GetForWindow(window);
  if (handler)
    handler->RevertDrag();
}

ui::mojom::EventResult WindowManager::OnAccelerator(
    uint32_t id,
    const ui::Event& event,
    std::unordered_map<std::string, std::vector<uint8_t>>* properties) {
  auto iter = accelerator_handlers_.find(GetAcceleratorNamespaceId(id));
  if (iter == accelerator_handlers_.end())
    return ui::mojom::EventResult::HANDLED;

  return iter->second->OnAccelerator(id, event, properties);
}

void WindowManager::OnCursorTouchVisibleChanged(bool enabled) {
  // Not applicable to Config::MUS.
  if (config_ == Config::MASH)
    ShellPortMash::Get()->OnCursorTouchVisibleChanged(enabled);
}

void WindowManager::OnWmSetClientArea(
    aura::Window* window,
    const gfx::Insets& insets,
    const std::vector<gfx::Rect>& additional_client_areas) {
  NonClientFrameController* non_client_frame_controller =
      NonClientFrameController::Get(window);
  if (!non_client_frame_controller)
    return;
  non_client_frame_controller->SetClientArea(insets, additional_client_areas);
}

bool WindowManager::IsWindowActive(aura::Window* window) {
  return Shell::Get()->activation_client()->GetActiveWindow() == window;
}

void WindowManager::OnWmDeactivateWindow(aura::Window* window) {
  Shell::Get()->activation_client()->DeactivateWindow(window);
}

void WindowManager::OnWmPerformAction(aura::Window* window,
                                      const std::string& action) {
  if (action == mojom::kAddWindowToTabletMode)
    ash::Shell::Get()->tablet_mode_controller()->AddWindow(window);
}

void WindowManager::OnEventBlockedByModalWindow(aura::Window* window) {
  AnimateWindow(window, ::wm::WINDOW_ANIMATION_TYPE_BOUNCE);
}

}  // namespace ash
