chromium/ash/wm/overview/scoped_overview_animation_settings.cc

// Copyright 2014 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/wm/overview/scoped_overview_animation_settings.h"

#include "ash/metrics/histogram_macros.h"
#include "ash/public/cpp/metrics_util.h"
#include "ash/wm/overview/overview_constants.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/animation/tween.h"

namespace ash {

namespace {

// The time duration for fading out when closing an item.
constexpr base::TimeDelta kCloseFadeOut = base::Milliseconds(100);

// The time duration for scaling down when an item is closed.
constexpr base::TimeDelta kCloseScale = base::Milliseconds(100);

// The time duration for widgets to fade in.
constexpr base::TimeDelta kFadeInDelay = base::Milliseconds(83);
constexpr base::TimeDelta kFadeIn = base::Milliseconds(167);

// The time duration for informed restore dialog to fade in.
constexpr base::TimeDelta kShowInformedRestoreDialog = base::Milliseconds(800);

// The time duration for widgets to fade out.
constexpr base::TimeDelta kFadeOut = base::Milliseconds(100);

// The time duration for birch bar to fade out.
constexpr base::TimeDelta kBirchBarFadeOut = base::Milliseconds(50);

constexpr base::TimeDelta kFromHomeLauncherDelay = base::Milliseconds(250);
constexpr base::TimeDelta kHomeLauncherTransition = base::Milliseconds(350);

// Time duration of the show animation of the drop target.
constexpr base::TimeDelta kDropTargetFade = base::Milliseconds(250);

// Time duration to fade in overview windows when a window drag slows down or
// stops.
constexpr base::TimeDelta kFadeInOnWindowDrag = base::Milliseconds(350);

constexpr base::TimeDelta kWindowRestoreDuration = base::Milliseconds(350);

base::TimeDelta GetAnimationDuration(OverviewAnimationType animation_type) {
  switch (animation_type) {
    case OVERVIEW_ANIMATION_NONE:
      return base::TimeDelta();
    case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN:
      return kFadeIn;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT:
      return kFadeOut;
    case OVERVIEW_ANIMATION_SHOW_INFORMED_RESTORE_DIALOG_ON_ENTER:
      return kShowInformedRestoreDialog;
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_ON_EXIT:
      return kWindowRestoreDuration;
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_ON_ENTER:
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW:
    case OVERVIEW_ANIMATION_RESTORE_WINDOW:
    case OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO:
    case OVERVIEW_ANIMATION_SPAWN_ITEM_IN_OVERVIEW:
      return kTransition;
    case OVERVIEW_ANIMATION_CLOSING_OVERVIEW_ITEM:
      return kCloseScale;
    case OVERVIEW_ANIMATION_CLOSE_OVERVIEW_ITEM:
      return kCloseFadeOut;
    case OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER:
    case OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER:
      return kHomeLauncherTransition;
    case OVERVIEW_ANIMATION_DROP_TARGET_FADE:
      return kDropTargetFade;
    case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
      return kTransition;
    case OVERVIEW_ANIMATION_OPACITY_ON_WINDOW_DRAG:
      return kFadeInOnWindowDrag;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_SAVED_DESK_GRID_FADE_OUT:
      return kFadeOut;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_BIRCH_BAR_FADE_OUT:
      return kBirchBarFadeOut;
  }
}

void ReportCloseSmoothness(int smoothness) {
  UMA_HISTOGRAM_PERCENTAGE_IN_CLAMSHELL(
      "Ash.Overview.AnimationSmoothness.Close.ClamshellMode", smoothness);
  UMA_HISTOGRAM_PERCENTAGE_IN_TABLET(
      "Ash.Overview.AnimationSmoothness.Close.TabletMode", smoothness);
}

}  // namespace

ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
    OverviewAnimationType animation_type,
    aura::Window* window)
    : ScopedOverviewAnimationSettings(animation_type,
                                      window->layer()->GetAnimator()) {}

ScopedOverviewAnimationSettings::ScopedOverviewAnimationSettings(
    OverviewAnimationType animation_type,
    ui::LayerAnimator* animator)
    : animation_settings_(
          std::make_unique<ui::ScopedLayerAnimationSettings>(animator)) {
  switch (animation_type) {
    case OVERVIEW_ANIMATION_NONE:
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
      break;
    case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN:
      animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
      animator->SchedulePauseForProperties(kFadeInDelay,
                                           ui::LayerAnimationElement::OPACITY);
      break;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_FADE_OUT:
      animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
      break;
    case OVERVIEW_ANIMATION_SHOW_INFORMED_RESTORE_DIALOG_ON_ENTER:
      animation_settings_->SetTweenType(gfx::Tween::EASE_IN_OUT_EMPHASIZED);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
      break;
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_ON_EXIT:
      animation_settings_->SetTweenType(gfx::Tween::ACCEL_20_DECEL_100);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_ON_ENTER:
    case OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW:
    case OVERVIEW_ANIMATION_RESTORE_WINDOW:
    case OVERVIEW_ANIMATION_SPAWN_ITEM_IN_OVERVIEW:
      animation_settings_->SetTweenType(gfx::Tween::EASE_OUT);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_RESTORE_WINDOW_ZERO:
      animation_settings_->SetTweenType(gfx::Tween::ZERO);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_CLOSING_OVERVIEW_ITEM:
    case OVERVIEW_ANIMATION_CLOSE_OVERVIEW_ITEM:
      animation_settings_->SetTweenType(gfx::Tween::EASE_OUT);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
      break;
    case OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER:
      animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
      // Add animation delay when entering from home launcher.
      animator->SchedulePauseForProperties(kFromHomeLauncherDelay,
                                           ui::LayerAnimationElement::OPACITY);
      break;
    case OVERVIEW_ANIMATION_EXIT_TO_HOME_LAUNCHER:
      animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
      break;
    case OVERVIEW_ANIMATION_DROP_TARGET_FADE:
      animation_settings_->SetTweenType(gfx::Tween::EASE_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_NO_RECENTS_FADE:
      animation_settings_->SetTweenType(gfx::Tween::EASE_IN_OUT);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_OPACITY_ON_WINDOW_DRAG:
      animation_settings_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_SAVED_DESK_GRID_FADE_OUT:
      animation_settings_->SetTweenType(gfx::Tween::LINEAR);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
    case OVERVIEW_ANIMATION_EXIT_OVERVIEW_MODE_BIRCH_BAR_FADE_OUT:
      animation_settings_->SetTweenType(gfx::Tween::LINEAR);
      animation_settings_->SetPreemptionStrategy(
          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
      break;
  }
  animation_settings_->SetTransitionDuration(
      GetAnimationDuration(animation_type));
  if (animation_type == OVERVIEW_ANIMATION_CLOSING_OVERVIEW_ITEM ||
      animation_type == OVERVIEW_ANIMATION_CLOSE_OVERVIEW_ITEM) {
    close_reporter_.emplace(animation_settings_->GetAnimator(),
                            metrics_util::ForSmoothnessV3(
                                base::BindRepeating(&ReportCloseSmoothness)));
  }
}

ScopedOverviewAnimationSettings::~ScopedOverviewAnimationSettings() = default;

void ScopedOverviewAnimationSettings::AddObserver(
    ui::ImplicitAnimationObserver* observer) {
  animation_settings_->AddObserver(observer);
}

void ScopedOverviewAnimationSettings::CacheRenderSurface() {
  animation_settings_->CacheRenderSurface();
}

void ScopedOverviewAnimationSettings::DeferPaint() {
  animation_settings_->DeferPaint();
}

void ScopedOverviewAnimationSettings::TrilinearFiltering() {
  animation_settings_->TrilinearFiltering();
}

ui::LayerAnimator* ScopedOverviewAnimationSettings::GetAnimator() {
  return animation_settings_->GetAnimator();
}

}  // namespace ash