Roll leveldb from r73 to r75.
[chromium-blink-merge.git] / ash / desktop_background / desktop_background_view.cc
blobe27a183463e8539a46d4f72a642437fcbf374f03
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.
5 #include "ash/desktop_background/desktop_background_view.h"
7 #include <limits>
9 #include "ash/ash_export.h"
10 #include "ash/desktop_background/desktop_background_controller.h"
11 #include "ash/desktop_background/desktop_background_widget_controller.h"
12 #include "ash/desktop_background/user_wallpaper_delegate.h"
13 #include "ash/root_window_controller.h"
14 #include "ash/session_state_delegate.h"
15 #include "ash/shell.h"
16 #include "ash/shell_window_ids.h"
17 #include "ash/wm/property_util.h"
18 #include "ash/wm/window_animations.h"
19 #include "base/message_loop.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "ui/aura/root_window.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/compositor/layer.h"
24 #include "ui/compositor/layer_animation_observer.h"
25 #include "ui/compositor/scoped_layer_animation_settings.h"
26 #include "ui/gfx/canvas.h"
27 #include "ui/gfx/image/image.h"
28 #include "ui/views/widget/widget.h"
29 #include "ui/views/widget/widget_observer.h"
31 namespace ash {
32 namespace internal {
33 namespace {
35 class ShowWallpaperAnimationObserver : public ui::ImplicitAnimationObserver,
36 public views::WidgetObserver {
37 public:
38 ShowWallpaperAnimationObserver(aura::RootWindow* root_window,
39 views::Widget* desktop_widget,
40 bool is_initial_animation)
41 : root_window_(root_window),
42 desktop_widget_(desktop_widget),
43 is_initial_animation_(is_initial_animation) {
44 DCHECK(desktop_widget_);
45 desktop_widget_->AddObserver(this);
48 virtual ~ShowWallpaperAnimationObserver() {
49 StopObservingImplicitAnimations();
50 if (desktop_widget_)
51 desktop_widget_->RemoveObserver(this);
54 private:
55 // Overridden from ui::ImplicitAnimationObserver:
56 virtual void OnImplicitAnimationsScheduled() OVERRIDE {
57 if (is_initial_animation_) {
58 GetRootWindowController(root_window_)->
59 HandleInitialDesktopBackgroundAnimationStarted();
63 virtual void OnImplicitAnimationsCompleted() OVERRIDE {
64 GetRootWindowController(root_window_)->HandleDesktopBackgroundVisible();
65 ash::Shell::GetInstance()->user_wallpaper_delegate()->
66 OnWallpaperAnimationFinished();
67 // Only removes old component when wallpaper animation finished. If we
68 // remove the old one before the new wallpaper is done fading in there will
69 // be a white flash during the animation.
70 if (root_window_->GetProperty(kAnimatingDesktopController)) {
71 DesktopBackgroundWidgetController* controller =
72 root_window_->GetProperty(kAnimatingDesktopController)->
73 GetController(true);
74 // |desktop_widget_| should be the same animating widget we try to move
75 // to |kDesktopController|. Otherwise, we may close |desktop_widget_|
76 // before move it to |kDesktopController|.
77 DCHECK_EQ(controller->widget(), desktop_widget_);
78 // Release the old controller and close its background widget.
79 root_window_->SetProperty(kDesktopController, controller);
81 delete this;
84 // Overridden from views::WidgetObserver.
85 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
86 delete this;
89 aura::RootWindow* root_window_;
90 views::Widget* desktop_widget_;
92 // Is this object observing the initial brightness/grayscale animation?
93 const bool is_initial_animation_;
95 DISALLOW_COPY_AND_ASSIGN(ShowWallpaperAnimationObserver);
98 // For our scaling ratios we need to round positive numbers.
99 int RoundPositive(double x) {
100 return static_cast<int>(floor(x + 0.5));
103 } // namespace
105 ////////////////////////////////////////////////////////////////////////////////
106 // DesktopBackgroundView, public:
108 DesktopBackgroundView::DesktopBackgroundView() {
109 set_context_menu_controller(this);
112 DesktopBackgroundView::~DesktopBackgroundView() {
115 ////////////////////////////////////////////////////////////////////////////////
116 // DesktopBackgroundView, views::View overrides:
118 void DesktopBackgroundView::OnPaint(gfx::Canvas* canvas) {
119 // Scale the image while maintaining the aspect ratio, cropping as
120 // necessary to fill the background. Ideally the image should be larger
121 // than the largest display supported, if not we will center it rather than
122 // streching to avoid upsampling artifacts (Note that we could tile too, but
123 // decided not to do this at the moment).
124 DesktopBackgroundController* controller =
125 ash::Shell::GetInstance()->desktop_background_controller();
126 gfx::ImageSkia wallpaper = controller->GetWallpaper();
127 WallpaperLayout wallpaper_layout = controller->GetWallpaperLayout();
129 gfx::Rect wallpaper_rect(0, 0, wallpaper.width(), wallpaper.height());
130 if (wallpaper_layout == WALLPAPER_LAYOUT_CENTER_CROPPED &&
131 wallpaper.width() > width() && wallpaper.height() > height()) {
132 // The dimension with the smallest ratio must be cropped, the other one
133 // is preserved. Both are set in gfx::Size cropped_size.
134 double horizontal_ratio = static_cast<double>(width()) /
135 static_cast<double>(wallpaper.width());
136 double vertical_ratio = static_cast<double>(height()) /
137 static_cast<double>(wallpaper.height());
139 gfx::Size cropped_size;
140 if (vertical_ratio > horizontal_ratio) {
141 cropped_size = gfx::Size(
142 RoundPositive(static_cast<double>(width()) / vertical_ratio),
143 wallpaper.height());
144 } else {
145 cropped_size = gfx::Size(wallpaper.width(),
146 RoundPositive(static_cast<double>(height()) / horizontal_ratio));
149 gfx::Rect wallpaper_cropped_rect = wallpaper_rect;
150 wallpaper_cropped_rect.ClampToCenteredSize(cropped_size);
151 canvas->DrawImageInt(wallpaper,
152 wallpaper_cropped_rect.x(), wallpaper_cropped_rect.y(),
153 wallpaper_cropped_rect.width(), wallpaper_cropped_rect.height(),
154 0, 0, width(), height(),
155 true);
156 } else if (wallpaper_layout == WALLPAPER_LAYOUT_TILE) {
157 canvas->TileImageInt(wallpaper, 0, 0, width(), height());
158 } else if (wallpaper_layout == WALLPAPER_LAYOUT_STRETCH) {
159 // This is generally not recommended as it may show artifacts.
160 canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(),
161 wallpaper.height(), 0, 0, width(), height(), true);
162 } else {
163 // All other are simply centered, and not scaled (but may be clipped).
164 canvas->DrawImageInt(wallpaper, (width() - wallpaper.width()) / 2,
165 (height() - wallpaper.height()) / 2);
169 bool DesktopBackgroundView::OnMousePressed(const ui::MouseEvent& event) {
170 return true;
173 void DesktopBackgroundView::ShowContextMenuForView(
174 views::View* source,
175 const gfx::Point& point,
176 ui::MenuSourceType source_type) {
177 Shell::GetInstance()->ShowContextMenu(point, source_type);
180 views::Widget* CreateDesktopBackground(aura::RootWindow* root_window,
181 int container_id) {
182 DesktopBackgroundController* controller =
183 ash::Shell::GetInstance()->desktop_background_controller();
184 ash::UserWallpaperDelegate* wallpaper_delegate =
185 ash::Shell::GetInstance()->user_wallpaper_delegate();
187 views::Widget* desktop_widget = new views::Widget;
188 views::Widget::InitParams params(
189 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
190 if (controller->GetWallpaper().isNull())
191 params.transparent = true;
192 params.parent = root_window->GetChildById(container_id);
193 desktop_widget->Init(params);
194 desktop_widget->SetContentsView(new DesktopBackgroundView());
195 int animation_type = wallpaper_delegate->GetAnimationType();
196 views::corewm::SetWindowVisibilityAnimationType(
197 desktop_widget->GetNativeView(), animation_type);
199 // Enable wallpaper transition for the following cases:
200 // 1. Initial(OOBE) wallpaper animation.
201 // 2. Wallpaper fades in from a non empty background.
202 // 3. From an empty background, chrome transit to a logged in user session.
203 // 4. From an empty background, guest user logged in.
204 if (wallpaper_delegate->ShouldShowInitialAnimation() ||
205 root_window->GetProperty(kAnimatingDesktopController) ||
206 Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers()) {
207 views::corewm::SetWindowVisibilityAnimationTransition(
208 desktop_widget->GetNativeView(), views::corewm::ANIMATE_SHOW);
209 } else {
210 // Disable animation if transition to login screen from an empty background.
211 views::corewm::SetWindowVisibilityAnimationTransition(
212 desktop_widget->GetNativeView(), views::corewm::ANIMATE_NONE);
215 desktop_widget->SetBounds(params.parent->bounds());
216 ui::ScopedLayerAnimationSettings settings(
217 desktop_widget->GetNativeView()->layer()->GetAnimator());
218 settings.SetPreemptionStrategy(ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
219 settings.AddObserver(new ShowWallpaperAnimationObserver(
220 root_window, desktop_widget,
221 wallpaper_delegate->ShouldShowInitialAnimation()));
222 desktop_widget->Show();
223 desktop_widget->GetNativeView()->SetName("DesktopBackgroundView");
224 return desktop_widget;
227 } // namespace internal
228 } // namespace ash