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 5#include "ash/wm/session_state_animator_impl.h" 6 7#include <vector> 8 9#include "ash/shell.h" 10#include "ash/shell_window_ids.h" 11#include "ash/wm/window_animations.h" 12#include "ui/aura/client/aura_constants.h" 13#include "ui/aura/window_event_dispatcher.h" 14#include "ui/compositor/layer_animation_observer.h" 15#include "ui/compositor/layer_animation_sequence.h" 16#include "ui/compositor/scoped_layer_animation_settings.h" 17#include "ui/views/widget/widget.h" 18 19namespace ash { 20namespace { 21 22// Slightly-smaller size that we scale the screen down to for the pre-lock and 23// pre-shutdown states. 24const float kSlowCloseSizeRatio = 0.95f; 25 26// Maximum opacity of white layer when animating pre-shutdown state. 27const float kPartialFadeRatio = 0.3f; 28 29// Minimum size. Not zero as it causes numeric issues. 30const float kMinimumScale = 1e-4f; 31 32// Returns the primary root window's container. 33aura::Window* GetBackground() { 34 aura::Window* root_window = Shell::GetPrimaryRootWindow(); 35 return Shell::GetContainer(root_window, 36 kShellWindowId_DesktopBackgroundContainer); 37} 38 39// Returns the transform that should be applied to containers for the slow-close 40// animation. 41gfx::Transform GetSlowCloseTransform() { 42 gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); 43 gfx::Transform transform; 44 transform.Translate( 45 floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.width() + 0.5), 46 floor(0.5 * (1.0 - kSlowCloseSizeRatio) * root_size.height() + 0.5)); 47 transform.Scale(kSlowCloseSizeRatio, kSlowCloseSizeRatio); 48 return transform; 49} 50 51// Returns the transform that should be applied to containers for the fast-close 52// animation. 53gfx::Transform GetFastCloseTransform() { 54 gfx::Size root_size = Shell::GetPrimaryRootWindow()->bounds().size(); 55 gfx::Transform transform; 56 57 transform.Translate(floor(0.5 * root_size.width() + 0.5), 58 floor(0.5 * root_size.height() + 0.5)); 59 transform.Scale(kMinimumScale, kMinimumScale); 60 return transform; 61} 62 63// Slowly shrinks |window| to a slightly-smaller size. 64void StartSlowCloseAnimationForWindow(aura::Window* window, 65 base::TimeDelta duration, 66 ui::LayerAnimationObserver* observer) { 67 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 68 animator->set_preemption_strategy( 69 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 70 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 71 ui::LayerAnimationElement::CreateTransformElement( 72 GetSlowCloseTransform(), 73 duration)); 74 if (observer) 75 sequence->AddObserver(observer); 76 animator->StartAnimation(sequence); 77} 78 79// Quickly undoes the effects of the slow-close animation on |window|. 80void StartUndoSlowCloseAnimationForWindow( 81 aura::Window* window, 82 base::TimeDelta duration, 83 ui::LayerAnimationObserver* observer) { 84 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 85 animator->set_preemption_strategy( 86 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 87 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 88 ui::LayerAnimationElement::CreateTransformElement( 89 gfx::Transform(), 90 duration)); 91 if (observer) 92 sequence->AddObserver(observer); 93 animator->StartAnimation(sequence); 94} 95 96// Quickly shrinks |window| down to a point in the center of the screen and 97// fades it out to 0 opacity. 98void StartFastCloseAnimationForWindow(aura::Window* window, 99 base::TimeDelta duration, 100 ui::LayerAnimationObserver* observer) { 101 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 102 animator->set_preemption_strategy( 103 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 104 animator->StartAnimation( 105 new ui::LayerAnimationSequence( 106 ui::LayerAnimationElement::CreateTransformElement( 107 GetFastCloseTransform(), duration))); 108 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 109 ui::LayerAnimationElement::CreateOpacityElement(0.0, duration)); 110 if (observer) 111 sequence->AddObserver(observer); 112 animator->StartAnimation(sequence); 113} 114 115// Fades |window| to |target_opacity| over |duration|. 116void StartPartialFadeAnimation(aura::Window* window, 117 float target_opacity, 118 base::TimeDelta duration, 119 ui::LayerAnimationObserver* observer) { 120 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 121 animator->set_preemption_strategy( 122 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 123 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 124 ui::LayerAnimationElement::CreateOpacityElement( 125 target_opacity, duration)); 126 if (observer) 127 sequence->AddObserver(observer); 128 animator->StartAnimation(sequence); 129} 130 131// Fades |window| to |opacity| over |duration|. 132void StartOpacityAnimationForWindow(aura::Window* window, 133 float opacity, 134 base::TimeDelta duration, 135 ui::LayerAnimationObserver* observer) { 136 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 137 animator->set_preemption_strategy( 138 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 139 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 140 ui::LayerAnimationElement::CreateOpacityElement(opacity, duration)); 141 if (observer) 142 sequence->AddObserver(observer); 143 animator->StartAnimation(sequence); 144} 145 146// Makes |window| fully transparent instantaneously. 147void HideWindowImmediately(aura::Window* window, 148 ui::LayerAnimationObserver* observer) { 149 window->layer()->SetOpacity(0.0); 150 if (observer) 151 observer->OnLayerAnimationEnded(NULL); 152} 153 154// Restores |window| to its original position and scale and full opacity 155// instantaneously. 156void RestoreWindow(aura::Window* window, ui::LayerAnimationObserver* observer) { 157 window->layer()->SetTransform(gfx::Transform()); 158 window->layer()->SetOpacity(1.0); 159 if (observer) 160 observer->OnLayerAnimationEnded(NULL); 161} 162 163void HideWindow(aura::Window* window, 164 base::TimeDelta duration, 165 bool above, 166 ui::LayerAnimationObserver* observer) { 167 ui::Layer* layer = window->layer(); 168 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 169 170 settings.SetPreemptionStrategy( 171 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 172 settings.SetTransitionDuration(duration); 173 174 settings.SetTweenType(gfx::Tween::EASE_OUT); 175 SetTransformForScaleAnimation(layer, 176 above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW); 177 178 settings.SetTweenType(gfx::Tween::EASE_IN_OUT); 179 layer->SetOpacity(0.0f); 180 181 // After the animation completes snap the transform back to the identity, 182 // otherwise any one that asks for screen bounds gets a slightly scaled 183 // version. 184 settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION); 185 settings.SetTransitionDuration(base::TimeDelta()); 186 layer->SetTransform(gfx::Transform()); 187 188 // A bit of a dirty trick: we need to catch the end of the animation we don't 189 // control. So we use two facts we know: which animator will be used and the 190 // target opacity to add "Do nothing" animation sequence. 191 // Unfortunately, we can not just use empty LayerAnimationSequence, because 192 // it does not call NotifyEnded(). 193 if (observer) { 194 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 195 ui::LayerAnimationElement::CreateOpacityElement( 196 0.0, base::TimeDelta())); 197 sequence->AddObserver(observer); 198 layer->GetAnimator()->ScheduleAnimation(sequence); 199 } 200} 201 202// Animates |window| to identity transform and full opacity over |duration|. 203void TransformWindowToBaseState(aura::Window* window, 204 base::TimeDelta duration, 205 ui::LayerAnimationObserver* observer) { 206 ui::Layer* layer = window->layer(); 207 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 208 209 // Animate to target values. 210 settings.SetPreemptionStrategy( 211 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 212 settings.SetTransitionDuration(duration); 213 214 settings.SetTweenType(gfx::Tween::EASE_OUT); 215 layer->SetTransform(gfx::Transform()); 216 217 settings.SetTweenType(gfx::Tween::EASE_IN_OUT); 218 layer->SetOpacity(1.0f); 219 220 // A bit of a dirty trick: we need to catch the end of the animation we don't 221 // control. So we use two facts we know: which animator will be used and the 222 // target opacity to add "Do nothing" animation sequence. 223 // Unfortunately, we can not just use empty LayerAnimationSequence, because 224 // it does not call NotifyEnded(). 225 if (observer) { 226 ui::LayerAnimationSequence* sequence = new ui::LayerAnimationSequence( 227 ui::LayerAnimationElement::CreateOpacityElement( 228 1.0, base::TimeDelta())); 229 sequence->AddObserver(observer); 230 layer->GetAnimator()->ScheduleAnimation(sequence); 231 } 232} 233 234void ShowWindow(aura::Window* window, 235 base::TimeDelta duration, 236 bool above, 237 ui::LayerAnimationObserver* observer) { 238 ui::Layer* layer = window->layer(); 239 ui::ScopedLayerAnimationSettings settings(layer->GetAnimator()); 240 241 // Set initial state of animation 242 settings.SetPreemptionStrategy( 243 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 244 settings.SetTransitionDuration(base::TimeDelta()); 245 SetTransformForScaleAnimation(layer, 246 above ? LAYER_SCALE_ANIMATION_ABOVE : LAYER_SCALE_ANIMATION_BELOW); 247 248 TransformWindowToBaseState(window, duration, observer); 249} 250 251// Starts grayscale/brightness animation for |window| over |duration|. Target 252// value for both grayscale and brightness are specified by |target|. 253void StartGrayscaleBrightnessAnimationForWindow( 254 aura::Window* window, 255 float target, 256 base::TimeDelta duration, 257 gfx::Tween::Type tween_type, 258 ui::LayerAnimationObserver* observer) { 259 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 260 261 scoped_ptr<ui::LayerAnimationSequence> brightness_sequence( 262 new ui::LayerAnimationSequence()); 263 scoped_ptr<ui::LayerAnimationSequence> grayscale_sequence( 264 new ui::LayerAnimationSequence()); 265 266 scoped_ptr<ui::LayerAnimationElement> brightness_element( 267 ui::LayerAnimationElement::CreateBrightnessElement( 268 target, duration)); 269 brightness_element->set_tween_type(tween_type); 270 brightness_sequence->AddElement(brightness_element.release()); 271 272 scoped_ptr<ui::LayerAnimationElement> grayscale_element( 273 ui::LayerAnimationElement::CreateGrayscaleElement( 274 target, duration)); 275 grayscale_element->set_tween_type(tween_type); 276 grayscale_sequence->AddElement(grayscale_element.release()); 277 278 std::vector<ui::LayerAnimationSequence*> animations; 279 animations.push_back(brightness_sequence.release()); 280 animations.push_back(grayscale_sequence.release()); 281 282 if (observer) 283 animations[0]->AddObserver(observer); 284 285 animator->set_preemption_strategy( 286 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 287 288 animator->StartTogether(animations); 289} 290 291// Animation observer that will drop animated foreground once animation is 292// finished. It is used in when undoing shutdown animation. 293class CallbackAnimationObserver : public ui::LayerAnimationObserver { 294 public: 295 explicit CallbackAnimationObserver(base::Closure callback) 296 : callback_(callback) { 297 } 298 virtual ~CallbackAnimationObserver() { 299 } 300 301 private: 302 // Overridden from ui::LayerAnimationObserver: 303 virtual void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) 304 OVERRIDE { 305 // Drop foreground once animation is over. 306 callback_.Run(); 307 delete this; 308 } 309 310 virtual void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) 311 OVERRIDE { 312 // Drop foreground once animation is over. 313 callback_.Run(); 314 delete this; 315 } 316 317 virtual void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) 318 OVERRIDE {} 319 320 base::Closure callback_; 321 322 DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver); 323}; 324 325 326bool IsLayerAnimated(ui::Layer* layer, 327 SessionStateAnimator::AnimationType type) { 328 switch (type) { 329 case SessionStateAnimator::ANIMATION_PARTIAL_CLOSE: 330 if (layer->GetTargetTransform() != GetSlowCloseTransform()) 331 return false; 332 break; 333 case SessionStateAnimator::ANIMATION_UNDO_PARTIAL_CLOSE: 334 if (layer->GetTargetTransform() != gfx::Transform()) 335 return false; 336 break; 337 case SessionStateAnimator::ANIMATION_FULL_CLOSE: 338 if (layer->GetTargetTransform() != GetFastCloseTransform() || 339 layer->GetTargetOpacity() > 0.0001) 340 return false; 341 break; 342 case SessionStateAnimator::ANIMATION_FADE_IN: 343 if (layer->GetTargetOpacity() < 0.9999) 344 return false; 345 break; 346 case SessionStateAnimator::ANIMATION_FADE_OUT: 347 if (layer->GetTargetOpacity() > 0.0001) 348 return false; 349 break; 350 case SessionStateAnimator::ANIMATION_HIDE_IMMEDIATELY: 351 if (layer->GetTargetOpacity() > 0.0001) 352 return false; 353 break; 354 case SessionStateAnimator::ANIMATION_RESTORE: 355 if (layer->opacity() < 0.9999 || layer->transform() != gfx::Transform()) 356 return false; 357 break; 358 case SessionStateAnimator::ANIMATION_GRAYSCALE_BRIGHTNESS: 359 if ((layer->GetTargetBrightness() < 0.9999) || 360 (layer->GetTargetGrayscale() < 0.9999)) 361 return false; 362 break; 363 case SessionStateAnimator::ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS: 364 if ((layer->GetTargetBrightness() > 0.0001) || 365 (layer->GetTargetGrayscale() > 0.0001)) 366 return false; 367 break; 368 case SessionStateAnimator::ANIMATION_DROP: 369 case SessionStateAnimator::ANIMATION_UNDO_LIFT: 370 //ToDo(antim) : check other effects 371 if (layer->GetTargetOpacity() < 0.9999) 372 return false; 373 break; 374 //ToDo(antim) : check other effects 375 case SessionStateAnimator::ANIMATION_LIFT: 376 if (layer->GetTargetOpacity() > 0.0001) 377 return false; 378 break; 379 case SessionStateAnimator::ANIMATION_RAISE_TO_SCREEN: 380 //ToDo(antim) : check other effects 381 if (layer->GetTargetOpacity() < 0.9999) 382 return false; 383 break; 384 //ToDo(antim) : check other effects 385 case SessionStateAnimator::ANIMATION_LOWER_BELOW_SCREEN: 386 if (layer->GetTargetOpacity() > 0.0001) 387 return false; 388 break; 389 default: 390 NOTREACHED() << "Unhandled animation type " << type; 391 return false; 392 } 393 return true; 394} 395 396} // namespace 397 398// This observer is intended to use in cases when some action has to be taken 399// once some animation successfully completes (i.e. it was not aborted). 400// Observer will count a number of sequences it is attached to, and a number of 401// finished sequences (either Ended or Aborted). Once these two numbers are 402// equal, observer will delete itself, calling callback passed to constructor if 403// there were no aborted animations. 404// This way it can be either used to wait for some animation to be finished in 405// multiple layers, to wait once a sequence of animations is finished in one 406// layer or the mixture of both. 407class SessionStateAnimatorImpl::AnimationSequence 408 : public SessionStateAnimator::AnimationSequence, 409 public ui::LayerAnimationObserver { 410 public: 411 explicit AnimationSequence( 412 SessionStateAnimatorImpl* animator, 413 base::Closure callback) 414 : SessionStateAnimator::AnimationSequence(callback), 415 animator_(animator), 416 sequences_attached_(0), 417 sequences_completed_(0) { 418 } 419 420 // SessionStateAnimator::AnimationSequence: 421 virtual void StartAnimation( 422 int container_mask, 423 SessionStateAnimator::AnimationType type, 424 SessionStateAnimator::AnimationSpeed speed) OVERRIDE { 425 animator_->StartAnimationInSequence(container_mask, type, speed, this); 426 } 427 428 private: 429 virtual ~AnimationSequence() {} 430 431 // ui::LayerAnimationObserver: 432 virtual void OnLayerAnimationEnded( 433 ui::LayerAnimationSequence* sequence) OVERRIDE { 434 sequences_completed_++; 435 if (sequences_completed_ == sequences_attached_) 436 OnAnimationCompleted(); 437 } 438 439 virtual void OnLayerAnimationAborted( 440 ui::LayerAnimationSequence* sequence) OVERRIDE { 441 sequences_completed_++; 442 if (sequences_completed_ == sequences_attached_) 443 OnAnimationAborted(); 444 } 445 446 virtual void OnLayerAnimationScheduled( 447 ui::LayerAnimationSequence* sequence) OVERRIDE {} 448 449 virtual void OnAttachedToSequence( 450 ui::LayerAnimationSequence* sequence) OVERRIDE { 451 LayerAnimationObserver::OnAttachedToSequence(sequence); 452 sequences_attached_++; 453 } 454 455 SessionStateAnimatorImpl* animator_; // not owned 456 457 // Number of sequences this observer was attached to. 458 int sequences_attached_; 459 460 // Number of sequences either ended or aborted. 461 int sequences_completed_; 462 463 DISALLOW_COPY_AND_ASSIGN(AnimationSequence); 464}; 465 466bool SessionStateAnimatorImpl::TestApi::ContainersAreAnimated( 467 int container_mask, AnimationType type) const { 468 aura::Window::Windows containers; 469 animator_->GetContainers(container_mask, &containers); 470 for (aura::Window::Windows::const_iterator it = containers.begin(); 471 it != containers.end(); ++it) { 472 aura::Window* window = *it; 473 ui::Layer* layer = window->layer(); 474 if (!IsLayerAnimated(layer, type)) 475 return false; 476 } 477 return true; 478} 479 480bool SessionStateAnimatorImpl::TestApi::RootWindowIsAnimated(AnimationType type) 481 const { 482 aura::Window* root_window = Shell::GetPrimaryRootWindow(); 483 ui::Layer* layer = root_window->layer(); 484 return IsLayerAnimated(layer, type); 485} 486 487SessionStateAnimatorImpl::SessionStateAnimatorImpl() { 488} 489 490SessionStateAnimatorImpl::~SessionStateAnimatorImpl() { 491} 492 493// Fills |containers| with the containers described by |container_mask|. 494void SessionStateAnimatorImpl::GetContainers(int container_mask, 495 aura::Window::Windows* containers) { 496 aura::Window* root_window = Shell::GetPrimaryRootWindow(); 497 containers->clear(); 498 499 if (container_mask & ROOT_CONTAINER) { 500 containers->push_back(Shell::GetPrimaryRootWindow()); 501 } 502 503 if (container_mask & DESKTOP_BACKGROUND) { 504 containers->push_back(Shell::GetContainer( 505 root_window, kShellWindowId_DesktopBackgroundContainer)); 506 } 507 if (container_mask & LAUNCHER) { 508 containers->push_back( 509 Shell::GetContainer(root_window, kShellWindowId_ShelfContainer)); 510 } 511 if (container_mask & NON_LOCK_SCREEN_CONTAINERS) { 512 // TODO(antrim): Figure out a way to eliminate a need to exclude launcher 513 // in such way. 514 aura::Window* non_lock_screen_containers = Shell::GetContainer( 515 root_window, kShellWindowId_NonLockScreenContainersContainer); 516 aura::Window::Windows children = non_lock_screen_containers->children(); 517 518 for (aura::Window::Windows::const_iterator it = children.begin(); 519 it != children.end(); ++it) { 520 aura::Window* window = *it; 521 if (window->id() == kShellWindowId_ShelfContainer) 522 continue; 523 containers->push_back(window); 524 } 525 } 526 if (container_mask & LOCK_SCREEN_BACKGROUND) { 527 containers->push_back(Shell::GetContainer( 528 root_window, kShellWindowId_LockScreenBackgroundContainer)); 529 } 530 if (container_mask & LOCK_SCREEN_CONTAINERS) { 531 containers->push_back(Shell::GetContainer( 532 root_window, kShellWindowId_LockScreenContainersContainer)); 533 } 534 if (container_mask & LOCK_SCREEN_RELATED_CONTAINERS) { 535 containers->push_back(Shell::GetContainer( 536 root_window, kShellWindowId_LockScreenRelatedContainersContainer)); 537 } 538} 539 540void SessionStateAnimatorImpl::StartAnimation(int container_mask, 541 AnimationType type, 542 AnimationSpeed speed) { 543 aura::Window::Windows containers; 544 GetContainers(container_mask, &containers); 545 for (aura::Window::Windows::const_iterator it = containers.begin(); 546 it != containers.end(); ++it) { 547 RunAnimationForWindow(*it, type, speed, NULL); 548 } 549} 550 551void SessionStateAnimatorImpl::StartAnimationWithCallback( 552 int container_mask, 553 AnimationType type, 554 AnimationSpeed speed, 555 base::Closure callback) { 556 aura::Window::Windows containers; 557 GetContainers(container_mask, &containers); 558 for (aura::Window::Windows::const_iterator it = containers.begin(); 559 it != containers.end(); ++it) { 560 ui::LayerAnimationObserver* observer = 561 new CallbackAnimationObserver(callback); 562 RunAnimationForWindow(*it, type, speed, observer); 563 } 564} 565 566SessionStateAnimator::AnimationSequence* 567 SessionStateAnimatorImpl::BeginAnimationSequence(base::Closure callback) { 568 return new AnimationSequence(this, callback); 569} 570 571bool SessionStateAnimatorImpl::IsBackgroundHidden() const { 572 return !GetBackground()->IsVisible(); 573} 574 575void SessionStateAnimatorImpl::ShowBackground() { 576 ui::ScopedLayerAnimationSettings settings( 577 GetBackground()->layer()->GetAnimator()); 578 settings.SetTransitionDuration(base::TimeDelta()); 579 GetBackground()->Show(); 580} 581 582void SessionStateAnimatorImpl::HideBackground() { 583 ui::ScopedLayerAnimationSettings settings( 584 GetBackground()->layer()->GetAnimator()); 585 settings.SetTransitionDuration(base::TimeDelta()); 586 GetBackground()->Hide(); 587} 588 589void SessionStateAnimatorImpl::StartAnimationInSequence( 590 int container_mask, 591 AnimationType type, 592 AnimationSpeed speed, 593 AnimationSequence* observer) { 594 aura::Window::Windows containers; 595 GetContainers(container_mask, &containers); 596 for (aura::Window::Windows::const_iterator it = containers.begin(); 597 it != containers.end(); ++it) { 598 RunAnimationForWindow(*it, type, speed, observer); 599 } 600} 601 602void SessionStateAnimatorImpl::RunAnimationForWindow( 603 aura::Window* window, 604 AnimationType type, 605 AnimationSpeed speed, 606 ui::LayerAnimationObserver* observer) { 607 base::TimeDelta duration = GetDuration(speed); 608 609 switch (type) { 610 case ANIMATION_PARTIAL_CLOSE: 611 StartSlowCloseAnimationForWindow(window, duration, observer); 612 break; 613 case ANIMATION_UNDO_PARTIAL_CLOSE: 614 StartUndoSlowCloseAnimationForWindow(window, duration, observer); 615 break; 616 case ANIMATION_FULL_CLOSE: 617 StartFastCloseAnimationForWindow(window, duration, observer); 618 break; 619 case ANIMATION_FADE_IN: 620 StartOpacityAnimationForWindow(window, 1.0, duration, observer); 621 break; 622 case ANIMATION_FADE_OUT: 623 StartOpacityAnimationForWindow(window, 0.0, duration, observer); 624 break; 625 case ANIMATION_HIDE_IMMEDIATELY: 626 DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE); 627 HideWindowImmediately(window, observer); 628 break; 629 case ANIMATION_RESTORE: 630 DCHECK_EQ(speed, ANIMATION_SPEED_IMMEDIATE); 631 RestoreWindow(window, observer); 632 break; 633 case ANIMATION_LIFT: 634 HideWindow(window, duration, true, observer); 635 break; 636 case ANIMATION_DROP: 637 ShowWindow(window, duration, true, observer); 638 break; 639 case ANIMATION_UNDO_LIFT: 640 TransformWindowToBaseState(window, duration, observer); 641 break; 642 case ANIMATION_RAISE_TO_SCREEN: 643 ShowWindow(window, duration, false, observer); 644 break; 645 case ANIMATION_LOWER_BELOW_SCREEN: 646 HideWindow(window, duration, false, observer); 647 break; 648 case ANIMATION_PARTIAL_FADE_IN: 649 StartPartialFadeAnimation( 650 window, kPartialFadeRatio, duration, observer); 651 break; 652 case ANIMATION_UNDO_PARTIAL_FADE_IN: 653 StartPartialFadeAnimation(window, 0.0, duration, observer); 654 break; 655 case ANIMATION_FULL_FADE_IN: 656 StartPartialFadeAnimation(window, 1.0, duration, observer); 657 break; 658 case ANIMATION_GRAYSCALE_BRIGHTNESS: 659 StartGrayscaleBrightnessAnimationForWindow( 660 window, 1.0, duration, gfx::Tween::EASE_IN, observer); 661 break; 662 case ANIMATION_UNDO_GRAYSCALE_BRIGHTNESS: 663 StartGrayscaleBrightnessAnimationForWindow( 664 window, 0.0, duration, gfx::Tween::EASE_IN_OUT, observer); 665 break; 666 } 667} 668 669} // namespace ash 670