// Copyright 2018 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 "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"

#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/base/hit_test.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/window/native_frame_view.h"
#include "ui/wm/core/window_util.h"

#if defined(OS_LINUX)
#include "ui/views/widget/desktop_aura/window_event_filter.h"
#endif

namespace views {

namespace {

ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
    const Widget::InitParams& params) {
  ui::PlatformWindowInitProperties properties;

  switch (params.type) {
    case Widget::InitParams::TYPE_WINDOW:
      properties.type = ui::PlatformWindowType::kWindow;
      break;

    case Widget::InitParams::TYPE_MENU:
      properties.type = ui::PlatformWindowType::kMenu;
      break;

    case Widget::InitParams::TYPE_TOOLTIP:
      properties.type = ui::PlatformWindowType::kTooltip;
      break;

    default:
      properties.type = ui::PlatformWindowType::kPopup;
      break;
  }

  properties.bounds = params.bounds;

  if (params.parent && params.parent->GetHost())
    properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();

  return properties;
}

}  // namespace
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostPlatform:

DesktopWindowTreeHostPlatform::DesktopWindowTreeHostPlatform(
    internal::NativeWidgetDelegate* native_widget_delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura)
    : native_widget_delegate_(native_widget_delegate),
      desktop_native_widget_aura_(desktop_native_widget_aura) {}

DesktopWindowTreeHostPlatform::~DesktopWindowTreeHostPlatform() {
  DCHECK(got_on_closed_);
  desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
  DestroyDispatcher();
}

void DesktopWindowTreeHostPlatform::SetBoundsInDIP(
    const gfx::Rect& bounds_in_dip) {
  DCHECK_NE(0, device_scale_factor());
  SetBoundsInPixels(
      gfx::ConvertRectToPixel(device_scale_factor(), bounds_in_dip),
      viz::LocalSurfaceId(), base::TimeTicks());
}

void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
  ui::PlatformWindowInitProperties properties =
      ConvertWidgetInitParamsToInitProperties(params);

  CreateAndSetPlatformWindow(std::move(properties));
  CreateCompositor(viz::FrameSinkId(), params.force_software_compositing);
  aura::WindowTreeHost::OnAcceleratedWidgetAvailable();
  InitHost();
  if (!params.bounds.IsEmpty())
    SetBoundsInDIP(params.bounds);
  window()->Show();
}

void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(
    const Widget::InitParams& params) {
  native_widget_delegate_->OnNativeWidgetCreated(true);

#if defined(OS_LINUX)
  // Setup a non_client_window_event_filter, which handles resize/move, double
  // click and other events.
  DCHECK(!non_client_window_event_filter_);
  std::unique_ptr<WindowEventFilter> window_event_filter =
      std::make_unique<WindowEventFilter>(this);
  auto* wm_move_resize_handler = GetWmMoveResizeHandler(*platform_window());
  if (wm_move_resize_handler)
    window_event_filter->SetWmMoveResizeHandler(
        GetWmMoveResizeHandler(*(platform_window())));

  non_client_window_event_filter_ = std::move(window_event_filter);
  window()->AddPreTargetHandler(non_client_window_event_filter_.get());
#endif
}

void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {}

void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {}

std::unique_ptr<corewm::Tooltip>
DesktopWindowTreeHostPlatform::CreateTooltip() {
  return std::make_unique<corewm::TooltipAura>();
}

std::unique_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostPlatform::CreateDragDropClient(
    DesktopNativeCursorManager* cursor_manager) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return nullptr;
}

void DesktopWindowTreeHostPlatform::Close() {
  if (waiting_for_close_now_)
    return;

  desktop_native_widget_aura_->content_window()->Hide();

  // Hide while waiting for the close.
  // Please note that it's better to call WindowTreeHost::Hide, which also calls
  // PlatformWindow::Hide and Compositor::SetVisible(false).
  Hide();

  waiting_for_close_now_ = true;
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&DesktopWindowTreeHostPlatform::CloseNow,
                                weak_factory_.GetWeakPtr()));
}

void DesktopWindowTreeHostPlatform::CloseNow() {
  auto weak_ref = weak_factory_.GetWeakPtr();
  // Deleting the PlatformWindow may not result in OnClosed() being called, if
  // not behave as though it was.
  SetPlatformWindow(nullptr);
  if (!weak_ref || got_on_closed_)
    return;

  RemoveNonClientEventFilter();

  native_widget_delegate_->OnNativeWidgetDestroying();

  got_on_closed_ = true;
  desktop_native_widget_aura_->OnHostClosed();
}

aura::WindowTreeHost* DesktopWindowTreeHostPlatform::AsWindowTreeHost() {
  return this;
}

void DesktopWindowTreeHostPlatform::Show(ui::WindowShowState show_state,
                                         const gfx::Rect& restore_bounds) {
  if (show_state == ui::SHOW_STATE_MAXIMIZED && !restore_bounds.IsEmpty())
    platform_window()->SetRestoredBoundsInPixels(ToPixelRect(restore_bounds));

  if (compositor()) {
    platform_window()->Show();
    compositor()->SetVisible(true);
  }

  switch (show_state) {
    case ui::SHOW_STATE_MAXIMIZED:
      platform_window()->Maximize();
      break;
    case ui::SHOW_STATE_MINIMIZED:
      platform_window()->Minimize();
      break;
    case ui::SHOW_STATE_FULLSCREEN:
      // TODO(sky): this isn't necessarily the same as explicitly setting
      // fullscreen.
      platform_window()->ToggleFullscreen();
      break;
    default:
      break;
  }

  if (native_widget_delegate_->CanActivate()) {
    if (show_state != ui::SHOW_STATE_INACTIVE)
      Activate();

    // SetInitialFocus() should be always be called, even for
    // SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
    // do the right thing.
    // Activate() might fail if the window is non-activatable. In this case, we
    // should pass SHOW_STATE_INACTIVE to SetInitialFocus() to stop the initial
    // focused view from getting focused. See https://crbug.com/515594 for
    // example.
    native_widget_delegate_->SetInitialFocus(
        IsActive() ? show_state : ui::SHOW_STATE_INACTIVE);
  }

  desktop_native_widget_aura_->content_window()->Show();
}

bool DesktopWindowTreeHostPlatform::IsVisible() const {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return true;
}

void DesktopWindowTreeHostPlatform::SetSize(const gfx::Size& size) {
  gfx::Rect screen_bounds =
      gfx::ConvertRectToDIP(device_scale_factor(), GetBoundsInPixels());
  screen_bounds.set_size(size);
  SetBoundsInDIP(screen_bounds);
}

void DesktopWindowTreeHostPlatform::StackAbove(aura::Window* window) {
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::StackAtTop() {
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::CenterWindow(const gfx::Size& size) {
  gfx::Rect bounds_to_center_in = GetWorkAreaBoundsInScreen();

  // If there is a transient parent and it fits |size|, then center over it.
  aura::Window* content_window = desktop_native_widget_aura_->content_window();
  if (wm::GetTransientParent(content_window)) {
    gfx::Rect transient_parent_bounds =
        wm::GetTransientParent(content_window)->GetBoundsInScreen();
    if (transient_parent_bounds.height() >= size.height() &&
        transient_parent_bounds.width() >= size.width()) {
      bounds_to_center_in = transient_parent_bounds;
    }
  }

  gfx::Rect resulting_bounds(bounds_to_center_in);
  resulting_bounds.ClampToCenteredSize(size);
  SetBoundsInDIP(resulting_bounds);
}

void DesktopWindowTreeHostPlatform::GetWindowPlacement(
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  NOTIMPLEMENTED_LOG_ONCE();
  *bounds = gfx::Rect(0, 0, 640, 840);
  *show_state = ui::SHOW_STATE_NORMAL;
}

gfx::Rect DesktopWindowTreeHostPlatform::GetWindowBoundsInScreen() const {
  gfx::Rect bounds =
      gfx::ConvertRectToDIP(device_scale_factor(), GetBoundsInPixels());
  bounds += display::Screen::GetScreen()
                ->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
                .bounds()
                .OffsetFromOrigin();
  return bounds;
}

gfx::Rect DesktopWindowTreeHostPlatform::GetClientAreaBoundsInScreen() const {
  // View-to-screen coordinate system transformations depend on this returning
  // the full window bounds, for example View::ConvertPointToScreen().
  return GetWindowBoundsInScreen();
}

gfx::Rect DesktopWindowTreeHostPlatform::GetRestoredBounds() const {
  gfx::Rect restored_bounds = platform_window()->GetRestoredBoundsInPixels();
  // When window is resized, |restored bounds| is not set and empty.
  // If |restored bounds| is empty, it returns the current window size.
  gfx::Rect bounds =
      !restored_bounds.IsEmpty() ? restored_bounds : GetBoundsInPixels();
  return ToDIPRect(bounds);
}

std::string DesktopWindowTreeHostPlatform::GetWorkspace() const {
  return std::string();
}

gfx::Rect DesktopWindowTreeHostPlatform::GetWorkAreaBoundsInScreen() const {
  // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
  return display::Screen::GetScreen()
      ->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
      .work_area();
}

void DesktopWindowTreeHostPlatform::SetShape(
    std::unique_ptr<Widget::ShapeRects> native_shape) {
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::Activate() {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::Deactivate() {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

bool DesktopWindowTreeHostPlatform::IsActive() const {
  return is_active_;
}

void DesktopWindowTreeHostPlatform::Maximize() {
  platform_window()->Maximize();
}

void DesktopWindowTreeHostPlatform::Minimize() {
  platform_window()->Minimize();
}

void DesktopWindowTreeHostPlatform::Restore() {
  platform_window()->Restore();
}

bool DesktopWindowTreeHostPlatform::IsMaximized() const {
  return platform_window()->GetPlatformWindowState() ==
         ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MAXIMIZED;
}

bool DesktopWindowTreeHostPlatform::IsMinimized() const {
  return platform_window()->GetPlatformWindowState() ==
         ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
}

bool DesktopWindowTreeHostPlatform::HasCapture() const {
  return platform_window()->HasCapture();
}

void DesktopWindowTreeHostPlatform::SetAlwaysOnTop(bool always_on_top) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

bool DesktopWindowTreeHostPlatform::IsAlwaysOnTop() const {
  // TODO: needs PlatformWindow support.
  return false;
}

void DesktopWindowTreeHostPlatform::SetVisibleOnAllWorkspaces(
    bool always_visible) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

bool DesktopWindowTreeHostPlatform::IsVisibleOnAllWorkspaces() const {
  // TODO: needs PlatformWindow support.
  return false;
}

bool DesktopWindowTreeHostPlatform::SetWindowTitle(
    const base::string16& title) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return false;
}

void DesktopWindowTreeHostPlatform::ClearNativeFocus() {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

Widget::MoveLoopResult DesktopWindowTreeHostPlatform::RunMoveLoop(
    const gfx::Vector2d& drag_offset,
    Widget::MoveLoopSource source,
    Widget::MoveLoopEscapeBehavior escape_behavior) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return Widget::MOVE_LOOP_CANCELED;
}

void DesktopWindowTreeHostPlatform::EndMoveLoop() {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::SetVisibilityChangedAnimationsEnabled(
    bool value) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

NonClientFrameView* DesktopWindowTreeHostPlatform::CreateNonClientFrameView() {
  return ShouldUseNativeFrame() ? new NativeFrameView(GetWidget()) : nullptr;
}

bool DesktopWindowTreeHostPlatform::ShouldUseNativeFrame() const {
  return false;
}

bool DesktopWindowTreeHostPlatform::ShouldWindowContentsBeTransparent() const {
  return false;
}

void DesktopWindowTreeHostPlatform::FrameTypeChanged() {}

void DesktopWindowTreeHostPlatform::SetFullscreen(bool fullscreen) {
  if (IsFullscreen() != fullscreen)
    platform_window()->ToggleFullscreen();
}

bool DesktopWindowTreeHostPlatform::IsFullscreen() const {
  return platform_window()->GetPlatformWindowState() ==
         ui::PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN;
}

void DesktopWindowTreeHostPlatform::SetOpacity(float opacity) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::SetWindowIcons(
    const gfx::ImageSkia& window_icon,
    const gfx::ImageSkia& app_icon) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::InitModalType(ui::ModalType modal_type) {
  // TODO: needs PlatformWindow support (alternatively, remove as
  // DesktopWindowTreeHostX11 doesn't support at all).
  NOTIMPLEMENTED_LOG_ONCE();
}

void DesktopWindowTreeHostPlatform::FlashFrame(bool flash_frame) {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

bool DesktopWindowTreeHostPlatform::IsAnimatingClosed() const {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return false;
}

bool DesktopWindowTreeHostPlatform::IsTranslucentWindowOpacitySupported()
    const {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
  return false;
}

void DesktopWindowTreeHostPlatform::SizeConstraintsChanged() {
  // TODO: needs PlatformWindow support.
  NOTIMPLEMENTED_LOG_ONCE();
}

bool DesktopWindowTreeHostPlatform::ShouldUpdateWindowTransparency() const {
  return false;
}

bool DesktopWindowTreeHostPlatform::ShouldUseDesktopNativeCursorManager()
    const {
  return true;
}

bool DesktopWindowTreeHostPlatform::ShouldCreateVisibilityController() const {
  return true;
}

void DesktopWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
#if defined(USE_OZONE)
  // Make sure the |event| is marked as a non-client if it's a non-client
  // mouse down event. This is needed to make sure the WindowEventDispatcher
  // does not set a |mouse_pressed_handler_| for such events, because they are
  // not always followed with non-client mouse up events in case of
  // Ozone/Wayland or Ozone/X11.
  //
  // Also see the comment in WindowEventDispatcher::PreDispatchMouseEvent..
  aura::Window* content_window = desktop_native_widget_aura_->content_window();
  if (content_window && content_window->delegate()) {
    if (event->IsMouseEvent()) {
      ui::MouseEvent* mouse_event = event->AsMouseEvent();
      int flags = mouse_event->flags();
      int hit_test_code = content_window->delegate()->GetNonClientComponent(
          mouse_event->location());
      if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE)
        flags |= ui::EF_IS_NON_CLIENT;
      mouse_event->set_flags(flags);
    }
  }
#endif

  WindowTreeHostPlatform::DispatchEvent(event);
}

void DesktopWindowTreeHostPlatform::OnClosed() {
  RemoveNonClientEventFilter();
  got_on_closed_ = true;
  desktop_native_widget_aura_->OnHostClosed();
}

void DesktopWindowTreeHostPlatform::OnWindowStateChanged(
    ui::PlatformWindowState new_state) {
  // Propagate minimization/restore to compositor to avoid drawing 'blank'
  // frames that could be treated as previews, which show content even if a
  // window is minimized.
  bool visible =
      new_state != ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
  if (visible != compositor()->IsVisible()) {
    compositor()->SetVisible(visible);
    native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
  }

  // It might require relayouting when state property has been changed.
  if (visible)
    Relayout();
}

void DesktopWindowTreeHostPlatform::OnCloseRequest() {
  GetWidget()->Close();
}

void DesktopWindowTreeHostPlatform::OnActivationChanged(bool active) {
  is_active_ = active;
  aura::WindowTreeHostPlatform::OnActivationChanged(active);
  desktop_native_widget_aura_->HandleActivationChanged(active);
}

void DesktopWindowTreeHostPlatform::Relayout() {
  Widget* widget = native_widget_delegate_->AsWidget();
  NonClientView* non_client_view = widget->non_client_view();
  // non_client_view may be NULL, especially during creation.
  if (non_client_view) {
    non_client_view->client_view()->InvalidateLayout();
    non_client_view->InvalidateLayout();
  }
  widget->GetRootView()->Layout();
}

void DesktopWindowTreeHostPlatform::RemoveNonClientEventFilter() {
  if (!non_client_window_event_filter_)
    return;

  window()->RemovePreTargetHandler(non_client_window_event_filter_.get());
  non_client_window_event_filter_.reset();
}

Widget* DesktopWindowTreeHostPlatform::GetWidget() {
  return native_widget_delegate_->AsWidget();
}

gfx::Rect DesktopWindowTreeHostPlatform::ToDIPRect(
    const gfx::Rect& rect_in_pixels) const {
  gfx::RectF rect_in_dip = gfx::RectF(rect_in_pixels);
  GetRootTransform().TransformRectReverse(&rect_in_dip);
  return gfx::ToEnclosingRect(rect_in_dip);
}

gfx::Rect DesktopWindowTreeHostPlatform::ToPixelRect(
    const gfx::Rect& rect_in_dip) const {
  gfx::RectF rect_in_pixels = gfx::RectF(rect_in_dip);
  GetRootTransform().TransformRect(&rect_in_pixels);
  return gfx::ToEnclosingRect(rect_in_pixels);
}

////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHost:

// static
DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
    internal::NativeWidgetDelegate* native_widget_delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura) {
  return new DesktopWindowTreeHostPlatform(native_widget_delegate,
                                           desktop_native_widget_aura);
}

}  // namespace views
