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 "ash/desktop_background/desktop_background_widget_controller.h"
6
7#include "ash/ash_export.h"
8#include "ash/desktop_background/user_wallpaper_delegate.h"
9#include "ash/root_window_controller.h"
10#include "ash/shell.h"
11#include "ui/aura/root_window.h"
12#include "ui/compositor/layer_animation_observer.h"
13#include "ui/compositor/scoped_layer_animation_settings.h"
14#include "ui/views/widget/widget.h"
15#include "ui/views/widget/widget_observer.h"
16
17namespace ash {
18namespace internal {
19namespace {
20
21class ShowWallpaperAnimationObserver : public ui::ImplicitAnimationObserver,
22                                       public views::WidgetObserver {
23 public:
24  ShowWallpaperAnimationObserver(RootWindowController* root_window_controller,
25                                 views::Widget* desktop_widget,
26                                 bool is_initial_animation)
27      : root_window_controller_(root_window_controller),
28        desktop_widget_(desktop_widget),
29        is_initial_animation_(is_initial_animation) {
30    DCHECK(desktop_widget_);
31    desktop_widget_->AddObserver(this);
32  }
33
34  virtual ~ShowWallpaperAnimationObserver() {
35    StopObservingImplicitAnimations();
36    if (desktop_widget_)
37      desktop_widget_->RemoveObserver(this);
38  }
39
40 private:
41  // Overridden from ui::ImplicitAnimationObserver:
42  virtual void OnImplicitAnimationsScheduled() OVERRIDE {
43    if (is_initial_animation_) {
44      root_window_controller_->
45          HandleInitialDesktopBackgroundAnimationStarted();
46    }
47  }
48
49  virtual void OnImplicitAnimationsCompleted() OVERRIDE {
50    root_window_controller_->OnWallpaperAnimationFinished(desktop_widget_);
51    delete this;
52  }
53
54  // Overridden from views::WidgetObserver.
55  virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
56    delete this;
57  }
58
59  RootWindowController* root_window_controller_;
60  views::Widget* desktop_widget_;
61
62  // Is this object observing the initial brightness/grayscale animation?
63  const bool is_initial_animation_;
64
65  DISALLOW_COPY_AND_ASSIGN(ShowWallpaperAnimationObserver);
66};
67
68}  // namespace
69
70DesktopBackgroundWidgetController::DesktopBackgroundWidgetController(
71    views::Widget* widget) : widget_(widget) {
72  DCHECK(widget_);
73  widget_->AddObserver(this);
74}
75
76DesktopBackgroundWidgetController::DesktopBackgroundWidgetController(
77    ui::Layer* layer) : widget_(NULL) {
78  layer_.reset(layer);
79}
80
81DesktopBackgroundWidgetController::~DesktopBackgroundWidgetController() {
82  if (widget_) {
83    widget_->RemoveObserver(this);
84    widget_->CloseNow();
85    widget_ = NULL;
86  } else if (layer_)
87    layer_.reset(NULL);
88}
89
90void DesktopBackgroundWidgetController::OnWidgetDestroying(
91    views::Widget* widget) {
92  widget_->RemoveObserver(this);
93  widget_ = NULL;
94}
95
96void DesktopBackgroundWidgetController::SetBounds(gfx::Rect bounds) {
97  if (widget_)
98    widget_->SetBounds(bounds);
99  else if (layer_)
100    layer_->SetBounds(bounds);
101}
102
103bool DesktopBackgroundWidgetController::Reparent(aura::RootWindow* root_window,
104                                                 int src_container,
105                                                 int dest_container) {
106  if (widget_) {
107    views::Widget::ReparentNativeView(widget_->GetNativeView(),
108        root_window->GetChildById(dest_container));
109    return true;
110  } else if (layer_) {
111    ui::Layer* layer = layer_.get();
112    root_window->GetChildById(src_container)->layer()->Remove(layer);
113    root_window->GetChildById(dest_container)->layer()->Add(layer);
114    return true;
115  }
116  // Nothing to reparent.
117  return false;
118}
119
120void DesktopBackgroundWidgetController::StartAnimating(
121    RootWindowController* root_window_controller) {
122  if (widget_) {
123    ui::ScopedLayerAnimationSettings settings(
124        widget_->GetNativeView()->layer()->GetAnimator());
125    settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
126    settings.AddObserver(new ShowWallpaperAnimationObserver(
127        root_window_controller, widget_,
128        Shell::GetInstance()->user_wallpaper_delegate()->
129            ShouldShowInitialAnimation()));
130    widget_->Show();
131    widget_->GetNativeView()->SetName("DesktopBackgroundView");
132  } else if (layer_)
133    root_window_controller->OnWallpaperAnimationFinished(NULL);
134}
135
136AnimatingDesktopController::AnimatingDesktopController(
137    DesktopBackgroundWidgetController* component) {
138  controller_.reset(component);
139}
140
141AnimatingDesktopController::~AnimatingDesktopController() {
142}
143
144void AnimatingDesktopController::StopAnimating() {
145  if (controller_) {
146    ui::Layer* layer = controller_->layer() ? controller_->layer() :
147        controller_->widget()->GetNativeView()->layer();
148    layer->GetAnimator()->StopAnimating();
149  }
150}
151
152DesktopBackgroundWidgetController* AnimatingDesktopController::GetController(
153    bool pass_ownership) {
154  if (pass_ownership)
155    return controller_.release();
156  return controller_.get();
157}
158
159}  // namespace internal
160}  // namespace ash
161