// Copyright 2016 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/mus/desktop_window_tree_host_mus.h"

#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/focus_synchronizer.h"
#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/hit_test.h"
#include "ui/display/screen.h"
#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/gestures/gesture_recognizer_observer.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/mus/mus_client.h"
#include "ui/views/mus/mus_property_mirror.h"
#include "ui/views/mus/window_manager_frame_values.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/native_widget_aura.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/cursor_manager.h"
#include "ui/wm/core/native_cursor_manager.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"

namespace views {

namespace {

// As the window manager renderers the non-client decorations this class does
// very little but honor kTopViewInset.
class ClientSideNonClientFrameView : public NonClientFrameView,
                                     public aura::WindowObserver {
 public:
  explicit ClientSideNonClientFrameView(views::Widget* widget)
      : widget_(widget) {
    // Not part of the accessibility node hierarchy because the window frame is
    // provided by the window manager.
    if (MusClient::Get()->use_remote_accessibility_host())
      GetViewAccessibility().OverrideIsIgnored(true);

    // Initialize kTopViewInset to a default value. Further updates will come
    // from Ash. This is necessary so that during app window creation,
    // GetWindowBoundsForClientBounds() can calculate correctly.
    const auto& values = views::WindowManagerFrameValues::instance();
    widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset,
                                           widget->IsMaximized()
                                               ? values.maximized_insets.top()
                                               : values.normal_insets.top());
    observed_.Add(window());
  }
  ~ClientSideNonClientFrameView() override {}

 private:
  gfx::Insets GetClientInsets() const {
    const int top_inset = window()->GetProperty(aura::client::kTopViewInset);
    return gfx::Insets(top_inset, 0, 0, 0);
  }

  // View:
  const char* GetClassName() const override {
    return "ClientSideNonClientFrameView";
  }

  // NonClientFrameView:
  gfx::Rect GetBoundsForClientView() const override {
    gfx::Rect result(GetLocalBounds());
    if (widget_->IsFullscreen())
      return result;
    result.Inset(GetClientInsets());
    return result;
  }
  gfx::Rect GetWindowBoundsForClientBounds(
      const gfx::Rect& client_bounds) const override {
    if (widget_->IsFullscreen())
      return client_bounds;

    gfx::Rect outset_bounds = client_bounds;
    outset_bounds.Inset(-GetClientInsets());
    return outset_bounds;
  }
  int NonClientHitTest(const gfx::Point& point) override { return HTNOWHERE; }
  void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override {
    // The window manager provides the shape; do nothing.
  }
  void ResetWindowControls() override {
    // TODO(sky): push to wm?
  }

  // These have no implementation. The Window Manager handles the actual
  // rendering of the icon/title. See NonClientFrameViewMash. The values
  // associated with these methods are pushed to the server by the way of
  // NativeWidgetMus functions.
  void UpdateWindowIcon() override {}
  void UpdateWindowTitle() override {}
  void SizeConstraintsChanged() override {}

  gfx::Size CalculatePreferredSize() const override {
    return widget_->non_client_view()
        ->GetWindowBoundsForClientBounds(
            gfx::Rect(widget_->client_view()->GetPreferredSize()))
        .size();
  }
  gfx::Size GetMinimumSize() const override {
    return widget_->non_client_view()
        ->GetWindowBoundsForClientBounds(
            gfx::Rect(widget_->client_view()->GetMinimumSize()))
        .size();
  }
  gfx::Size GetMaximumSize() const override {
    gfx::Size max_size = widget_->client_view()->GetMaximumSize();
    gfx::Size converted_size =
        widget_->non_client_view()
            ->GetWindowBoundsForClientBounds(gfx::Rect(max_size))
            .size();
    return gfx::Size(max_size.width() == 0 ? 0 : converted_size.width(),
                     max_size.height() == 0 ? 0 : converted_size.height());
  }

  // aura::WindowObserver:
  void OnWindowDestroying(aura::Window* window) override {
    observed_.Remove(window);
  }

  void OnWindowPropertyChanged(aura::Window* window,
                               const void* key,
                               intptr_t old) override {
    if (key == aura::client::kTopViewInset) {
      InvalidateLayout();
      widget_->GetRootView()->Layout();
    }
  }

  aura::Window* window() const {
    return widget_->GetNativeWindow()->GetRootWindow();
  }

  views::Widget* widget_;
  ScopedObserver<aura::Window, aura::WindowObserver> observed_{this};

  DISALLOW_COPY_AND_ASSIGN(ClientSideNonClientFrameView);
};

class NativeCursorManagerMus : public wm::NativeCursorManager {
 public:
  explicit NativeCursorManagerMus(aura::Window* window) : window_(window) {}
  ~NativeCursorManagerMus() override {}

  // wm::NativeCursorManager:
  void SetDisplay(const display::Display& display,
                  wm::NativeCursorManagerDelegate* delegate) override {
    // We ignore this entirely, as cursor are set on the client.
  }

  void SetCursor(gfx::NativeCursor cursor,
                 wm::NativeCursorManagerDelegate* delegate) override {
    ui::CursorData mojo_cursor;
    if (cursor.native_type() == ui::CursorType::kCustom) {
      mojo_cursor =
          ui::CursorData(cursor.GetHotspot(), {cursor.GetBitmap()},
                         cursor.device_scale_factor(), base::TimeDelta());
    } else {
      mojo_cursor = ui::CursorData(cursor.native_type());
    }

    aura::WindowPortMus::Get(window_)->SetCursor(mojo_cursor);
    delegate->CommitCursor(cursor);
  }

  void SetVisibility(bool visible,
                     wm::NativeCursorManagerDelegate* delegate) override {
    delegate->CommitVisibility(visible);

    if (visible) {
      SetCursor(delegate->GetCursor(), delegate);
    } else {
      aura::WindowPortMus::Get(window_)->SetCursor(
          ui::CursorData(ui::CursorType::kNone));
    }
  }

  void SetCursorSize(ui::CursorSize cursor_size,
                     wm::NativeCursorManagerDelegate* delegate) override {
    // TODO(erg): For now, ignore the difference between SET_NORMAL and
    // SET_LARGE here. This feels like a thing that mus should decide instead.
    //
    // Also, it's NOTIMPLEMENTED() in the desktop version!? Including not
    // acknowledging the call in the delegate.
    NOTIMPLEMENTED();
  }

  void SetMouseEventsEnabled(
      bool enabled,
      wm::NativeCursorManagerDelegate* delegate) override {
    // TODO(erg): How do we actually implement this?
    //
    // Mouse event dispatch is potentially done in a different process,
    // definitely in a different mojo service. Each app is fairly locked down.
    delegate->CommitMouseEventsEnabled(enabled);
    NOTIMPLEMENTED();
  }

 private:
  aura::Window* window_;

  DISALLOW_COPY_AND_ASSIGN(NativeCursorManagerMus);
};

void OnMoveLoopEnd(bool* out_success,
                   base::Closure quit_closure,
                   bool in_success) {
  *out_success = in_success;
  quit_closure.Run();
}

// ScopedTouchTransferController controls the transfer of touch events for
// window move loop. It transfers touches before the window move starts, and
// then transfers them back to the original window when the window move ends.
// However this transferring back to the original shouldn't happen if the client
// wants to continue the dragging on another window (like attaching the dragged
// tab to another window).
class ScopedTouchTransferController : public ui::GestureRecognizerObserver {
 public:
  ScopedTouchTransferController(aura::Window* source, aura::Window* dest)
      : tracker_({source, dest}),
        gesture_recognizer_(source->env()->gesture_recognizer()) {
    gesture_recognizer_->TransferEventsTo(
        source, dest, ui::TransferTouchesBehavior::kDontCancel);
    gesture_recognizer_->AddObserver(this);
  }
  ~ScopedTouchTransferController() override {
    gesture_recognizer_->RemoveObserver(this);
    if (tracker_.windows().size() == 2) {
      aura::Window* source = tracker_.Pop();
      aura::Window* dest = tracker_.Pop();
      gesture_recognizer_->TransferEventsTo(
          dest, source, ui::TransferTouchesBehavior::kDontCancel);
    }
  }

 private:
  // ui::GestureRecognizerObserver:
  void OnActiveTouchesCanceledExcept(
      ui::GestureConsumer* not_cancelled) override {}
  void OnEventsTransferred(
      ui::GestureConsumer* current_consumer,
      ui::GestureConsumer* new_consumer,
      ui::TransferTouchesBehavior transfer_touches_behavior) override {
    if (tracker_.windows().size() <= 1)
      return;
    aura::Window* dest = tracker_.windows()[1];
    if (current_consumer == dest)
      tracker_.Remove(dest);
  }
  void OnActiveTouchesCanceled(ui::GestureConsumer* consumer) override {}

  aura::WindowTracker tracker_;

  ui::GestureRecognizer* gesture_recognizer_;

  DISALLOW_COPY_AND_ASSIGN(ScopedTouchTransferController);
};

}  // namespace

// WindowObserver installed on DesktopWindowTreeHostMus::window(). Mostly
// forwards interesting events to DesktopWindowTreeHostMus. To avoid having
// DesktopWindowTreeHostMus be a WindowObserver on two windows (which is mildly
// error prone), this helper class is used.
class DesktopWindowTreeHostMus::WindowTreeHostWindowObserver
    : public aura::WindowObserver {
 public:
  explicit WindowTreeHostWindowObserver(DesktopWindowTreeHostMus* host)
      : host_(host) {
    host->window()->AddObserver(this);
  }
  ~WindowTreeHostWindowObserver() override {
    host_->window()->RemoveObserver(this);
  }

  void set_is_waiting_for_restore(bool value) {
    is_waiting_for_restore_ = value;
  }
  bool is_waiting_for_restore() const { return is_waiting_for_restore_; }

  // aura::WindowObserver:
  void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
    if (window == host_->window())
      host_->OnWindowTreeHostWindowVisibilityChanged(visible);
  }
  void OnWindowPropertyChanged(aura::Window* window,
                               const void* key,
                               intptr_t old) override {
    if (key == aura::client::kShowStateKey)
      is_waiting_for_restore_ = false;
  }

 private:
  DesktopWindowTreeHostMus* host_;

  // True while waiting for the show state to change.
  bool is_waiting_for_restore_ = false;

  DISALLOW_COPY_AND_ASSIGN(WindowTreeHostWindowObserver);
};

DesktopWindowTreeHostMus::DesktopWindowTreeHostMus(
    aura::WindowTreeHostMusInitParams init_params,
    internal::NativeWidgetDelegate* native_widget_delegate,
    DesktopNativeWidgetAura* desktop_native_widget_aura)
    : aura::WindowTreeHostMus(std::move(init_params)),
      native_widget_delegate_(native_widget_delegate),
      desktop_native_widget_aura_(desktop_native_widget_aura),
      close_widget_factory_(this) {
  MusClient::Get()->AddObserver(this);
  MusClient::Get()->window_tree_client()->focus_synchronizer()->AddObserver(
      this);
  content_window()->AddObserver(this);
  // DesktopNativeWidgetAura registers the association between |content_window_|
  // and Widget, but code may also want to go from the root (window()) to the
  // Widget. This call enables that.
  NativeWidgetAura::RegisterNativeWidgetForWindow(desktop_native_widget_aura,
                                                  window());

  window_tree_host_window_observer_ =
      std::make_unique<WindowTreeHostWindowObserver>(this);
  // TODO: use display id and bounds if available, likely need to pass in
  // InitParams for that.
}

DesktopWindowTreeHostMus::~DesktopWindowTreeHostMus() {
  window_tree_host_window_observer_.reset();

  // The cursor-client can be accessed during WindowTreeHostMus tear-down. So
  // the cursor-client needs to be unset on the root-window before
  // |cursor_manager_| is destroyed.
  aura::client::SetCursorClient(window(), nullptr);
  content_window()->RemoveObserver(this);
  MusClient::Get()->RemoveObserver(this);
  MusClient::Get()->window_tree_client()->focus_synchronizer()->RemoveObserver(
      this);
  desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
}

void DesktopWindowTreeHostMus::SendClientAreaToServer() {
  if (!ShouldSendClientAreaToServer())
    return;

  NonClientView* non_client_view =
      native_widget_delegate_->AsWidget()->non_client_view();
  if (!non_client_view || !non_client_view->client_view())
    return;

  View* client_view = non_client_view->client_view();
  if (!observed_client_view_.IsObserving(client_view))
    observed_client_view_.Add(client_view);

  const gfx::Rect client_area_rect(non_client_view->client_view()->bounds());
  SetClientArea(
      gfx::Insets(
          client_area_rect.y(), client_area_rect.x(),
          non_client_view->bounds().height() - client_area_rect.bottom(),
          non_client_view->bounds().width() - client_area_rect.right()),
      std::vector<gfx::Rect>());
}

bool DesktopWindowTreeHostMus::IsFocusClientInstalledOnFocusSynchronizer()
    const {
  return MusClient::Get()
             ->window_tree_client()
             ->focus_synchronizer()
             ->active_focus_client() == aura::client::GetFocusClient(window());
}

float DesktopWindowTreeHostMus::GetScaleFactor() const {
  // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
  return display::Screen::GetScreen()
      ->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
      .device_scale_factor();
}

void DesktopWindowTreeHostMus::SetBoundsInDIP(const gfx::Rect& bounds_in_dip) {
  // Do not use ConvertRectToPixel, enclosing rects cause problems.
  const gfx::Rect rect(
      gfx::ScaleToFlooredPoint(bounds_in_dip.origin(), GetScaleFactor()),
      gfx::ScaleToCeiledSize(bounds_in_dip.size(), GetScaleFactor()));
  SetBoundsInPixels(rect, viz::LocalSurfaceIdAllocation());
}

bool DesktopWindowTreeHostMus::IsWaitingForRestoreToComplete() const {
  return window_tree_host_window_observer_->is_waiting_for_restore();
}

bool DesktopWindowTreeHostMus::ShouldSendClientAreaToServer() const {
  if (!auto_update_client_area_)
    return false;

  using WIP = views::Widget::InitParams;
  const WIP::Type type = desktop_native_widget_aura_->widget_type();
  return type == WIP::TYPE_WINDOW || type == WIP::TYPE_PANEL;
}

void DesktopWindowTreeHostMus::RestoreToPreminimizedState() {
  DCHECK(IsMinimized());
  window_tree_host_window_observer_->set_is_waiting_for_restore(true);
  base::AutoReset<bool> setter(&is_updating_window_visibility_, true);
  window()->Show();
}

void DesktopWindowTreeHostMus::OnWindowTreeHostWindowVisibilityChanged(
    bool visible) {
  if (is_updating_window_visibility_)
    return;

  // Call Show()/Hide() so that the visibility state is mirrored correctly. This
  // function makes it so that calling Show()/Hide() on window() is the same as
  // calling Show()/Hide() on the Widget.
  base::AutoReset<bool> setter(&is_updating_window_visibility_, true);
  if (visible)
    Show(ui::SHOW_STATE_INACTIVE, gfx::Rect());
  else
    Hide();
}

void DesktopWindowTreeHostMus::Init(const Widget::InitParams& params) {
  const bool translucent =
      MusClient::ShouldMakeWidgetWindowsTranslucent(params);
  content_window()->SetTransparent(translucent);
  window()->SetTransparent(translucent);

  // The window manager may provide the initial show state, for example for
  // Chrome OS lock screen windows. https://crbug.com/899055
  if (params.show_state != ui::SHOW_STATE_DEFAULT)
    window()->SetProperty(aura::client::kShowStateKey, params.show_state);

  if (!params.bounds.IsEmpty()) {
    // Init the scale now (before InitHost below), it is used by SetBoundsInDIP.
    IntializeDeviceScaleFactor(GetDisplay().device_scale_factor());
    SetBoundsInDIP(params.bounds);
  }

  cursor_manager_ = std::make_unique<wm::CursorManager>(
      std::make_unique<NativeCursorManagerMus>(window()));
  aura::client::SetCursorClient(window(), cursor_manager_.get());
  InitHost();

  NativeWidgetAura::SetShadowElevationFromInitParams(window(), params);

  // Widget's |InitParams::parent| has different meanings depending on the
  // NativeWidgetPrivate implementation that the Widget creates (each Widget
  // creates a NativeWidgetPrivate). When DesktopNativeWidgetAura is used as
  // the NativeWidgetPrivate implementation, |InitParams::parent| means the
  // entirety of the contents of the new Widget should be stacked above the
  // entirety of the contents of the Widget for |InitParams::parent|, and
  // the new Widget should be deleted when the Widget for
  // |InitParams::parent| is deleted. Aura and mus provide support for
  // transient windows, which provides both the stacking and ownership needed to
  // support |InitParams::parent|.
  //
  // DesktopNativeWidgetAura internally creates two aura::Windows (one by
  // WindowTreeHost, the other in |DesktopNativeWidgetAura::content_window_|).
  // To have the entirety of the contents of the Widget appear on top of the
  // entirety of the contents of another Widget, the stacking is done on the
  // WindowTreeHost's window. For these reasons, the following code uses the
  // Window associated with the WindowTreeHost of the |params.parent|.
  //
  // Views/Aura provide support for child-modal windows. Child-modal windows
  // are windows that are modal to their transient parent. Because this code
  // implements |InitParams::parent| in terms of transient parents, it means
  // it is not possible to support both |InitParams::parent| as well as a
  // child-modal window. This is *only* an issue if a Widget that uses a
  // DesktopNativeWidgetAura needs to be child-modal to another window. At
  // the current time NativeWidgetAura is always used for child-modal windows,
  // so this isn't an issue.
  //
  // If we end up needing to use DesktopNativeWidgetAura for child-modal
  // Widgets then we need something different. Possibilities include:
  // . Have mus ignore child-modal windows and instead implement child-modal
  //   entirely in the client (this is what we do on Windows). To get this
  //   right likely means we need the ability to disable windows (see
  //   HWNDMessageHandler::InitModalType() for how Windows OS does this).
  // . Implement |InitParams::parent| using a different (new) API.
  if (params.parent && params.parent->GetHost()) {
    aura::client::GetTransientWindowClient()->AddTransientChild(
        params.parent->GetHost()->window(), window());
  }

  if (!params.accept_events)
    window()->SetEventTargetingPolicy(ws::mojom::EventTargetingPolicy::NONE);
  else
    aura::WindowPortMus::Get(content_window())->SetCanAcceptDrops(true);

  // Sets the has-content info for the occlusion tracker that runs on the Window
  // Service side.
  content_window()->SetProperty(
      aura::client::kClientWindowHasContent,
      params.layer_type != ui::LAYER_NOT_DRAWN &&
          params.opacity == views::Widget::InitParams::OPAQUE_WINDOW);
}

void DesktopWindowTreeHostMus::OnNativeWidgetCreated(
    const Widget::InitParams& params) {
  if (params.parent && params.parent->GetHost()) {
    parent_ = static_cast<DesktopWindowTreeHostMus*>(params.parent->GetHost());
    parent_->children_.insert(this);
  }
  native_widget_delegate_->OnNativeWidgetCreated(true);
}

void DesktopWindowTreeHostMus::OnActiveWindowChanged(bool active) {
  // This function is called when there is a change in the active window the
  // FocusClient for window() is associated with. This needs to potentially
  // propagate to mus (the change may originate locally, not from mus).
  // Propagating to the server is done by resetting the ActiveFocusClient.
  if (active && !IsFocusClientInstalledOnFocusSynchronizer()) {
    MusClient::Get()
        ->window_tree_client()
        ->focus_synchronizer()
        ->SetActiveFocusClient(aura::client::GetFocusClient(window()),
                               window());
  } else if (!active && IsFocusClientInstalledOnFocusSynchronizer()) {
    MusClient::Get()
        ->window_tree_client()
        ->focus_synchronizer()
        ->SetActiveFocusClient(nullptr, nullptr);
  }
}

void DesktopWindowTreeHostMus::OnWidgetInitDone() {
  // Because of construction order it's possible the bounds have changed before
  // the NonClientView was created, which means we may not have sent the
  // client-area and hit-test-mask.
  SendClientAreaToServer();

  MusClient::Get()->OnCaptureClientSet(
      aura::client::GetCaptureClient(window()));

  // These views are not part of the accessibility node hierarchy because the
  // window frame is provided by the window manager.
  Widget* widget = native_widget_delegate_->AsWidget();
  if (MusClient::Get()->use_remote_accessibility_host()) {
    if (widget->non_client_view())
      widget->non_client_view()->GetViewAccessibility().OverrideIsIgnored(true);
    if (widget->client_view())
      widget->client_view()->GetViewAccessibility().OverrideIsIgnored(true);
  }

  MusClient::Get()->OnWidgetInitDone(widget);
}

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

std::unique_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostMus::CreateDragDropClient(
    DesktopNativeCursorManager* cursor_manager) {
  // aura-mus handles installing a DragDropClient.
  return nullptr;
}

void DesktopWindowTreeHostMus::Close() {
  if (close_widget_factory_.HasWeakPtrs())
    return;

  // Even though we don't close immediately, we need to hide immediately
  // (otherwise events may be processed, which is unexpected).
  Hide();

  // This has to happen *after* Hide() above, otherwise animations won't work.
  content_window()->Hide();

  // Close doesn't delete this immediately, as 'this' may still be on the stack
  // resulting in possible crashes when the stack unwindes.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&DesktopWindowTreeHostMus::CloseNow,
                                close_widget_factory_.GetWeakPtr()));
}

void DesktopWindowTreeHostMus::CloseNow() {
  MusClient::Get()->OnCaptureClientUnset(
      aura::client::GetCaptureClient(window()));

  native_widget_delegate_->OnNativeWidgetDestroying();

  // If we have children, close them. Use a copy for iteration because they'll
  // remove themselves from |children_|.
  std::set<DesktopWindowTreeHostMus*> children_copy = children_;
  for (DesktopWindowTreeHostMus* child : children_copy)
    child->CloseNow();
  DCHECK(children_.empty());

  if (parent_) {
    parent_->children_.erase(this);
    parent_ = nullptr;
  }

  DestroyCompositor();
  desktop_native_widget_aura_->OnHostClosed();
}

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

void DesktopWindowTreeHostMus::Show(ui::WindowShowState show_state,
                                    const gfx::Rect& restore_bounds) {
  // Only notify if the visibility is really changing.
  const bool notify_visibility_change =
      is_updating_window_visibility_ || !IsVisible();
  if (notify_visibility_change)
    native_widget_delegate_->OnNativeWidgetVisibilityChanging(true);

  // NOTE: this code is called from Widget::Show() (no args). Widget::Show()
  // supplies ui::SHOW_STATE_DEFAULT as the |show_state| after the first call.
  // If SHOW_STATE_DEFAULT is supplied, and the Window is currently minimized,
  // the window should be restored to its preminimized state.

  if (show_state == ui::SHOW_STATE_MAXIMIZED && !restore_bounds.IsEmpty()) {
    window()->SetProperty(aura::client::kRestoreBoundsKey,
                          new gfx::Rect(restore_bounds));
  }
  if (show_state == ui::SHOW_STATE_MAXIMIZED ||
      show_state == ui::SHOW_STATE_FULLSCREEN) {
    window()->SetProperty(aura::client::kShowStateKey, show_state);
    window_tree_host_window_observer_->set_is_waiting_for_restore(false);
  } else if (show_state == ui::SHOW_STATE_DEFAULT && IsMinimized()) {
    RestoreToPreminimizedState();
  } else if (show_state == ui::SHOW_STATE_MINIMIZED && !IsMinimized()) {
    Minimize();
  }
  // DesktopWindowTreeHostMus is unique in that it calls window()->Show() here.
  // All other implementations call window()->Show() from the constructor. This
  // is necessary as window()'s visibility is mirrored in the server, on other
  // platforms it's the visibility of the AcceleratedWidget that matters and
  // dictates what is actually drawn on screen.
  {
    base::AutoReset<bool> setter(&is_updating_window_visibility_, true);
    window()->Show();
  }
  if (compositor())
    compositor()->SetVisible(true);

  // |content_window_| is the Window that will be focused by way of Activate().
  // Ensure |content_window_| is visible before the call to Activate(),
  // otherwise focus goes to window().
  content_window()->Show();

  if (notify_visibility_change)
    native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);

  if (native_widget_delegate_->CanActivate()) {
    if (show_state != ui::SHOW_STATE_INACTIVE &&
        show_state != ui::SHOW_STATE_MINIMIZED) {
      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 crbug.com/515594 for example.
    native_widget_delegate_->SetInitialFocus(
        IsActive() ? show_state : ui::SHOW_STATE_INACTIVE);
  }
}

bool DesktopWindowTreeHostMus::IsVisible() const {
  // Go through the DesktopNativeWidgetAura::IsVisible() for checking
  // visibility of the parent as it has additional checks beyond checking the
  // aura::Window.
  return window()->IsVisible() &&
         (!parent_ ||
          static_cast<const internal::NativeWidgetPrivate*>(
              parent_->desktop_native_widget_aura_)
              ->IsVisible());
}

void DesktopWindowTreeHostMus::SetSize(const gfx::Size& size) {
  // Use GetBoundsInPixels(), as the origin of window() is always at (0, 0).
  gfx::Rect screen_bounds =
      gfx::ConvertRectToDIP(GetScaleFactor(), GetBoundsInPixels());
  screen_bounds.set_size(size);
  SetBoundsInDIP(screen_bounds);
}

void DesktopWindowTreeHostMus::StackAbove(aura::Window* relative) {
  // Windows and X11 check for |relative| being nullptr and fail silently. It
  // also looks like |relative| is usually multiple children deep in the root
  // window, which we must pass instead.
  if (relative && relative->GetRootWindow())
    WindowTreeHostMus::StackAbove(relative->GetRootWindow());
}

void DesktopWindowTreeHostMus::StackAtTop() {
  // Request to the server to stack our current mus window at the top. Our
  // window() is a root, and we can't reach up past it so we can't just request
  // a Reorder(), which is what we'd do to reorder our own subwindows.
  WindowTreeHostMus::StackAtTop();
}

void DesktopWindowTreeHostMus::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.
  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 DesktopWindowTreeHostMus::GetWindowPlacement(
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  // Implementation matches that of NativeWidgetAura.
  *bounds = GetRestoredBounds();
  if (IsWaitingForRestoreToComplete()) {
    // The real state is not known, use ui::SHOW_STATE_NORMAL to avoid saving
    // the minimized state.
    *show_state = ui::SHOW_STATE_NORMAL;
  } else {
    *show_state = window()->GetProperty(aura::client::kShowStateKey);
  }
}

gfx::Rect DesktopWindowTreeHostMus::GetWindowBoundsInScreen() const {
  return gfx::ConvertRectToDIP(GetScaleFactor(), GetBoundsInPixels());
}

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

gfx::Rect DesktopWindowTreeHostMus::GetRestoredBounds() const {
  // Restored bounds should only be relevant if the window is minimized,
  // maximized, or fullscreen. However, in some places the code expects
  // GetRestoredBounds() to return the current window bounds if the window is
  // not in either state.
  if (IsMinimized() || IsMaximized() || IsFullscreen()) {
    // Restore bounds are in screen coordinates, no need to convert.
    gfx::Rect* restore_bounds =
        window()->GetProperty(aura::client::kRestoreBoundsKey);
    if (restore_bounds)
      return *restore_bounds;
  }
  return GetWindowBoundsInScreen();
}

std::string DesktopWindowTreeHostMus::GetWorkspace() const {
  // Only used on x11.
  return std::string();
}

gfx::Rect DesktopWindowTreeHostMus::GetWorkAreaBoundsInScreen() const {
  return GetDisplay().work_area();
}

void DesktopWindowTreeHostMus::SetShape(
    std::unique_ptr<Widget::ShapeRects> native_shape) {
  NOTIMPLEMENTED();
}

void DesktopWindowTreeHostMus::Activate() {
  if (!IsVisible() && !IsMinimized())
    return;

  // Activate() is expected to restore a minimized window.
  if (IsMinimized())
    RestoreToPreminimizedState();

  // This should result in OnActiveFocusClientChanged() being called, which
  // triggers a call to DesktopNativeWidgetAura::HandleActivationChanged(),
  // which focuses the right window.
  MusClient::Get()
      ->window_tree_client()
      ->focus_synchronizer()
      ->SetActiveFocusClient(aura::client::GetFocusClient(window()), window());
  if (is_active_)
    window()->SetProperty(aura::client::kDrawAttentionKey, false);
}

void DesktopWindowTreeHostMus::Deactivate() {
  if (!is_active_)
    return;

  // Reset the active focus client, which will trigger resetting active status.
  // This is done so that we deactivate immediately.
  DCHECK(IsFocusClientInstalledOnFocusSynchronizer());
  MusClient::Get()
      ->window_tree_client()
      ->focus_synchronizer()
      ->SetActiveFocusClient(nullptr, nullptr);
  DCHECK(!is_active_);

  // Then ask the window manager to deactivate, which effectively means pick
  // another window to activate.
  DeactivateWindow();
}

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

void DesktopWindowTreeHostMus::Maximize() {
  window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
}

void DesktopWindowTreeHostMus::Minimize() {
  window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);

  // When minimized, this should no longer be active.
  if (IsFocusClientInstalledOnFocusSynchronizer()) {
    MusClient::Get()
        ->window_tree_client()
        ->focus_synchronizer()
        ->SetActiveFocusClient(nullptr, nullptr);
  }
}

void DesktopWindowTreeHostMus::Restore() {
  window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
}

bool DesktopWindowTreeHostMus::IsMaximized() const {
  return window()->GetProperty(aura::client::kShowStateKey) ==
         ui::SHOW_STATE_MAXIMIZED;
}

bool DesktopWindowTreeHostMus::IsMinimized() const {
  return window()->GetProperty(aura::client::kShowStateKey) ==
             ui::SHOW_STATE_MINIMIZED &&
         !IsWaitingForRestoreToComplete();
}

bool DesktopWindowTreeHostMus::HasCapture() const {
  // Capture state is held by DesktopNativeWidgetAura::content_window_.
  // DesktopNativeWidgetAura::HasCapture() calls content_window_->HasCapture(),
  // and this. That means this function can always return true.
  return true;
}

void DesktopWindowTreeHostMus::SetAlwaysOnTop(bool always_on_top) {
  window()->SetProperty(aura::client::kAlwaysOnTopKey, always_on_top);
}

bool DesktopWindowTreeHostMus::IsAlwaysOnTop() const {
  return window()->GetProperty(aura::client::kAlwaysOnTopKey);
}

void DesktopWindowTreeHostMus::SetVisibleOnAllWorkspaces(bool always_visible) {
  // Not applicable to chromeos.
}

bool DesktopWindowTreeHostMus::IsVisibleOnAllWorkspaces() const {
  return false;
}

bool DesktopWindowTreeHostMus::SetWindowTitle(const base::string16& title) {
  WidgetDelegate* widget_delegate =
      native_widget_delegate_->AsWidget()->widget_delegate();
  const bool show = widget_delegate && widget_delegate->ShouldShowWindowTitle();
  if (window()->GetTitle() == title &&
      window()->GetProperty(aura::client::kTitleShownKey) == show) {
    return false;
  }
  window()->SetProperty(aura::client::kTitleShownKey, show);
  window()->SetTitle(title);
  return true;
}

void DesktopWindowTreeHostMus::ClearNativeFocus() {
  aura::client::FocusClient* client = aura::client::GetFocusClient(window());
  if (client && window()->Contains(client->GetFocusedWindow()))
    client->ResetFocusWithinActiveWindow(window());
}

Widget::MoveLoopResult DesktopWindowTreeHostMus::RunMoveLoop(
    const gfx::Vector2d& drag_offset,
    Widget::MoveLoopSource source,
    Widget::MoveLoopEscapeBehavior escape_behavior) {
  // When using WindowService, the touch events for the window move will
  // happen on the root window, so the events need to be transferred from
  // widget to its root before starting move loop.
  ScopedTouchTransferController scoped_controller(content_window(), window());

  static_cast<internal::NativeWidgetPrivate*>(
      desktop_native_widget_aura_)->ReleaseCapture();

  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);

  ws::mojom::MoveLoopSource mus_source =
      source == Widget::MOVE_LOOP_SOURCE_MOUSE
          ? ws::mojom::MoveLoopSource::MOUSE
          : ws::mojom::MoveLoopSource::TOUCH;

  bool success = false;
  // Don't use display::Screen::GetCursorScreenPoint() -- that's incorrect for
  // touch events. Rather the cursor location can be computed from window's
  // location with drag_offset.
  gfx::Point cursor_location = window()->GetBoundsInScreen().origin() +
                               gfx::ToFlooredVector2d(drag_offset);
  WindowTreeHostMus::PerformWindowMove(
      mus_source, cursor_location,
      base::Bind(OnMoveLoopEnd, &success, run_loop.QuitClosure()));

  run_loop.Run();

  return success ? Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
}

void DesktopWindowTreeHostMus::EndMoveLoop() {
  WindowTreeHostMus::CancelWindowMove();
}

void DesktopWindowTreeHostMus::SetVisibilityChangedAnimationsEnabled(
    bool value) {
  window()->SetProperty(aura::client::kAnimationsDisabledKey, !value);
}

NonClientFrameView* DesktopWindowTreeHostMus::CreateNonClientFrameView() {
  if (!ShouldSendClientAreaToServer())
    return nullptr;

  return new ClientSideNonClientFrameView(native_widget_delegate_->AsWidget());
}

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

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

void DesktopWindowTreeHostMus::FrameTypeChanged() {
  native_widget_delegate_->AsWidget()->ThemeChanged();
}

void DesktopWindowTreeHostMus::SetFullscreen(bool fullscreen) {
  if (IsFullscreen() == fullscreen)
    return;  // Nothing to do.

  wm::SetWindowFullscreen(window(), fullscreen);
}

bool DesktopWindowTreeHostMus::IsFullscreen() const {
  return window()->GetProperty(aura::client::kShowStateKey) ==
         ui::SHOW_STATE_FULLSCREEN;
}

void DesktopWindowTreeHostMus::SetOpacity(float opacity) {
  WindowTreeHostMus::SetOpacity(opacity);
}

void DesktopWindowTreeHostMus::SetWindowIcons(const gfx::ImageSkia& window_icon,
                                              const gfx::ImageSkia& app_icon) {
  NativeWidgetAura::AssignIconToAuraWindow(window(), window_icon, app_icon);
}

void DesktopWindowTreeHostMus::InitModalType(ui::ModalType modal_type) {
  // See comment in Init() related to |InitParams::parent| as to why this DCHECK
  // is here.
  DCHECK_NE(modal_type, ui::MODAL_TYPE_CHILD);
  window()->SetProperty(aura::client::kModalKey, modal_type);
}

void DesktopWindowTreeHostMus::FlashFrame(bool flash_frame) {
  window()->SetProperty(aura::client::kDrawAttentionKey, flash_frame);
}

bool DesktopWindowTreeHostMus::IsAnimatingClosed() const {
  return false;
}

bool DesktopWindowTreeHostMus::IsTranslucentWindowOpacitySupported() const {
  return true;
}

void DesktopWindowTreeHostMus::SizeConstraintsChanged() {
  int32_t behavior = ws::mojom::kResizeBehaviorNone;
  Widget* widget = native_widget_delegate_->AsWidget();
  if (widget->widget_delegate())
    behavior = widget->widget_delegate()->GetResizeBehavior();
  window()->SetProperty(aura::client::kResizeBehaviorKey, behavior);
}

bool DesktopWindowTreeHostMus::ShouldUpdateWindowTransparency() const {
  // Needed so the window manager can render the client decorations.
  return false;
}

bool DesktopWindowTreeHostMus::ShouldUseDesktopNativeCursorManager() const {
  // We manage the cursor ourself.
  return false;
}

bool DesktopWindowTreeHostMus::ShouldCreateVisibilityController() const {
  // Window manager takes care of all top-level window animations.
  return false;
}

void DesktopWindowTreeHostMus::OnWindowManagerFrameValuesChanged() {
  NonClientView* non_client_view =
      native_widget_delegate_->AsWidget()->non_client_view();
  if (non_client_view) {
    non_client_view->Layout();
    non_client_view->SchedulePaint();
  }

  SendClientAreaToServer();
}

void DesktopWindowTreeHostMus::OnActiveFocusClientChanged(
    aura::client::FocusClient* focus_client,
    aura::Window* focus_client_root) {
  if (focus_client_root == this->window()) {
    is_active_ = true;
    desktop_native_widget_aura_->HandleActivationChanged(true);
  } else if (is_active_) {
    is_active_ = false;
    desktop_native_widget_aura_->HandleActivationChanged(false);
  }
}

void DesktopWindowTreeHostMus::OnWindowPropertyChanged(aura::Window* window,
                                                       const void* key,
                                                       intptr_t old) {
  DCHECK_EQ(window, content_window());
  DCHECK(!window->GetRootWindow() || this->window() == window->GetRootWindow());
  if (!this->window())
    return;

  // Allow mus clients to mirror widget window properties to their root windows.
  MusPropertyMirror* property_mirror = MusClient::Get()->mus_property_mirror();
  if (property_mirror) {
    property_mirror->MirrorPropertyFromWidgetWindowToRootWindow(
        window, this->window(), key);
  }
}

void DesktopWindowTreeHostMus::ShowImpl() {
  // This code path is hit when the server initiated the change. In such a case
  // the window should not be made active. If the server wants the window to be
  // active, it will make the window active.
  Show(ui::SHOW_STATE_INACTIVE, gfx::Rect());
}

void DesktopWindowTreeHostMus::HideImpl() {
  // If |is_updating_window_visibility_| is true, this is being called in
  // response to window()'s visibility changing, in which case we need to
  // continue on to complete processing of the hide.
  if (!IsVisible() && !is_updating_window_visibility_)
    return;

  native_widget_delegate_->OnNativeWidgetVisibilityChanging(false);
  {
    base::AutoReset<bool> setter(&is_updating_window_visibility_, true);
    WindowTreeHostMus::HideImpl();
  }
  native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);

  // When hiding we can't possibly be active any more. Reset the FocusClient,
  // which effectively triggers giving up focus (and activation). Mus will
  // eventually generate a focus event, but that's async. This should be done
  // after the window gets hidden actually, since some code (like
  // WindowActivityWatcher) assumes closing window is already invisible when the
  // focus is lost. See https://crbug.com/896080.
  if (IsFocusClientInstalledOnFocusSynchronizer()) {
    MusClient::Get()
        ->window_tree_client()
        ->focus_synchronizer()
        ->SetActiveFocusClient(nullptr, nullptr);
  }
}

void DesktopWindowTreeHostMus::SetBoundsInPixels(
    const gfx::Rect& bounds_in_pixels,
    const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) {
  gfx::Rect final_bounds_in_pixels = bounds_in_pixels;
  if (GetBoundsInPixels().size() != bounds_in_pixels.size()) {
    gfx::Size size = bounds_in_pixels.size();
    size.SetToMax(gfx::ConvertSizeToPixel(
        GetScaleFactor(), native_widget_delegate_->GetMinimumSize()));
    const gfx::Size max_size_in_pixels = gfx::ConvertSizeToPixel(
        GetScaleFactor(), native_widget_delegate_->GetMaximumSize());
    if (!max_size_in_pixels.IsEmpty())
      size.SetToMin(max_size_in_pixels);
    final_bounds_in_pixels.set_size(size);
  }
  WindowTreeHostMus::SetBoundsInPixels(final_bounds_in_pixels,
                                       local_surface_id_allocation);
}

void DesktopWindowTreeHostMus::OnViewBoundsChanged(views::View* observed_view) {
  DCHECK_EQ(
      observed_view,
      native_widget_delegate_->AsWidget()->non_client_view()->client_view());

  SendClientAreaToServer();
}

void DesktopWindowTreeHostMus::OnViewIsDeleting(View* observed_view) {
  observed_client_view_.Remove(observed_view);
}

aura::Window* DesktopWindowTreeHostMus::content_window() {
  return desktop_native_widget_aura_->content_window();
}

}  // namespace views
