| OLD | NEW |
| (Empty) |
| 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_controller.h" | |
| 6 | |
| 7 #include "ash/aura/wm_window_aura.h" | |
| 8 #include "ash/common/display/display_info.h" | |
| 9 #include "ash/common/shell_window_ids.h" | |
| 10 #include "ash/common/wallpaper/wallpaper_delegate.h" | |
| 11 #include "ash/common/wm_shell.h" | |
| 12 #include "ash/desktop_background/desktop_background_controller_observer.h" | |
| 13 #include "ash/desktop_background/desktop_background_view.h" | |
| 14 #include "ash/desktop_background/desktop_background_widget_controller.h" | |
| 15 #include "ash/root_window_controller.h" | |
| 16 #include "ash/shell.h" | |
| 17 #include "base/bind.h" | |
| 18 #include "base/logging.h" | |
| 19 #include "base/threading/sequenced_worker_pool.h" | |
| 20 #include "components/wallpaper/wallpaper_resizer.h" | |
| 21 #include "ui/aura/window.h" | |
| 22 #include "ui/display/screen.h" | |
| 23 #include "ui/views/widget/widget.h" | |
| 24 | |
| 25 namespace ash { | |
| 26 namespace { | |
| 27 | |
| 28 // How long to wait reloading the wallpaper after the display size has changed. | |
| 29 const int kWallpaperReloadDelayMs = 100; | |
| 30 | |
| 31 } // namespace | |
| 32 | |
| 33 DesktopBackgroundController::DesktopBackgroundController( | |
| 34 base::SequencedWorkerPool* blocking_pool) | |
| 35 : locked_(false), | |
| 36 desktop_background_mode_(BACKGROUND_NONE), | |
| 37 wallpaper_reload_delay_(kWallpaperReloadDelayMs), | |
| 38 blocking_pool_(blocking_pool) { | |
| 39 WmShell::Get()->AddDisplayObserver(this); | |
| 40 WmShell::Get()->AddShellObserver(this); | |
| 41 } | |
| 42 | |
| 43 DesktopBackgroundController::~DesktopBackgroundController() { | |
| 44 WmShell::Get()->RemoveDisplayObserver(this); | |
| 45 WmShell::Get()->RemoveShellObserver(this); | |
| 46 } | |
| 47 | |
| 48 gfx::ImageSkia DesktopBackgroundController::GetWallpaper() const { | |
| 49 if (current_wallpaper_) | |
| 50 return current_wallpaper_->image(); | |
| 51 return gfx::ImageSkia(); | |
| 52 } | |
| 53 | |
| 54 void DesktopBackgroundController::AddObserver( | |
| 55 DesktopBackgroundControllerObserver* observer) { | |
| 56 observers_.AddObserver(observer); | |
| 57 } | |
| 58 | |
| 59 void DesktopBackgroundController::RemoveObserver( | |
| 60 DesktopBackgroundControllerObserver* observer) { | |
| 61 observers_.RemoveObserver(observer); | |
| 62 } | |
| 63 | |
| 64 wallpaper::WallpaperLayout DesktopBackgroundController::GetWallpaperLayout() | |
| 65 const { | |
| 66 if (current_wallpaper_) | |
| 67 return current_wallpaper_->layout(); | |
| 68 return wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; | |
| 69 } | |
| 70 | |
| 71 bool DesktopBackgroundController::SetWallpaperImage( | |
| 72 const gfx::ImageSkia& image, | |
| 73 wallpaper::WallpaperLayout layout) { | |
| 74 VLOG(1) << "SetWallpaper: image_id=" | |
| 75 << wallpaper::WallpaperResizer::GetImageId(image) | |
| 76 << " layout=" << layout; | |
| 77 | |
| 78 if (WallpaperIsAlreadyLoaded(image, true /* compare_layouts */, layout)) { | |
| 79 VLOG(1) << "Wallpaper is already loaded"; | |
| 80 return false; | |
| 81 } | |
| 82 | |
| 83 current_wallpaper_.reset(new wallpaper::WallpaperResizer( | |
| 84 image, GetMaxDisplaySizeInNative(), layout, blocking_pool_)); | |
| 85 current_wallpaper_->StartResize(); | |
| 86 | |
| 87 FOR_EACH_OBSERVER(DesktopBackgroundControllerObserver, observers_, | |
| 88 OnWallpaperDataChanged()); | |
| 89 desktop_background_mode_ = BACKGROUND_IMAGE; | |
| 90 InstallDesktopControllerForAllWindows(); | |
| 91 return true; | |
| 92 } | |
| 93 | |
| 94 void DesktopBackgroundController::CreateEmptyWallpaper() { | |
| 95 current_wallpaper_.reset(); | |
| 96 desktop_background_mode_ = BACKGROUND_IMAGE; | |
| 97 InstallDesktopControllerForAllWindows(); | |
| 98 } | |
| 99 | |
| 100 bool DesktopBackgroundController::MoveDesktopToLockedContainer() { | |
| 101 if (locked_) | |
| 102 return false; | |
| 103 locked_ = true; | |
| 104 return ReparentBackgroundWidgets(GetBackgroundContainerId(false), | |
| 105 GetBackgroundContainerId(true)); | |
| 106 } | |
| 107 | |
| 108 bool DesktopBackgroundController::MoveDesktopToUnlockedContainer() { | |
| 109 if (!locked_) | |
| 110 return false; | |
| 111 locked_ = false; | |
| 112 return ReparentBackgroundWidgets(GetBackgroundContainerId(true), | |
| 113 GetBackgroundContainerId(false)); | |
| 114 } | |
| 115 | |
| 116 void DesktopBackgroundController::OnDisplayConfigurationChanged() { | |
| 117 gfx::Size max_display_size = GetMaxDisplaySizeInNative(); | |
| 118 if (current_max_display_size_ != max_display_size) { | |
| 119 current_max_display_size_ = max_display_size; | |
| 120 if (desktop_background_mode_ == BACKGROUND_IMAGE && current_wallpaper_) { | |
| 121 timer_.Stop(); | |
| 122 timer_.Start(FROM_HERE, | |
| 123 base::TimeDelta::FromMilliseconds(wallpaper_reload_delay_), | |
| 124 base::Bind(&DesktopBackgroundController::UpdateWallpaper, | |
| 125 base::Unretained(this), false /* clear cache */)); | |
| 126 } | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 void DesktopBackgroundController::OnRootWindowAdded(WmWindow* root_window) { | |
| 131 // The background hasn't been set yet. | |
| 132 if (desktop_background_mode_ == BACKGROUND_NONE) | |
| 133 return; | |
| 134 | |
| 135 // Handle resolution change for "built-in" images. | |
| 136 gfx::Size max_display_size = GetMaxDisplaySizeInNative(); | |
| 137 if (current_max_display_size_ != max_display_size) { | |
| 138 current_max_display_size_ = max_display_size; | |
| 139 if (desktop_background_mode_ == BACKGROUND_IMAGE && current_wallpaper_) | |
| 140 UpdateWallpaper(true /* clear cache */); | |
| 141 } | |
| 142 | |
| 143 InstallDesktopController(root_window); | |
| 144 } | |
| 145 | |
| 146 // static | |
| 147 gfx::Size DesktopBackgroundController::GetMaxDisplaySizeInNative() { | |
| 148 // Return an empty size for test environments where the screen is null. | |
| 149 if (!display::Screen::GetScreen()) | |
| 150 return gfx::Size(); | |
| 151 | |
| 152 // Note that |shell| is null when this is called from Chrome running in Mash. | |
| 153 WmShell* shell = WmShell::Get(); | |
| 154 | |
| 155 gfx::Size max; | |
| 156 for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { | |
| 157 // Use the native size, not DisplayInfo::size_in_pixel or Display::size. | |
| 158 // TODO(msw): Avoid using Display::size here; see http://crbug.com/613657. | |
| 159 gfx::Size size = display.size(); | |
| 160 if (shell) | |
| 161 size = shell->GetDisplayInfo(display.id()).bounds_in_native().size(); | |
| 162 if (display.rotation() == display::Display::ROTATE_90 || | |
| 163 display.rotation() == display::Display::ROTATE_270) { | |
| 164 size = gfx::Size(size.height(), size.width()); | |
| 165 } | |
| 166 max.SetToMax(size); | |
| 167 } | |
| 168 | |
| 169 return max; | |
| 170 } | |
| 171 | |
| 172 bool DesktopBackgroundController::WallpaperIsAlreadyLoaded( | |
| 173 const gfx::ImageSkia& image, | |
| 174 bool compare_layouts, | |
| 175 wallpaper::WallpaperLayout layout) const { | |
| 176 if (!current_wallpaper_) | |
| 177 return false; | |
| 178 | |
| 179 // Compare layouts only if necessary. | |
| 180 if (compare_layouts && layout != current_wallpaper_->layout()) | |
| 181 return false; | |
| 182 | |
| 183 return wallpaper::WallpaperResizer::GetImageId(image) == | |
| 184 current_wallpaper_->original_image_id(); | |
| 185 } | |
| 186 | |
| 187 void DesktopBackgroundController::InstallDesktopController( | |
| 188 WmWindow* root_window) { | |
| 189 DesktopBackgroundWidgetController* component = nullptr; | |
| 190 int container_id = GetBackgroundContainerId(locked_); | |
| 191 | |
| 192 switch (desktop_background_mode_) { | |
| 193 case BACKGROUND_IMAGE: { | |
| 194 component = new DesktopBackgroundWidgetController( | |
| 195 CreateDesktopBackground(root_window, container_id)); | |
| 196 break; | |
| 197 } | |
| 198 case BACKGROUND_NONE: | |
| 199 NOTREACHED(); | |
| 200 return; | |
| 201 } | |
| 202 | |
| 203 aura::Window* aura_root_window = WmWindowAura::GetAuraWindow(root_window); | |
| 204 RootWindowController* controller = GetRootWindowController(aura_root_window); | |
| 205 controller->SetAnimatingWallpaperController( | |
| 206 new AnimatingDesktopController(component)); | |
| 207 component->StartAnimating(controller); | |
| 208 } | |
| 209 | |
| 210 void DesktopBackgroundController::InstallDesktopControllerForAllWindows() { | |
| 211 for (WmWindow* root : WmShell::Get()->GetAllRootWindows()) | |
| 212 InstallDesktopController(root); | |
| 213 current_max_display_size_ = GetMaxDisplaySizeInNative(); | |
| 214 } | |
| 215 | |
| 216 bool DesktopBackgroundController::ReparentBackgroundWidgets(int src_container, | |
| 217 int dst_container) { | |
| 218 bool moved = false; | |
| 219 for (auto* root_window_controller : Shell::GetAllRootWindowControllers()) { | |
| 220 // In the steady state (no animation playing) the background widget | |
| 221 // controller exists in the RootWindowController. | |
| 222 DesktopBackgroundWidgetController* desktop_controller = | |
| 223 root_window_controller->wallpaper_controller(); | |
| 224 if (desktop_controller) { | |
| 225 moved |= | |
| 226 desktop_controller->Reparent(root_window_controller->GetRootWindow(), | |
| 227 src_container, dst_container); | |
| 228 } | |
| 229 // During desktop show animations the controller lives in | |
| 230 // AnimatingDesktopController owned by RootWindowController. | |
| 231 // NOTE: If a wallpaper load happens during a desktop show animation there | |
| 232 // can temporarily be two desktop background widgets. We must reparent | |
| 233 // both of them - one above and one here. | |
| 234 DesktopBackgroundWidgetController* animating_controller = | |
| 235 root_window_controller->animating_wallpaper_controller() | |
| 236 ? root_window_controller->animating_wallpaper_controller() | |
| 237 ->GetController(false) | |
| 238 : nullptr; | |
| 239 if (animating_controller) { | |
| 240 moved |= animating_controller->Reparent( | |
| 241 root_window_controller->GetRootWindow(), src_container, | |
| 242 dst_container); | |
| 243 } | |
| 244 } | |
| 245 return moved; | |
| 246 } | |
| 247 | |
| 248 int DesktopBackgroundController::GetBackgroundContainerId(bool locked) { | |
| 249 return locked ? kShellWindowId_LockScreenBackgroundContainer | |
| 250 : kShellWindowId_DesktopBackgroundContainer; | |
| 251 } | |
| 252 | |
| 253 void DesktopBackgroundController::UpdateWallpaper(bool clear_cache) { | |
| 254 current_wallpaper_.reset(); | |
| 255 WmShell::Get()->wallpaper_delegate()->UpdateWallpaper(clear_cache); | |
| 256 } | |
| 257 | |
| 258 } // namespace ash | |
| OLD | NEW |