blob: c98fa1dbc15e3e32cd1d67fec634d25dd54f3742 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/common/wm_shell.h"
#include <utility>
#include "ash/common/accelerators/accelerator_controller.h"
#include "ash/common/accelerators/ash_focus_manager_factory.h"
#include "ash/common/accessibility_delegate.h"
#include "ash/common/focus_cycler.h"
#include "ash/common/keyboard/keyboard_ui.h"
#include "ash/common/new_window_delegate.h"
#include "ash/common/palette_delegate.h"
#include "ash/common/session/session_state_delegate.h"
#include "ash/common/shelf/app_list_shelf_item_delegate.h"
#include "ash/common/shelf/shelf_delegate.h"
#include "ash/common/shelf/shelf_model.h"
#include "ash/common/shelf/shelf_window_watcher.h"
#include "ash/common/shell_delegate.h"
#include "ash/common/shell_window_ids.h"
#include "ash/common/system/brightness_control_delegate.h"
#include "ash/common/system/keyboard_brightness_control_delegate.h"
#include "ash/common/system/toast/toast_manager.h"
#include "ash/common/system/tray/system_tray_delegate.h"
#include "ash/common/system/tray/system_tray_notifier.h"
#include "ash/common/wallpaper/wallpaper_delegate.h"
#include "ash/common/wm/immersive_context_ash.h"
#include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
#include "ash/common/wm/mru_window_tracker.h"
#include "ash/common/wm/overview/window_selector_controller.h"
#include "ash/common/wm/window_cycle_controller.h"
#include "ash/common/wm_window.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "ui/app_list/presenter/app_list_presenter.h"
#include "ui/display/display.h"
#include "ui/views/focus/focus_manager_factory.h"
#if defined(OS_CHROMEOS)
#include "ash/common/system/chromeos/brightness/brightness_controller_chromeos.h"
#include "ash/common/system/chromeos/keyboard_brightness_controller.h"
#include "ash/common/system/chromeos/session/logout_confirmation_controller.h"
#endif
namespace ash {
// static
WmShell* WmShell::instance_ = nullptr;
// static
void WmShell::Set(WmShell* instance) {
instance_ = instance;
}
// static
WmShell* WmShell::Get() {
return instance_;
}
void WmShell::Initialize() {
// Some delegates access WmShell during their construction. Create them here
// instead of the WmShell constructor.
accessibility_delegate_.reset(delegate_->CreateAccessibilityDelegate());
media_delegate_.reset(delegate_->CreateMediaDelegate());
palette_delegate_ = delegate_->CreatePaletteDelegate();
toast_manager_.reset(new ToastManager);
// Create the app list item in the shelf data model.
AppListShelfItemDelegate::CreateAppListItemAndDelegate(shelf_model_.get());
// Install the custom factory early on so that views::FocusManagers for Tray,
// Shelf, and WallPaper could be created by the factory.
views::FocusManagerFactory::Install(new AshFocusManagerFactory);
new_window_delegate_.reset(delegate_->CreateNewWindowDelegate());
}
void WmShell::Shutdown() {
// Accesses WmShell in its destructor.
accessibility_delegate_.reset();
// ShelfWindowWatcher has window observers and a pointer to the shelf model.
shelf_window_watcher_.reset();
// ShelfItemDelegate subclasses it owns have complex cleanup to run (e.g. ARC
// shelf items in Chrome) so explicitly shutdown early.
shelf_model_->DestroyItemDelegates();
// Must be destroyed before FocusClient.
shelf_delegate_.reset();
// Balances the Install() in Initialize().
views::FocusManagerFactory::Install(nullptr);
}
void WmShell::CreateShelfDelegate() {
// May be called multiple times as shelves are created and destroyed.
if (shelf_delegate_)
return;
// Must occur after SessionStateDelegate creation and user login because
// Chrome's implementation of ShelfDelegate assumes it can get information
// about multi-profile login state.
DCHECK(GetSessionStateDelegate());
DCHECK_GT(GetSessionStateDelegate()->NumberOfLoggedInUsers(), 0);
shelf_delegate_.reset(delegate_->CreateShelfDelegate(shelf_model_.get()));
shelf_window_watcher_.reset(new ShelfWindowWatcher(shelf_model_.get()));
}
void WmShell::OnMaximizeModeStarted() {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_, OnMaximizeModeStarted());
}
void WmShell::OnMaximizeModeEnded() {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_, OnMaximizeModeEnded());
}
void WmShell::NotifyFullscreenStateChanged(bool is_fullscreen,
WmWindow* root_window) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnFullscreenStateChanged(is_fullscreen, root_window));
}
void WmShell::NotifyPinnedStateChanged(WmWindow* pinned_window) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnPinnedStateChanged(pinned_window));
}
void WmShell::NotifyVirtualKeyboardActivated(bool activated) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnVirtualKeyboardStateChanged(activated));
}
void WmShell::NotifyShelfCreatedForRootWindow(WmWindow* root_window) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnShelfCreatedForRootWindow(root_window));
}
void WmShell::NotifyShelfAlignmentChanged(WmWindow* root_window) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnShelfAlignmentChanged(root_window));
}
void WmShell::NotifyShelfAutoHideBehaviorChanged(WmWindow* root_window) {
FOR_EACH_OBSERVER(ShellObserver, shell_observers_,
OnShelfAutoHideBehaviorChanged(root_window));
}
void WmShell::AddShellObserver(ShellObserver* observer) {
shell_observers_.AddObserver(observer);
}
void WmShell::RemoveShellObserver(ShellObserver* observer) {
shell_observers_.RemoveObserver(observer);
}
void WmShell::OnLockStateEvent(LockStateObserver::EventType event) {
FOR_EACH_OBSERVER(LockStateObserver, lock_state_observers_,
OnLockStateEvent(event));
}
void WmShell::AddLockStateObserver(LockStateObserver* observer) {
lock_state_observers_.AddObserver(observer);
}
void WmShell::RemoveLockStateObserver(LockStateObserver* observer) {
lock_state_observers_.RemoveObserver(observer);
}
void WmShell::SetShelfDelegateForTesting(
std::unique_ptr<ShelfDelegate> test_delegate) {
shelf_delegate_ = std::move(test_delegate);
}
void WmShell::SetPaletteDelegateForTesting(
std::unique_ptr<PaletteDelegate> palette_delegate) {
palette_delegate_ = std::move(palette_delegate);
}
WmShell::WmShell(std::unique_ptr<ShellDelegate> shell_delegate)
: delegate_(std::move(shell_delegate)),
focus_cycler_(new FocusCycler),
immersive_context_(base::MakeUnique<ImmersiveContextAsh>()),
shelf_model_(new ShelfModel), // Must create before ShelfDelegate.
system_tray_notifier_(new SystemTrayNotifier),
wallpaper_delegate_(delegate_->CreateWallpaperDelegate()),
window_cycle_controller_(new WindowCycleController),
window_selector_controller_(new WindowSelectorController) {
#if defined(OS_CHROMEOS)
brightness_control_delegate_.reset(new system::BrightnessControllerChromeos);
keyboard_brightness_control_delegate_.reset(new KeyboardBrightnessController);
#endif
}
WmShell::~WmShell() {}
WmWindow* WmShell::GetRootWindowForNewWindows() {
if (scoped_root_window_for_new_windows_)
return scoped_root_window_for_new_windows_;
return root_window_for_new_windows_;
}
bool WmShell::IsSystemModalWindowOpen() {
if (simulate_modal_window_open_for_testing_)
return true;
// Traverse all system modal containers, and find its direct child window
// with "SystemModal" setting, and visible.
for (WmWindow* root : GetAllRootWindows()) {
WmWindow* system_modal =
root->GetChildByShellWindowId(kShellWindowId_SystemModalContainer);
if (!system_modal)
continue;
for (const WmWindow* child : system_modal->GetChildren()) {
if (child->IsSystemModal() && child->GetTargetVisibility()) {
return true;
}
}
}
return false;
}
void WmShell::ShowAppList() {
// Show the app list on the default display for new windows.
int64_t display_id =
GetRootWindowForNewWindows()->GetDisplayNearestWindow().id();
delegate_->GetAppListPresenter()->Show(display_id);
}
void WmShell::DismissAppList() {
delegate_->GetAppListPresenter()->Dismiss();
}
void WmShell::ToggleAppList() {
// Show the app list on the default display for new windows.
int64_t display_id =
GetRootWindowForNewWindows()->GetDisplayNearestWindow().id();
delegate_->GetAppListPresenter()->ToggleAppList(display_id);
}
bool WmShell::IsApplistVisible() const {
return delegate_->GetAppListPresenter()->IsVisible();
}
bool WmShell::GetAppListTargetVisibility() const {
return delegate_->GetAppListPresenter()->GetTargetVisibility();
}
void WmShell::SetKeyboardUI(std::unique_ptr<KeyboardUI> keyboard_ui) {
keyboard_ui_ = std::move(keyboard_ui);
}
void WmShell::SetSystemTrayDelegate(
std::unique_ptr<SystemTrayDelegate> delegate) {
DCHECK(delegate);
DCHECK(!system_tray_delegate_);
// TODO(jamescook): Create via ShellDelegate once it moves to //ash/common.
system_tray_delegate_ = std::move(delegate);
system_tray_delegate_->Initialize();
#if defined(OS_CHROMEOS)
logout_confirmation_controller_.reset(new LogoutConfirmationController(
base::Bind(&SystemTrayDelegate::SignOut,
base::Unretained(system_tray_delegate_.get()))));
#endif
}
void WmShell::DeleteSystemTrayDelegate() {
DCHECK(system_tray_delegate_);
#if defined(OS_CHROMEOS)
logout_confirmation_controller_.reset();
#endif
system_tray_delegate_.reset();
}
void WmShell::DeleteWindowCycleController() {
window_cycle_controller_.reset();
}
void WmShell::DeleteWindowSelectorController() {
window_selector_controller_.reset();
}
void WmShell::CreateMaximizeModeController() {
maximize_mode_controller_.reset(new MaximizeModeController);
}
void WmShell::DeleteMaximizeModeController() {
maximize_mode_controller_.reset();
}
void WmShell::CreateMruWindowTracker() {
mru_window_tracker_.reset(new MruWindowTracker);
}
void WmShell::DeleteMruWindowTracker() {
mru_window_tracker_.reset();
}
void WmShell::DeleteToastManager() {
toast_manager_.reset();
}
void WmShell::SetAcceleratorController(
std::unique_ptr<AcceleratorController> accelerator_controller) {
accelerator_controller_ = std::move(accelerator_controller);
}
} // namespace ash