blob: 17a465cbbd6ea8fc8ab902557c510273c4781767 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wallpaper/wallpaper_widget_controller.h"
#include <utility>
#include "ash/ash_export.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/wallpaper/wallpaper_view.h"
#include "base/scoped_observer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/wm/core/window_util.h"
namespace ash {
WallpaperWidgetController::WallpaperWidgetController(
aura::Window* root_window,
base::OnceClosure wallpaper_set_callback)
: root_window_(root_window),
wallpaper_set_callback_(std::move(wallpaper_set_callback)) {}
WallpaperWidgetController::~WallpaperWidgetController() {
widget_->CloseNow();
}
void WallpaperWidgetController::Init(int container) {
widget_ = CreateWallpaperWidget(
root_window_, container, wallpaper_constants::kClear, &wallpaper_view_);
}
views::Widget* WallpaperWidgetController::GetWidget() {
return widget_.get();
}
bool WallpaperWidgetController::IsAnimating() const {
return wallpaper_view_->layer()->GetAnimator()->is_animating();
}
void WallpaperWidgetController::StopAnimating() {
wallpaper_view_->layer()->GetAnimator()->StopAnimating();
if (old_layer_tree_owner_) {
old_layer_tree_owner_->root()->GetAnimator()->StopAnimating();
old_layer_tree_owner_.reset();
}
}
void WallpaperWidgetController::AddAnimationEndCallback(
base::OnceClosure callback) {
animation_end_callbacks_.emplace_back(std::move(callback));
}
bool WallpaperWidgetController::Reparent(int container) {
auto* parent = GetWidget()->GetNativeWindow()->parent();
auto* root_window = parent->GetRootWindow();
aura::Window* new_parent = root_window->GetChildById(container);
if (parent == new_parent)
return false;
new_parent->AddChild(GetWidget()->GetNativeWindow());
return true;
}
bool WallpaperWidgetController::SetWallpaperProperty(
const WallpaperProperty& property,
const base::TimeDelta& animation_duration) {
StopAnimating();
bool property_changed = !(wallpaper_view_->property() == property);
wallpaper_view_->set_wallpaper_property(property);
// Show the widget when we have something to show.
if (!widget_->IsVisible())
widget_->Show();
if (!animation_duration.is_zero()) {
ApplyCrossFadeAnimation(animation_duration);
} else {
wallpaper_view_->SchedulePaint();
// Since there is no actual animation scheduled, just call completed method.
OnImplicitAnimationsCompleted();
}
return property_changed;
}
const WallpaperProperty& WallpaperWidgetController::GetWallpaperProperty()
const {
return wallpaper_view_->property();
}
void WallpaperWidgetController::OnImplicitAnimationsCompleted() {
StopAnimating();
wallpaper_view_->SetLockShieldEnabled(
wallpaper_view_->GetWidget()->GetNativeWindow()->parent()->id() ==
kShellWindowId_LockScreenWallpaperContainer);
RunAnimationEndCallbacks();
}
void WallpaperWidgetController::RunAnimationEndCallbacks() {
std::list<base::OnceClosure> callbacks;
animation_end_callbacks_.swap(callbacks);
for (auto& callback : callbacks)
std::move(callback).Run();
}
void WallpaperWidgetController::ApplyCrossFadeAnimation(
base::TimeDelta duration) {
DCHECK(wallpaper_view_);
old_layer_tree_owner_ = ::wm::RecreateLayers(wallpaper_view_);
old_layer_tree_owner_->root()->parent()->StackAbove(
old_layer_tree_owner_->root(), wallpaper_view_->layer());
ui::Layer* old_layer = old_layer_tree_owner_->root();
ui::Layer* new_layer = wallpaper_view_->layer();
old_layer->SetOpacity(1.f);
new_layer->SetOpacity(0.f);
ui::ScopedLayerAnimationSettings original_settings(new_layer->GetAnimator());
ui::ScopedLayerAnimationSettings copy_settings(old_layer->GetAnimator());
original_settings.SetTransitionDuration(duration);
original_settings.SetTweenType(gfx::Tween::EASE_OUT);
original_settings.AddObserver(this);
copy_settings.SetTransitionDuration(duration);
copy_settings.SetTweenType(gfx::Tween::EASE_IN);
new_layer->SetOpacity(1.f);
old_layer->SetOpacity(0.f);
}
} // namespace ash