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

#include "components/exo/shell_surface.h"

#include <optional>

#include "ash/frame/frame_view_ash.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/desks/desks_util.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "ash/wm/window_resizer.h"
#include "ash/wm/window_state.h"
#include "base/containers/adapters.h"
#include "base/debug/crash_logging.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "cc/layers/deadline_policy.h"
#include "chromeos/ui/base/window_properties.h"
#include "chromeos/ui/base/window_state_type.h"
#include "components/exo/custom_window_state_delegate.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/window_properties.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/scoped_animation_disabler.h"
#include "ui/wm/core/transient_window_manager.h"
#include "ui/wm/core/window_util.h"

namespace exo {
namespace {

// Default maximum amount of time to wait for contents to change. For example,
// happens during a maximize, or fullscreen or pinned state change.
constexpr int kDefaultCompositorLockTimeoutMs = 100;

// Compositor lock timeout for slower changes (e.g. display scale change).
constexpr int kSlowCompositorLockTimeoutMs = 500;

gfx::Rect GetClientBoundsInScreen(views::Widget* widget) {
  gfx::Rect window_bounds = widget->GetWindowBoundsInScreen();
  // Account for popup windows not having a non-client view.
  if (widget->non_client_view()) {
    return static_cast<ash::FrameViewAsh*>(
               widget->non_client_view()->frame_view())
        ->GetClientBoundsForWindowBounds(window_bounds);
  }
  return window_bounds;
}

// HTCLIENT can be used to drag the window in specific scenario.
// (e.g. Drag from shelf)
bool IsMoveComponent(int resize_component) {
  return resize_component == HTCAPTION || resize_component == HTCLIENT;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// ShellSurface, Config:

// Surface state associated with each configure request.
struct ShellSurface::Config {
  Config(uint32_t serial,
         const gfx::Vector2d& origin_offset,
         int resize_component,
         const viz::LocalSurfaceId& viz_surface_id,
         base::WeakPtr<ui::Layer> old_layer,
         std::unique_ptr<ui::CompositorLock> compositor_lock);
  ~Config() = default;

  uint32_t serial;
  gfx::Vector2d origin_offset;
  int resize_component;
  const viz::LocalSurfaceId viz_surface_id;
  base::WeakPtr<ui::Layer> old_layer;
  std::unique_ptr<ui::CompositorLock> compositor_lock;
};

ShellSurface::Config::Config(
    uint32_t serial,
    const gfx::Vector2d& origin_offset,
    int resize_component,
    const viz::LocalSurfaceId& viz_surface_id,
    base::WeakPtr<ui::Layer> old_layer,
    std::unique_ptr<ui::CompositorLock> compositor_lock)
    : serial(serial),
      origin_offset(origin_offset),
      resize_component(resize_component),
      viz_surface_id(viz_surface_id),
      old_layer(std::move(old_layer)),
      compositor_lock(std::move(compositor_lock)) {}

////////////////////////////////////////////////////////////////////////////////
// ShellSurface, ScopedConfigure:

ShellSurface::ScopedConfigure::ScopedConfigure(ShellSurface* shell_surface,
                                               bool force_configure)
    : shell_surface_(shell_surface), force_configure_(force_configure) {
  // ScopedConfigure instances cannot be nested.
  DCHECK(!shell_surface_->scoped_configure_);
  shell_surface_->scoped_configure_ = this;
}

ShellSurface::ScopedConfigure::~ScopedConfigure() {
  DCHECK_EQ(shell_surface_->scoped_configure_, this);
  shell_surface_->scoped_configure_ = nullptr;
  if (needs_configure_ || force_configure_)
    shell_surface_->Configure();
  // ScopedConfigure instance might have suppressed a widget bounds update.
  if (shell_surface_->widget_) {
    shell_surface_->UpdateWidgetBounds();
    shell_surface_->UpdateShadow();
  }
}

////////////////////////////////////////////////////////////////////////////////
// ShellSurface, OcclusionObserver:

ShellSurface::OcclusionObserver::OcclusionObserver(ShellSurface* shell_surface,
                                                   aura::Window* window)
    : state_(window->GetOcclusionState()), shell_surface_(shell_surface) {
  window->TrackOcclusionState();
  window_observation_.Observe(window);
}

ShellSurface::OcclusionObserver::~OcclusionObserver() = default;

void ShellSurface::OcclusionObserver::OnWindowDestroying(aura::Window* window) {
  window_observation_.Reset();
}

void ShellSurface::OcclusionObserver::OnWindowOcclusionChanged(
    aura::Window* window) {
  MaybeConfigure(window);
}

void ShellSurface::OcclusionObserver::MaybeConfigure(aura::Window* window) {
  auto new_state = window->GetOcclusionState();
  if (state_ != new_state && shell_surface_->IsReady()) {
    state_ = new_state;
    shell_surface_->Configure();
  }
}

aura::Window::OcclusionState
ShellSurface::OcclusionObserver::GetInitialStateForConfigure(
    chromeos::WindowStateType state_type) {
  // TODO(crbug.com/328172097): Put this back to sending HIDDEN for minimized
  // when we have some guarantee that the client will produce content while
  // hidden for the initial configure.
  state_ = aura::Window::OcclusionState::VISIBLE;
  return state_;
}

////////////////////////////////////////////////////////////////////////////////
// ShellSurface, public:

ShellSurface::ShellSurface(Surface* surface,
                           const gfx::Point& origin,
                           bool can_minimize,
                           int container)
    : ShellSurfaceBase(surface, origin, can_minimize, container) {
  CHECK(surface->window());
  occlusion_observer_.emplace(this, surface->window());
}

ShellSurface::ShellSurface(Surface* surface)
    : ShellSurfaceBase(surface,
                       gfx::Point(),
                       /*can_minimize=*/true,
                       ash::desks_util::GetActiveDeskContainerId()) {
  CHECK(surface->window());
  occlusion_observer_.emplace(this, surface->window());
}

ShellSurface::~ShellSurface() {
  DCHECK(!scoped_configure_);
  // Client is gone by now, so don't call callback.
  configure_callback_.Reset();
  origin_change_callback_.Reset();
  ash::WindowState* window_state =
      widget_ ? ash::WindowState::Get(widget_->GetNativeWindow()) : nullptr;
  if (window_state)
    window_state->RemoveObserver(this);

  for (auto& observer : observers_)
    observer.OnShellSurfaceDestroyed();
}

void ShellSurface::AcknowledgeConfigure(uint32_t serial) {
  TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial);

  // Apply all configs that are older or equal to |serial|. The result is that
  // the origin of the main surface will move and the resize direction will
  // change to reflect the acknowledgement of configure request with |serial|
  // at the next call to Commit().
  while (!pending_configs_.empty()) {
    std::unique_ptr<Config> config = std::move(pending_configs_.front());
    pending_configs_.pop_front();

    // Add the config offset to the accumulated offset that will be applied when
    // Commit() is called.
    pending_origin_offset_ += config->origin_offset;
    // Set the resize direction that will be applied when Commit() is called.
    pending_resize_component_ = config->resize_component;

    if (config->serial == serial) {
      // `config` needs to stay alive until the next Commit() call.
      config_waiting_for_commit_ = std::move(config);
      break;
    }
  }

  for (auto& observer : observers_)
    observer.OnAcknowledgeConfigure(serial);

  // Shadow bounds update should be called in the next Commit() when applying
  // config instead of updating right when the client acknowledge the config.
}

void ShellSurface::SetParent(ShellSurface* parent) {
  TRACE_EVENT1("exo", "ShellSurface::SetParent", "parent",
               parent ? base::UTF16ToASCII(parent->GetWindowTitle()) : "null");
  SetParentWindow(parent ? parent->GetWidget()->GetNativeWindow() : nullptr);
}

bool ShellSurface::CanMaximize() const {
  // Prevent non-resizable windows being resized via maximize.
  return ShellSurfaceBase::CanMaximize() && CanResize();
}

void ShellSurface::Maximize() {
  TRACE_EVENT0("exo", "ShellSurface::Maximize");

  if (!widget_) {
    if (initial_show_state_ != ui::mojom::WindowShowState::kFullscreen ||
        ShouldExitFullscreenFromRestoreOrMaximized()) {
      initial_show_state_ = ui::mojom::WindowShowState::kMaximized;
    }
    return;
  }

  if (!widget_->IsFullscreen() ||
      ShouldExitFullscreenFromRestoreOrMaximized()) {
    // Note: This will ask client to configure its surface even if already
    // maximized.
    ScopedConfigure scoped_configure(this, true);
    widget_->Maximize();
  }
}

void ShellSurface::Minimize() {
  TRACE_EVENT0("exo", "ShellSurface::Minimize");

  if (!widget_) {
    initial_show_state_ = ui::mojom::WindowShowState::kMinimized;
    return;
  }

  // Note: This will ask client to configure its surface even if already
  // minimized.
  ScopedConfigure scoped_configure(this, true);
  widget_->Minimize();
}

void ShellSurface::Restore() {
  TRACE_EVENT0("exo", "ShellSurface::Restore");

  if (!widget_) {
    if (initial_show_state_ != ui::mojom::WindowShowState::kFullscreen ||
        ShouldExitFullscreenFromRestoreOrMaximized()) {
      initial_show_state_ = ui::mojom::WindowShowState::kNormal;
    }
    return;
  }

  if (!widget_->IsFullscreen() ||
      ShouldExitFullscreenFromRestoreOrMaximized()) {
    // Note: This will ask client to configure its surface even if already
    // maximized.
    ScopedConfigure scoped_configure(this, true);
    widget_->Restore();
  }
}

void ShellSurface::SetFullscreen(bool fullscreen, int64_t display_id) {
  TRACE_EVENT2("exo", "ShellSurface::SetFullscreen", "fullscreen", fullscreen,
               "display_id", display_id);
  if (!widget_) {
    if (fullscreen) {
      initial_show_state_ = ui::mojom::WindowShowState::kFullscreen;
    } else if (initial_show_state_ == ui::mojom::WindowShowState::kFullscreen) {
      initial_show_state_ = ui::mojom::WindowShowState::kDefault;
    }
    return;
  }

  // Note: This will ask client to configure its surface even if fullscreen
  // state doesn't change.
  ScopedConfigure scoped_configure(this, true);
  widget_->SetFullscreen(fullscreen, display_id);
}

void ShellSurface::SetPopup() {
  DCHECK(!widget_);
  is_popup_ = true;
}

void ShellSurface::AckRotateFocus(uint32_t serial, bool handled) {
  CHECK(!rotate_focus_inflight_requests_.empty())
      << "unexpected ack received, no requests currently inflight";

  auto request = rotate_focus_inflight_requests_.front();
  rotate_focus_inflight_requests_.pop();
  CHECK(request.serial == serial)
      << "unexpected ack requests, expected acks to be received in order. Got: "
      << serial << ", expected: " << request.serial;

  if (!handled) {
    ash::Shell::Get()->focus_cycler()->RotateFocus(
        request.direction, /*move_to_next_widget=*/true);
  }
}

void ShellSurface::Grab() {
  DCHECK(is_popup_);
  DCHECK(!widget_);
  has_grab_ = true;
}

bool ShellSurface::StartMove() {
  TRACE_EVENT0("exo", "ShellSurface::StartMove");

  if (!widget_) {
    return false;
  }

  return AttemptToStartDrag(HTCAPTION);
}

bool ShellSurface::RotatePaneFocusFromView(views::View* focused_view,
                                           bool forward,
                                           bool enable_wrapping) {
  if (rotate_focus_callback_.is_null()) {
    VLOG(1) << "no callback provided, falling back to default behaviour";
    return WidgetDelegate::RotatePaneFocusFromView(focused_view, forward,
                                                   enable_wrapping);
  }

  auto direction =
      forward ? ash::FocusCycler::FORWARD : ash::FocusCycler::BACKWARD;
  auto serial = rotate_focus_callback_.Run(direction, enable_wrapping);
  rotate_focus_inflight_requests_.push({
      serial,
      direction,
  });
  return true;
}

bool ShellSurface::StartResize(int component) {
  TRACE_EVENT1("exo", "ShellSurface::StartResize", "component", component);

  if (!widget_) {
    return false;
  }

  return AttemptToStartDrag(component);
}

void ShellSurface::AddObserver(ShellSurfaceObserver* observer) {
  observers_.AddObserver(observer);
}

void ShellSurface::RemoveObserver(ShellSurfaceObserver* observer) {
  observers_.RemoveObserver(observer);
}

void ShellSurface::MaybeSetCompositorLockForNextConfigure(int milliseconds) {
  if (!configure_callback_.is_null()) {
    ui::Compositor* compositor =
        widget_->GetNativeWindow()->layer()->GetCompositor();
    configure_compositor_lock_ = compositor->GetCompositorLock(
        nullptr, base::Milliseconds(milliseconds));
  }
}

////////////////////////////////////////////////////////////////////////////////
// SurfaceDelegate overrides:

void ShellSurface::OnSetFrame(SurfaceFrameType type) {
  ShellSurfaceBase::OnSetFrame(type);

  if (!widget_)
    return;
  widget_->GetNativeWindow()->SetProperty(
      aura::client::kUseWindowBoundsForShadow,
      frame_type_ != SurfaceFrameType::SHADOW);
}

void ShellSurface::OnSetParent(Surface* parent, const gfx::Point& position) {
  views::Widget* parent_widget =
      parent ? views::Widget::GetTopLevelWidgetForNativeView(parent->window())
             : nullptr;
  if (parent_widget) {
    // Set parent window if using one of the desks container and the container
    // itself is not the parent.
    if (ash::desks_util::IsDeskContainerId(container_))
      SetParentWindow(parent_widget->GetNativeWindow());

    origin_ = position;
    views::View::ConvertPointToScreen(
        parent_widget->widget_delegate()->GetContentsView(), &origin_);

    if (!widget_)
      return;

    ash::WindowState* window_state =
        ash::WindowState::Get(widget_->GetNativeWindow());
    if (window_state->is_dragged())
      return;

    gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen();
    gfx::Rect new_widget_bounds(origin_, widget_bounds.size());
    if (new_widget_bounds != widget_bounds) {
      base::AutoReset<bool> notify_bounds_changes(&notify_bounds_changes_,
                                                  false);
      widget_->SetBounds(new_widget_bounds);
      UpdateHostWindowOrigin();
    }
  } else {
    SetParentWindow(nullptr);
  }
}

////////////////////////////////////////////////////////////////////////////////
// SurfaceTreeHost overrides:

void ShellSurface::MaybeActivateSurface() {
  // Keep `host_window()`'s SurfaceId up to date in case it's queried elsewhere.
  host_window()->UpdateLocalSurfaceIdFromEmbeddedClient(
      GetCurrentLocalSurfaceId());

  // `GetCurrentLocalSurfaceId()` may have a newer `child_sequence_number`, b/c
  // Wayland client changed the surface hierarchy bounds or scale factor. Update
  // `old_layer` surface range s.t. the range strictly includes
  // `GetCurrentLocalSurfaceId()`.
  for (auto& config : pending_configs_) {
    if (config->old_layer) {
      UpdateLayerSurfaceRange(config->old_layer.get(),
                              GetCurrentLocalSurfaceId());
    }
  }

  // Before the first CompositorFrame is submitted by SurfaceTreeHost,
  // `host_window()`'s layer doesn't have a SurfaceId yet, so set it to embed
  // the upcoming CompositorFrame.
  if (!host_window()->layer()->GetSurfaceId()) {
    DCHECK(host_window()->GetLocalSurfaceId().parent_sequence_number() ==
               GetCurrentLocalSurfaceId().parent_sequence_number() ||
           !pending_configs_.empty());
    host_window()->layer()->SetShowSurface(
        host_window()->GetSurfaceId(), host_window()->bounds().size(),
        SK_ColorWHITE, cc::DeadlinePolicy::UseDefaultDeadline(),
        false /* stretch_content_to_fill_bounds */);
    host_window()->layer()->SetOldestAcceptableFallback(viz::SurfaceId{});
  }

  UpdateLayerSurfaceRange(host_window()->layer(), GetCurrentLocalSurfaceId());
}

ui::Layer* ShellSurface::GetCommitTargetLayer() {
  return const_cast<ui::Layer*>(
      const_cast<const ShellSurface*>(this)->GetCommitTargetLayer());
}

const ui::Layer* ShellSurface::GetCommitTargetLayer() const {
  if (!host_window()->layer()->GetSurfaceId()) {
    return host_window()->layer();
  }
  // `commit_target_layer` is the layer that will have current LSI. The order of
  // LocalSurfaceId parent_sequence_number is:
  //   GetCurrentLocalSurfaceId() <= pending_config->old_layer <= old_layer_ <=
  //   host_window()->layer() <= host_window()
  //
  // Search from newest to oldest layers, if no parent_sequence_number matches,
  // return nullptr, as the `commit_target_layer` is too old and already
  // destroyed.
  if (host_window()
          ->layer()
          ->GetSurfaceId()
          ->local_surface_id()
          .parent_sequence_number() ==
      GetCurrentLocalSurfaceId().parent_sequence_number()) {
    return host_window()->layer();
  }

  if (old_layer_ &&
      old_layer_->GetSurfaceId()->local_surface_id().parent_sequence_number() ==
          GetCurrentLocalSurfaceId().parent_sequence_number()) {
    return old_layer_.get();
  }

  for (const auto& config : base::Reversed(pending_configs_)) {
    if (config->old_layer &&
        config->old_layer->GetSurfaceId()
                ->local_surface_id()
                .parent_sequence_number() ==
            GetCurrentLocalSurfaceId().parent_sequence_number()) {
      return config->old_layer.get();
    }
  }

  return nullptr;
}

////////////////////////////////////////////////////////////////////////////////
// ShellSurfaceBase overrides:

void ShellSurface::OnSurfaceCommit() {
  // Send configure only after the effect of the commit is finalized.
  ScopedConfigure scoped_configure(this, false);
  ShellSurfaceBase::OnSurfaceCommit();
}

void ShellSurface::InitializeWindowState(ash::WindowState* window_state) {
  window_state->AddObserver(this);
  window_state->set_allow_set_bounds_direct(movement_disabled_);
  window_state->set_ignore_keyboard_bounds_change(movement_disabled_);
  widget_->set_movement_disabled(movement_disabled_);

  // If this window is a child of some window, it should be made transient.
  MaybeMakeTransient();
}

std::optional<gfx::Rect> ShellSurface::GetWidgetBounds() const {
  // Defer if configure requests are pending.
  if (!pending_configs_.empty() || scoped_configure_)
    return std::nullopt;

  gfx::Rect new_widget_bounds = GetWidgetBoundsFromVisibleBounds();

  if (movement_disabled_) {
    new_widget_bounds.set_origin(origin_);
  } else if (IsMoveComponent(resize_component_)) {
    // Preserve widget position.
    new_widget_bounds.set_origin(widget_->GetWindowBoundsInScreen().origin());
  } else {
    // Compute widget origin using surface origin if the current location of
    // surface is being anchored to one side of the widget as a result of a
    // resize operation.
    gfx::Rect visible_bounds = GetVisibleBounds();
    gfx::Point origin = GetSurfaceOrigin() + visible_bounds.OffsetFromOrigin();
    wm::ConvertPointToScreen(widget_->GetNativeWindow(), &origin);
    new_widget_bounds.set_origin(origin);
  }
  return new_widget_bounds;
}

gfx::Point ShellSurface::GetSurfaceOrigin() const {
  DCHECK(!movement_disabled_ || IsMoveComponent(resize_component_));
  gfx::Rect visible_bounds = GetVisibleBounds();
  gfx::Rect client_bounds = GetClientViewBounds();

  switch (resize_component_) {
    case HTCAPTION:
    case HTCLIENT:
      return gfx::Point() + origin_offset_ - visible_bounds.OffsetFromOrigin();
    case HTBOTTOM:
    case HTRIGHT:
    case HTBOTTOMRIGHT:
      return gfx::Point() - visible_bounds.OffsetFromOrigin();
    case HTTOP:
    case HTTOPRIGHT:
      return gfx::Point(0, client_bounds.height() - visible_bounds.height()) -
             visible_bounds.OffsetFromOrigin();
    case HTLEFT:
    case HTBOTTOMLEFT:
      return gfx::Point(client_bounds.width() - visible_bounds.width(), 0) -
             visible_bounds.OffsetFromOrigin();
    case HTTOPLEFT:
      return gfx::Point(client_bounds.width() - visible_bounds.width(),
                        client_bounds.height() - visible_bounds.height()) -
             visible_bounds.OffsetFromOrigin();
    default:
      NOTREACHED() << "Unsupported component:" << resize_component_;
  }
}

void ShellSurface::SetUseImmersiveForFullscreen(bool value) {
  ShellSurfaceBase::SetUseImmersiveForFullscreen(value);
  // Ensure that the widget has been created before attempting to configure it.
  // Otherwise, the positioning of the window could be undefined.
  if (widget_)
    Configure();
}

void ShellSurface::OnDidProcessDisplayChanges(
    const DisplayConfigurationChange& configuration_change) {
  ShellSurfaceBase::OnDidProcessDisplayChanges(configuration_change);

  // Keep client surface coordinates in sync with the server when display
  // layouts change.
  const bool should_update_window_position = std::ranges::any_of(
      configuration_change.display_metrics_changes,
      [id = output_display_id()](
          const DisplayManagerObserver::DisplayMetricsChange& change) {
        return change.display->id() == id &&
               (change.changed_metrics &
                    display::DisplayObserver::DISPLAY_METRIC_BOUNDS ||
                change.changed_metrics &
                    display::DisplayObserver::DISPLAY_METRIC_WORK_AREA);
      });
  if (widget_ && should_update_window_position) {
    OnWidgetScreenPositionChanged();
  }
}

////////////////////////////////////////////////////////////////////////////////
// aura::WindowObserver overrides:

void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
                                         const gfx::Rect& old_bounds,
                                         const gfx::Rect& new_bounds,
                                         ui::PropertyChangeReason reason) {
  if (!root_surface() || !notify_bounds_changes_) {
    return;
  }
  if (IsShellSurfaceWindow(window)) {
    auto* window_state = ash::WindowState::Get(window);
    if (window_state && window_state->is_moving_to_another_display()) {
      old_screen_bounds_for_pending_move_ = old_bounds;
      wm::ConvertRectToScreen(window->parent(),
                              &old_screen_bounds_for_pending_move_);
      return;
    }

    if (new_bounds.size() == old_bounds.size()) {
      OnWidgetScreenPositionChanged();
      return;
    }

    gfx::Vector2d delta = new_bounds.origin() - old_bounds.origin();
    origin_offset_ -= delta;
    pending_origin_offset_accumulator_ += delta;

    if (!old_layer_) {
      // If size changed then give the client a chance to produce new contents
      // before origin on screen is changed. Retain the old origin by reverting
      // the origin delta until the next configure is acknowledged.
      UpdateHostWindowOrigin();
    } else {
      // `old_layer_` means the current `host_window()->layer()`'s is cloned
      // from the `old_layer_`. In this case `host_window()->layer()`'s surface
      // dependency won't be fulfilled until corresponding configure
      // acknowledgement.
      // Synchronize bounds to it, s.t. the fallback surface looks reasonable.
      // TODO(crbug.com/40057347): Take non-zero origin introduced by geometry
      // or clipping into account.
      viz::ScopedSurfaceIdAllocator scoped_suppression =
          host_window()->GetSurfaceIdAllocator(base::NullCallback());
      host_window()->layer()->SetBounds(
          gfx::Rect(GetClientBoundsInScreen(widget_).size()));
    }

    // The shadow size may be updated to match the widget. Change it back
    // to the shadow content size. Note that this relies on
    // wm::ShadowController being notified of the change before |this|.
    UpdateShadow();

    // A window state change will send a configuration event. Avoid sending
    // two configuration events for the same change.
    if (!window_state_is_changing_) {
      // Lock when the display scale changes and we are a maximized window to
      // prevent flashes.
      if (reason != ui::PropertyChangeReason::FROM_ANIMATION &&
          ash::WindowState::Get(window)->IsMaximizedOrFullscreenOrPinned()) {
        // TODO(crbug.com/40249858): See if we can rid of the slow lock timeout
        // by adjusting the order of resize of windows to top to bottom.
        MaybeSetCompositorLockForNextConfigure(kSlowCompositorLockTimeoutMs);
      }

      Configure();
    }
  }
}

void ShellSurface::OnWindowAddedToRootWindow(aura::Window* window) {
  ShellSurfaceBase::OnWindowAddedToRootWindow(window);
  if (!IsShellSurfaceWindow(window)) {
    return;
  }
  auto* window_state = ash::WindowState::Get(window);
  if (window_state && window_state->is_moving_to_another_display() &&
      !old_screen_bounds_for_pending_move_.IsEmpty()) {
    gfx::Rect new_bounds_in_screen = window->bounds();
    wm::ConvertRectToScreen(window->parent(), &new_bounds_in_screen);

    gfx::Vector2d delta = new_bounds_in_screen.origin() -
                          old_screen_bounds_for_pending_move_.origin();
    old_screen_bounds_for_pending_move_ = gfx::Rect();
    origin_offset_ -= delta;
    pending_origin_offset_accumulator_ += delta;
    UpdateHostWindowOrigin();
    UpdateShadow();

    if (!window_state_is_changing_)
      Configure();

  } else {
    OnWidgetScreenPositionChanged();
  }
}

void ShellSurface::OnWindowPropertyChanged(aura::Window* window,
                                           const void* key,
                                           intptr_t old_value) {
  ShellSurfaceBase::OnWindowPropertyChanged(window, key, old_value);
  if (IsShellSurfaceWindow(window)) {
    if (key == chromeos::kIsShowingInOverviewKey) {
      if (!overview_change_callback_.is_null()) {
        overview_change_callback_.Run(
            window->GetProperty(chromeos::kIsShowingInOverviewKey));
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
// ash::WindowStateObserver overrides:

void ShellSurface::OnPreWindowStateTypeChange(
    ash::WindowState* window_state,
    chromeos::WindowStateType old_type) {
  window_state_is_changing_ = true;
  chromeos::WindowStateType new_type = window_state->GetStateType();
  if (chromeos::IsMinimizedWindowStateType(old_type) ||
      chromeos::IsMinimizedWindowStateType(new_type)) {
    return;
  }

  if (chromeos::IsMaximizedOrFullscreenOrPinnedWindowStateType(old_type) ||
      chromeos::IsMaximizedOrFullscreenOrPinnedWindowStateType(new_type) ||
      window_state->IsMinimized()) {
    CHECK(widget_);

    // When transitioning in/out of maximized or fullscreen mode, we need to
    // make sure we have a configure callback before we allow the default
    // cross-fade animations. The configure callback provides a mechanism for
    // the client to inform us that a frame has taken the state change into
    // account, and without this cross-fade animations are unreliable.
    if (!configure_callback_.is_null()) {
      // Give client a chance to produce a frame that takes state change into
      // account by acquiring a compositor lock.
      MaybeSetCompositorLockForNextConfigure(kDefaultCompositorLockTimeoutMs);
    } else {
      animations_disabler_ = std::make_unique<wm::ScopedAnimationDisabler>(
          widget_->GetNativeWindow());
    }
  }
}

void ShellSurface::OnPostWindowStateTypeChange(
    ash::WindowState* window_state,
    chromeos::WindowStateType old_type) {
  // Send the new state to the exo-client when the state changes. This is
  // important for client presentation. For example exo-client using client-side
  // decoration, window-state information is needed to toggle the maximize and
  // restore buttons. When the window is restored, we show a maximized button;
  // otherwise we show a restore button.
  //
  // Note that configuration events on bounds change is suppressed during state
  // change, because it is assumed that a configuration event will always be
  // sent at the end of a state change.
  Configure();

  if (widget_) {
    // This may not be necessary.
    set_bounds_is_dirty(true);
    UpdateWidgetBounds();
    UpdateShadow();
  }

  if (root_surface() && window_state->GetStateType() != old_type &&
      (IsFullscreenOrPinnedWindowStateType(window_state->GetStateType()) ||
       IsFullscreenOrPinnedWindowStateType(old_type))) {
    root_surface()->OnFullscreenStateChanged(window_state->IsFullscreen() ||
                                             window_state->IsPinned());
  }

  // Re-enable animations if they were disabled in pre state change handler.
  animations_disabler_.reset();
  window_state_is_changing_ = false;
}

////////////////////////////////////////////////////////////////////////////////
// wm::ActivationChangeObserver overrides:

void ShellSurface::OnWindowActivated(ActivationReason reason,
                                     aura::Window* gained_active,
                                     aura::Window* lost_active) {
  ShellSurfaceBase::OnWindowActivated(reason, gained_active, lost_active);

  if (!widget_)
    return;

  if (gained_active == widget_->GetNativeWindow() ||
      lost_active == widget_->GetNativeWindow()) {
    Configure();
  }
}

////////////////////////////////////////////////////////////////////////////////
// ShellSurfaceBase overrides:

gfx::Rect ShellSurface::ComputeAdjustedBounds(const gfx::Rect& bounds) const {
  DCHECK(widget_);
  auto min_size = widget_->GetMinimumSize();
  auto max_size = widget_->GetMaximumSize();
  gfx::Size size = bounds.size();
  // use `minimum_size_` as the GetMinimumSize always return min size
  // bigger or equal to 1x1.
  if (!requested_minimum_size_.IsEmpty() && !min_size.IsEmpty()) {
    size.SetToMax(min_size);
  }
  if (!max_size.IsEmpty()) {
    size.SetToMin(max_size);
  }

  // The size should never be bigger than work area, even if the min size is
  // bigger than that.
  auto work_area = display::Screen::Get()
                       ->GetDisplayNearestWindow(widget_->GetNativeWindow())
                       .work_area();
  size.SetToMin(work_area.size());

  // Keep the origin instead of center.
  return gfx::Rect(bounds.origin(), size);
}

void ShellSurface::SetWidgetBounds(const gfx::Rect& bounds,
                                   bool adjusted_by_server) {
  if (bounds == widget_->GetWindowBoundsInScreen() && !adjusted_by_server)
    return;

  // Set |notify_bounds_changes_| as this change to window bounds
  // should not result in a configure request unless the bounds is modified by
  // the server.
  DCHECK(notify_bounds_changes_);
  notify_bounds_changes_ = adjusted_by_server;

  if (IsDragged()) {
    // Do not move the root window.
    auto* window = widget_->GetNativeWindow();
    auto* screen_position_client =
        aura::client::GetScreenPositionClient(window->GetRootWindow());
    gfx::PointF origin(bounds.origin());
    screen_position_client->ConvertPointFromScreen(window->parent(), &origin);
    widget_->GetNativeWindow()->SetBounds(
        gfx::Rect(origin.x(), origin.y(), bounds.width(), bounds.height()));
  } else {
    widget_->SetBounds(bounds);
  }
  UpdateHostWindowOrigin();

  notify_bounds_changes_ = true;
}

bool ShellSurface::OnPreWidgetCommit() {
  if (!widget_ && GetEnabled()) {
    // Defer widget creation and commit until surface has contents.
    if (host_window()->bounds().IsEmpty() &&
        root_surface()->surface_hierarchy_content_bounds().IsEmpty()) {
      Configure();

      if (initial_show_state_ != ui::mojom::WindowShowState::kMinimized) {
        needs_layout_on_show_ = true;
      }
    }

    CreateShellSurfaceWidget(initial_show_state_);
  }

  // Apply the accumulated pending origin offset to reflect acknowledged
  // configure requests.
  origin_offset_ += pending_origin_offset_;
  pending_origin_offset_ = gfx::Vector2d();

  // Update resize direction to reflect acknowledged configure requests.
  resize_component_ = pending_resize_component_;

  if (config_waiting_for_commit_) {
    UpdateLocalSurfaceIdFromParent(config_waiting_for_commit_->viz_surface_id);
  }
  config_waiting_for_commit_.reset();

  return true;
}

void ShellSurface::ShowWidget(bool activate) {
  ShellSurfaceBase::ShowWidget(activate);

  // Now that the shell surface is ready, make sure it has up to date occlusion
  // state.
  CHECK(IsReady());
  occlusion_observer_->MaybeConfigure(root_surface()->window());
}

std::unique_ptr<views::FrameView> ShellSurface::CreateFrameView(
    views::Widget* widget) {
  ash::WindowState* window_state =
      ash::WindowState::Get(widget->GetNativeWindow());
  window_state->SetDelegate(std::make_unique<CustomWindowStateDelegate>(this));
  return CreateFrameViewInternal(widget);
}

void ShellSurface::SetRootSurface(Surface* root_surface) {
  ShellSurfaceBase::SetRootSurface(root_surface);
  if (root_surface) {
    occlusion_observer_.emplace(this, root_surface->window());
  }
}

////////////////////////////////////////////////////////////////////////////////
// ui::LayerOwner::Observer overrides:
void ShellSurface::OnLayerRecreated(ui::Layer* old_layer) {
  DCHECK(!old_layer_);
  // Layer recreation may happen before the first shell_surface commit with
  // content. Disregard the old_layer in this case as the old_layer can't show
  // anything.
  if (old_layer->GetSurfaceId()) {
    old_layer_ = old_layer->AsWeakPtr();
    // TODO(b/319939913): Remove this log when the issue is fixed.
    old_layer_->SetName(old_layer_->name() + "-old-has-surface");
  } else {
    old_layer->SetName(old_layer->name() + "-old-no-surface");
  }
  CHECK(old_layer->parent());
  CHECK(host_window()->layer()->parent());
}

////////////////////////////////////////////////////////////////////////////////
// ShellSurface, private:

void ShellSurface::SetParentWindow(aura::Window* new_parent) {
  if (new_parent && widget_) {
    const aura::Window* window = widget_->GetNativeWindow();
    const aura::Window* ancestor = new_parent;
    while (ancestor) {
      if (ancestor == window) {
        // Some apps try to be their own parent, e.g. crbug/1210235, or parent
        // to its ancestors, e.g., b/342265753. Ignore them to prevent chrome
        // from locking up/crashing.
        auto* app_id = GetShellApplicationId(host_window());
        LOG(WARNING) << "Client attempts to parent to itself or its transient "
                        "ancestors: app_id="
                     << app_id;
        return;
      }

      auto* transient_window_manager =
          wm::TransientWindowManager::GetIfExists(ancestor);
      ancestor = transient_window_manager
                     ? transient_window_manager->transient_parent()
                     : nullptr;
    }
  }

  if (parent()) {
    parent()->RemoveObserver(this);
    if (widget_) {
      aura::Window* child_window = widget_->GetNativeWindow();
      wm::TransientWindowManager::GetOrCreate(child_window)
          ->set_parent_controls_visibility(false);
      wm::RemoveTransientChild(parent(), child_window);
    }
  }
  SetParentInternal(new_parent);
  if (parent()) {
    parent()->AddObserver(this);
    MaybeMakeTransient();
  }
}

void ShellSurface::MaybeMakeTransient() {
  if (!parent() || !widget_)
    return;
  aura::Window* child_window = widget_->GetNativeWindow();
  wm::AddTransientChild(parent(), child_window);
  // In the case of activatable non-popups, we also want the parent to control
  // the child's visibility.
  if (!widget_->is_top_level() || !widget_->CanActivate())
    return;
  wm::TransientWindowManager::GetOrCreate(child_window)
      ->set_parent_controls_visibility(true);
}

void ShellSurface::Configure(bool ends_drag) {
  // Delay configure callback if |scoped_configure_| is set. But if
  // |widget_| is not set yet then it ignores |scoped_configure_| so that an
  // initial configure can be sent.
  if (widget_ && scoped_configure_) {
    scoped_configure_->set_needs_configure();
    return;
  }

  gfx::Vector2d origin_offset = pending_origin_offset_accumulator_;
  pending_origin_offset_accumulator_ = gfx::Vector2d();

  auto* window_state =
      widget_ ? ash::WindowState::Get(widget_->GetNativeWindow()) : nullptr;
  int resize_component = HTCAPTION;
  // If surface is being resized, save the resize direction.
  if (window_state && window_state->is_dragged() && !ends_drag)
    resize_component = window_state->drag_details()->window_component;

  uint32_t serial = 0;

  if (!configure_callback_.is_null()) {
    if (window_state) {
      auto occlusion_state = occlusion_observer_->state();
      auto restore_state_type = std::optional<chromeos::WindowStateType>{
          window_state->GetRestoreWindowState()};
      serial = configure_callback_.Run(
          GetClientBoundsInScreen(widget_), window_state->GetStateType(),
          IsResizing(), widget_->IsActive(), origin_offset,
          /*raster_scale=*/1.0, occlusion_state, restore_state_type);
    } else {
      auto state = chromeos::ToWindowStateType(initial_show_state_);
      auto occlusion_state =
          occlusion_observer_->GetInitialStateForConfigure(state);
      gfx::Rect bounds = GetInitialBoundsForState(state);
      serial = configure_callback_.Run(bounds, state, false, false,
                                       origin_offset, /*raster_scale=*/1.0,
                                       occlusion_state, std::nullopt);
    }
  }

  if (!serial) {
    pending_origin_offset_ += origin_offset;
    pending_resize_component_ = resize_component;
    return;
  }

  if (widget_ && host_window()->GetLocalSurfaceId().parent_sequence_number() !=
                     GetCurrentLocalSurfaceId().parent_sequence_number()) {
    host_window()->layer()->SetShowSurface(
        host_window()->GetSurfaceId(), GetClientBoundsInScreen(widget_).size(),
        SK_ColorWHITE, cc::DeadlinePolicy::UseDefaultDeadline(),
        /*stretch_content_to_fill_bounds=*/true);
    host_window()->layer()->SetOldestAcceptableFallback(GetSurfaceId());
  }
  // Apply origin offset and resize component at the first Commit() after this
  // configure request has been acknowledged.
  // `host_window()` is changing the window properties of `shell_surface`,
  // controlled by a wayland client. `shell_surface` needs to know that the
  // advanced LocalSurfaceId can be embedded, by looking at the config `serial`.
  pending_configs_.push_back(std::make_unique<Config>(
      serial, origin_offset, resize_component,
      host_window()->GetLocalSurfaceId(), std::move(old_layer_),
      std::move(configure_compositor_lock_)));
  LOG_IF(WARNING, pending_configs_.size() > 100)
      << "Number of pending configure acks for shell surface has reached: "
      << pending_configs_.size();

  for (auto& observer : observers_)
    observer.OnConfigure(serial);
}

bool ShellSurface::GetCanResizeFromSizeConstraints() const {
  // Both the default min and max sizes are empty and windows must be resizable
  // in that case.
  return (requested_minimum_size_.IsEmpty() ||
          requested_minimum_size_ != requested_maximum_size_);
}

bool ShellSurface::AttemptToStartDrag(int component) {
  ash::WindowState* window_state =
      ash::WindowState::Get(widget_->GetNativeWindow());

  // Ignore if surface is already being dragged.
  if (window_state->is_dragged()) {
    return true;
  }

  aura::Window* target = widget_->GetNativeWindow();
  ash::ToplevelWindowEventHandler* toplevel_handler =
      ash::Shell::Get()->toplevel_window_event_handler();
  aura::Window* mouse_pressed_handler =
      target->GetHost()->dispatcher()->mouse_pressed_handler();
  // Start dragging only if:
  // 1) touch guesture is in progress.
  // 2) mouse was pressed on the target or its subsurfaces.
  aura::Window* gesture_target = toplevel_handler->gesture_target();
  if (!gesture_target && !mouse_pressed_handler &&
      target->Contains(mouse_pressed_handler)) {
    return false;
  }

  bool started = false;

  if (gesture_target) {
    gfx::PointF location = toplevel_handler->event_location_in_gesture_target();
    aura::Window::ConvertPointToTarget(
        gesture_target, widget_->GetNativeWindow()->GetRootWindow(), &location);
    started =
        toplevel_handler->AttemptToStartDrag(target, location, component, {});
  } else {
    gfx::Point location = aura::Env::GetInstance()->last_mouse_location();
    ::wm::ConvertPointFromScreen(widget_->GetNativeWindow()->GetRootWindow(),
                                 &location);
    started = toplevel_handler->AttemptToStartDrag(
        target, gfx::PointF(location), component, {});
  }
  // Notify client that resizing state has changed.
  if (IsResizing())
    Configure();

  return started;
}

void ShellSurface::EndDrag() {
  if (!IsMoveComponent(resize_component_))
    Configure(/*ends_drag=*/true);
}

gfx::Rect ShellSurface::GetInitialBoundsForState(
    const chromeos::WindowStateType state) const {
  if (state == chromeos::WindowStateType::kMaximized) {
    return GetDisplayForInitialBounds().work_area();
  }
  if (IsFullscreenOrPinnedWindowStateType(state)) {
    return GetDisplayForInitialBounds().bounds();
  }
  if (initial_bounds_) {
    // TODO(oshima): Consider just using the `initial_bounds_`.
    return gfx::Rect(initial_bounds_->origin(), {});
  }
  return gfx::Rect();
}

display::Display ShellSurface::GetDisplayForInitialBounds() const {
  auto* screen = display::Screen::Get();
  display::Display display = screen->GetDisplayForNewWindows();
  // Use `pending_display_id_` as this is called before first commit.
  if (!screen->GetDisplayWithDisplayId(pending_display_id_, &display) &&
      initial_bounds_ && !initial_bounds_->IsEmpty()) {
    display = screen->GetDisplayMatching(*initial_bounds_);
  }
  return display;
}

void ShellSurface::UpdateLayerSurfaceRange(
    ui::Layer* layer,
    const viz::LocalSurfaceId& current_lsi) {
  auto& layer_lsi = layer->GetSurfaceId()->local_surface_id();

  DCHECK_EQ(layer_lsi.embed_token(), current_lsi.embed_token());
  // `layer` with old parent seq should be consumed by config acks and not
  // appear here.
  DCHECK_LE(
      layer_lsi.parent_sequence_number() - current_lsi.parent_sequence_number(),
      (1u << 31));
  // child seq is controlled by client so it should always be newer.
  DCHECK_LE(
      current_lsi.child_sequence_number() - layer_lsi.child_sequence_number(),
      (1u << 31));

  if (layer_lsi.parent_sequence_number() !=
      current_lsi.parent_sequence_number()) {
    // `current_lsi` is behind, specify a surface range, and stretch content.
    if (layer_lsi.child_sequence_number() !=
        current_lsi.child_sequence_number()) {
      layer->SetShowSurface(
          viz::SurfaceId(frame_sink_id_, {layer_lsi.parent_sequence_number(),
                                          current_lsi.child_sequence_number(),
                                          current_lsi.embed_token()}),
          SK_ColorWHITE, cc::DeadlinePolicy::UseDefaultDeadline(),
          true /* stretch_content_to_fill_bounds */);
    }
    layer->SetOldestAcceptableFallback(
        viz::SurfaceId(frame_sink_id_, current_lsi));
  } else {
    viz::SurfaceId surface_id(frame_sink_id_, current_lsi);
    // Update the surface only when the surface id changes or the surface still
    // have an fallback, which indicates that the change needs to be
    // synchronized due to size change or scale change.
    if (!layer->GetSurfaceId() || *layer->GetSurfaceId() != surface_id ||
        layer->GetOldestAcceptableFallback()) {
      // `current_lsi` has caught up to `layer`. Allow the shell_surface to
      // modify the surface layer bounds, clear the oldest fallback and disable
      // stretch.
      layer->SetShowSurface(surface_id, layer->bounds().size(), SK_ColorWHITE,
                            cc::DeadlinePolicy::UseDefaultDeadline(),
                            false /* stretch_content_to_fill_bounds */);
      layer->SetOldestAcceptableFallback(viz::SurfaceId{});
    }
  }
}

void ShellSurface::OnWidgetScreenPositionChanged() {
  if (!origin_change_callback_.is_null()) {
    origin_change_callback_.Run(GetClientBoundsInScreen(widget_).origin());
  }
  // Ensure the host window's origin is kept in sync with the widget.
  UpdateHostWindowOrigin();
}

}  // namespace exo
