| OLD | NEW |
| (Empty) |
| 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 "ui/views/corewm/window_animations.h" | |
| 6 | |
| 7 #include <math.h> | |
| 8 | |
| 9 #include <algorithm> | |
| 10 #include <vector> | |
| 11 | |
| 12 #include "base/command_line.h" | |
| 13 #include "base/compiler_specific.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/message_loop/message_loop.h" | |
| 16 #include "base/stl_util.h" | |
| 17 #include "base/time/time.h" | |
| 18 #include "ui/aura/client/animation_host.h" | |
| 19 #include "ui/aura/client/aura_constants.h" | |
| 20 #include "ui/aura/window.h" | |
| 21 #include "ui/aura/window_delegate.h" | |
| 22 #include "ui/aura/window_observer.h" | |
| 23 #include "ui/aura/window_property.h" | |
| 24 #include "ui/compositor/compositor_observer.h" | |
| 25 #include "ui/compositor/layer.h" | |
| 26 #include "ui/compositor/layer_animation_observer.h" | |
| 27 #include "ui/compositor/layer_animation_sequence.h" | |
| 28 #include "ui/compositor/layer_animator.h" | |
| 29 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 30 #include "ui/gfx/animation/animation.h" | |
| 31 #include "ui/gfx/interpolated_transform.h" | |
| 32 #include "ui/gfx/rect_conversions.h" | |
| 33 #include "ui/gfx/screen.h" | |
| 34 #include "ui/gfx/vector2d.h" | |
| 35 #include "ui/gfx/vector3d_f.h" | |
| 36 #include "ui/views/corewm/corewm_switches.h" | |
| 37 #include "ui/views/corewm/window_util.h" | |
| 38 | |
| 39 DECLARE_WINDOW_PROPERTY_TYPE(int) | |
| 40 DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationType) | |
| 41 DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationTransition) | |
| 42 DECLARE_WINDOW_PROPERTY_TYPE(float) | |
| 43 DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT, bool) | |
| 44 | |
| 45 using aura::Window; | |
| 46 using base::TimeDelta; | |
| 47 using ui::Layer; | |
| 48 | |
| 49 namespace views { | |
| 50 namespace corewm { | |
| 51 namespace { | |
| 52 const float kWindowAnimation_Vertical_TranslateY = 15.f; | |
| 53 } // namespace | |
| 54 | |
| 55 DEFINE_WINDOW_PROPERTY_KEY(int, | |
| 56 kWindowVisibilityAnimationTypeKey, | |
| 57 WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); | |
| 58 DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0); | |
| 59 DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition, | |
| 60 kWindowVisibilityAnimationTransitionKey, | |
| 61 ANIMATE_BOTH); | |
| 62 DEFINE_WINDOW_PROPERTY_KEY(float, | |
| 63 kWindowVisibilityAnimationVerticalPositionKey, | |
| 64 kWindowAnimation_Vertical_TranslateY); | |
| 65 | |
| 66 namespace { | |
| 67 | |
| 68 const int kDefaultAnimationDurationForMenuMS = 150; | |
| 69 | |
| 70 const float kWindowAnimation_HideOpacity = 0.f; | |
| 71 const float kWindowAnimation_ShowOpacity = 1.f; | |
| 72 const float kWindowAnimation_TranslateFactor = 0.5f; | |
| 73 const float kWindowAnimation_ScaleFactor = .95f; | |
| 74 | |
| 75 const int kWindowAnimation_Rotate_DurationMS = 180; | |
| 76 const int kWindowAnimation_Rotate_OpacityDurationPercent = 90; | |
| 77 const float kWindowAnimation_Rotate_TranslateY = -20.f; | |
| 78 const float kWindowAnimation_Rotate_PerspectiveDepth = 500.f; | |
| 79 const float kWindowAnimation_Rotate_DegreesX = 5.f; | |
| 80 const float kWindowAnimation_Rotate_ScaleFactor = .99f; | |
| 81 | |
| 82 const float kWindowAnimation_Bounce_Scale = 1.02f; | |
| 83 const int kWindowAnimation_Bounce_DurationMS = 180; | |
| 84 const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40; | |
| 85 | |
| 86 base::TimeDelta GetWindowVisibilityAnimationDuration( | |
| 87 const aura::Window& window) { | |
| 88 int duration = | |
| 89 window.GetProperty(kWindowVisibilityAnimationDurationKey); | |
| 90 if (duration == 0 && window.type() == ui::wm::WINDOW_TYPE_MENU) { | |
| 91 return base::TimeDelta::FromMilliseconds( | |
| 92 kDefaultAnimationDurationForMenuMS); | |
| 93 } | |
| 94 return TimeDelta::FromInternalValue(duration); | |
| 95 } | |
| 96 | |
| 97 // Gets/sets the WindowVisibilityAnimationType associated with a window. | |
| 98 // TODO(beng): redundant/fold into method on public api? | |
| 99 int GetWindowVisibilityAnimationType(aura::Window* window) { | |
| 100 int type = window->GetProperty(kWindowVisibilityAnimationTypeKey); | |
| 101 if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) { | |
| 102 return (window->type() == ui::wm::WINDOW_TYPE_MENU || | |
| 103 window->type() == ui::wm::WINDOW_TYPE_TOOLTIP) | |
| 104 ? WINDOW_VISIBILITY_ANIMATION_TYPE_FADE | |
| 105 : WINDOW_VISIBILITY_ANIMATION_TYPE_DROP; | |
| 106 } | |
| 107 return type; | |
| 108 } | |
| 109 | |
| 110 // Observes a hide animation. | |
| 111 // A window can be hidden for a variety of reasons. Sometimes, Hide() will be | |
| 112 // called and life is simple. Sometimes, the window is actually bound to a | |
| 113 // views::Widget and that Widget is closed, and life is a little more | |
| 114 // complicated. When a Widget is closed the aura::Window* is actually not | |
| 115 // destroyed immediately - it is actually just immediately hidden and then | |
| 116 // destroyed when the stack unwinds. To handle this case, we start the hide | |
| 117 // animation immediately when the window is hidden, then when the window is | |
| 118 // subsequently destroyed this object acquires ownership of the window's layer, | |
| 119 // so that it can continue animating it until the animation completes. | |
| 120 // Regardless of whether or not the window is destroyed, this object deletes | |
| 121 // itself when the animation completes. | |
| 122 class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, | |
| 123 public aura::WindowObserver { | |
| 124 public: | |
| 125 explicit HidingWindowAnimationObserver(aura::Window* window) | |
| 126 : window_(window) { | |
| 127 window_->AddObserver(this); | |
| 128 } | |
| 129 virtual ~HidingWindowAnimationObserver() { | |
| 130 STLDeleteElements(&layers_); | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 // Overridden from ui::ImplicitAnimationObserver: | |
| 135 virtual void OnImplicitAnimationsCompleted() OVERRIDE { | |
| 136 // Window may have been destroyed by this point. | |
| 137 if (window_) { | |
| 138 aura::client::AnimationHost* animation_host = | |
| 139 aura::client::GetAnimationHost(window_); | |
| 140 if (animation_host) | |
| 141 animation_host->OnWindowHidingAnimationCompleted(); | |
| 142 window_->RemoveObserver(this); | |
| 143 } | |
| 144 delete this; | |
| 145 } | |
| 146 | |
| 147 // Overridden from aura::WindowObserver: | |
| 148 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { | |
| 149 DCHECK_EQ(window, window_); | |
| 150 DCHECK(layers_.empty()); | |
| 151 AcquireAllLayers(window_->layer()); | |
| 152 window_->RemoveObserver(this); | |
| 153 window_ = NULL; | |
| 154 } | |
| 155 | |
| 156 void AcquireAllLayers(ui::Layer* layer) { | |
| 157 if (layer->owner()) { | |
| 158 ui::Layer* released = layer->owner()->AcquireLayer(); | |
| 159 DCHECK_EQ(layer, released); | |
| 160 layers_.push_back(released); | |
| 161 } | |
| 162 std::vector<Layer*>::const_iterator it = layer->children().begin(); | |
| 163 for (; it != layer->children().end(); ++it) | |
| 164 AcquireAllLayers(*it); | |
| 165 } | |
| 166 | |
| 167 aura::Window* window_; | |
| 168 std::vector<ui::Layer*> layers_; | |
| 169 | |
| 170 DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); | |
| 171 }; | |
| 172 | |
| 173 void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { | |
| 174 const Layer* root = layer; | |
| 175 while (root->parent()) | |
| 176 root = root->parent(); | |
| 177 layer->GetTargetTransformRelativeTo(root, transform); | |
| 178 } | |
| 179 | |
| 180 gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer, | |
| 181 const gfx::Transform& transform) { | |
| 182 gfx::Transform in_world = transform; | |
| 183 GetTransformRelativeToRoot(layer, &in_world); | |
| 184 | |
| 185 gfx::RectF transformed = layer->bounds(); | |
| 186 in_world.TransformRect(&transformed); | |
| 187 | |
| 188 return gfx::ToEnclosingRect(transformed); | |
| 189 } | |
| 190 | |
| 191 // Augment the host window so that the enclosing bounds of the full | |
| 192 // animation will fit inside of it. | |
| 193 void AugmentWindowSize(aura::Window* window, | |
| 194 const gfx::Transform& end_transform) { | |
| 195 aura::client::AnimationHost* animation_host = | |
| 196 aura::client::GetAnimationHost(window); | |
| 197 if (!animation_host) | |
| 198 return; | |
| 199 | |
| 200 const gfx::Rect& world_at_start = window->bounds(); | |
| 201 gfx::Rect world_at_end = | |
| 202 GetLayerWorldBoundsAfterTransform(window->layer(), end_transform); | |
| 203 gfx::Rect union_in_window_space = | |
| 204 gfx::UnionRects(world_at_start, world_at_end); | |
| 205 | |
| 206 // Calculate the top left and bottom right deltas to be added to the window | |
| 207 // bounds. | |
| 208 gfx::Vector2d top_left_delta(world_at_start.x() - union_in_window_space.x(), | |
| 209 world_at_start.y() - union_in_window_space.y()); | |
| 210 | |
| 211 gfx::Vector2d bottom_right_delta( | |
| 212 union_in_window_space.x() + union_in_window_space.width() - | |
| 213 (world_at_start.x() + world_at_start.width()), | |
| 214 union_in_window_space.y() + union_in_window_space.height() - | |
| 215 (world_at_start.y() + world_at_start.height())); | |
| 216 | |
| 217 DCHECK(top_left_delta.x() >= 0 && top_left_delta.y() >= 0 && | |
| 218 bottom_right_delta.x() >= 0 && bottom_right_delta.y() >= 0); | |
| 219 | |
| 220 animation_host->SetHostTransitionOffsets(top_left_delta, bottom_right_delta); | |
| 221 } | |
| 222 | |
| 223 // Shows a window using an animation, animating its opacity from 0.f to 1.f, | |
| 224 // its visibility to true, and its transform from |start_transform| to | |
| 225 // |end_transform|. | |
| 226 void AnimateShowWindowCommon(aura::Window* window, | |
| 227 const gfx::Transform& start_transform, | |
| 228 const gfx::Transform& end_transform) { | |
| 229 window->layer()->set_delegate(window); | |
| 230 | |
| 231 AugmentWindowSize(window, end_transform); | |
| 232 | |
| 233 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); | |
| 234 window->layer()->SetTransform(start_transform); | |
| 235 window->layer()->SetVisible(true); | |
| 236 | |
| 237 { | |
| 238 // Property sets within this scope will be implicitly animated. | |
| 239 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 240 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window); | |
| 241 if (duration.ToInternalValue() > 0) | |
| 242 settings.SetTransitionDuration(duration); | |
| 243 | |
| 244 window->layer()->SetTransform(end_transform); | |
| 245 window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 // Hides a window using an animation, animating its opacity from 1.f to 0.f, | |
| 250 // its visibility to false, and its transform to |end_transform|. | |
| 251 void AnimateHideWindowCommon(aura::Window* window, | |
| 252 const gfx::Transform& end_transform) { | |
| 253 AugmentWindowSize(window, end_transform); | |
| 254 window->layer()->set_delegate(NULL); | |
| 255 | |
| 256 // Property sets within this scope will be implicitly animated. | |
| 257 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); | |
| 258 settings.AddObserver(new HidingWindowAnimationObserver(window)); | |
| 259 | |
| 260 base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window); | |
| 261 if (duration.ToInternalValue() > 0) | |
| 262 settings.SetTransitionDuration(duration); | |
| 263 | |
| 264 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); | |
| 265 window->layer()->SetTransform(end_transform); | |
| 266 window->layer()->SetVisible(false); | |
| 267 } | |
| 268 | |
| 269 static gfx::Transform GetScaleForWindow(aura::Window* window) { | |
| 270 gfx::Rect bounds = window->bounds(); | |
| 271 gfx::Transform scale = gfx::GetScaleTransform( | |
| 272 gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(), | |
| 273 kWindowAnimation_TranslateFactor * bounds.height()), | |
| 274 kWindowAnimation_ScaleFactor); | |
| 275 return scale; | |
| 276 } | |
| 277 | |
| 278 // Show/Hide windows using a shrink animation. | |
| 279 void AnimateShowWindow_Drop(aura::Window* window) { | |
| 280 AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform()); | |
| 281 } | |
| 282 | |
| 283 void AnimateHideWindow_Drop(aura::Window* window) { | |
| 284 AnimateHideWindowCommon(window, GetScaleForWindow(window)); | |
| 285 } | |
| 286 | |
| 287 // Show/Hide windows using a vertical Glenimation. | |
| 288 void AnimateShowWindow_Vertical(aura::Window* window) { | |
| 289 gfx::Transform transform; | |
| 290 transform.Translate(0, window->GetProperty( | |
| 291 kWindowVisibilityAnimationVerticalPositionKey)); | |
| 292 AnimateShowWindowCommon(window, transform, gfx::Transform()); | |
| 293 } | |
| 294 | |
| 295 void AnimateHideWindow_Vertical(aura::Window* window) { | |
| 296 gfx::Transform transform; | |
| 297 transform.Translate(0, window->GetProperty( | |
| 298 kWindowVisibilityAnimationVerticalPositionKey)); | |
| 299 AnimateHideWindowCommon(window, transform); | |
| 300 } | |
| 301 | |
| 302 // Show/Hide windows using a fade. | |
| 303 void AnimateShowWindow_Fade(aura::Window* window) { | |
| 304 AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform()); | |
| 305 } | |
| 306 | |
| 307 void AnimateHideWindow_Fade(aura::Window* window) { | |
| 308 AnimateHideWindowCommon(window, gfx::Transform()); | |
| 309 } | |
| 310 | |
| 311 ui::LayerAnimationElement* CreateGrowShrinkElement( | |
| 312 aura::Window* window, bool grow) { | |
| 313 scoped_ptr<ui::InterpolatedTransform> scale(new ui::InterpolatedScale( | |
| 314 gfx::Point3F(kWindowAnimation_Bounce_Scale, | |
| 315 kWindowAnimation_Bounce_Scale, | |
| 316 1), | |
| 317 gfx::Point3F(1, 1, 1))); | |
| 318 scoped_ptr<ui::InterpolatedTransform> scale_about_pivot( | |
| 319 new ui::InterpolatedTransformAboutPivot( | |
| 320 gfx::Point(window->bounds().width() * 0.5, | |
| 321 window->bounds().height() * 0.5), | |
| 322 scale.release())); | |
| 323 scale_about_pivot->SetReversed(grow); | |
| 324 scoped_ptr<ui::LayerAnimationElement> transition( | |
| 325 ui::LayerAnimationElement::CreateInterpolatedTransformElement( | |
| 326 scale_about_pivot.release(), | |
| 327 base::TimeDelta::FromMilliseconds( | |
| 328 kWindowAnimation_Bounce_DurationMS * | |
| 329 kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100))); | |
| 330 transition->set_tween_type(grow ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN); | |
| 331 return transition.release(); | |
| 332 } | |
| 333 | |
| 334 void AnimateBounce(aura::Window* window) { | |
| 335 ui::ScopedLayerAnimationSettings scoped_settings( | |
| 336 window->layer()->GetAnimator()); | |
| 337 scoped_settings.SetPreemptionStrategy( | |
| 338 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | |
| 339 window->layer()->set_delegate(window); | |
| 340 scoped_ptr<ui::LayerAnimationSequence> sequence( | |
| 341 new ui::LayerAnimationSequence); | |
| 342 sequence->AddElement(CreateGrowShrinkElement(window, true)); | |
| 343 sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement( | |
| 344 ui::LayerAnimationElement::BOUNDS, | |
| 345 base::TimeDelta::FromMilliseconds( | |
| 346 kWindowAnimation_Bounce_DurationMS * | |
| 347 (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent) / | |
| 348 100))); | |
| 349 sequence->AddElement(CreateGrowShrinkElement(window, false)); | |
| 350 window->layer()->GetAnimator()->StartAnimation(sequence.release()); | |
| 351 } | |
| 352 | |
| 353 void AddLayerAnimationsForRotate(aura::Window* window, bool show) { | |
| 354 window->layer()->set_delegate(window); | |
| 355 if (show) | |
| 356 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); | |
| 357 | |
| 358 base::TimeDelta duration = base::TimeDelta::FromMilliseconds( | |
| 359 kWindowAnimation_Rotate_DurationMS); | |
| 360 | |
| 361 if (!show) { | |
| 362 new HidingWindowAnimationObserver(window); | |
| 363 window->layer()->GetAnimator()->SchedulePauseForProperties( | |
| 364 duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100, | |
| 365 ui::LayerAnimationElement::OPACITY); | |
| 366 } | |
| 367 scoped_ptr<ui::LayerAnimationElement> opacity( | |
| 368 ui::LayerAnimationElement::CreateOpacityElement( | |
| 369 show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity, | |
| 370 duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100)); | |
| 371 opacity->set_tween_type(gfx::Tween::EASE_IN_OUT); | |
| 372 window->layer()->GetAnimator()->ScheduleAnimation( | |
| 373 new ui::LayerAnimationSequence(opacity.release())); | |
| 374 | |
| 375 float xcenter = window->bounds().width() * 0.5; | |
| 376 | |
| 377 gfx::Transform transform; | |
| 378 transform.Translate(xcenter, 0); | |
| 379 transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth); | |
| 380 transform.Translate(-xcenter, 0); | |
| 381 scoped_ptr<ui::InterpolatedTransform> perspective( | |
| 382 new ui::InterpolatedConstantTransform(transform)); | |
| 383 | |
| 384 scoped_ptr<ui::InterpolatedTransform> scale( | |
| 385 new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor)); | |
| 386 scoped_ptr<ui::InterpolatedTransform> scale_about_pivot( | |
| 387 new ui::InterpolatedTransformAboutPivot( | |
| 388 gfx::Point(xcenter, kWindowAnimation_Rotate_TranslateY), | |
| 389 scale.release())); | |
| 390 | |
| 391 scoped_ptr<ui::InterpolatedTransform> translation( | |
| 392 new ui::InterpolatedTranslation(gfx::Point(), gfx::Point( | |
| 393 0, kWindowAnimation_Rotate_TranslateY))); | |
| 394 | |
| 395 scoped_ptr<ui::InterpolatedTransform> rotation( | |
| 396 new ui::InterpolatedAxisAngleRotation( | |
| 397 gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX)); | |
| 398 | |
| 399 scale_about_pivot->SetChild(perspective.release()); | |
| 400 translation->SetChild(scale_about_pivot.release()); | |
| 401 rotation->SetChild(translation.release()); | |
| 402 rotation->SetReversed(show); | |
| 403 | |
| 404 scoped_ptr<ui::LayerAnimationElement> transition( | |
| 405 ui::LayerAnimationElement::CreateInterpolatedTransformElement( | |
| 406 rotation.release(), duration)); | |
| 407 | |
| 408 window->layer()->GetAnimator()->ScheduleAnimation( | |
| 409 new ui::LayerAnimationSequence(transition.release())); | |
| 410 } | |
| 411 | |
| 412 void AnimateShowWindow_Rotate(aura::Window* window) { | |
| 413 AddLayerAnimationsForRotate(window, true); | |
| 414 } | |
| 415 | |
| 416 void AnimateHideWindow_Rotate(aura::Window* window) { | |
| 417 AddLayerAnimationsForRotate(window, false); | |
| 418 } | |
| 419 | |
| 420 bool AnimateShowWindow(aura::Window* window) { | |
| 421 if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) { | |
| 422 if (HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) { | |
| 423 // Since hide animation may have changed opacity and transform, | |
| 424 // reset them to show the window. | |
| 425 window->layer()->set_delegate(window); | |
| 426 window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); | |
| 427 window->layer()->SetTransform(gfx::Transform()); | |
| 428 } | |
| 429 return false; | |
| 430 } | |
| 431 | |
| 432 switch (GetWindowVisibilityAnimationType(window)) { | |
| 433 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: | |
| 434 AnimateShowWindow_Drop(window); | |
| 435 return true; | |
| 436 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: | |
| 437 AnimateShowWindow_Vertical(window); | |
| 438 return true; | |
| 439 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: | |
| 440 AnimateShowWindow_Fade(window); | |
| 441 return true; | |
| 442 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: | |
| 443 AnimateShowWindow_Rotate(window); | |
| 444 return true; | |
| 445 default: | |
| 446 return false; | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 bool AnimateHideWindow(aura::Window* window) { | |
| 451 if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) { | |
| 452 if (HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) { | |
| 453 // Since show animation may have changed opacity and transform, | |
| 454 // reset them, though the change should be hidden. | |
| 455 window->layer()->set_delegate(NULL); | |
| 456 window->layer()->SetOpacity(kWindowAnimation_HideOpacity); | |
| 457 window->layer()->SetTransform(gfx::Transform()); | |
| 458 } | |
| 459 return false; | |
| 460 } | |
| 461 | |
| 462 switch (GetWindowVisibilityAnimationType(window)) { | |
| 463 case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: | |
| 464 AnimateHideWindow_Drop(window); | |
| 465 return true; | |
| 466 case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: | |
| 467 AnimateHideWindow_Vertical(window); | |
| 468 return true; | |
| 469 case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: | |
| 470 AnimateHideWindow_Fade(window); | |
| 471 return true; | |
| 472 case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: | |
| 473 AnimateHideWindow_Rotate(window); | |
| 474 return true; | |
| 475 default: | |
| 476 return false; | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 } // namespace | |
| 481 | |
| 482 //////////////////////////////////////////////////////////////////////////////// | |
| 483 // External interface | |
| 484 | |
| 485 void SetWindowVisibilityAnimationType(aura::Window* window, int type) { | |
| 486 window->SetProperty(kWindowVisibilityAnimationTypeKey, type); | |
| 487 } | |
| 488 | |
| 489 int GetWindowVisibilityAnimationType(aura::Window* window) { | |
| 490 return window->GetProperty(kWindowVisibilityAnimationTypeKey); | |
| 491 } | |
| 492 | |
| 493 void SetWindowVisibilityAnimationTransition( | |
| 494 aura::Window* window, | |
| 495 WindowVisibilityAnimationTransition transition) { | |
| 496 window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition); | |
| 497 } | |
| 498 | |
| 499 bool HasWindowVisibilityAnimationTransition( | |
| 500 aura::Window* window, | |
| 501 WindowVisibilityAnimationTransition transition) { | |
| 502 WindowVisibilityAnimationTransition prop = window->GetProperty( | |
| 503 kWindowVisibilityAnimationTransitionKey); | |
| 504 return (prop & transition) != 0; | |
| 505 } | |
| 506 | |
| 507 void SetWindowVisibilityAnimationDuration(aura::Window* window, | |
| 508 const TimeDelta& duration) { | |
| 509 window->SetProperty(kWindowVisibilityAnimationDurationKey, | |
| 510 static_cast<int>(duration.ToInternalValue())); | |
| 511 } | |
| 512 | |
| 513 base::TimeDelta GetWindowVisibilityAnimationDuration( | |
| 514 const aura::Window& window) { | |
| 515 return base::TimeDelta::FromInternalValue( | |
| 516 window.GetProperty(kWindowVisibilityAnimationDurationKey)); | |
| 517 } | |
| 518 | |
| 519 void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window, | |
| 520 float position) { | |
| 521 window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position); | |
| 522 } | |
| 523 | |
| 524 ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( | |
| 525 aura::Window* window) { | |
| 526 return new HidingWindowAnimationObserver(window); | |
| 527 } | |
| 528 | |
| 529 bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { | |
| 530 if (WindowAnimationsDisabled(window)) | |
| 531 return false; | |
| 532 if (visible) | |
| 533 return AnimateShowWindow(window); | |
| 534 // Don't start hiding the window again if it's already being hidden. | |
| 535 return window->layer()->GetTargetOpacity() != 0.0f && | |
| 536 AnimateHideWindow(window); | |
| 537 } | |
| 538 | |
| 539 bool AnimateWindow(aura::Window* window, WindowAnimationType type) { | |
| 540 switch (type) { | |
| 541 case WINDOW_ANIMATION_TYPE_BOUNCE: | |
| 542 AnimateBounce(window); | |
| 543 return true; | |
| 544 default: | |
| 545 NOTREACHED(); | |
| 546 return false; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 bool WindowAnimationsDisabled(aura::Window* window) { | |
| 551 return (!gfx::Animation::ShouldRenderRichAnimation() || (window && | |
| 552 window->GetProperty(aura::client::kAnimationsDisabledKey)) || | |
| 553 CommandLine::ForCurrentProcess()->HasSwitch( | |
| 554 switches::kWindowAnimationsDisabled)); | |
| 555 } | |
| 556 | |
| 557 } // namespace corewm | |
| 558 } // namespace views | |
| OLD | NEW |