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 |