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