OLD | NEW |
| (Empty) |
1 // Copyright 2016 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/wm_shell.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "ash/common/accelerators/accelerator_controller.h" | |
10 #include "ash/common/accelerators/ash_focus_manager_factory.h" | |
11 #include "ash/common/accessibility_delegate.h" | |
12 #include "ash/common/cast_config_controller.h" | |
13 #include "ash/common/devtools/ash_devtools_css_agent.h" | |
14 #include "ash/common/devtools/ash_devtools_dom_agent.h" | |
15 #include "ash/common/focus_cycler.h" | |
16 #include "ash/common/keyboard/keyboard_ui.h" | |
17 #include "ash/common/media_controller.h" | |
18 #include "ash/common/new_window_controller.h" | |
19 #include "ash/common/palette_delegate.h" | |
20 #include "ash/common/session/session_controller.h" | |
21 #include "ash/common/session/session_state_delegate.h" | |
22 #include "ash/common/shelf/app_list_shelf_item_delegate.h" | |
23 #include "ash/common/shelf/shelf_controller.h" | |
24 #include "ash/common/shelf/shelf_delegate.h" | |
25 #include "ash/common/shelf/shelf_model.h" | |
26 #include "ash/common/shelf/shelf_window_watcher.h" | |
27 #include "ash/common/shell_delegate.h" | |
28 #include "ash/common/shutdown_controller.h" | |
29 #include "ash/common/wallpaper/wallpaper_controller.h" | |
30 #include "ash/common/wallpaper/wallpaper_delegate.h" | |
31 #include "ash/common/wm/immersive_context_ash.h" | |
32 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" | |
33 #include "ash/common/wm/mru_window_tracker.h" | |
34 #include "ash/common/wm/overview/window_selector_controller.h" | |
35 #include "ash/common/wm/root_window_finder.h" | |
36 #include "ash/common/wm/system_modal_container_layout_manager.h" | |
37 #include "ash/common/wm/window_cycle_controller.h" | |
38 #include "ash/common/wm_activation_observer.h" | |
39 #include "ash/common/wm_window.h" | |
40 #include "ash/public/cpp/shell_window_ids.h" | |
41 #include "ash/root_window_controller.h" | |
42 #include "ash/shell.h" | |
43 #include "ash/system/brightness/brightness_controller_chromeos.h" | |
44 #include "ash/system/brightness_control_delegate.h" | |
45 #include "ash/system/keyboard_brightness_control_delegate.h" | |
46 #include "ash/system/keyboard_brightness_controller.h" | |
47 #include "ash/system/locale/locale_notification_controller.h" | |
48 #include "ash/system/network/vpn_list.h" | |
49 #include "ash/system/session/logout_confirmation_controller.h" | |
50 #include "ash/system/toast/toast_manager.h" | |
51 #include "ash/system/tray/system_tray_controller.h" | |
52 #include "ash/system/tray/system_tray_delegate.h" | |
53 #include "ash/system/tray/system_tray_notifier.h" | |
54 #include "base/bind.h" | |
55 #include "base/logging.h" | |
56 #include "base/memory/ptr_util.h" | |
57 #include "base/threading/sequenced_worker_pool.h" | |
58 #include "services/preferences/public/cpp/pref_client_store.h" | |
59 #include "services/preferences/public/interfaces/preferences.mojom.h" | |
60 #include "services/service_manager/public/cpp/connector.h" | |
61 #include "ui/app_list/presenter/app_list.h" | |
62 #include "ui/display/display.h" | |
63 #include "ui/views/focus/focus_manager_factory.h" | |
64 #include "ui/wm/public/activation_client.h" | |
65 | |
66 namespace ash { | |
67 | |
68 // static | |
69 WmShell* WmShell::instance_ = nullptr; | |
70 | |
71 WmShell::~WmShell() { | |
72 session_controller_->RemoveSessionStateObserver(this); | |
73 } | |
74 | |
75 // static | |
76 void WmShell::Set(WmShell* instance) { | |
77 instance_ = instance; | |
78 } | |
79 | |
80 // static | |
81 WmShell* WmShell::Get() { | |
82 return instance_; | |
83 } | |
84 | |
85 void WmShell::Initialize(const scoped_refptr<base::SequencedWorkerPool>& pool) { | |
86 blocking_pool_ = pool; | |
87 | |
88 // Some delegates access WmShell during their construction. Create them here | |
89 // instead of the WmShell constructor. | |
90 accessibility_delegate_.reset(delegate_->CreateAccessibilityDelegate()); | |
91 palette_delegate_ = delegate_->CreatePaletteDelegate(); | |
92 toast_manager_.reset(new ToastManager); | |
93 | |
94 // Create the app list item in the shelf data model. | |
95 AppListShelfItemDelegate::CreateAppListItemAndDelegate(shelf_model()); | |
96 | |
97 // Install the custom factory early on so that views::FocusManagers for Tray, | |
98 // Shelf, and WallPaper could be created by the factory. | |
99 views::FocusManagerFactory::Install(new AshFocusManagerFactory); | |
100 | |
101 wallpaper_controller_.reset(new WallpaperController(blocking_pool_)); | |
102 | |
103 // Start devtools server | |
104 devtools_server_ = ui::devtools::UiDevToolsServer::Create(nullptr); | |
105 if (devtools_server_) { | |
106 auto dom_backend = base::MakeUnique<devtools::AshDevToolsDOMAgent>(this); | |
107 auto css_backend = | |
108 base::MakeUnique<devtools::AshDevToolsCSSAgent>(dom_backend.get()); | |
109 auto devtools_client = base::MakeUnique<ui::devtools::UiDevToolsClient>( | |
110 "Ash", devtools_server_.get()); | |
111 devtools_client->AddAgent(std::move(dom_backend)); | |
112 devtools_client->AddAgent(std::move(css_backend)); | |
113 devtools_server_->AttachClient(std::move(devtools_client)); | |
114 } | |
115 } | |
116 | |
117 void WmShell::Shutdown() { | |
118 if (added_activation_observer_) | |
119 Shell::GetInstance()->activation_client()->RemoveObserver(this); | |
120 | |
121 // These members access WmShell in their destructors. | |
122 wallpaper_controller_.reset(); | |
123 accessibility_delegate_.reset(); | |
124 | |
125 // ShelfWindowWatcher has window observers and a pointer to the shelf model. | |
126 shelf_window_watcher_.reset(); | |
127 // ShelfItemDelegate subclasses it owns have complex cleanup to run (e.g. ARC | |
128 // shelf items in Chrome) so explicitly shutdown early. | |
129 shelf_model()->DestroyItemDelegates(); | |
130 // Must be destroyed before FocusClient. | |
131 shelf_delegate_.reset(); | |
132 | |
133 // Balances the Install() in Initialize(). | |
134 views::FocusManagerFactory::Install(nullptr); | |
135 | |
136 // Removes itself as an observer of |pref_store_|. | |
137 shelf_controller_.reset(); | |
138 } | |
139 | |
140 ShelfModel* WmShell::shelf_model() { | |
141 return shelf_controller_->model(); | |
142 } | |
143 | |
144 void WmShell::ShowContextMenu(const gfx::Point& location_in_screen, | |
145 ui::MenuSourceType source_type) { | |
146 // Bail if there is no active user session or if the screen is locked. | |
147 if (GetSessionStateDelegate()->NumberOfLoggedInUsers() < 1 || | |
148 GetSessionStateDelegate()->IsScreenLocked()) { | |
149 return; | |
150 } | |
151 | |
152 WmWindow* root = wm::GetRootWindowAt(location_in_screen); | |
153 root->GetRootWindowController()->ShowContextMenu(location_in_screen, | |
154 source_type); | |
155 } | |
156 | |
157 void WmShell::CreateShelfView() { | |
158 // Must occur after SessionStateDelegate creation and user login. | |
159 DCHECK(GetSessionStateDelegate()); | |
160 DCHECK_GT(GetSessionStateDelegate()->NumberOfLoggedInUsers(), 0); | |
161 CreateShelfDelegate(); | |
162 | |
163 for (WmWindow* root_window : GetAllRootWindows()) | |
164 root_window->GetRootWindowController()->CreateShelfView(); | |
165 } | |
166 | |
167 void WmShell::CreateShelfDelegate() { | |
168 // May be called multiple times as shelves are created and destroyed. | |
169 if (shelf_delegate_) | |
170 return; | |
171 // Must occur after SessionStateDelegate creation and user login because | |
172 // Chrome's implementation of ShelfDelegate assumes it can get information | |
173 // about multi-profile login state. | |
174 DCHECK(GetSessionStateDelegate()); | |
175 DCHECK_GT(GetSessionStateDelegate()->NumberOfLoggedInUsers(), 0); | |
176 shelf_delegate_.reset(delegate_->CreateShelfDelegate(shelf_model())); | |
177 shelf_window_watcher_.reset(new ShelfWindowWatcher(shelf_model())); | |
178 } | |
179 | |
180 void WmShell::OnMaximizeModeStarted() { | |
181 for (auto& observer : shell_observers_) | |
182 observer.OnMaximizeModeStarted(); | |
183 } | |
184 | |
185 void WmShell::OnMaximizeModeEnding() { | |
186 for (auto& observer : shell_observers_) | |
187 observer.OnMaximizeModeEnding(); | |
188 } | |
189 | |
190 void WmShell::OnMaximizeModeEnded() { | |
191 for (auto& observer : shell_observers_) | |
192 observer.OnMaximizeModeEnded(); | |
193 } | |
194 | |
195 void WmShell::UpdateAfterLoginStatusChange(LoginStatus status) { | |
196 for (WmWindow* root_window : GetAllRootWindows()) { | |
197 root_window->GetRootWindowController()->UpdateAfterLoginStatusChange( | |
198 status); | |
199 } | |
200 } | |
201 | |
202 void WmShell::NotifyFullscreenStateChanged(bool is_fullscreen, | |
203 WmWindow* root_window) { | |
204 for (auto& observer : shell_observers_) | |
205 observer.OnFullscreenStateChanged(is_fullscreen, root_window); | |
206 } | |
207 | |
208 void WmShell::NotifyPinnedStateChanged(WmWindow* pinned_window) { | |
209 for (auto& observer : shell_observers_) | |
210 observer.OnPinnedStateChanged(pinned_window); | |
211 } | |
212 | |
213 void WmShell::NotifyVirtualKeyboardActivated(bool activated) { | |
214 for (auto& observer : shell_observers_) | |
215 observer.OnVirtualKeyboardStateChanged(activated); | |
216 } | |
217 | |
218 void WmShell::NotifyShelfCreatedForRootWindow(WmWindow* root_window) { | |
219 for (auto& observer : shell_observers_) | |
220 observer.OnShelfCreatedForRootWindow(root_window); | |
221 } | |
222 | |
223 void WmShell::NotifyShelfAlignmentChanged(WmWindow* root_window) { | |
224 for (auto& observer : shell_observers_) | |
225 observer.OnShelfAlignmentChanged(root_window); | |
226 } | |
227 | |
228 void WmShell::NotifyShelfAutoHideBehaviorChanged(WmWindow* root_window) { | |
229 for (auto& observer : shell_observers_) | |
230 observer.OnShelfAutoHideBehaviorChanged(root_window); | |
231 } | |
232 | |
233 void WmShell::AddActivationObserver(WmActivationObserver* observer) { | |
234 if (!added_activation_observer_) { | |
235 added_activation_observer_ = true; | |
236 Shell::GetInstance()->activation_client()->AddObserver(this); | |
237 } | |
238 activation_observers_.AddObserver(observer); | |
239 } | |
240 | |
241 void WmShell::RemoveActivationObserver(WmActivationObserver* observer) { | |
242 activation_observers_.RemoveObserver(observer); | |
243 } | |
244 | |
245 void WmShell::AddShellObserver(ShellObserver* observer) { | |
246 shell_observers_.AddObserver(observer); | |
247 } | |
248 | |
249 void WmShell::RemoveShellObserver(ShellObserver* observer) { | |
250 shell_observers_.RemoveObserver(observer); | |
251 } | |
252 | |
253 void WmShell::OnLockStateEvent(LockStateObserver::EventType event) { | |
254 for (auto& observer : lock_state_observers_) | |
255 observer.OnLockStateEvent(event); | |
256 } | |
257 | |
258 void WmShell::AddLockStateObserver(LockStateObserver* observer) { | |
259 lock_state_observers_.AddObserver(observer); | |
260 } | |
261 | |
262 void WmShell::RemoveLockStateObserver(LockStateObserver* observer) { | |
263 lock_state_observers_.RemoveObserver(observer); | |
264 } | |
265 | |
266 void WmShell::SetShelfDelegateForTesting( | |
267 std::unique_ptr<ShelfDelegate> test_delegate) { | |
268 shelf_delegate_ = std::move(test_delegate); | |
269 } | |
270 | |
271 void WmShell::SetPaletteDelegateForTesting( | |
272 std::unique_ptr<PaletteDelegate> palette_delegate) { | |
273 palette_delegate_ = std::move(palette_delegate); | |
274 } | |
275 | |
276 WmShell::WmShell(std::unique_ptr<ShellDelegate> shell_delegate) | |
277 : delegate_(std::move(shell_delegate)), | |
278 app_list_(base::MakeUnique<app_list::AppList>()), | |
279 brightness_control_delegate_( | |
280 base::MakeUnique<system::BrightnessControllerChromeos>()), | |
281 cast_config_(base::MakeUnique<CastConfigController>()), | |
282 focus_cycler_(base::MakeUnique<FocusCycler>()), | |
283 immersive_context_(base::MakeUnique<ImmersiveContextAsh>()), | |
284 keyboard_brightness_control_delegate_( | |
285 base::MakeUnique<KeyboardBrightnessController>()), | |
286 locale_notification_controller_( | |
287 base::MakeUnique<LocaleNotificationController>()), | |
288 media_controller_(base::MakeUnique<MediaController>()), | |
289 new_window_controller_(base::MakeUnique<NewWindowController>()), | |
290 session_controller_(base::MakeUnique<SessionController>()), | |
291 shelf_controller_(base::MakeUnique<ShelfController>()), | |
292 shutdown_controller_(base::MakeUnique<ShutdownController>()), | |
293 system_tray_controller_(base::MakeUnique<SystemTrayController>()), | |
294 system_tray_notifier_(base::MakeUnique<SystemTrayNotifier>()), | |
295 vpn_list_(base::MakeUnique<VpnList>()), | |
296 wallpaper_delegate_(delegate_->CreateWallpaperDelegate()), | |
297 window_cycle_controller_(base::MakeUnique<WindowCycleController>()), | |
298 window_selector_controller_( | |
299 base::MakeUnique<WindowSelectorController>()) { | |
300 session_controller_->AddSessionStateObserver(this); | |
301 | |
302 prefs::mojom::PreferencesServiceFactoryPtr pref_factory_ptr; | |
303 // Can be null in tests. | |
304 if (!delegate_->GetShellConnector()) | |
305 return; | |
306 delegate_->GetShellConnector()->BindInterface(prefs::mojom::kServiceName, | |
307 &pref_factory_ptr); | |
308 pref_store_ = new preferences::PrefClientStore(std::move(pref_factory_ptr)); | |
309 } | |
310 | |
311 RootWindowController* WmShell::GetPrimaryRootWindowController() { | |
312 return GetPrimaryRootWindow()->GetRootWindowController(); | |
313 } | |
314 | |
315 WmWindow* WmShell::GetRootWindowForNewWindows() { | |
316 if (scoped_root_window_for_new_windows_) | |
317 return scoped_root_window_for_new_windows_; | |
318 return root_window_for_new_windows_; | |
319 } | |
320 | |
321 bool WmShell::IsSystemModalWindowOpen() { | |
322 if (simulate_modal_window_open_for_testing_) | |
323 return true; | |
324 | |
325 // Traverse all system modal containers, and find its direct child window | |
326 // with "SystemModal" setting, and visible. | |
327 for (WmWindow* root : GetAllRootWindows()) { | |
328 WmWindow* system_modal = | |
329 root->GetChildByShellWindowId(kShellWindowId_SystemModalContainer); | |
330 if (!system_modal) | |
331 continue; | |
332 for (const WmWindow* child : system_modal->GetChildren()) { | |
333 if (child->IsSystemModal() && child->GetTargetVisibility()) { | |
334 return true; | |
335 } | |
336 } | |
337 } | |
338 return false; | |
339 } | |
340 | |
341 void WmShell::CreateModalBackground(WmWindow* window) { | |
342 for (WmWindow* root_window : GetAllRootWindows()) { | |
343 root_window->GetRootWindowController() | |
344 ->GetSystemModalLayoutManager(window) | |
345 ->CreateModalBackground(); | |
346 } | |
347 } | |
348 | |
349 void WmShell::OnModalWindowRemoved(WmWindow* removed) { | |
350 WmWindow::Windows root_windows = GetAllRootWindows(); | |
351 for (WmWindow* root_window : root_windows) { | |
352 if (root_window->GetRootWindowController() | |
353 ->GetSystemModalLayoutManager(removed) | |
354 ->ActivateNextModalWindow()) { | |
355 return; | |
356 } | |
357 } | |
358 for (WmWindow* root_window : root_windows) { | |
359 root_window->GetRootWindowController() | |
360 ->GetSystemModalLayoutManager(removed) | |
361 ->DestroyModalBackground(); | |
362 } | |
363 } | |
364 | |
365 void WmShell::ShowAppList() { | |
366 // Show the app list on the default display for new windows. | |
367 app_list_->Show(GetRootWindowForNewWindows()->GetDisplayNearestWindow().id()); | |
368 } | |
369 | |
370 void WmShell::DismissAppList() { | |
371 app_list_->Dismiss(); | |
372 } | |
373 | |
374 void WmShell::ToggleAppList() { | |
375 // Toggle the app list on the default display for new windows. | |
376 app_list_->ToggleAppList( | |
377 GetRootWindowForNewWindows()->GetDisplayNearestWindow().id()); | |
378 } | |
379 | |
380 bool WmShell::IsApplistVisible() const { | |
381 return app_list_->IsVisible(); | |
382 } | |
383 | |
384 bool WmShell::GetAppListTargetVisibility() const { | |
385 return app_list_->GetTargetVisibility(); | |
386 } | |
387 | |
388 void WmShell::SetKeyboardUI(std::unique_ptr<KeyboardUI> keyboard_ui) { | |
389 keyboard_ui_ = std::move(keyboard_ui); | |
390 } | |
391 | |
392 void WmShell::SetSystemTrayDelegate( | |
393 std::unique_ptr<SystemTrayDelegate> delegate) { | |
394 DCHECK(delegate); | |
395 system_tray_delegate_ = std::move(delegate); | |
396 system_tray_delegate_->Initialize(); | |
397 // Accesses WmShell in its constructor. | |
398 logout_confirmation_controller_.reset(new LogoutConfirmationController( | |
399 base::Bind(&SystemTrayController::SignOut, | |
400 base::Unretained(system_tray_controller_.get())))); | |
401 } | |
402 | |
403 void WmShell::DeleteSystemTrayDelegate() { | |
404 DCHECK(system_tray_delegate_); | |
405 // Accesses WmShell in its destructor. | |
406 logout_confirmation_controller_.reset(); | |
407 system_tray_delegate_.reset(); | |
408 } | |
409 | |
410 void WmShell::DeleteWindowCycleController() { | |
411 window_cycle_controller_.reset(); | |
412 } | |
413 | |
414 void WmShell::DeleteWindowSelectorController() { | |
415 window_selector_controller_.reset(); | |
416 } | |
417 | |
418 void WmShell::CreateMaximizeModeController() { | |
419 maximize_mode_controller_.reset(new MaximizeModeController); | |
420 } | |
421 | |
422 void WmShell::DeleteMaximizeModeController() { | |
423 maximize_mode_controller_.reset(); | |
424 } | |
425 | |
426 void WmShell::CreateMruWindowTracker() { | |
427 mru_window_tracker_.reset(new MruWindowTracker); | |
428 } | |
429 | |
430 void WmShell::DeleteMruWindowTracker() { | |
431 mru_window_tracker_.reset(); | |
432 } | |
433 | |
434 void WmShell::DeleteToastManager() { | |
435 toast_manager_.reset(); | |
436 } | |
437 | |
438 void WmShell::SetAcceleratorController( | |
439 std::unique_ptr<AcceleratorController> accelerator_controller) { | |
440 accelerator_controller_ = std::move(accelerator_controller); | |
441 } | |
442 | |
443 void WmShell::SessionStateChanged(session_manager::SessionState state) { | |
444 // Create the shelf when a session becomes active. It's safe to do this | |
445 // multiple times (e.g. initial login vs. multiprofile add session). | |
446 if (state == session_manager::SessionState::ACTIVE) | |
447 CreateShelfView(); | |
448 } | |
449 | |
450 void WmShell::OnWindowActivated( | |
451 aura::client::ActivationChangeObserver::ActivationReason reason, | |
452 aura::Window* gained_active, | |
453 aura::Window* lost_active) { | |
454 WmWindow* gained_active_wm = WmWindow::Get(gained_active); | |
455 WmWindow* lost_active_wm = WmWindow::Get(lost_active); | |
456 if (gained_active_wm) | |
457 set_root_window_for_new_windows(gained_active_wm->GetRootWindow()); | |
458 for (auto& observer : activation_observers_) | |
459 observer.OnWindowActivated(gained_active_wm, lost_active_wm); | |
460 } | |
461 | |
462 void WmShell::OnAttemptToReactivateWindow(aura::Window* request_active, | |
463 aura::Window* actual_active) { | |
464 for (auto& observer : activation_observers_) { | |
465 observer.OnAttemptToReactivateWindow(WmWindow::Get(request_active), | |
466 WmWindow::Get(actual_active)); | |
467 } | |
468 } | |
469 | |
470 } // namespace ash | |
OLD | NEW |