window_animations.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/wm/window_animations.h"
  5. #include <math.h>
  6. #include <algorithm>
  7. #include <utility>
  8. #include <vector>
  9. #include "ash/public/cpp/metrics_util.h"
  10. #include "ash/public/cpp/window_animation_types.h"
  11. #include "ash/shelf/shelf.h"
  12. #include "ash/shell.h"
  13. #include "ash/wm/pip/pip_positioner.h"
  14. #include "ash/wm/window_util.h"
  15. #include "ash/wm/workspace_controller.h"
  16. #include "base/bind.h"
  17. #include "base/check.h"
  18. #include "base/i18n/rtl.h"
  19. #include "base/metrics/histogram_functions.h"
  20. #include "base/metrics/histogram_macros.h"
  21. #include "base/notreached.h"
  22. #include "base/time/time.h"
  23. #include "third_party/abseil-cpp/absl/types/optional.h"
  24. #include "ui/aura/client/aura_constants.h"
  25. #include "ui/aura/window.h"
  26. #include "ui/aura/window_observer.h"
  27. #include "ui/base/class_property.h"
  28. #include "ui/compositor/animation_throughput_reporter.h"
  29. #include "ui/compositor/compositor.h"
  30. #include "ui/compositor/compositor_observer.h"
  31. #include "ui/compositor/layer.h"
  32. #include "ui/compositor/layer_animation_observer.h"
  33. #include "ui/compositor/layer_animation_sequence.h"
  34. #include "ui/compositor/layer_animator.h"
  35. #include "ui/compositor/layer_tree_owner.h"
  36. #include "ui/compositor/scoped_layer_animation_settings.h"
  37. #include "ui/display/display.h"
  38. #include "ui/display/screen.h"
  39. #include "ui/gfx/geometry/transform.h"
  40. #include "ui/gfx/interpolated_transform.h"
  41. #include "ui/wm/core/coordinate_conversion.h"
  42. #include "ui/wm/core/window_util.h"
  43. namespace ash {
  44. namespace {
  45. const int kLayerAnimationsForMinimizeDurationMS = 200;
  46. // Amount of time for the cross fade animation.
  47. constexpr base::TimeDelta kCrossFadeDuration = base::Milliseconds(200);
  48. constexpr base::TimeDelta kCrossFadeMaxDuration = base::Milliseconds(400);
  49. // Durations for the brightness/grayscale fade animation, in milliseconds.
  50. const int kBrightnessGrayscaleFadeDurationMs = 1000;
  51. // Duration for fade in animation, in milliseconds.
  52. const int kFadeInAnimationMs = 200;
  53. // Brightness/grayscale values for hide/show window animations.
  54. const float kWindowAnimation_HideBrightnessGrayscale = 1.f;
  55. const float kWindowAnimation_ShowBrightnessGrayscale = 0.f;
  56. const float kWindowAnimation_HideOpacity = 0.f;
  57. const float kWindowAnimation_ShowOpacity = 1.f;
  58. // Duration for gfx::Tween::ZERO animation of showing window.
  59. constexpr base::TimeDelta kZeroAnimationMs = base::Milliseconds(300);
  60. constexpr char kCrossFadeSmoothness[] =
  61. "Ash.Window.AnimationSmoothness.CrossFade";
  62. base::TimeDelta GetCrossFadeDuration(aura::Window* window,
  63. const gfx::RectF& old_bounds,
  64. const gfx::Rect& new_bounds) {
  65. if (::wm::WindowAnimationsDisabled(window))
  66. return base::TimeDelta();
  67. int old_area = static_cast<int>(old_bounds.width() * old_bounds.height());
  68. int new_area = new_bounds.width() * new_bounds.height();
  69. int max_area = std::max(old_area, new_area);
  70. // Avoid divide by zero.
  71. if (max_area == 0)
  72. return kCrossFadeDuration;
  73. int delta_area = std::abs(old_area - new_area);
  74. // If the area didn't change, the animation is instantaneous.
  75. if (delta_area == 0)
  76. return kCrossFadeDuration;
  77. float factor = static_cast<float>(delta_area) / static_cast<float>(max_area);
  78. const auto kRange = kCrossFadeMaxDuration - kCrossFadeDuration;
  79. return kCrossFadeDuration + factor * kRange;
  80. }
  81. // Observer for a window cross-fade animation. If either the window closes or
  82. // the layer's animation completes, it deletes the layer and removes itself as
  83. // an observer.
  84. class CrossFadeObserver : public aura::WindowObserver,
  85. public ui::ImplicitAnimationObserver {
  86. public:
  87. // Observes |window| for destruction, but does not take ownership.
  88. // Takes ownership of |layer_owner| and its child layers.
  89. CrossFadeObserver(aura::Window* window,
  90. std::unique_ptr<ui::LayerTreeOwner> layer_owner,
  91. absl::optional<std::string> histogram_name)
  92. : window_(window),
  93. layer_(window->layer()),
  94. layer_owner_(std::move(layer_owner)) {
  95. window_->AddObserver(this);
  96. smoothness_tracker_ =
  97. layer_->GetCompositor()->RequestNewThroughputTracker();
  98. smoothness_tracker_->Start(metrics_util::ForSmoothness(base::BindRepeating(
  99. [](const absl::optional<std::string>& histogram_name, int smoothness) {
  100. if (histogram_name) {
  101. DCHECK(!histogram_name->empty());
  102. base::UmaHistogramPercentage(*histogram_name, smoothness);
  103. } else {
  104. UMA_HISTOGRAM_PERCENTAGE(kCrossFadeSmoothness, smoothness);
  105. }
  106. },
  107. std::move(histogram_name))));
  108. }
  109. CrossFadeObserver(const CrossFadeObserver&) = delete;
  110. CrossFadeObserver& operator=(const CrossFadeObserver&) = delete;
  111. ~CrossFadeObserver() override {
  112. smoothness_tracker_->Stop();
  113. smoothness_tracker_.reset();
  114. // Stop the old animator to trigger aborts or ends on any observers it may
  115. // have.
  116. layer_owner_->root()->GetAnimator()->StopAnimating();
  117. window_->RemoveObserver(this);
  118. window_ = nullptr;
  119. layer_ = nullptr;
  120. }
  121. // aura::WindowObserver:
  122. void OnWindowDestroying(aura::Window* window) override { StopAnimating(); }
  123. void OnWindowRemovingFromRootWindow(aura::Window* window,
  124. aura::Window* new_root) override {
  125. StopAnimating();
  126. }
  127. void OnWindowLayerRecreated(aura::Window* window) override {
  128. // If the window layer is recreated. |layer_| will hold the LayerAnimator we
  129. // were originally observing. Layer recreation is usually done when doing
  130. // another window animation, so stop this current one and trigger
  131. // OnImplicitAnimationsCompleted to delete ourselves.
  132. layer_->GetAnimator()->StopAnimating();
  133. }
  134. // ui::ImplicitAnimationObserver:
  135. void OnImplicitAnimationsCompleted() override { delete this; }
  136. protected:
  137. void StopAnimating() {
  138. // Trigger OnImplicitAnimationsCompleted() to be called and deletes us. If
  139. // no animation is running then do the deletion ourselves.
  140. DCHECK(window_);
  141. window_->layer()->GetAnimator()->StopAnimating();
  142. }
  143. // The window and the associated layer this observer is watching. The window
  144. // layer may be recreated during the course of the animation so |layer_| will
  145. // be different |window_->layer()| after construction.
  146. aura::Window* window_;
  147. ui::Layer* layer_;
  148. std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
  149. absl::optional<ui::ThroughputTracker> smoothness_tracker_;
  150. };
  151. // A version of CrossFadeObserver which updates its transform to match the
  152. // visible bounds of the window it is cross-fading. It is expected users of this
  153. // will not perform their own transform animation on the passed LayerTreeOwner.
  154. class CrossFadeUpdateTransformObserver
  155. : public CrossFadeObserver,
  156. public ui::CompositorAnimationObserver {
  157. public:
  158. CrossFadeUpdateTransformObserver(
  159. aura::Window* window,
  160. std::unique_ptr<ui::LayerTreeOwner> layer_owner,
  161. absl::optional<std::string> histogram_name)
  162. : CrossFadeObserver(window, std::move(layer_owner), histogram_name) {
  163. compositor_ = window->layer()->GetCompositor();
  164. compositor_->AddAnimationObserver(this);
  165. }
  166. CrossFadeUpdateTransformObserver(const CrossFadeUpdateTransformObserver&) =
  167. delete;
  168. CrossFadeUpdateTransformObserver& operator=(
  169. const CrossFadeUpdateTransformObserver&) = delete;
  170. ~CrossFadeUpdateTransformObserver() override {
  171. compositor_->RemoveAnimationObserver(this);
  172. }
  173. // CrossFadeObserver:
  174. void OnLayerAnimationStarted(ui::LayerAnimationSequence* sequence) override {
  175. DCHECK(!layer_owner_->root()->GetAnimator()->IsAnimatingProperty(
  176. ui::LayerAnimationElement::TRANSFORM));
  177. CrossFadeObserver::OnLayerAnimationStarted(sequence);
  178. }
  179. // ui::CompositorAnimationObserver:
  180. void OnAnimationStep(base::TimeTicks timestamp) override {
  181. // If these get shut down or destroyed we should delete ourselves.
  182. DCHECK(compositor_);
  183. DCHECK(window_);
  184. // Calculate the transform needed to place |layer_owner_| in the same bounds
  185. // plus transform as |window_|.
  186. gfx::RectF old_bounds(layer_owner_->root()->bounds());
  187. gfx::RectF new_bounds(window_->bounds());
  188. gfx::Transform new_transform = window_->transform();
  189. DCHECK(new_transform.IsScaleOrTranslation());
  190. // Apply the transform on the bounds to get the location of |window_|.
  191. // Transforms are calculated in a way where scale does not affect position,
  192. // so use the same logic here.
  193. gfx::RectF effective_bounds(new_bounds.size());
  194. new_transform.TransformRect(&effective_bounds);
  195. effective_bounds.set_x(effective_bounds.x() + new_bounds.x());
  196. effective_bounds.set_y(effective_bounds.y() + new_bounds.y());
  197. const gfx::Transform old_transform =
  198. gfx::TransformBetweenRects(old_bounds, effective_bounds);
  199. layer_owner_->root()->SetTransform(old_transform);
  200. }
  201. void OnCompositingShuttingDown(ui::Compositor* compositor) override {
  202. DCHECK_EQ(compositor_, compositor);
  203. StopAnimating();
  204. }
  205. private:
  206. ui::Compositor* compositor_ = nullptr;
  207. };
  208. // Internal implementation of a cross fade animation. If
  209. // |animate_old_layer_transform| is true, both new and old layers will animate
  210. // their opacities and transforms. Otherwise, the old layer will on animate its
  211. // opacity; its transforms will be updated via an observer.
  212. void CrossFadeAnimationInternal(
  213. aura::Window* window,
  214. std::unique_ptr<ui::LayerTreeOwner> old_layer_owner,
  215. bool animate_old_layer_transform,
  216. absl::optional<base::TimeDelta> duration,
  217. absl::optional<gfx::Tween::Type> tween_type,
  218. absl::optional<std::string> histogram_name) {
  219. ui::Layer* old_layer = old_layer_owner->root();
  220. ui::Layer* new_layer = window->layer();
  221. DCHECK(old_layer);
  222. const gfx::Rect old_bounds(old_layer_owner->root()->bounds());
  223. gfx::RectF old_transformed_bounds(old_bounds);
  224. gfx::Transform old_transform(old_layer_owner->root()->transform());
  225. gfx::Transform old_transform_in_root;
  226. old_transform_in_root.Translate(old_bounds.x(), old_bounds.y());
  227. old_transform_in_root.PreconcatTransform(old_transform);
  228. old_transform_in_root.Translate(-old_bounds.x(), -old_bounds.y());
  229. old_transform_in_root.TransformRect(&old_transformed_bounds);
  230. const gfx::Rect new_bounds(window->bounds());
  231. const bool old_on_top = (old_bounds.width() > new_bounds.width());
  232. // Ensure the higher-resolution layer is on top.
  233. if (old_on_top)
  234. old_layer->parent()->StackBelow(new_layer, old_layer);
  235. else
  236. old_layer->parent()->StackAbove(new_layer, old_layer);
  237. // Shorten the animation if there's not much visual movement.
  238. const base::TimeDelta animation_duration = duration.value_or(
  239. GetCrossFadeDuration(window, old_transformed_bounds, new_bounds));
  240. const gfx::Tween::Type animation_tween_type =
  241. tween_type.value_or(gfx::Tween::EASE_OUT);
  242. // Scale up the old layer while translating to new position.
  243. {
  244. ui::Layer* old_layer = old_layer_owner->root();
  245. old_layer->GetAnimator()->StopAnimating();
  246. // If Overview exit animation is in the sequence, stopping animation may
  247. // trigger `OverviewController::OnEndingAnimationComplete` which may finally
  248. // start the frame animation.
  249. // 'FrameHeader::FrameAnimatorView::StartAnimation' recreates the window
  250. // layer such that the `new_layer` is no longer the window's current layer.
  251. // Therefore, we should update the `new_layer`. Refer to
  252. // https://crbug.com/1313977.
  253. // TODO(zxdan): find a way to change the window state after exiting Overview
  254. // or avoid frame animation when setting bounds.
  255. new_layer = window->layer();
  256. old_layer->SetTransform(old_transform);
  257. ui::ScopedLayerAnimationSettings settings(old_layer->GetAnimator());
  258. settings.SetTransitionDuration(animation_duration);
  259. settings.SetTweenType(animation_tween_type);
  260. settings.DeferPaint();
  261. if (old_on_top) {
  262. // Only caching render surface when there is an opacity animation and
  263. // multiple layers.
  264. if (!old_layer->children().empty())
  265. settings.CacheRenderSurface();
  266. // The old layer is on top, and should fade out. The new layer below will
  267. // stay opaque to block the desktop.
  268. old_layer->SetOpacity(kWindowAnimation_HideOpacity);
  269. } else if (!animate_old_layer_transform) {
  270. // If |animate_old_layer_transform| and |old_on_top| are both false, then
  271. // the old layer will have no animations and the observer will delete
  272. // itself (and the old layer) right away. To make sure the old layer stays
  273. // behind the new layer with opacity 1.f for the duration of the
  274. // animation, change the tween to zero.
  275. settings.SetTweenType(gfx::Tween::ZERO);
  276. old_layer->SetOpacity(kWindowAnimation_HideOpacity);
  277. }
  278. if (animate_old_layer_transform) {
  279. gfx::Transform out_transform;
  280. float scale_x =
  281. new_bounds.width() / static_cast<float>(old_bounds.width());
  282. float scale_y =
  283. new_bounds.height() / static_cast<float>(old_bounds.height());
  284. out_transform.Translate(new_bounds.x() - old_bounds.x(),
  285. new_bounds.y() - old_bounds.y());
  286. out_transform.Scale(scale_x, scale_y);
  287. old_layer->SetTransform(out_transform);
  288. }
  289. // In tests |old_layer| is deleted here, as animations have zero duration.
  290. old_layer = nullptr;
  291. }
  292. // Set the new layer's current transform, such that the user sees a scaled
  293. // version of the window with the original bounds at the original position.
  294. gfx::Transform in_transform;
  295. const float scale_x =
  296. old_transformed_bounds.width() / static_cast<float>(new_bounds.width());
  297. const float scale_y =
  298. old_transformed_bounds.height() / static_cast<float>(new_bounds.height());
  299. in_transform.Translate(old_transformed_bounds.x() - new_bounds.x(),
  300. old_transformed_bounds.y() - new_bounds.y());
  301. in_transform.Scale(scale_x, scale_y);
  302. new_layer->SetTransform(in_transform);
  303. if (!old_on_top) {
  304. // The new layer is on top and should fade in. The old layer below will
  305. // stay opaque and block the desktop.
  306. new_layer->SetOpacity(kWindowAnimation_HideOpacity);
  307. }
  308. {
  309. // Animation observer owns the old layer and deletes itself. It should be
  310. // attached to the new layer so that if the new layer animation gets
  311. // aborted, we can delete the old layer.
  312. CrossFadeObserver* observer =
  313. animate_old_layer_transform
  314. ? new CrossFadeObserver(window, std::move(old_layer_owner),
  315. histogram_name)
  316. : new CrossFadeUpdateTransformObserver(
  317. window, std::move(old_layer_owner), histogram_name);
  318. // Animate the new layer to the identity transform, so the window goes to
  319. // its newly set bounds.
  320. ui::ScopedLayerAnimationSettings settings(new_layer->GetAnimator());
  321. settings.AddObserver(observer);
  322. settings.SetTransitionDuration(animation_duration);
  323. settings.SetTweenType(animation_tween_type);
  324. settings.DeferPaint();
  325. if (!old_on_top) {
  326. // Only caching render surface when there is an opacity animation and
  327. // multiple layers.
  328. if (!new_layer->children().empty())
  329. settings.CacheRenderSurface();
  330. // New layer is on top, fade it in.
  331. new_layer->SetOpacity(kWindowAnimation_ShowOpacity);
  332. }
  333. new_layer->SetTransform(gfx::Transform());
  334. }
  335. }
  336. } // namespace
  337. void SetTransformForScaleAnimation(ui::Layer* layer,
  338. LayerScaleAnimationDirection type) {
  339. // Scales for windows above and below the current workspace.
  340. constexpr float kLayerScaleAboveSize = 1.1f;
  341. constexpr float kLayerScaleBelowSize = .9f;
  342. const float scale = type == LAYER_SCALE_ANIMATION_ABOVE
  343. ? kLayerScaleAboveSize
  344. : kLayerScaleBelowSize;
  345. gfx::Transform transform;
  346. transform.Translate(-layer->bounds().width() * (scale - 1.0f) / 2,
  347. -layer->bounds().height() * (scale - 1.0f) / 2);
  348. transform.Scale(scale, scale);
  349. layer->SetTransform(transform);
  350. }
  351. void AddLayerAnimationsForMinimize(aura::Window* window, bool show) {
  352. // Recalculate the transform at restore time since the launcher item may have
  353. // moved while the window was minimized.
  354. gfx::Rect bounds = window->bounds();
  355. gfx::Rect target_bounds = GetMinimizeAnimationTargetBoundsInScreen(window);
  356. ::wm::ConvertRectFromScreen(window->parent(), &target_bounds);
  357. float scale_x = static_cast<float>(target_bounds.width()) / bounds.width();
  358. float scale_y = static_cast<float>(target_bounds.height()) / bounds.height();
  359. std::unique_ptr<ui::InterpolatedTransform> scale =
  360. std::make_unique<ui::InterpolatedScale>(
  361. gfx::Point3F(1, 1, 1), gfx::Point3F(scale_x, scale_y, 1));
  362. std::unique_ptr<ui::InterpolatedTransform> translation =
  363. std::make_unique<ui::InterpolatedTranslation>(
  364. gfx::PointF(), gfx::PointF(target_bounds.x() - bounds.x(),
  365. target_bounds.y() - bounds.y()));
  366. scale->SetChild(std::move(translation));
  367. scale->SetReversed(show);
  368. base::TimeDelta duration =
  369. window->layer()->GetAnimator()->GetTransitionDuration();
  370. std::unique_ptr<ui::LayerAnimationElement> transition =
  371. ui::LayerAnimationElement::CreateInterpolatedTransformElement(
  372. std::move(scale), duration);
  373. transition->set_tween_type(show ? gfx::Tween::EASE_IN
  374. : gfx::Tween::EASE_IN_OUT);
  375. window->layer()->GetAnimator()->ScheduleAnimation(
  376. new ui::LayerAnimationSequence(std::move(transition)));
  377. // When hiding a window, turn off blending until the animation is 3 / 4 done
  378. // to save bandwidth and reduce jank.
  379. if (!show) {
  380. window->layer()->GetAnimator()->SchedulePauseForProperties(
  381. (duration * 3) / 4, ui::LayerAnimationElement::OPACITY);
  382. }
  383. // Fade in and out quickly when the window is small to reduce jank.
  384. float opacity = show ? 1.0f : 0.0f;
  385. window->layer()->GetAnimator()->ScheduleAnimation(
  386. new ui::LayerAnimationSequence(
  387. ui::LayerAnimationElement::CreateOpacityElement(opacity,
  388. duration / 4)));
  389. // Reset the transform to identity when the minimize animation is completed.
  390. window->layer()->GetAnimator()->ScheduleAnimation(
  391. new ui::LayerAnimationSequence(
  392. ui::LayerAnimationElement::CreateTransformElement(
  393. gfx::Transform(), base::TimeDelta())));
  394. }
  395. void AnimateShowWindow_Minimize(aura::Window* window) {
  396. window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
  397. ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
  398. ui::AnimationThroughputReporter reporter(
  399. settings.GetAnimator(),
  400. metrics_util::ForSmoothness(
  401. base::BindRepeating(static_cast<void (*)(const char*, int)>(
  402. &base::UmaHistogramPercentage),
  403. "Ash.Window.AnimationSmoothness.Unminimize")));
  404. base::TimeDelta duration =
  405. base::Milliseconds(kLayerAnimationsForMinimizeDurationMS);
  406. settings.SetTransitionDuration(duration);
  407. AddLayerAnimationsForMinimize(window, true);
  408. // Now that the window has been restored, we need to clear its animation style
  409. // to default so that normal animation applies.
  410. ::wm::SetWindowVisibilityAnimationType(
  411. window, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
  412. }
  413. void AnimateHideWindow_Minimize(aura::Window* window) {
  414. // Property sets within this scope will be implicitly animated.
  415. ::wm::ScopedHidingAnimationSettings hiding_settings(window);
  416. // Report animation smoothness for animations created within this scope.
  417. ui::AnimationThroughputReporter reporter(
  418. hiding_settings.layer_animation_settings()->GetAnimator(),
  419. metrics_util::ForSmoothness(
  420. base::BindRepeating(static_cast<void (*)(const char*, int)>(
  421. &base::UmaHistogramPercentage),
  422. "Ash.Window.AnimationSmoothness.Minimize")));
  423. base::TimeDelta duration =
  424. base::Milliseconds(kLayerAnimationsForMinimizeDurationMS);
  425. hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
  426. window->layer()->SetVisible(false);
  427. AddLayerAnimationsForMinimize(window, false);
  428. }
  429. void AnimateShowHideWindowCommon_BrightnessGrayscale(aura::Window* window,
  430. bool show) {
  431. float start_value, end_value;
  432. if (show) {
  433. start_value = kWindowAnimation_HideBrightnessGrayscale;
  434. end_value = kWindowAnimation_ShowBrightnessGrayscale;
  435. } else {
  436. start_value = kWindowAnimation_ShowBrightnessGrayscale;
  437. end_value = kWindowAnimation_HideBrightnessGrayscale;
  438. }
  439. window->layer()->SetLayerBrightness(start_value);
  440. window->layer()->SetLayerGrayscale(start_value);
  441. if (show) {
  442. window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
  443. window->layer()->SetVisible(true);
  444. }
  445. base::TimeDelta duration =
  446. base::Milliseconds(kBrightnessGrayscaleFadeDurationMs);
  447. if (show) {
  448. ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
  449. window->layer()->GetAnimator()->ScheduleTogether(
  450. CreateBrightnessGrayscaleAnimationSequence(end_value, duration));
  451. } else {
  452. ::wm::ScopedHidingAnimationSettings hiding_settings(window);
  453. window->layer()->GetAnimator()->ScheduleTogether(
  454. CreateBrightnessGrayscaleAnimationSequence(end_value, duration));
  455. window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
  456. window->layer()->SetVisible(false);
  457. }
  458. }
  459. void AnimateShowWindow_BrightnessGrayscale(aura::Window* window) {
  460. AnimateShowHideWindowCommon_BrightnessGrayscale(window, true);
  461. }
  462. // TODO(edcourtney): Consolidate with AnimateShowWindow_Fade in ui/wm/core.
  463. void AnimateShowWindow_FadeIn(aura::Window* window) {
  464. window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
  465. ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
  466. settings.SetTransitionDuration(base::Milliseconds(kFadeInAnimationMs));
  467. window->layer()->SetVisible(true);
  468. window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
  469. }
  470. void AnimateHideWindow_BrightnessGrayscale(aura::Window* window) {
  471. AnimateShowHideWindowCommon_BrightnessGrayscale(window, false);
  472. }
  473. void AnimateHideWindow_SlideOut(aura::Window* window) {
  474. base::TimeDelta duration =
  475. base::Milliseconds(PipPositioner::kPipDismissTimeMs);
  476. ::wm::ScopedHidingAnimationSettings settings(window);
  477. settings.layer_animation_settings()->SetTransitionDuration(duration);
  478. window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
  479. window->layer()->SetVisible(false);
  480. gfx::Rect bounds = window->GetBoundsInScreen();
  481. display::Display display =
  482. display::Screen::GetScreen()->GetDisplayNearestWindow(window);
  483. gfx::Rect dismissed_bounds =
  484. PipPositioner::GetDismissedPosition(display, bounds);
  485. ::wm::ConvertRectFromScreen(window->parent(), &dismissed_bounds);
  486. window->layer()->SetBounds(dismissed_bounds);
  487. }
  488. void AnimateShowWindow_StepEnd(aura::Window* window) {
  489. window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
  490. ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
  491. settings.SetTransitionDuration(kZeroAnimationMs);
  492. settings.SetTweenType(gfx::Tween::ZERO);
  493. window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
  494. }
  495. void AnimateHideWindow_StepEnd(aura::Window* window) {
  496. ::wm::ScopedHidingAnimationSettings settings(window);
  497. settings.layer_animation_settings()->SetTransitionDuration(kZeroAnimationMs);
  498. settings.layer_animation_settings()->SetTweenType(gfx::Tween::ZERO);
  499. window->layer()->SetVisible(false);
  500. }
  501. bool AnimateShowWindow(aura::Window* window) {
  502. if (!::wm::HasWindowVisibilityAnimationTransition(window,
  503. ::wm::ANIMATE_SHOW)) {
  504. return false;
  505. }
  506. switch (::wm::GetWindowVisibilityAnimationType(window)) {
  507. case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
  508. AnimateShowWindow_Minimize(window);
  509. return true;
  510. case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE:
  511. AnimateShowWindow_BrightnessGrayscale(window);
  512. return true;
  513. case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE_IN_SLIDE_OUT:
  514. AnimateShowWindow_FadeIn(window);
  515. return true;
  516. case WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END:
  517. AnimateShowWindow_StepEnd(window);
  518. return true;
  519. default:
  520. NOTREACHED();
  521. return false;
  522. }
  523. }
  524. bool AnimateHideWindow(aura::Window* window) {
  525. if (!::wm::HasWindowVisibilityAnimationTransition(window,
  526. ::wm::ANIMATE_HIDE)) {
  527. return false;
  528. }
  529. switch (::wm::GetWindowVisibilityAnimationType(window)) {
  530. case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE:
  531. AnimateHideWindow_Minimize(window);
  532. return true;
  533. case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE:
  534. AnimateHideWindow_BrightnessGrayscale(window);
  535. return true;
  536. case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE_IN_SLIDE_OUT:
  537. AnimateHideWindow_SlideOut(window);
  538. return true;
  539. case WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END:
  540. AnimateHideWindow_StepEnd(window);
  541. return true;
  542. default:
  543. NOTREACHED();
  544. return false;
  545. }
  546. }
  547. void CrossFadeAnimation(aura::Window* window,
  548. std::unique_ptr<ui::LayerTreeOwner> old_layer_owner) {
  549. CrossFadeAnimationInternal(
  550. window, std::move(old_layer_owner), /*animate_old_layer=*/true,
  551. /*duration=*/absl::nullopt, /*tween_type=*/absl::nullopt,
  552. /*histogram_name=*/absl::nullopt);
  553. }
  554. void CrossFadeAnimationAnimateNewLayerOnly(aura::Window* window,
  555. const gfx::Rect& target_bounds,
  556. base::TimeDelta duration,
  557. gfx::Tween::Type tween_type,
  558. const std::string& histogram_name) {
  559. std::unique_ptr<ui::LayerTreeOwner> old_layer_owner =
  560. ::wm::RecreateLayers(window);
  561. window->SetBounds(target_bounds);
  562. CrossFadeAnimationInternal(window, std::move(old_layer_owner),
  563. /*animate_old_layer=*/false, duration, tween_type,
  564. histogram_name);
  565. }
  566. bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
  567. if (::wm::WindowAnimationsDisabled(window))
  568. return false;
  569. // Attempt to run CoreWm supplied animation types.
  570. if (::wm::AnimateOnChildWindowVisibilityChanged(window, visible))
  571. return true;
  572. // Otherwise try to run an Ash-specific animation.
  573. if (visible)
  574. return AnimateShowWindow(window);
  575. // Don't start hiding the window again if it's already being hidden.
  576. return window->layer()->GetTargetOpacity() != 0.0f &&
  577. AnimateHideWindow(window);
  578. }
  579. std::vector<ui::LayerAnimationSequence*>
  580. CreateBrightnessGrayscaleAnimationSequence(float target_value,
  581. base::TimeDelta duration) {
  582. gfx::Tween::Type animation_type = gfx::Tween::EASE_OUT;
  583. std::unique_ptr<ui::LayerAnimationSequence> brightness_sequence =
  584. std::make_unique<ui::LayerAnimationSequence>();
  585. std::unique_ptr<ui::LayerAnimationSequence> grayscale_sequence =
  586. std::make_unique<ui::LayerAnimationSequence>();
  587. std::unique_ptr<ui::LayerAnimationElement> brightness_element =
  588. ui::LayerAnimationElement::CreateBrightnessElement(target_value,
  589. duration);
  590. brightness_element->set_tween_type(animation_type);
  591. brightness_sequence->AddElement(std::move(brightness_element));
  592. std::unique_ptr<ui::LayerAnimationElement> grayscale_element =
  593. ui::LayerAnimationElement::CreateGrayscaleElement(target_value, duration);
  594. grayscale_element->set_tween_type(animation_type);
  595. grayscale_sequence->AddElement(std::move(grayscale_element));
  596. std::vector<ui::LayerAnimationSequence*> animations;
  597. animations.push_back(brightness_sequence.release());
  598. animations.push_back(grayscale_sequence.release());
  599. return animations;
  600. }
  601. gfx::Rect GetMinimizeAnimationTargetBoundsInScreen(aura::Window* window) {
  602. Shelf* shelf = Shelf::ForWindow(window);
  603. gfx::Rect item_rect = shelf->GetScreenBoundsOfItemIconForWindow(window);
  604. // The launcher item is visible and has an icon.
  605. if (!item_rect.IsEmpty())
  606. return item_rect;
  607. // If both the icon width and height are 0, then there is no icon in the
  608. // launcher for |window|. If the launcher is auto hidden, one of the height or
  609. // width will be 0 but the position in the launcher and the major dimension
  610. // are still reported correctly and the window can be animated to the launcher
  611. // item's light bar.
  612. if (item_rect.width() != 0 || item_rect.height() != 0) {
  613. if (shelf->GetVisibilityState() == SHELF_AUTO_HIDE) {
  614. gfx::Rect shelf_bounds = shelf->GetWindow()->GetBoundsInScreen();
  615. if (shelf->alignment() == ShelfAlignment::kLeft)
  616. item_rect.set_x(shelf_bounds.right());
  617. else if (shelf->alignment() == ShelfAlignment::kRight)
  618. item_rect.set_x(shelf_bounds.x());
  619. else
  620. item_rect.set_y(shelf_bounds.y());
  621. return item_rect;
  622. }
  623. }
  624. // Coming here, there is no visible icon of that shelf item and we zoom back
  625. // to the location of the application launcher (which is fixed as first item
  626. // of the shelf).
  627. gfx::Rect work_area =
  628. display::Screen::GetScreen()->GetDisplayNearestWindow(window).work_area();
  629. int ltr_adjusted_x = base::i18n::IsRTL() ? work_area.right() : work_area.x();
  630. switch (shelf->alignment()) {
  631. case ShelfAlignment::kBottom:
  632. case ShelfAlignment::kBottomLocked:
  633. return gfx::Rect(ltr_adjusted_x, work_area.bottom(), 0, 0);
  634. case ShelfAlignment::kLeft:
  635. return gfx::Rect(work_area.x(), work_area.y(), 0, 0);
  636. case ShelfAlignment::kRight:
  637. return gfx::Rect(work_area.right(), work_area.y(), 0, 0);
  638. }
  639. NOTREACHED();
  640. return gfx::Rect();
  641. }
  642. } // namespace ash