Index: ash/system/tray/tray_background_view.cc |
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc |
index b6d06da3232dfe8f30e6006f32e71270dbc25ccf..a166da3d5ff46aca4467a46acd129e8a9f49aaa9 100644 |
--- a/ash/system/tray/tray_background_view.cc |
+++ b/ash/system/tray/tray_background_view.cc |
@@ -22,12 +22,17 @@ |
#include "ui/aura/window.h" |
#include "ui/aura/window_event_dispatcher.h" |
#include "ui/base/resource/resource_bundle.h" |
+#include "ui/compositor/layer.h" |
+#include "ui/compositor/layer_animation_element.h" |
+#include "ui/compositor/scoped_layer_animation_settings.h" |
+#include "ui/gfx/animation/tween.h" |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/image/image_skia.h" |
#include "ui/gfx/image/image_skia_operations.h" |
#include "ui/gfx/rect.h" |
#include "ui/gfx/screen.h" |
#include "ui/gfx/skia_util.h" |
+#include "ui/gfx/transform.h" |
#include "ui/views/background.h" |
#include "ui/views/layout/box_layout.h" |
@@ -37,7 +42,15 @@ const int kTrayBackgroundAlpha = 100; |
const int kTrayBackgroundHoverAlpha = 150; |
const SkColor kTrayBackgroundPressedColor = SkColorSetRGB(66, 129, 244); |
-const int kAnimationDurationForPopupMS = 200; |
+const int kAnimationDurationForPopupMs = 200; |
+ |
+// Duration of opacity animation for visibility changes. |
+const int kAnimationDurationForVisibilityMs = 250; |
+ |
+// When becoming visible delay the animation so that StatusAreaWidgetDelegate |
+// can animate sibling views out of the position to be occuped by the |
+// TrayBackgroundView. |
+const int kShowAnimationDelayMs = 100; |
} // namespace |
@@ -307,6 +320,9 @@ TrayBackgroundView::TrayBackgroundView(StatusAreaWidget* status_area_widget) |
tray_container_ = new TrayContainer(shelf_alignment_); |
SetContents(tray_container_); |
tray_event_filter_.reset(new TrayEventFilter); |
+ |
+ SetPaintToLayer(true); |
+ SetFillsBoundsOpaquely(false); |
} |
TrayBackgroundView::~TrayBackgroundView() { |
@@ -319,6 +335,56 @@ void TrayBackgroundView::Initialize() { |
SetTrayBorder(); |
} |
+void TrayBackgroundView::SetVisible(bool visible) { |
+ if (visible == layer()->GetTargetVisibility()) |
+ return; |
+ |
+ if (visible) { |
+ // The alignment of the shelf can change while the TrayBackgroundView is |
+ // hidden. Reset the offscreen transform so that the animation to becoming |
+ // visible reflects the current layout. |
+ HideTransformation(); |
+ // SetVisible(false) is defered until the animation for hiding is done. |
+ // Otherwise the view is immediately hidden and the animation does not |
+ // render. |
+ views::View::SetVisible(true); |
+ // If SetVisible(true) is called while animating to not visible, then |
+ // views::View::SetVisible(true) is a no-op. When the previous animation |
+ // ends layer->SetVisible(false) is called. To prevent this |
+ // layer->SetVisible(true) immediately interrupts the animation of this |
+ // property, and keeps the layer visible. |
+ layer()->SetVisible(true); |
+ } |
+ |
+ ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); |
+ animation.SetTransitionDuration(base::TimeDelta::FromMilliseconds( |
+ kAnimationDurationForVisibilityMs)); |
+ animation.SetPreemptionStrategy( |
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
+ |
+ if (visible) { |
+ animation.SetTweenType(gfx::Tween::EASE_OUT); |
+ // Show is delayed so as to allow time for other children of |
+ // StatusAreaWidget to begin animating to their new positions. |
+ layer()->GetAnimator()->SchedulePauseForProperties( |
+ base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs), |
+ ui::LayerAnimationElement::OPACITY | |
+ ui::LayerAnimationElement::TRANSFORM); |
+ layer()->SetOpacity(1.0f); |
+ gfx::Transform transform; |
+ transform.Translate(0.0f, 0.0f); |
+ layer()->SetTransform(transform); |
+ } else { |
+ // Listen only to the hide animation. As we cannot turn off visibility |
+ // until the animation is over. |
+ animation.AddObserver(this); |
+ animation.SetTweenType(gfx::Tween::EASE_IN); |
+ layer()->SetOpacity(0.0f); |
+ layer()->SetVisible(false); |
+ HideTransformation(); |
+ } |
+} |
+ |
const char* TrayBackgroundView::GetClassName() const { |
return kViewClassName; |
} |
@@ -420,6 +486,29 @@ void TrayBackgroundView::SetTrayBorder() { |
top_edge, left_edge, bottom_edge, right_edge)); |
} |
+void TrayBackgroundView::OnImplicitAnimationsCompleted() { |
+ // If there is another animation in the queue, the reverse animation was |
+ // triggered before the completion of animating to invisible. Do not turn off |
+ // the visibility so that the next animation may render. The value of |
+ // layer()->GetTargetVisibility() can be incorrect if the hide animation was |
+ // aborted to schedule an animation to become visible. As the new animation |
+ // is not yet added to the queue. crbug.com/374236 |
+ if(layer()->GetAnimator()->is_animating() || |
+ layer()->GetTargetVisibility()) |
+ return; |
+ views::View::SetVisible(false); |
+} |
+ |
+void TrayBackgroundView::HideTransformation() { |
+ gfx::Transform transform; |
+ if (shelf_alignment_ == SHELF_ALIGNMENT_BOTTOM || |
+ shelf_alignment_ == SHELF_ALIGNMENT_TOP) |
+ transform.Translate(width(), 0.0f); |
+ else |
+ transform.Translate(0.0f, height()); |
+ layer()->SetTransform(transform); |
+} |
+ |
void TrayBackgroundView::InitializeBubbleAnimations( |
views::Widget* bubble_widget) { |
wm::SetWindowVisibilityAnimationType( |
@@ -430,7 +519,7 @@ void TrayBackgroundView::InitializeBubbleAnimations( |
wm::ANIMATE_HIDE); |
wm::SetWindowVisibilityAnimationDuration( |
bubble_widget->GetNativeWindow(), |
- base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); |
+ base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs)); |
} |
aura::Window* TrayBackgroundView::GetBubbleWindowContainer() const { |