Index: ash/wm/shelf_layout_manager.cc |
diff --git a/ash/wm/shelf_layout_manager.cc b/ash/wm/shelf_layout_manager.cc |
index 1283fe5b120858119314aeda524ed369ca2341cd..d5a804a0a35f311e14b3e0b5e5f17450c7c1cfbb 100644 |
--- a/ash/wm/shelf_layout_manager.cc |
+++ b/ash/wm/shelf_layout_manager.cc |
@@ -10,10 +10,13 @@ |
#include "ui/aura/root_window.h" |
#include "ui/aura/screen_aura.h" |
#include "ui/gfx/compositor/layer.h" |
+#include "ui/gfx/compositor/layer_animation_observer.h" |
#include "ui/gfx/compositor/layer_animator.h" |
#include "ui/gfx/compositor/scoped_layer_animation_settings.h" |
#include "ui/views/widget/widget.h" |
+using ui::ImplicitAnimationObserver; |
+ |
namespace ash { |
namespace internal { |
@@ -23,6 +26,23 @@ ui::Layer* GetLayer(views::Widget* widget) { |
return widget->GetNativeView()->layer(); |
} |
+class ShelfAnimationObserver : public ImplicitAnimationObserver { |
+ public: |
+ ShelfAnimationObserver(ShelfAnimationObserverClient* client) |
+ : client_(client) {} |
+ virtual ~ShelfAnimationObserver() {} |
+ |
+ private: |
+ // Implementation of ImplicitAnimationObserver |
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE { |
+ client_->OnShelfAnimationsCompleted(this); |
+ } |
+ |
+ ShelfAnimationObserverClient* client_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ShelfAnimationObserver); |
+}; |
+ |
} // namespace |
//////////////////////////////////////////////////////////////////////////////// |
@@ -30,8 +50,7 @@ ui::Layer* GetLayer(views::Widget* widget) { |
ShelfLayoutManager::ShelfLayoutManager(views::Widget* launcher, |
views::Widget* status) |
- : animating_(false), |
- in_layout_(false), |
+ : in_layout_(false), |
visible_(true), |
max_height_(-1), |
launcher_(launcher), |
@@ -39,14 +58,20 @@ ShelfLayoutManager::ShelfLayoutManager(views::Widget* launcher, |
gfx::Rect launcher_bounds = launcher->GetWindowScreenBounds(); |
gfx::Rect status_bounds = status->GetWindowScreenBounds(); |
max_height_ = std::max(launcher_bounds.height(), status_bounds.height()); |
- GetLayer(launcher)->GetAnimator()->AddObserver(this); |
} |
ShelfLayoutManager::~ShelfLayoutManager() { |
- GetLayer(launcher_)->GetAnimator()->RemoveObserver(this); |
// Without a shelf we don't need special insets anymore. |
aura::RootWindow::GetInstance()-> |
screen()->set_work_area_insets(gfx::Insets()); |
+ |
+ if (launcher_animation_observer_.get()) |
+ GetLayer(launcher_)->GetAnimator()->RemoveObserver( |
+ launcher_animation_observer_.get()); |
+ |
+ if (status_animation_observer_.get()) |
+ GetLayer(status_)->GetAnimator()->RemoveObserver( |
+ status_animation_observer_.get()); |
} |
void ShelfLayoutManager::LayoutShelf() { |
@@ -66,19 +91,33 @@ void ShelfLayoutManager::LayoutShelf() { |
} |
void ShelfLayoutManager::SetVisible(bool visible) { |
- bool current_visibility = animating_ ? !visible_ : visible_; |
+ // TODO(vollick): once visibility is animatable, use GetTargetVisibility. |
+ bool current_visibility = visible_ && |
+ GetLayer(launcher_)->GetTargetOpacity() > 0.0f && |
+ GetLayer(status_)->GetTargetOpacity() > 0.0f; |
+ |
if (visible == current_visibility) |
return; // Nothing changed. |
StopAnimating(); |
+ visible_ = visible; |
TargetBounds target_bounds; |
float target_opacity = visible ? 1.0f : 0.0f; |
CalculateTargetBounds(visible, &target_bounds); |
- AnimateWidgetTo(launcher_, target_bounds.launcher_bounds, target_opacity); |
- AnimateWidgetTo(status_, target_bounds.status_bounds, target_opacity); |
- animating_ = true; |
- // |visible_| is updated once the animation completes. |
+ |
+ launcher_animation_observer_.reset(new ShelfAnimationObserver(this)); |
+ status_animation_observer_.reset(new ShelfAnimationObserver(this)); |
+ |
+ AnimateWidgetTo(launcher_, |
+ launcher_animation_observer_.get(), |
+ target_bounds.launcher_bounds, |
+ target_opacity); |
+ |
+ AnimateWidgetTo(status_, |
+ status_animation_observer_.get(), |
+ target_bounds.status_bounds, |
+ target_opacity); |
} |
//////////////////////////////////////////////////////////////////////////////// |
@@ -109,10 +148,6 @@ void ShelfLayoutManager::SetChildBounds(aura::Window* child, |
// ShelfLayoutManager, private: |
void ShelfLayoutManager::StopAnimating() { |
- if (animating_) { |
- animating_ = false; |
- visible_ = !visible_; |
- } |
GetLayer(launcher_)->GetAnimator()->StopAnimating(); |
GetLayer(status_)->GetAnimator()->StopAnimating(); |
} |
@@ -136,26 +171,34 @@ void ShelfLayoutManager::CalculateTargetBounds(bool visible, |
} |
void ShelfLayoutManager::AnimateWidgetTo(views::Widget* widget, |
+ ImplicitAnimationObserver* observer, |
const gfx::Rect& target_bounds, |
float target_opacity) { |
ui::Layer* layer = GetLayer(widget); |
ui::ScopedLayerAnimationSettings animation_setter(layer->GetAnimator()); |
+ animation_setter.AddObserver(observer); |
// Don't go through the widget, otherwise we end up back in SetChildBounds and |
// cancel the animation/layout. |
layer->SetBounds(target_bounds); |
layer->SetOpacity(target_opacity); |
} |
-void ShelfLayoutManager::OnLayerAnimationEnded( |
- const ui::LayerAnimationSequence* sequence) { |
- if (!animating_) |
- return; |
- animating_ = false; |
- visible_ = !visible_; |
- TargetBounds target_bounds; |
- CalculateTargetBounds(visible_, &target_bounds); |
- aura::RootWindow::GetInstance()->screen()->set_work_area_insets( |
- target_bounds.work_area_insets); |
+void ShelfLayoutManager::OnShelfAnimationsCompleted( |
+ ImplicitAnimationObserver* observer) { |
+ if (observer == launcher_animation_observer_.get()) |
+ launcher_animation_observer_.reset(NULL); |
+ else if (observer == status_animation_observer_.get()) |
+ status_animation_observer_.reset(NULL); |
+ else |
+ NOTREACHED() << "Unknown observer in OnShelfAnimationsCompleted"; |
+ |
+ if (!launcher_animation_observer_.get() && |
+ !status_animation_observer_.get()) { |
+ TargetBounds target_bounds; |
+ CalculateTargetBounds(visible_, &target_bounds); |
+ aura::RootWindow::GetInstance()->screen()->set_work_area_insets( |
+ target_bounds.work_area_insets); |
+ } |
} |
} // namespace internal |