| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/desktop_background/desktop_background_controller.h" | 5 #include "ash/desktop_background/desktop_background_controller.h" |
| 6 | 6 |
| 7 #include "ash/desktop_background/desktop_background_view.h" | 7 #include "ash/desktop_background/desktop_background_view.h" |
| 8 #include "ash/desktop_background/desktop_background_widget_controller.h" |
| 8 #include "ash/shell.h" | 9 #include "ash/shell.h" |
| 9 #include "ash/shell_factory.h" | 10 #include "ash/shell_factory.h" |
| 10 #include "ash/shell_window_ids.h" | 11 #include "ash/shell_window_ids.h" |
| 11 #include "ash/wm/root_window_layout_manager.h" | 12 #include "ash/wm/root_window_layout_manager.h" |
| 12 #include "base/bind.h" | 13 #include "base/bind.h" |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/synchronization/cancellation_flag.h" | 15 #include "base/synchronization/cancellation_flag.h" |
| 15 #include "base/threading/worker_pool.h" | 16 #include "base/threading/worker_pool.h" |
| 16 #include "grit/ui_resources.h" | 17 #include "grit/ui_resources.h" |
| 17 #include "ui/aura/root_window.h" | 18 #include "ui/aura/root_window.h" |
| 18 #include "ui/aura/window.h" | 19 #include "ui/aura/window.h" |
| 19 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
| 20 #include "ui/compositor/layer.h" | 21 #include "ui/compositor/layer.h" |
| 22 #include "ui/gfx/rect.h" |
| 21 #include "ui/gfx/image/image.h" | 23 #include "ui/gfx/image/image.h" |
| 22 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
| 23 | 25 |
| 24 namespace ash { | 26 namespace ash { |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 27 const int kSmallWallpaperMaximalWidth = 1366; | 29 const int kSmallWallpaperMaximalWidth = 1366; |
| 28 const int kSmallWallpaperMaximalHeight = 800; | 30 const int kSmallWallpaperMaximalHeight = 800; |
| 29 | 31 |
| 30 internal::RootWindowLayoutManager* GetRootWindowLayoutManager( | 32 internal::RootWindowLayoutManager* GetRootWindowLayoutManager( |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 scoped_ptr<WallpaperData> wallpaper_data_; | 94 scoped_ptr<WallpaperData> wallpaper_data_; |
| 93 | 95 |
| 94 const int index_; | 96 const int index_; |
| 95 | 97 |
| 96 const WallpaperResolution resolution_; | 98 const WallpaperResolution resolution_; |
| 97 | 99 |
| 98 DISALLOW_COPY_AND_ASSIGN(WallpaperOperation); | 100 DISALLOW_COPY_AND_ASSIGN(WallpaperOperation); |
| 99 }; | 101 }; |
| 100 | 102 |
| 101 DesktopBackgroundController::DesktopBackgroundController() | 103 DesktopBackgroundController::DesktopBackgroundController() |
| 102 : desktop_background_mode_(BACKGROUND_IMAGE), | 104 : locked_(false), |
| 105 desktop_background_mode_(BACKGROUND_SOLID_COLOR), |
| 103 background_color_(SK_ColorGRAY), | 106 background_color_(SK_ColorGRAY), |
| 104 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 107 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 108 InstallComponentForAllWindows(); |
| 105 } | 109 } |
| 106 | 110 |
| 107 DesktopBackgroundController::~DesktopBackgroundController() { | 111 DesktopBackgroundController::~DesktopBackgroundController() { |
| 108 CancelPendingWallpaperOperation(); | 112 CancelPendingWallpaperOperation(); |
| 109 } | 113 } |
| 110 | 114 |
| 111 gfx::ImageSkia DesktopBackgroundController::GetWallpaper() const { | 115 gfx::ImageSkia DesktopBackgroundController::GetWallpaper() const { |
| 112 if (current_wallpaper_.get()) | 116 if (current_wallpaper_.get()) |
| 113 return current_wallpaper_->wallpaper_image; | 117 return current_wallpaper_->wallpaper_image; |
| 114 return gfx::ImageSkia(); | 118 return gfx::ImageSkia(); |
| 115 } | 119 } |
| 116 | 120 |
| 117 WallpaperLayout DesktopBackgroundController::GetWallpaperLayout() const { | 121 WallpaperLayout DesktopBackgroundController::GetWallpaperLayout() const { |
| 118 if (current_wallpaper_.get()) | 122 if (current_wallpaper_.get()) |
| 119 return current_wallpaper_->wallpaper_layout; | 123 return current_wallpaper_->wallpaper_layout; |
| 120 return CENTER_CROPPED; | 124 return CENTER_CROPPED; |
| 121 } | 125 } |
| 122 | 126 |
| 123 SkBitmap DesktopBackgroundController::GetCurrentWallpaperImage() { | 127 SkBitmap DesktopBackgroundController::GetCurrentWallpaperImage() { |
| 124 if (desktop_background_mode_ != BACKGROUND_IMAGE) | 128 if (desktop_background_mode_ != BACKGROUND_IMAGE) |
| 125 return SkBitmap(); | 129 return SkBitmap(); |
| 126 return GetWallpaper(); | 130 return GetWallpaper(); |
| 127 } | 131 } |
| 128 | 132 |
| 129 void DesktopBackgroundController::OnRootWindowAdded( | 133 void DesktopBackgroundController::OnRootWindowAdded( |
| 130 aura::RootWindow* root_window) { | 134 aura::RootWindow* root_window) { |
| 131 switch (desktop_background_mode_) { | 135 // Handle resolution change for "built-in" images." |
| 132 case BACKGROUND_IMAGE: | 136 if (BACKGROUND_IMAGE == desktop_background_mode_) { |
| 133 if (current_wallpaper_.get()) { | 137 if (current_wallpaper_.get()) { |
| 134 gfx::Size root_window_size = root_window->GetHostSize(); | 138 gfx::Size root_window_size = root_window->GetHostSize(); |
| 135 int wallpaper_width = current_wallpaper_->wallpaper_image.width(); | 139 int wallpaper_width = current_wallpaper_->wallpaper_image.width(); |
| 136 int wallpaper_height = current_wallpaper_->wallpaper_image.height(); | 140 int wallpaper_height = current_wallpaper_->wallpaper_image.height(); |
| 137 // Loads a higher resolution wallpaper if needed. | 141 // Loads a higher resolution wallpaper if needed. |
| 138 if ((wallpaper_width < root_window_size.width() || | 142 if ((wallpaper_width < root_window_size.width() || |
| 139 wallpaper_height < root_window_size.height()) && | 143 wallpaper_height < root_window_size.height()) && |
| 140 current_wallpaper_->wallpaper_index != -1 && | 144 current_wallpaper_->wallpaper_index != -1 && |
| 141 current_wallpaper_->wallpaper_layout != TILE) | 145 current_wallpaper_->wallpaper_layout != TILE) |
| 142 SetDefaultWallpaper(current_wallpaper_->wallpaper_index, true); | 146 SetDefaultWallpaper(current_wallpaper_->wallpaper_index, true); |
| 143 else | 147 } |
| 144 SetDesktopBackgroundImage(root_window); | |
| 145 } else { | |
| 146 internal::CreateDesktopBackground(root_window); | |
| 147 } | |
| 148 break; | |
| 149 case BACKGROUND_SOLID_COLOR: | |
| 150 SetDesktopBackgroundSolidColorMode(background_color_); | |
| 151 break; | |
| 152 } | 148 } |
| 149 |
| 150 InstallComponent(root_window); |
| 153 } | 151 } |
| 154 | 152 |
| 155 void DesktopBackgroundController::SetDefaultWallpaper(int index, | 153 void DesktopBackgroundController::SetDefaultWallpaper(int index, |
| 156 bool force_reload) { | 154 bool force_reload) { |
| 157 // We should not change background when index is invalid. For instance, at | 155 // We should not change background when index is invalid. For instance, at |
| 158 // login screen or stub_user login. | 156 // login screen or stub_user login. |
| 159 if (index == ash::GetInvalidWallpaperIndex()) { | 157 if (index == GetInvalidWallpaperIndex()) { |
| 160 CreateEmptyWallpaper(); | 158 CreateEmptyWallpaper(); |
| 161 return; | 159 return; |
| 162 } else if (index == ash::GetSolidColorIndex()) { | 160 } else if (index == GetSolidColorIndex()) { |
| 163 SetDesktopBackgroundSolidColorMode(kLoginWallpaperColor); | 161 SetDesktopBackgroundSolidColorMode(kLoginWallpaperColor); |
| 164 return; | 162 return; |
| 165 } | 163 } |
| 166 | 164 |
| 167 if (!force_reload && current_wallpaper_.get() && | 165 if (!force_reload && current_wallpaper_.get() && |
| 168 current_wallpaper_->wallpaper_index == index) | 166 current_wallpaper_->wallpaper_index == index) |
| 169 return; | 167 return; |
| 170 | 168 |
| 171 CancelPendingWallpaperOperation(); | 169 CancelPendingWallpaperOperation(); |
| 172 | 170 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 188 weak_ptr_factory_.GetWeakPtr(), | 186 weak_ptr_factory_.GetWeakPtr(), |
| 189 wallpaper_op_), | 187 wallpaper_op_), |
| 190 true /* task_is_slow */); | 188 true /* task_is_slow */); |
| 191 } | 189 } |
| 192 | 190 |
| 193 void DesktopBackgroundController::SetCustomWallpaper( | 191 void DesktopBackgroundController::SetCustomWallpaper( |
| 194 const gfx::ImageSkia& wallpaper, | 192 const gfx::ImageSkia& wallpaper, |
| 195 WallpaperLayout layout) { | 193 WallpaperLayout layout) { |
| 196 CancelPendingWallpaperOperation(); | 194 CancelPendingWallpaperOperation(); |
| 197 current_wallpaper_.reset(new WallpaperData(layout, wallpaper)); | 195 current_wallpaper_.reset(new WallpaperData(layout, wallpaper)); |
| 198 desktop_background_mode_ = BACKGROUND_IMAGE; | 196 SetDesktopBackgroundImageMode(); |
| 199 UpdateDesktopBackgroundImageMode(); | |
| 200 } | 197 } |
| 201 | 198 |
| 202 void DesktopBackgroundController::CancelPendingWallpaperOperation() { | 199 void DesktopBackgroundController::CancelPendingWallpaperOperation() { |
| 203 // Set canceled flag of previous request to skip unneeded loading. | 200 // Set canceled flag of previous request to skip unneeded loading. |
| 204 if (wallpaper_op_.get()) | 201 if (wallpaper_op_.get()) |
| 205 wallpaper_op_->Cancel(); | 202 wallpaper_op_->Cancel(); |
| 206 | 203 |
| 207 // Cancel reply callback for previous request. | 204 // Cancel reply callback for previous request. |
| 208 weak_ptr_factory_.InvalidateWeakPtrs(); | 205 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 209 } | 206 } |
| 210 | 207 |
| 211 void DesktopBackgroundController::SetDesktopBackgroundSolidColorMode( | 208 void DesktopBackgroundController::SetDesktopBackgroundSolidColorMode( |
| 212 SkColor color) { | 209 SkColor color) { |
| 213 // Set a solid black background. | |
| 214 // TODO(derat): Remove this in favor of having the compositor only clear the | |
| 215 // viewport when there are regions not covered by a layer: | |
| 216 // http://crbug.com/113445 | |
| 217 current_wallpaper_.reset(NULL); | |
| 218 background_color_ = color; | 210 background_color_ = color; |
| 219 desktop_background_mode_ = BACKGROUND_SOLID_COLOR; | 211 if (desktop_background_mode_ != BACKGROUND_SOLID_COLOR) { |
| 212 desktop_background_mode_ = BACKGROUND_SOLID_COLOR; |
| 213 InstallComponentForAllWindows(); |
| 214 return; |
| 215 } |
| 216 |
| 220 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 217 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 221 for (Shell::RootWindowList::iterator iter = root_windows.begin(); | 218 for (Shell::RootWindowList::iterator iter = root_windows.begin(); |
| 222 iter != root_windows.end(); ++iter) { | 219 iter != root_windows.end(); ++iter) { |
| 223 ui::Layer* background_layer = new ui::Layer(ui::LAYER_SOLID_COLOR); | |
| 224 background_layer->SetColor(color); | |
| 225 aura::RootWindow* root_window = *iter; | 220 aura::RootWindow* root_window = *iter; |
| 226 Shell::GetContainer( | 221 internal::DesktopBackgroundWidgetController* component = root_window-> |
| 227 root_window, | 222 GetProperty(internal::kWindowDesktopComponent); |
| 228 internal::kShellWindowId_DesktopBackgroundContainer)-> | 223 DCHECK(component); |
| 229 layer()->Add(background_layer); | 224 DCHECK(component->layer()); |
| 230 GetRootWindowLayoutManager(root_window)->SetBackgroundLayer( | 225 component->layer()->SetColor(background_color_ ); |
| 231 background_layer); | |
| 232 GetRootWindowLayoutManager(root_window)->SetBackgroundWidget(NULL); | |
| 233 } | 226 } |
| 234 } | 227 } |
| 235 | 228 |
| 236 void DesktopBackgroundController::SetDesktopBackgroundImage( | 229 void DesktopBackgroundController::CreateEmptyWallpaper() { |
| 237 aura::RootWindow* root_window) { | 230 current_wallpaper_.reset(NULL); |
| 238 GetRootWindowLayoutManager(root_window)->SetBackgroundLayer(NULL); | 231 SetDesktopBackgroundImageMode(); |
| 239 if (current_wallpaper_.get() && | |
| 240 !current_wallpaper_->wallpaper_image.empty()) | |
| 241 internal::CreateDesktopBackground(root_window); | |
| 242 } | 232 } |
| 243 | 233 |
| 244 void DesktopBackgroundController::UpdateDesktopBackgroundImageMode() { | 234 void DesktopBackgroundController::MoveDesktopToLockedContainer() { |
| 235 if (locked_) |
| 236 return; |
| 237 locked_ = true; |
| 238 ReparentBackgroundWidgets(GetBackgroundContainerId(false), |
| 239 GetBackgroundContainerId(true)); |
| 240 } |
| 241 |
| 242 void DesktopBackgroundController::MoveDesktopToUnlockedContainer() { |
| 243 if (!locked_) |
| 244 return; |
| 245 locked_ = false; |
| 246 ReparentBackgroundWidgets(GetBackgroundContainerId(true), |
| 247 GetBackgroundContainerId(false)); |
| 248 } |
| 249 |
| 250 void DesktopBackgroundController::OnWindowDestroying(aura::Window* window) { |
| 251 window->SetProperty(internal::kWindowDesktopComponent, |
| 252 static_cast<internal::DesktopBackgroundWidgetController*>(NULL)); |
| 253 } |
| 254 |
| 255 void DesktopBackgroundController::SetDesktopBackgroundImageMode() { |
| 256 if (desktop_background_mode_ != BACKGROUND_IMAGE) { |
| 257 desktop_background_mode_ = BACKGROUND_IMAGE; |
| 258 InstallComponentForAllWindows(); |
| 259 return; |
| 260 } |
| 261 |
| 245 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 262 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 246 | |
| 247 for (Shell::RootWindowList::iterator iter = root_windows.begin(); | 263 for (Shell::RootWindowList::iterator iter = root_windows.begin(); |
| 248 iter != root_windows.end(); ++iter) { | 264 iter != root_windows.end(); ++iter) { |
| 249 SetDesktopBackgroundImage(*iter); | 265 aura::RootWindow* root_window = *iter; |
| 266 internal::DesktopBackgroundWidgetController* component = root_window-> |
| 267 GetProperty(internal::kWindowDesktopComponent); |
| 268 DCHECK(component); |
| 269 DCHECK(component->widget()); |
| 270 aura::Window* window = component->widget()->GetNativeView(); |
| 271 gfx::Rect bounds = window->bounds(); |
| 272 window->SchedulePaintInRect(gfx::Rect(0, 0, |
| 273 bounds.width(), bounds.height())); |
| 250 } | 274 } |
| 251 desktop_background_mode_ = BACKGROUND_IMAGE; | |
| 252 } | 275 } |
| 253 | 276 |
| 254 void DesktopBackgroundController::OnWallpaperLoadCompleted( | 277 void DesktopBackgroundController::OnWallpaperLoadCompleted( |
| 255 scoped_refptr<WallpaperOperation> wo) { | 278 scoped_refptr<WallpaperOperation> wo) { |
| 256 current_wallpaper_.reset(wo->ReleaseWallpaperData()); | 279 current_wallpaper_.reset(wo->ReleaseWallpaperData()); |
| 257 | 280 |
| 258 UpdateDesktopBackgroundImageMode(); | 281 SetDesktopBackgroundImageMode(); |
| 259 | 282 |
| 260 DCHECK(wo.get() == wallpaper_op_.get()); | 283 DCHECK(wo.get() == wallpaper_op_.get()); |
| 261 wallpaper_op_ = NULL; | 284 wallpaper_op_ = NULL; |
| 262 } | 285 } |
| 263 | 286 |
| 264 void DesktopBackgroundController::CreateEmptyWallpaper() { | 287 ui::Layer* DesktopBackgroundController::SetColorLayerForContainer( |
| 265 current_wallpaper_.reset(NULL); | 288 SkColor color, |
| 266 desktop_background_mode_ = BACKGROUND_IMAGE; | 289 aura::RootWindow* root_window, |
| 290 int container_id) { |
| 291 ui::Layer* background_layer = new ui::Layer(ui::LAYER_SOLID_COLOR); |
| 292 background_layer->SetColor(color); |
| 293 |
| 294 Shell::GetContainer(root_window,container_id)-> |
| 295 layer()->Add(background_layer); |
| 296 return background_layer; |
| 297 } |
| 298 |
| 299 void DesktopBackgroundController::InstallComponent( |
| 300 aura::RootWindow* root_window) { |
| 301 internal::DesktopBackgroundWidgetController* component = NULL; |
| 302 int container_id = GetBackgroundContainerId(locked_); |
| 303 |
| 304 switch (desktop_background_mode_) { |
| 305 case BACKGROUND_IMAGE: { |
| 306 views::Widget* widget = internal::CreateDesktopBackground(root_window, |
| 307 container_id); |
| 308 component = new internal::DesktopBackgroundWidgetController(widget); |
| 309 break; |
| 310 } |
| 311 case BACKGROUND_SOLID_COLOR: { |
| 312 ui::Layer* layer = SetColorLayerForContainer(background_color_, |
| 313 root_window, |
| 314 container_id); |
| 315 component = new internal::DesktopBackgroundWidgetController(layer); |
| 316 break; |
| 317 } |
| 318 default: { |
| 319 NOTREACHED(); |
| 320 } |
| 321 } |
| 322 if (NULL == root_window->GetProperty(internal::kWindowDesktopComponent)) { |
| 323 // First time for this root window |
| 324 root_window->AddObserver(this); |
| 325 } |
| 326 root_window->SetProperty(internal::kWindowDesktopComponent, component); |
| 327 } |
| 328 |
| 329 void DesktopBackgroundController::InstallComponentForAllWindows() { |
| 267 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 330 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 268 for (Shell::RootWindowList::iterator iter = root_windows.begin(); | 331 for (Shell::RootWindowList::iterator iter = root_windows.begin(); |
| 269 iter != root_windows.end(); ++iter) { | 332 iter != root_windows.end(); ++iter) { |
| 270 internal::CreateDesktopBackground(*iter); | 333 InstallComponent(*iter); |
| 271 } | 334 } |
| 272 } | 335 } |
| 273 | 336 |
| 337 void DesktopBackgroundController::ReparentBackgroundWidgets(int src_container, |
| 338 int dst_container) { |
| 339 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 340 for (Shell::RootWindowList::iterator iter = root_windows.begin(); |
| 341 iter != root_windows.end(); ++iter) { |
| 342 aura::RootWindow* root_window = *iter; |
| 343 internal::DesktopBackgroundWidgetController* component = root_window-> |
| 344 GetProperty(internal::kWindowDesktopComponent); |
| 345 DCHECK(component); |
| 346 component->Reparent(root_window, |
| 347 src_container, |
| 348 dst_container); |
| 349 } |
| 350 } |
| 351 |
| 352 int DesktopBackgroundController::GetBackgroundContainerId(bool locked) { |
| 353 return locked ? internal::kShellWindowId_LockScreenBackgroundContainer : |
| 354 internal::kShellWindowId_DesktopBackgroundContainer; |
| 355 } |
| 356 |
| 274 } // namespace ash | 357 } // namespace ash |
| OLD | NEW |