chromium/ash/style/system_shadow_on_nine_patch_layer.cc

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

#include "ash/style/system_shadow_on_nine_patch_layer.h"

#include "ash/root_window_controller.h"
#include "ash/style/ash_color_provider_source.h"
#include "ash/style/style_util.h"
#include "ui/color/color_provider.h"
#include "ui/compositor/layer.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace ash {

// -----------------------------------------------------------------------------
// SystemShadowOnNinePatchLayer:
SystemShadowOnNinePatchLayer::~SystemShadowOnNinePatchLayer() = default;

void SystemShadowOnNinePatchLayer::SetType(SystemShadow::Type type) {
  shadow()->SetElevation(SystemShadow::GetElevationFromType(type));
}

void SystemShadowOnNinePatchLayer::SetContentBounds(const gfx::Rect& bounds) {
  shadow()->SetContentBounds(bounds);
}

void SystemShadowOnNinePatchLayer::SetRoundedCornerRadius(int corner_radius) {
  shadow()->SetRoundedCornerRadius(corner_radius);
}

void SystemShadowOnNinePatchLayer::SetRoundedCorners(
    const gfx::RoundedCornersF& rounded_corners) {
  // TODO(http://b/307326019): use corresponding interface of `ui::Shadow` when
  // available.
  NOTREACHED() << "Setting uneven rounded corners to the shadow on nine patch "
                  "layer is not ready.";
}

const gfx::Rect& SystemShadowOnNinePatchLayer::GetContentBounds() {
  return shadow()->content_bounds();
}

ui::Layer* SystemShadowOnNinePatchLayer::GetLayer() {
  return shadow()->layer();
}

ui::Layer* SystemShadowOnNinePatchLayer::GetNinePatchLayer() {
  return shadow()->shadow_layer();
}

const gfx::ShadowValues
SystemShadowOnNinePatchLayer::GetShadowValuesForTesting() const {
  return shadow()->details_for_testing()->values;
}

void SystemShadowOnNinePatchLayer::UpdateShadowColors(
    const ui::ColorProvider* color_provider) {
  shadow()->SetElevationToColorsMap(
      StyleUtil::CreateShadowElevationToColorsMap(color_provider));
}

// -----------------------------------------------------------------------------
// SystemShadowOnNinePatchLayerImpl:
SystemShadowOnNinePatchLayerImpl::SystemShadowOnNinePatchLayerImpl(
    SystemShadow::Type type,
    const LayerRecreatedCallback& layer_recreated_callback)
    : layer_recreated_callback_(layer_recreated_callback) {
  shadow_.Init(SystemShadow::GetElevationFromType(type));
  shadow_.SetShadowStyle(gfx::ShadowStyle::kChromeOSSystemUI);

  if (layer_recreated_callback) {
    shadow_observation_.Observe(&shadow_);
  }
}

SystemShadowOnNinePatchLayerImpl::~SystemShadowOnNinePatchLayerImpl() = default;

void SystemShadowOnNinePatchLayerImpl::OnLayerRecreated(ui::Layer* old_layer) {
  layer_recreated_callback_.Run(old_layer, shadow_.layer());
}

ui::Shadow* SystemShadowOnNinePatchLayerImpl::shadow() {
  return &shadow_;
}

const ui::Shadow* SystemShadowOnNinePatchLayerImpl::shadow() const {
  return &shadow_;
}

// -----------------------------------------------------------------------------
// SystemViewShadowOnNinePatchLayer:
SystemViewShadowOnNinePatchLayer::SystemViewShadowOnNinePatchLayer(
    views::View* view,
    SystemShadow::Type type)
    : view_shadow_(view, SystemShadow::GetElevationFromType(type)) {
  view_shadow_.shadow()->SetShadowStyle(gfx::ShadowStyle::kChromeOSSystemUI);
  view_observation_.Observe(view);
  if (auto* widget = view->GetWidget()) {
    ObserveColorProviderSource(widget);
  }
}

SystemViewShadowOnNinePatchLayer::~SystemViewShadowOnNinePatchLayer() = default;

void SystemViewShadowOnNinePatchLayer::SetRoundedCornerRadius(
    int corner_radius) {
  view_shadow_.SetRoundedCornerRadius(corner_radius);
}

void SystemViewShadowOnNinePatchLayer::OnViewAddedToWidget(
    views::View* observed_view) {
  ObserveColorProviderSource(observed_view->GetWidget());
}

void SystemViewShadowOnNinePatchLayer::OnViewIsDeleting(
    views::View* observed_view) {
  view_observation_.Reset();
}

void SystemViewShadowOnNinePatchLayer::SetContentBounds(
    const gfx::Rect& content_bounds) {}

ui::Shadow* SystemViewShadowOnNinePatchLayer::shadow() {
  return view_shadow_.shadow();
}

const ui::Shadow* SystemViewShadowOnNinePatchLayer::shadow() const {
  return view_shadow_.shadow();
}

// -----------------------------------------------------------------------------
// SystemWindowShadowOnNinePatchLayer:
SystemWindowShadowOnNinePatchLayer::SystemWindowShadowOnNinePatchLayer(
    aura::Window* window,
    SystemShadow::Type type)
    : SystemShadowOnNinePatchLayerImpl(type, LayerRecreatedCallback()) {
  auto* window_layer = window->layer();
  auto* shadow_layer = GetLayer();
  window_layer->Add(shadow_layer);
  window_layer->StackAtBottom(shadow_layer);
  SystemShadowOnNinePatchLayerImpl::SetContentBounds(window_layer->bounds());

  window_observation_.Observe(window);

  if (window->GetRootWindow()) {
    ObserveColorProviderSource(
        RootWindowController::ForWindow(window)->color_provider_source());
  }
}

SystemWindowShadowOnNinePatchLayer::~SystemWindowShadowOnNinePatchLayer() =
    default;

void SystemWindowShadowOnNinePatchLayer::OnWindowBoundsChanged(
    aura::Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds,
    ui::PropertyChangeReason reason) {
  SystemShadowOnNinePatchLayerImpl::SetContentBounds(
      gfx::Rect(new_bounds.size()));
}

void SystemWindowShadowOnNinePatchLayer::OnWindowDestroyed(
    aura::Window* window) {
  window_observation_.Reset();
}

void SystemWindowShadowOnNinePatchLayer::OnWindowAddedToRootWindow(
    aura::Window* window) {
  ObserveColorProviderSource(
      RootWindowController::ForWindow(window)->color_provider_source());
}

void SystemWindowShadowOnNinePatchLayer::SetContentBounds(
    const gfx::Rect& content_bounds) {}

}  // namespace ash