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 |