chromium/chromecast/ui/display_settings_manager_impl.cc

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

#include "chromecast/ui/display_settings_manager_impl.h"

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "chromecast/graphics/cast_window_manager.h"
#include "chromecast/ui/display_settings/brightness_animation.h"
#include "chromecast/ui/display_settings/color_temperature_animation.h"
#include "ui/display/types/gamma_ramp_rgb_entry.h"

#if defined(USE_AURA)
#include "chromecast/browser/cast_display_configurator.h"  // nogncheck
#include "chromecast/ui/display_settings/gamma_configurator.h"
#endif  // defined(USE_AURA)

namespace chromecast {

namespace {

constexpr base::TimeDelta kAnimationDuration = base::Seconds(2);

const float kMinApiBrightness = 0.0f;
const float kMaxApiBrightness = 1.0f;
const float kDefaultApiBrightness = kMaxApiBrightness;

}  // namespace

DisplaySettingsManagerImpl::DisplaySettingsManagerImpl(
    CastWindowManager* window_manager,
    shell::CastDisplayConfigurator* display_configurator)
    : window_manager_(window_manager),
      display_configurator_(display_configurator),
#if defined(USE_AURA)
      gamma_configurator_(
          std::make_unique<GammaConfigurator>(display_configurator_)),
#endif  // defined(USE_AURA)
      brightness_(-1.0f),
      screen_power_controller_(ScreenPowerController::Create(this)),
      weak_factory_(this) {
  DCHECK(window_manager_);
#if defined(USE_AURA)
  DCHECK(display_configurator_);
#endif  // defined(USE_AURA)
}

DisplaySettingsManagerImpl::~DisplaySettingsManagerImpl() = default;

void DisplaySettingsManagerImpl::SetDelegate(
    DisplaySettingsManager::Delegate* delegate) {
  brightness_animation_ = std::make_unique<BrightnessAnimation>(delegate);
}

void DisplaySettingsManagerImpl::ResetDelegate() {
  // Skip a brightess animation to its last step and stop
  // This is important for the final brightness to be cached on reboot
  brightness_animation_.reset();
}

void DisplaySettingsManagerImpl::SetColorTemperatureConfig(
    const DisplaySettingsManager::ColorTemperatureConfig& config) {
  DCHECK(!color_temperature_animation_);
  color_temperature_animation_ = std::make_unique<ColorTemperatureAnimation>(
      display_configurator_, config);
}

void DisplaySettingsManagerImpl::SetGammaCalibration(
    const std::vector<display::GammaRampRGBEntry>& gamma) {
#if defined(USE_AURA)
  gamma_configurator_->OnCalibratedGammaLoaded(gamma);
#endif  // defined(USE_AURA)
}

void DisplaySettingsManagerImpl::NotifyBrightnessChanged(float new_brightness,
                                                         float old_brightness) {
  for (auto& observer : observers_)
    observer->OnDisplayBrightnessChanged(new_brightness);
}

void DisplaySettingsManagerImpl::SetColorInversion(bool enable) {
#if defined(USE_AURA)
  gamma_configurator_->SetColorInversion(enable);
#endif  // defined(USE_AURA)
}

void DisplaySettingsManagerImpl::AddReceiver(
    mojo::PendingReceiver<mojom::DisplaySettings> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void DisplaySettingsManagerImpl::SetScreenPowerOn(PowerToggleCallback callback) {
#if defined(USE_AURA)
  display_configurator_->EnableDisplay(std::move(callback));
#endif  // defined(USE_AURA)
}

void DisplaySettingsManagerImpl::SetScreenPowerOff(PowerToggleCallback callback) {
#if defined(USE_AURA)
  display_configurator_->DisableDisplay(std::move(callback));
#endif  // defined(USE_AURA)
}

void DisplaySettingsManagerImpl::SetScreenBrightnessOn(
    bool brightness_on,
    base::TimeDelta duration) {
  UpdateBrightness(brightness_on ? brightness_ : 0, duration);
  window_manager_->SetTouchInputDisabled(!brightness_on);
}

void DisplaySettingsManagerImpl::SetColorTemperature(float temperature) {
  DVLOG(4) << "Setting color temperature to " << temperature << " Kelvin.";
  if (!color_temperature_animation_) {
    return;
  }
  color_temperature_animation_->AnimateToNewValue(temperature,
                                                  kAnimationDuration);
}

void DisplaySettingsManagerImpl::SetColorTemperatureSmooth(
    float temperature,
    base::TimeDelta duration) {
  DVLOG(4) << "Setting color temperature to " << temperature
           << " Kelvin. Duration: " << duration;
  if (!color_temperature_animation_) {
    return;
  }
  color_temperature_animation_->AnimateToNewValue(temperature, duration);
}

void DisplaySettingsManagerImpl::ResetColorTemperature() {
  if (!color_temperature_animation_) {
    return;
  }
  color_temperature_animation_->AnimateToNeutral(kAnimationDuration);
}

void DisplaySettingsManagerImpl::SetBrightness(float brightness) {
  SetBrightnessSmooth(brightness, base::Seconds(0));
}

void DisplaySettingsManagerImpl::SetBrightnessSmooth(float brightness,
                                                     base::TimeDelta duration) {
  if (brightness < kMinApiBrightness) {
    LOG(ERROR) << "brightness " << brightness
               << " is less than minimum brightness " << kMinApiBrightness
               << ".";
    return;
  }

  if (brightness > kMaxApiBrightness) {
    LOG(ERROR) << "brightness " << brightness
               << " is greater than maximum brightness " << kMaxApiBrightness
               << ".";
    return;
  }

  brightness_ = brightness;

  // If the screen is off, keep the new brightness but don't apply it
  if (!screen_power_controller_->IsScreenOn()) {
    return;
  }

  UpdateBrightness(brightness_, duration);
}

void DisplaySettingsManagerImpl::ResetBrightness() {
  SetBrightness(kDefaultApiBrightness);
}

void DisplaySettingsManagerImpl::SetScreenOn(bool screen_on) {
  if (screen_on) {
    screen_power_controller_->SetScreenOn();
  } else {
    screen_power_controller_->SetScreenOff();
  }
}

void DisplaySettingsManagerImpl::SetAllowScreenPowerOff(bool allow_power_off) {
  screen_power_controller_->SetAllowScreenPowerOff(allow_power_off);
}

void DisplaySettingsManagerImpl::AddDisplaySettingsObserver(
    mojo::PendingRemote<mojom::DisplaySettingsObserver> observer) {
  mojo::Remote<mojom::DisplaySettingsObserver> observer_remote(
      std::move(observer));
  observers_.Add(std::move(observer_remote));
}

void DisplaySettingsManagerImpl::UpdateBrightness(float brightness,
                                                  base::TimeDelta duration) {
  if (brightness_animation_)
    brightness_animation_->AnimateToNewValue(brightness, duration);
}

}  // namespace chromecast