This source file includes following definitions.
- callback_
- AddNewAnimator
- OnSingleTaskCompleted
- OnSingleTaskAborted
- observer_
- OnLayerAnimationEnded
- OnLayerAnimationAborted
- OnLayerAnimationScheduled
- RequiresNotificationWhenAnimatorDestroyed
- StartFadeOutAnimation
- StartFadeInAnimation
- OnDisplayModeChanged
- OnDisplayModeChangeFailed
- ClearHidingLayers
#include "ash/display/output_configurator_animation.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "base/bind.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
namespace ash {
namespace {
const int kFadingAnimationDurationInMS = 200;
const int kFadingTimeoutDurationInSeconds = 10;
class CallbackRunningObserver {
public:
CallbackRunningObserver(base::Closure callback)
: completed_counter_(0),
animation_aborted_(false),
callback_(callback) {}
void AddNewAnimator(ui::LayerAnimator* animator) {
Observer* observer = new Observer(animator, this);
animator->AddObserver(observer);
observer_list_.push_back(observer);
}
private:
void OnSingleTaskCompleted() {
completed_counter_++;
if (completed_counter_ >= observer_list_.size()) {
base::MessageLoopForUI::current()->DeleteSoon(FROM_HERE, this);
if (!animation_aborted_)
base::MessageLoopForUI::current()->PostTask(FROM_HERE, callback_);
}
}
void OnSingleTaskAborted() {
animation_aborted_ = true;
OnSingleTaskCompleted();
}
class Observer : public ui::LayerAnimationObserver {
public:
Observer(ui::LayerAnimator* animator,
CallbackRunningObserver* observer)
: animator_(animator),
observer_(observer) {}
protected:
virtual void OnLayerAnimationEnded(
ui::LayerAnimationSequence* sequence) OVERRIDE {
animator_->RemoveObserver(this);
observer_->OnSingleTaskCompleted();
}
virtual void OnLayerAnimationAborted(
ui::LayerAnimationSequence* sequence) OVERRIDE {
animator_->RemoveObserver(this);
observer_->OnSingleTaskAborted();
}
virtual void OnLayerAnimationScheduled(
ui::LayerAnimationSequence* sequence) OVERRIDE {
}
virtual bool RequiresNotificationWhenAnimatorDestroyed() const OVERRIDE {
return true;
}
private:
ui::LayerAnimator* animator_;
CallbackRunningObserver* observer_;
DISALLOW_COPY_AND_ASSIGN(Observer);
};
size_t completed_counter_;
bool animation_aborted_;
ScopedVector<Observer> observer_list_;
base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(CallbackRunningObserver);
};
}
OutputConfiguratorAnimation::OutputConfiguratorAnimation() {
}
OutputConfiguratorAnimation::~OutputConfiguratorAnimation() {
ClearHidingLayers();
}
void OutputConfiguratorAnimation::StartFadeOutAnimation(
base::Closure callback) {
CallbackRunningObserver* observer = new CallbackRunningObserver(callback);
ClearHidingLayers();
aura::Window::Windows root_windows =
Shell::GetInstance()->GetAllRootWindows();
for (aura::Window::Windows::const_iterator it = root_windows.begin();
it != root_windows.end(); ++it) {
aura::Window* root_window = *it;
ui::Layer* hiding_layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
hiding_layer->SetColor(SK_ColorBLACK);
hiding_layer->SetBounds(root_window->bounds());
ui::Layer* parent =
ash::Shell::GetContainer(root_window,
ash::kShellWindowId_OverlayContainer)->layer();
parent->Add(hiding_layer);
hiding_layer->SetOpacity(0.0);
ui::ScopedLayerAnimationSettings settings(hiding_layer->GetAnimator());
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
kFadingAnimationDurationInMS));
observer->AddNewAnimator(hiding_layer->GetAnimator());
hiding_layer->SetOpacity(1.0f);
hiding_layer->SetVisible(true);
hiding_layers_[root_window] = hiding_layer;
}
timer_.reset(new base::OneShotTimer<OutputConfiguratorAnimation>());
timer_->Start(FROM_HERE,
base::TimeDelta::FromSeconds(kFadingTimeoutDurationInSeconds),
this,
&OutputConfiguratorAnimation::ClearHidingLayers);
}
void OutputConfiguratorAnimation::StartFadeInAnimation() {
CallbackRunningObserver* observer = new CallbackRunningObserver(
base::Bind(&OutputConfiguratorAnimation::ClearHidingLayers,
base::Unretained(this)));
for (std::map<aura::Window*, ui::Layer*>::iterator it =
hiding_layers_.begin(); it != hiding_layers_.end(); ++it) {
ui::LayerAnimator* animator = it->second->GetAnimator();
if (animator->is_animating())
animator->StopAnimating();
}
aura::Window::Windows root_windows =
Shell::GetInstance()->GetAllRootWindows();
for (aura::Window::Windows::const_iterator it = root_windows.begin();
it != root_windows.end(); ++it) {
aura::Window* root_window = *it;
ui::Layer* hiding_layer = NULL;
if (hiding_layers_.find(root_window) == hiding_layers_.end()) {
hiding_layer = new ui::Layer(ui::LAYER_SOLID_COLOR);
hiding_layer->SetColor(SK_ColorBLACK);
hiding_layer->SetBounds(root_window->bounds());
ui::Layer* parent =
ash::Shell::GetContainer(
root_window, ash::kShellWindowId_OverlayContainer)->layer();
parent->Add(hiding_layer);
hiding_layer->SetOpacity(1.0f);
hiding_layer->SetVisible(true);
hiding_layers_[root_window] = hiding_layer;
} else {
hiding_layer = hiding_layers_[root_window];
if (hiding_layer->bounds() != root_window->bounds())
hiding_layer->SetBounds(root_window->bounds());
}
ui::ScopedLayerAnimationSettings settings(hiding_layer->GetAnimator());
settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
kFadingAnimationDurationInMS));
observer->AddNewAnimator(hiding_layer->GetAnimator());
hiding_layer->SetOpacity(0.0f);
hiding_layer->SetVisible(false);
}
}
void OutputConfiguratorAnimation::OnDisplayModeChanged(
const ui::OutputConfigurator::DisplayStateList& outputs) {
if (!hiding_layers_.empty())
StartFadeInAnimation();
}
void OutputConfiguratorAnimation::OnDisplayModeChangeFailed(
ui::OutputState failed_new_state) {
if (!hiding_layers_.empty())
StartFadeInAnimation();
}
void OutputConfiguratorAnimation::ClearHidingLayers() {
if (timer_) {
timer_->Stop();
timer_.reset();
}
STLDeleteContainerPairSecondPointers(
hiding_layers_.begin(), hiding_layers_.end());
hiding_layers_.clear();
}
}