| 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/common/wallpaper/wallpaper_controller.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "ash/common/ash_switches.h" | |
| 11 #include "ash/common/wallpaper/wallpaper_controller_observer.h" | |
| 12 #include "ash/common/wallpaper/wallpaper_delegate.h" | |
| 13 #include "ash/common/wallpaper/wallpaper_view.h" | |
| 14 #include "ash/common/wallpaper/wallpaper_widget_controller.h" | |
| 15 #include "ash/common/wm_shell.h" | |
| 16 #include "ash/common/wm_window.h" | |
| 17 #include "ash/public/cpp/shell_window_ids.h" | |
| 18 #include "ash/root_window_controller.h" | |
| 19 #include "base/bind.h" | |
| 20 #include "base/command_line.h" | |
| 21 #include "base/logging.h" | |
| 22 #include "base/task_runner.h" | |
| 23 #include "components/wallpaper/wallpaper_color_calculator.h" | |
| 24 #include "components/wallpaper/wallpaper_resizer.h" | |
| 25 #include "ui/display/manager/managed_display_info.h" | |
| 26 #include "ui/display/screen.h" | |
| 27 #include "ui/gfx/color_analysis.h" | |
| 28 #include "ui/views/widget/widget.h" | |
| 29 | |
| 30 namespace ash { | |
| 31 | |
| 32 namespace { | |
| 33 | |
| 34 // How long to wait reloading the wallpaper after the display size has changed. | |
| 35 const int kWallpaperReloadDelayMs = 100; | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 // static | |
| 40 bool WallpaperController::GetProminentColorProfile( | |
| 41 color_utils::LumaRange* luma, | |
| 42 color_utils::SaturationRange* saturation) { | |
| 43 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 44 switches::kAshShelfColor)) { | |
| 45 return false; | |
| 46 } | |
| 47 | |
| 48 *luma = color_utils::LumaRange::NORMAL; | |
| 49 *saturation = color_utils::SaturationRange::VIBRANT; | |
| 50 | |
| 51 const std::string switch_value = | |
| 52 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 53 switches::kAshShelfColor); | |
| 54 if (switch_value.find("light") != std::string::npos) | |
| 55 *luma = color_utils::LumaRange::LIGHT; | |
| 56 else if (switch_value.find("normal") != std::string::npos) | |
| 57 *luma = color_utils::LumaRange::NORMAL; | |
| 58 else if (switch_value.find("dark") != std::string::npos) | |
| 59 *luma = color_utils::LumaRange::DARK; | |
| 60 | |
| 61 if (switch_value.find("vibrant") != std::string::npos) | |
| 62 *saturation = color_utils::SaturationRange::VIBRANT; | |
| 63 else if (switch_value.find("muted") != std::string::npos) | |
| 64 *saturation = color_utils::SaturationRange::MUTED; | |
| 65 | |
| 66 return true; | |
| 67 } | |
| 68 | |
| 69 WallpaperController::WallpaperController( | |
| 70 const scoped_refptr<base::TaskRunner>& task_runner) | |
| 71 : locked_(false), | |
| 72 wallpaper_mode_(WALLPAPER_NONE), | |
| 73 prominent_color_(SK_ColorTRANSPARENT), | |
| 74 wallpaper_reload_delay_(kWallpaperReloadDelayMs), | |
| 75 task_runner_(task_runner) { | |
| 76 WmShell::Get()->AddDisplayObserver(this); | |
| 77 WmShell::Get()->AddShellObserver(this); | |
| 78 } | |
| 79 | |
| 80 WallpaperController::~WallpaperController() { | |
| 81 if (current_wallpaper_) | |
| 82 current_wallpaper_->RemoveObserver(this); | |
| 83 if (color_calculator_) | |
| 84 color_calculator_->RemoveObserver(this); | |
| 85 WmShell::Get()->RemoveDisplayObserver(this); | |
| 86 WmShell::Get()->RemoveShellObserver(this); | |
| 87 } | |
| 88 | |
| 89 void WallpaperController::BindRequest( | |
| 90 mojom::WallpaperControllerRequest request) { | |
| 91 bindings_.AddBinding(this, std::move(request)); | |
| 92 } | |
| 93 | |
| 94 gfx::ImageSkia WallpaperController::GetWallpaper() const { | |
| 95 if (current_wallpaper_) | |
| 96 return current_wallpaper_->image(); | |
| 97 return gfx::ImageSkia(); | |
| 98 } | |
| 99 | |
| 100 void WallpaperController::AddObserver(WallpaperControllerObserver* observer) { | |
| 101 observers_.AddObserver(observer); | |
| 102 } | |
| 103 | |
| 104 void WallpaperController::RemoveObserver( | |
| 105 WallpaperControllerObserver* observer) { | |
| 106 observers_.RemoveObserver(observer); | |
| 107 } | |
| 108 | |
| 109 wallpaper::WallpaperLayout WallpaperController::GetWallpaperLayout() const { | |
| 110 if (current_wallpaper_) | |
| 111 return current_wallpaper_->layout(); | |
| 112 return wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED; | |
| 113 } | |
| 114 | |
| 115 void WallpaperController::SetWallpaperImage(const gfx::ImageSkia& image, | |
| 116 wallpaper::WallpaperLayout layout) { | |
| 117 VLOG(1) << "SetWallpaper: image_id=" | |
| 118 << wallpaper::WallpaperResizer::GetImageId(image) | |
| 119 << " layout=" << layout; | |
| 120 | |
| 121 if (WallpaperIsAlreadyLoaded(image, true /* compare_layouts */, layout)) { | |
| 122 VLOG(1) << "Wallpaper is already loaded"; | |
| 123 return; | |
| 124 } | |
| 125 | |
| 126 current_wallpaper_.reset(new wallpaper::WallpaperResizer( | |
| 127 image, GetMaxDisplaySizeInNative(), layout, task_runner_)); | |
| 128 current_wallpaper_->AddObserver(this); | |
| 129 current_wallpaper_->StartResize(); | |
| 130 | |
| 131 for (auto& observer : observers_) | |
| 132 observer.OnWallpaperDataChanged(); | |
| 133 wallpaper_mode_ = WALLPAPER_IMAGE; | |
| 134 InstallDesktopControllerForAllWindows(); | |
| 135 } | |
| 136 | |
| 137 void WallpaperController::CreateEmptyWallpaper() { | |
| 138 SetProminentColor(SK_ColorTRANSPARENT); | |
| 139 current_wallpaper_.reset(); | |
| 140 wallpaper_mode_ = WALLPAPER_IMAGE; | |
| 141 InstallDesktopControllerForAllWindows(); | |
| 142 } | |
| 143 | |
| 144 bool WallpaperController::MoveToLockedContainer() { | |
| 145 if (locked_) | |
| 146 return false; | |
| 147 locked_ = true; | |
| 148 return ReparentWallpaper(GetWallpaperContainerId(true)); | |
| 149 } | |
| 150 | |
| 151 bool WallpaperController::MoveToUnlockedContainer() { | |
| 152 if (!locked_) | |
| 153 return false; | |
| 154 locked_ = false; | |
| 155 return ReparentWallpaper(GetWallpaperContainerId(false)); | |
| 156 } | |
| 157 | |
| 158 void WallpaperController::OnDisplayConfigurationChanged() { | |
| 159 gfx::Size max_display_size = GetMaxDisplaySizeInNative(); | |
| 160 if (current_max_display_size_ != max_display_size) { | |
| 161 current_max_display_size_ = max_display_size; | |
| 162 if (wallpaper_mode_ == WALLPAPER_IMAGE && current_wallpaper_) { | |
| 163 timer_.Stop(); | |
| 164 timer_.Start(FROM_HERE, | |
| 165 base::TimeDelta::FromMilliseconds(wallpaper_reload_delay_), | |
| 166 base::Bind(&WallpaperController::UpdateWallpaper, | |
| 167 base::Unretained(this), false /* clear cache */)); | |
| 168 } | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 void WallpaperController::OnRootWindowAdded(WmWindow* root_window) { | |
| 173 // The wallpaper hasn't been set yet. | |
| 174 if (wallpaper_mode_ == WALLPAPER_NONE) | |
| 175 return; | |
| 176 | |
| 177 // Handle resolution change for "built-in" images. | |
| 178 gfx::Size max_display_size = GetMaxDisplaySizeInNative(); | |
| 179 if (current_max_display_size_ != max_display_size) { | |
| 180 current_max_display_size_ = max_display_size; | |
| 181 if (wallpaper_mode_ == WALLPAPER_IMAGE && current_wallpaper_) | |
| 182 UpdateWallpaper(true /* clear cache */); | |
| 183 } | |
| 184 | |
| 185 InstallDesktopController(root_window); | |
| 186 } | |
| 187 | |
| 188 // static | |
| 189 gfx::Size WallpaperController::GetMaxDisplaySizeInNative() { | |
| 190 // Return an empty size for test environments where the screen is null. | |
| 191 if (!display::Screen::GetScreen()) | |
| 192 return gfx::Size(); | |
| 193 | |
| 194 // Note that |shell| is null when this is called from Chrome running in Mash. | |
| 195 WmShell* shell = WmShell::Get(); | |
| 196 | |
| 197 gfx::Size max; | |
| 198 for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) { | |
| 199 // Use the native size, not ManagedDisplayInfo::size_in_pixel or | |
| 200 // Display::size. | |
| 201 // TODO(msw): Avoid using Display::size here; see http://crbug.com/613657. | |
| 202 gfx::Size size = display.size(); | |
| 203 if (shell) { | |
| 204 display::ManagedDisplayInfo info = shell->GetDisplayInfo(display.id()); | |
| 205 // TODO(mash): Mash returns a fake ManagedDisplayInfo. crbug.com/622480 | |
| 206 if (info.id() == display.id()) | |
| 207 size = info.bounds_in_native().size(); | |
| 208 } | |
| 209 if (display.rotation() == display::Display::ROTATE_90 || | |
| 210 display.rotation() == display::Display::ROTATE_270) { | |
| 211 size = gfx::Size(size.height(), size.width()); | |
| 212 } | |
| 213 max.SetToMax(size); | |
| 214 } | |
| 215 | |
| 216 return max; | |
| 217 } | |
| 218 | |
| 219 bool WallpaperController::WallpaperIsAlreadyLoaded( | |
| 220 const gfx::ImageSkia& image, | |
| 221 bool compare_layouts, | |
| 222 wallpaper::WallpaperLayout layout) const { | |
| 223 if (!current_wallpaper_) | |
| 224 return false; | |
| 225 | |
| 226 // Compare layouts only if necessary. | |
| 227 if (compare_layouts && layout != current_wallpaper_->layout()) | |
| 228 return false; | |
| 229 | |
| 230 return wallpaper::WallpaperResizer::GetImageId(image) == | |
| 231 current_wallpaper_->original_image_id(); | |
| 232 } | |
| 233 | |
| 234 void WallpaperController::OpenSetWallpaperPage() { | |
| 235 if (wallpaper_picker_ && | |
| 236 WmShell::Get()->wallpaper_delegate()->CanOpenSetWallpaperPage()) { | |
| 237 wallpaper_picker_->Open(); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 void WallpaperController::SetWallpaperPicker(mojom::WallpaperPickerPtr picker) { | |
| 242 wallpaper_picker_ = std::move(picker); | |
| 243 } | |
| 244 | |
| 245 void WallpaperController::SetWallpaper(const SkBitmap& wallpaper, | |
| 246 wallpaper::WallpaperLayout layout) { | |
| 247 if (wallpaper.isNull()) | |
| 248 return; | |
| 249 | |
| 250 SetWallpaperImage(gfx::ImageSkia::CreateFrom1xBitmap(wallpaper), layout); | |
| 251 } | |
| 252 | |
| 253 void WallpaperController::OnWallpaperResized() { | |
| 254 CalculateWallpaperColors(); | |
| 255 } | |
| 256 | |
| 257 void WallpaperController::OnColorCalculationComplete() { | |
| 258 const SkColor color = color_calculator_->prominent_color(); | |
| 259 color_calculator_.reset(); | |
| 260 SetProminentColor(color); | |
| 261 } | |
| 262 | |
| 263 void WallpaperController::InstallDesktopController(WmWindow* root_window) { | |
| 264 WallpaperWidgetController* component = nullptr; | |
| 265 int container_id = GetWallpaperContainerId(locked_); | |
| 266 | |
| 267 switch (wallpaper_mode_) { | |
| 268 case WALLPAPER_IMAGE: { | |
| 269 component = new WallpaperWidgetController( | |
| 270 CreateWallpaper(root_window, container_id)); | |
| 271 break; | |
| 272 } | |
| 273 case WALLPAPER_NONE: | |
| 274 NOTREACHED(); | |
| 275 return; | |
| 276 } | |
| 277 | |
| 278 RootWindowController* controller = root_window->GetRootWindowController(); | |
| 279 controller->SetAnimatingWallpaperWidgetController( | |
| 280 new AnimatingWallpaperWidgetController(component)); | |
| 281 component->StartAnimating(controller); | |
| 282 } | |
| 283 | |
| 284 void WallpaperController::InstallDesktopControllerForAllWindows() { | |
| 285 for (WmWindow* root : WmShell::Get()->GetAllRootWindows()) | |
| 286 InstallDesktopController(root); | |
| 287 current_max_display_size_ = GetMaxDisplaySizeInNative(); | |
| 288 } | |
| 289 | |
| 290 bool WallpaperController::ReparentWallpaper(int container) { | |
| 291 bool moved = false; | |
| 292 for (WmWindow* root_window : WmShell::Get()->GetAllRootWindows()) { | |
| 293 RootWindowController* root_window_controller = | |
| 294 root_window->GetRootWindowController(); | |
| 295 // In the steady state (no animation playing) the wallpaper widget | |
| 296 // controller exists in the RootWindowController. | |
| 297 WallpaperWidgetController* wallpaper_widget_controller = | |
| 298 root_window_controller->wallpaper_widget_controller(); | |
| 299 if (wallpaper_widget_controller) { | |
| 300 moved |= wallpaper_widget_controller->Reparent( | |
| 301 root_window_controller->GetWindow(), container); | |
| 302 } | |
| 303 // During wallpaper show animations the controller lives in | |
| 304 // AnimatingWallpaperWidgetController owned by RootWindowController. | |
| 305 // NOTE: If an image load happens during a wallpaper show animation there | |
| 306 // can temporarily be two wallpaper widgets. We must reparent both of them, | |
| 307 // one above and one here. | |
| 308 WallpaperWidgetController* animating_controller = | |
| 309 root_window_controller->animating_wallpaper_widget_controller() | |
| 310 ? root_window_controller->animating_wallpaper_widget_controller() | |
| 311 ->GetController(false) | |
| 312 : nullptr; | |
| 313 if (animating_controller) { | |
| 314 moved |= animating_controller->Reparent( | |
| 315 root_window_controller->GetWindow(), container); | |
| 316 } | |
| 317 } | |
| 318 return moved; | |
| 319 } | |
| 320 | |
| 321 int WallpaperController::GetWallpaperContainerId(bool locked) { | |
| 322 return locked ? kShellWindowId_LockScreenWallpaperContainer | |
| 323 : kShellWindowId_WallpaperContainer; | |
| 324 } | |
| 325 | |
| 326 void WallpaperController::UpdateWallpaper(bool clear_cache) { | |
| 327 current_wallpaper_.reset(); | |
| 328 WmShell::Get()->wallpaper_delegate()->UpdateWallpaper(clear_cache); | |
| 329 } | |
| 330 | |
| 331 void WallpaperController::SetProminentColor(SkColor color) { | |
| 332 if (prominent_color_ == color) | |
| 333 return; | |
| 334 | |
| 335 prominent_color_ = color; | |
| 336 for (auto& observer : observers_) | |
| 337 observer.OnWallpaperColorsChanged(); | |
| 338 } | |
| 339 | |
| 340 void WallpaperController::CalculateWallpaperColors() { | |
| 341 color_utils::LumaRange luma; | |
| 342 color_utils::SaturationRange saturation; | |
| 343 if (!GetProminentColorProfile(&luma, &saturation)) | |
| 344 return; | |
| 345 | |
| 346 if (color_calculator_) | |
| 347 color_calculator_->RemoveObserver(this); | |
| 348 | |
| 349 color_calculator_ = base::MakeUnique<wallpaper::WallpaperColorCalculator>( | |
| 350 GetWallpaper(), luma, saturation, task_runner_); | |
| 351 color_calculator_->AddObserver(this); | |
| 352 if (!color_calculator_->StartCalculation()) | |
| 353 SetProminentColor(SK_ColorTRANSPARENT); | |
| 354 } | |
| 355 | |
| 356 } // namespace ash | |
| OLD | NEW |