| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/wm/window_animations.h" | 5 #include "ash/wm/window_animations.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 const float kWindowAnimation_HideBrightnessGrayscale = 1.f; | 80 const float kWindowAnimation_HideBrightnessGrayscale = 1.f; |
| 81 const float kWindowAnimation_ShowBrightnessGrayscale = 0.f; | 81 const float kWindowAnimation_ShowBrightnessGrayscale = 0.f; |
| 82 | 82 |
| 83 const float kWindowAnimation_HideOpacity = 0.f; | 83 const float kWindowAnimation_HideOpacity = 0.f; |
| 84 const float kWindowAnimation_ShowOpacity = 1.f; | 84 const float kWindowAnimation_ShowOpacity = 1.f; |
| 85 const float kWindowAnimation_TranslateFactor = 0.025f; | 85 const float kWindowAnimation_TranslateFactor = 0.025f; |
| 86 const float kWindowAnimation_ScaleFactor = .95f; | 86 const float kWindowAnimation_ScaleFactor = .95f; |
| 87 // TODO(sky): if we end up sticking with 0, nuke the code doing the rotation. | 87 // TODO(sky): if we end up sticking with 0, nuke the code doing the rotation. |
| 88 const float kWindowAnimation_MinimizeRotate = 0.f; | 88 const float kWindowAnimation_MinimizeRotate = 0.f; |
| 89 | 89 |
| 90 // Amount windows are scaled during workspace animations. | |
| 91 const float kWorkspaceScale = .95f; | |
| 92 | |
| 93 // Tween type when cross fading a workspace window. | 90 // Tween type when cross fading a workspace window. |
| 94 const ui::Tween::Type kCrossFadeTweenType = ui::Tween::EASE_IN_OUT; | 91 const ui::Tween::Type kCrossFadeTweenType = ui::Tween::EASE_IN_OUT; |
| 95 | 92 |
| 96 int64 Round64(float f) { | 93 int64 Round64(float f) { |
| 97 return static_cast<int64>(f + 0.5f); | 94 return static_cast<int64>(f + 0.5f); |
| 98 } | 95 } |
| 99 | 96 |
| 100 base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) { | 97 base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) { |
| 101 int duration = | 98 int duration = |
| 102 window->GetProperty(kWindowVisibilityAnimationDurationKey); | 99 window->GetProperty(kWindowVisibilityAnimationDurationKey); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 311 |
| 315 // Show/Hide windows using a fade. | 312 // Show/Hide windows using a fade. |
| 316 void AnimateShowWindow_Fade(aura::Window* window) { | 313 void AnimateShowWindow_Fade(aura::Window* window) { |
| 317 AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform()); | 314 AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform()); |
| 318 } | 315 } |
| 319 | 316 |
| 320 void AnimateHideWindow_Fade(aura::Window* window) { | 317 void AnimateHideWindow_Fade(aura::Window* window) { |
| 321 AnimateHideWindowCommon(window, gfx::Transform()); | 318 AnimateHideWindowCommon(window, gfx::Transform()); |
| 322 } | 319 } |
| 323 | 320 |
| 324 // Builds the transform used when switching workspaces for the specified | |
| 325 // window. | |
| 326 gfx::Transform BuildWorkspaceSwitchTransform(aura::Window* window, | |
| 327 float scale) { | |
| 328 // Animations for transitioning workspaces scale all windows. To give the | |
| 329 // effect of scaling from the center of the screen the windows are translated. | |
| 330 gfx::Rect bounds = window->bounds(); | |
| 331 gfx::Rect parent_bounds(window->parent()->bounds()); | |
| 332 | |
| 333 float mid_x = static_cast<float>(parent_bounds.width()) / 2.0f; | |
| 334 float initial_x = | |
| 335 (static_cast<float>(bounds.x()) - mid_x) * scale + mid_x; | |
| 336 float mid_y = static_cast<float>(parent_bounds.height()) / 2.0f; | |
| 337 float initial_y = | |
| 338 (static_cast<float>(bounds.y()) - mid_y) * scale + mid_y; | |
| 339 | |
| 340 gfx::Transform transform; | |
| 341 transform.ConcatTranslate( | |
| 342 initial_x - static_cast<float>(bounds.x()), | |
| 343 initial_y - static_cast<float>(bounds.y())); | |
| 344 transform.ConcatScale(scale, scale); | |
| 345 return transform; | |
| 346 } | |
| 347 | |
| 348 void AnimateShowWindow_Workspace(aura::Window* window) { | |
| 349 gfx::Transform transform( | |
| 350 BuildWorkspaceSwitchTransform(window, kWorkspaceScale)); | |
| 351 // When we call SetOpacity here, if a hide sequence is already running, | |
| 352 // the default animation preemption strategy fast forwards the hide sequence | |
| 353 // to completion and notifies the WorkspaceHidingWindowAnimationObserver to | |
| 354 // set the layer to be invisible. We should call SetVisible after SetOpacity | |
| 355 // to ensure our layer is visible again. | |
| 356 window->layer()->SetOpacity(0.0f); | |
| 357 window->layer()->SetTransform(transform); | |
| 358 window->layer()->SetVisible(true); | |
| 359 | |
| 360 { | |
| 361 // Property sets within this scope will be implicitly animated. | |
| 362 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 363 | |
| 364 window->layer()->SetTransform(gfx::Transform()); | |
| 365 // Opacity animates only during the first half of the animation. | |
| 366 settings.SetTransitionDuration(settings.GetTransitionDuration() / 2); | |
| 367 window->layer()->SetOpacity(1.0f); | |
| 368 } | |
| 369 } | |
| 370 | |
| 371 void AnimateHideWindow_Workspace(aura::Window* window) { | |
| 372 gfx::Transform transform( | |
| 373 BuildWorkspaceSwitchTransform(window, kWorkspaceScale)); | |
| 374 window->layer()->SetOpacity(1.0f); | |
| 375 window->layer()->SetTransform(gfx::Transform()); | |
| 376 | |
| 377 // Opacity animates from 1 to 0 only over the second half of the animation. To | |
| 378 // get this functionality two animations are schedule for opacity, the first | |
| 379 // from 1 to 1 (which effectively does nothing) the second from 1 to 0. | |
| 380 // Because we're scheduling two animations of the same property we need to | |
| 381 // change the preemption strategy. | |
| 382 ui::LayerAnimator* animator = window->layer()->GetAnimator(); | |
| 383 animator->set_preemption_strategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); | |
| 384 { | |
| 385 // Property sets within this scope will be implicitly animated. | |
| 386 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 387 // Add an observer that sets visibility of the layer to false once animation | |
| 388 // completes. | |
| 389 settings.AddObserver(new WorkspaceHidingWindowAnimationObserver(window)); | |
| 390 window->layer()->SetTransform(transform); | |
| 391 settings.SetTransitionDuration(settings.GetTransitionDuration() / 2); | |
| 392 window->layer()->SetOpacity(1.0f); | |
| 393 window->layer()->SetOpacity(0.0f); | |
| 394 } | |
| 395 animator->set_preemption_strategy( | |
| 396 ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET); | |
| 397 } | |
| 398 | |
| 399 gfx::Rect GetMinimizeRectForWindow(aura::Window* window) { | 321 gfx::Rect GetMinimizeRectForWindow(aura::Window* window) { |
| 400 gfx::Rect target_bounds = Shell::GetInstance()->launcher()-> | 322 gfx::Rect target_bounds = Shell::GetInstance()->launcher()-> |
| 401 GetScreenBoundsOfItemIconForWindow(window); | 323 GetScreenBoundsOfItemIconForWindow(window); |
| 402 if (target_bounds.IsEmpty()) { | 324 if (target_bounds.IsEmpty()) { |
| 403 // Assume the launcher is overflowed, zoom off to the bottom right of the | 325 // Assume the launcher is overflowed, zoom off to the bottom right of the |
| 404 // work area. | 326 // work area. |
| 405 gfx::Rect work_area = | 327 gfx::Rect work_area = |
| 406 Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); | 328 Shell::GetScreen()->GetDisplayNearestWindow(window).work_area(); |
| 407 target_bounds.SetRect(work_area.right(), work_area.bottom(), 0, 0); | 329 target_bounds.SetRect(work_area.right(), work_area.bottom(), 0, 0); |
| 408 } | 330 } |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 switch (GetWindowVisibilityAnimationType(window)) { | 498 switch (GetWindowVisibilityAnimationType(window)) { |
| 577 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: | 499 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: |
| 578 AnimateShowWindow_Drop(window); | 500 AnimateShowWindow_Drop(window); |
| 579 return true; | 501 return true; |
| 580 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: | 502 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: |
| 581 AnimateShowWindow_Vertical(window); | 503 AnimateShowWindow_Vertical(window); |
| 582 return true; | 504 return true; |
| 583 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: | 505 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: |
| 584 AnimateShowWindow_Fade(window); | 506 AnimateShowWindow_Fade(window); |
| 585 return true; | 507 return true; |
| 586 case WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_SHOW: | |
| 587 AnimateShowWindow_Workspace(window); | |
| 588 return true; | |
| 589 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: | 508 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: |
| 590 AnimateShowWindow_Minimize(window); | 509 AnimateShowWindow_Minimize(window); |
| 591 return true; | 510 return true; |
| 592 case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: | 511 case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: |
| 593 AnimateShowWindow_BrightnessGrayscale(window); | 512 AnimateShowWindow_BrightnessGrayscale(window); |
| 594 return true; | 513 return true; |
| 595 default: | 514 default: |
| 596 NOTREACHED(); | 515 NOTREACHED(); |
| 597 return false; | 516 return false; |
| 598 } | 517 } |
| 599 } | 518 } |
| 600 | 519 |
| 601 bool AnimateHideWindow(aura::Window* window) { | 520 bool AnimateHideWindow(aura::Window* window) { |
| 602 if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) | 521 if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) |
| 603 return false; | 522 return false; |
| 604 | 523 |
| 605 switch (GetWindowVisibilityAnimationType(window)) { | 524 switch (GetWindowVisibilityAnimationType(window)) { |
| 606 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: | 525 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: |
| 607 AnimateHideWindow_Drop(window); | 526 AnimateHideWindow_Drop(window); |
| 608 return true; | 527 return true; |
| 609 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: | 528 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: |
| 610 AnimateHideWindow_Vertical(window); | 529 AnimateHideWindow_Vertical(window); |
| 611 return true; | 530 return true; |
| 612 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: | 531 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: |
| 613 AnimateHideWindow_Fade(window); | 532 AnimateHideWindow_Fade(window); |
| 614 return true; | 533 return true; |
| 615 case WINDOW_VISIBILITY_ANIMATION_TYPE_WORKSPACE_HIDE: | |
| 616 AnimateHideWindow_Workspace(window); | |
| 617 return true; | |
| 618 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: | 534 case WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE: |
| 619 AnimateHideWindow_Minimize(window); | 535 AnimateHideWindow_Minimize(window); |
| 620 return true; | 536 return true; |
| 621 case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: | 537 case WINDOW_VISIBILITY_ANIMATION_TYPE_BRIGHTNESS_GRAYSCALE: |
| 622 AnimateHideWindow_BrightnessGrayscale(window); | 538 AnimateHideWindow_BrightnessGrayscale(window); |
| 623 return true; | 539 return true; |
| 624 default: | 540 default: |
| 625 NOTREACHED(); | 541 NOTREACHED(); |
| 626 return false; | 542 return false; |
| 627 } | 543 } |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 | 751 |
| 836 CrossFadeImpl(window, old_layer, internal::kCrossFadeTweenType); | 752 CrossFadeImpl(window, old_layer, internal::kCrossFadeTweenType); |
| 837 } | 753 } |
| 838 | 754 |
| 839 TimeDelta GetCrossFadeDuration(const gfx::Rect& old_bounds, | 755 TimeDelta GetCrossFadeDuration(const gfx::Rect& old_bounds, |
| 840 const gfx::Rect& new_bounds) { | 756 const gfx::Rect& new_bounds) { |
| 841 if (CommandLine::ForCurrentProcess()->HasSwitch( | 757 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 842 ash::switches::kAshWindowAnimationsDisabled)) | 758 ash::switches::kAshWindowAnimationsDisabled)) |
| 843 return base::TimeDelta(); | 759 return base::TimeDelta(); |
| 844 | 760 |
| 845 const int min_time_ms = internal::WorkspaceController::IsWorkspace2Enabled() ? | |
| 846 internal::kWorkspaceSwitchTimeMS : 0; | |
| 847 int old_area = old_bounds.width() * old_bounds.height(); | 761 int old_area = old_bounds.width() * old_bounds.height(); |
| 848 int new_area = new_bounds.width() * new_bounds.height(); | 762 int new_area = new_bounds.width() * new_bounds.height(); |
| 849 int max_area = std::max(old_area, new_area); | 763 int max_area = std::max(old_area, new_area); |
| 850 // Avoid divide by zero. | 764 // Avoid divide by zero. |
| 851 if (max_area == 0) | 765 if (max_area == 0) |
| 852 return TimeDelta::FromMilliseconds(min_time_ms); | 766 return TimeDelta::FromMilliseconds(internal::kWorkspaceSwitchTimeMS); |
| 853 | 767 |
| 854 int delta_area = std::abs(old_area - new_area); | 768 int delta_area = std::abs(old_area - new_area); |
| 855 // If the area didn't change, the animation is instantaneous. | 769 // If the area didn't change, the animation is instantaneous. |
| 856 if (delta_area == 0) | 770 if (delta_area == 0) |
| 857 return TimeDelta::FromMilliseconds(min_time_ms); | 771 return TimeDelta::FromMilliseconds(internal::kWorkspaceSwitchTimeMS); |
| 858 | 772 |
| 859 float factor = | 773 float factor = |
| 860 static_cast<float>(delta_area) / static_cast<float>(max_area); | 774 static_cast<float>(delta_area) / static_cast<float>(max_area); |
| 861 const float kRange = internal::kCrossFadeDurationMaxMs - | 775 const float kRange = internal::kCrossFadeDurationMaxMs - |
| 862 internal::kCrossFadeDurationMinMs; | 776 internal::kCrossFadeDurationMinMs; |
| 863 return TimeDelta::FromMilliseconds( | 777 return TimeDelta::FromMilliseconds( |
| 864 internal::Round64(internal::kCrossFadeDurationMinMs + (factor * kRange))); | 778 internal::Round64(internal::kCrossFadeDurationMinMs + (factor * kRange))); |
| 865 } | 779 } |
| 866 | 780 |
| 867 namespace internal { | 781 namespace internal { |
| 868 | 782 |
| 869 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { | 783 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { |
| 870 if (window->GetProperty(aura::client::kAnimationsDisabledKey) || | 784 if (window->GetProperty(aura::client::kAnimationsDisabledKey) || |
| 871 CommandLine::ForCurrentProcess()->HasSwitch( | 785 CommandLine::ForCurrentProcess()->HasSwitch( |
| 872 switches::kAshWindowAnimationsDisabled)) { | 786 switches::kAshWindowAnimationsDisabled)) { |
| 873 return false; | 787 return false; |
| 874 } | 788 } |
| 875 if (visible) { | 789 if (visible) { |
| 876 return AnimateShowWindow(window); | 790 return AnimateShowWindow(window); |
| 877 } else { | 791 } else { |
| 878 // Don't start hiding the window again if it's already being hidden. | 792 // Don't start hiding the window again if it's already being hidden. |
| 879 return window->layer()->GetTargetOpacity() != 0.0f && | 793 return window->layer()->GetTargetOpacity() != 0.0f && |
| 880 AnimateHideWindow(window); | 794 AnimateHideWindow(window); |
| 881 } | 795 } |
| 882 } | 796 } |
| 883 | 797 |
| 884 } // namespace internal | 798 } // namespace internal |
| 885 } // namespace ash | 799 } // namespace ash |
| OLD | NEW |