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 |