| 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 |