blob: 9e932322e2facd5b0d8cd576dc6f1b60400fed1e [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/mus/bridge/shell_port_mash.h"
#include <utility>
#include "ash/accelerators/accelerator_controller.h"
#include "ash/accelerators/accelerator_controller_delegate_aura.h"
#include "ash/aura/key_event_watcher_aura.h"
#include "ash/aura/pointer_watcher_adapter.h"
#include "ash/host/ash_window_tree_host_init_params.h"
#include "ash/key_event_watcher.h"
#include "ash/laser/laser_pointer_controller.h"
#include "ash/magnifier/partial_magnification_controller.h"
#include "ash/mus/accelerators/accelerator_controller_delegate_mus.h"
#include "ash/mus/accelerators/accelerator_controller_registrar.h"
#include "ash/mus/ash_window_tree_host_mus.h"
#include "ash/mus/bridge/immersive_handler_factory_mus.h"
#include "ash/mus/bridge/workspace_event_handler_mus.h"
#include "ash/mus/display_synchronizer.h"
#include "ash/mus/drag_window_resizer.h"
#include "ash/mus/keyboard_ui_mus.h"
#include "ash/mus/touch_transform_setter_mus.h"
#include "ash/mus/window_manager.h"
#include "ash/public/cpp/config.h"
#include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/root_window_controller.h"
#include "ash/root_window_settings.h"
#include "ash/shell.h"
#include "ash/system/tray/system_tray_delegate.h"
#include "ash/virtual_keyboard_controller.h"
#include "ash/wallpaper/wallpaper_delegate.h"
#include "ash/wm/drag_window_resizer.h"
#include "ash/wm/maximize_mode/maximize_mode_event_handler.h"
#include "ash/wm/maximize_mode/maximize_mode_event_handler_aura.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_cycle_event_filter.h"
#include "ash/wm/window_cycle_event_filter_aura.h"
#include "ash/wm/window_resizer.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/workspace_event_handler_aura.h"
#include "base/memory/ptr_util.h"
#include "components/user_manager/user_info_impl.h"
#include "services/ui/public/interfaces/constants.mojom.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/focus_synchronizer.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/window.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/views/mus/pointer_watcher_event_router.h"
#if defined(USE_OZONE)
#include "ui/display/manager/forwarding_display_delegate.h"
#endif
namespace ash {
namespace mus {
ShellPortMash::MashSpecificState::MashSpecificState() = default;
ShellPortMash::MashSpecificState::~MashSpecificState() = default;
ShellPortMash::MusSpecificState::MusSpecificState() = default;
ShellPortMash::MusSpecificState::~MusSpecificState() = default;
ShellPortMash::ShellPortMash(
WindowManager* window_manager,
views::PointerWatcherEventRouter* pointer_watcher_event_router)
: window_manager_(window_manager) {
if (GetAshConfig() == Config::MASH) {
mash_state_ = base::MakeUnique<MashSpecificState>();
mash_state_->pointer_watcher_event_router = pointer_watcher_event_router;
mash_state_->immersive_handler_factory =
base::MakeUnique<ImmersiveHandlerFactoryMus>();
} else {
DCHECK_EQ(Config::MUS, GetAshConfig());
mus_state_ = base::MakeUnique<MusSpecificState>();
}
}
ShellPortMash::~ShellPortMash() {}
// static
ShellPortMash* ShellPortMash::Get() {
const ash::Config config = ShellPort::Get()->GetAshConfig();
CHECK(config == Config::MUS || config == Config::MASH);
return static_cast<ShellPortMash*>(ShellPort::Get());
}
RootWindowController* ShellPortMash::GetRootWindowControllerWithDisplayId(
int64_t id) {
for (RootWindowController* root_window_controller :
RootWindowController::root_window_controllers()) {
RootWindowSettings* settings =
GetRootWindowSettings(root_window_controller->GetRootWindow());
DCHECK(settings);
if (settings->display_id == id)
return root_window_controller;
}
return nullptr;
}
aura::WindowTreeClient* ShellPortMash::window_tree_client() {
return window_manager_->window_tree_client();
}
void ShellPortMash::Shutdown() {
display_synchronizer_.reset();
if (mus_state_)
mus_state_->pointer_watcher_adapter.reset();
ShellPort::Shutdown();
}
Config ShellPortMash::GetAshConfig() const {
return window_manager_->config();
}
std::unique_ptr<display::TouchTransformSetter>
ShellPortMash::CreateTouchTransformDelegate() {
return base::MakeUnique<TouchTransformSetterMus>(
window_manager_->connector());
}
void ShellPortMash::LockCursor() {
// When we are running in mus, we need to keep track of state not just in the
// window server, but also locally in ash because ash treats the cursor
// manager as the canonical state for now. NativeCursorManagerAsh will keep
// this state, while also forwarding it to the window manager for us.
if (GetAshConfig() == Config::MUS)
Shell::Get()->cursor_manager()->LockCursor();
else
window_manager_->window_manager_client()->LockCursor();
}
void ShellPortMash::UnlockCursor() {
if (GetAshConfig() == Config::MUS)
Shell::Get()->cursor_manager()->UnlockCursor();
else
window_manager_->window_manager_client()->UnlockCursor();
}
void ShellPortMash::ShowCursor() {
if (GetAshConfig() == Config::MUS)
Shell::Get()->cursor_manager()->ShowCursor();
else
window_manager_->window_manager_client()->SetCursorVisible(true);
}
void ShellPortMash::HideCursor() {
if (GetAshConfig() == Config::MUS)
Shell::Get()->cursor_manager()->HideCursor();
else
window_manager_->window_manager_client()->SetCursorVisible(false);
}
void ShellPortMash::SetCursorSize(ui::CursorSize cursor_size) {
if (GetAshConfig() == Config::MUS)
Shell::Get()->cursor_manager()->SetCursorSize(cursor_size);
else
window_manager_->window_manager_client()->SetCursorSize(cursor_size);
}
void ShellPortMash::SetGlobalOverrideCursor(
base::Optional<ui::CursorData> cursor) {
DCHECK(mash_state_);
window_manager_->window_manager_client()->SetGlobalOverrideCursor(
std::move(cursor));
}
bool ShellPortMash::IsMouseEventsEnabled() {
// TODO: http://crbug.com/637853
NOTIMPLEMENTED();
return true;
}
std::unique_ptr<WindowResizer> ShellPortMash::CreateDragWindowResizer(
std::unique_ptr<WindowResizer> next_window_resizer,
wm::WindowState* window_state) {
if (GetAshConfig() == Config::MUS) {
return base::WrapUnique(ash::DragWindowResizer::Create(
next_window_resizer.release(), window_state));
}
return base::MakeUnique<ash::mus::DragWindowResizer>(
std::move(next_window_resizer), window_state);
}
std::unique_ptr<WindowCycleEventFilter>
ShellPortMash::CreateWindowCycleEventFilter() {
if (GetAshConfig() == Config::MUS)
return base::MakeUnique<WindowCycleEventFilterAura>();
// TODO: implement me, http://crbug.com/629191.
return nullptr;
}
std::unique_ptr<wm::MaximizeModeEventHandler>
ShellPortMash::CreateMaximizeModeEventHandler() {
if (GetAshConfig() == Config::MUS)
return base::MakeUnique<wm::MaximizeModeEventHandlerAura>();
// TODO: need support for window manager to get events before client:
// http://crbug.com/624157.
NOTIMPLEMENTED();
return nullptr;
}
std::unique_ptr<WorkspaceEventHandler>
ShellPortMash::CreateWorkspaceEventHandler(aura::Window* workspace_window) {
if (GetAshConfig() == Config::MUS)
return base::MakeUnique<WorkspaceEventHandlerAura>(workspace_window);
return base::MakeUnique<WorkspaceEventHandlerMus>(workspace_window);
}
std::unique_ptr<ImmersiveFullscreenController>
ShellPortMash::CreateImmersiveFullscreenController() {
return base::MakeUnique<ImmersiveFullscreenController>();
}
std::unique_ptr<KeyboardUI> ShellPortMash::CreateKeyboardUI() {
if (GetAshConfig() == Config::MUS)
return KeyboardUI::Create();
return KeyboardUIMus::Create(window_manager_->connector());
}
std::unique_ptr<KeyEventWatcher> ShellPortMash::CreateKeyEventWatcher() {
if (GetAshConfig() == Config::MUS)
return base::MakeUnique<KeyEventWatcherAura>();
// TODO: needs implementation for mus, http://crbug.com/649600.
NOTIMPLEMENTED();
return std::unique_ptr<KeyEventWatcher>();
}
void ShellPortMash::AddPointerWatcher(views::PointerWatcher* watcher,
views::PointerWatcherEventTypes events) {
if (GetAshConfig() == Config::MUS) {
mus_state_->pointer_watcher_adapter->AddPointerWatcher(watcher, events);
return;
}
// TODO: implement drags for mus pointer watcher, http://crbug.com/641164.
// NOTIMPLEMENTED drags for mus pointer watcher.
mash_state_->pointer_watcher_event_router->AddPointerWatcher(
watcher, events == views::PointerWatcherEventTypes::MOVES);
}
void ShellPortMash::RemovePointerWatcher(views::PointerWatcher* watcher) {
if (GetAshConfig() == Config::MUS) {
mus_state_->pointer_watcher_adapter->RemovePointerWatcher(watcher);
return;
}
mash_state_->pointer_watcher_event_router->RemovePointerWatcher(watcher);
}
bool ShellPortMash::IsTouchDown() {
if (GetAshConfig() == Config::MUS)
return aura::Env::GetInstance()->is_touch_down();
// TODO: implement me, http://crbug.com/634967.
// NOTIMPLEMENTED is too spammy here.
return false;
}
void ShellPortMash::ToggleIgnoreExternalKeyboard() {
if (GetAshConfig() == Config::MUS) {
Shell::Get()->virtual_keyboard_controller()->ToggleIgnoreExternalKeyboard();
return;
}
NOTIMPLEMENTED();
}
void ShellPortMash::SetLaserPointerEnabled(bool enabled) {
if (GetAshConfig() == Config::MUS) {
Shell::Get()->laser_pointer_controller()->SetEnabled(enabled);
return;
}
NOTIMPLEMENTED();
}
void ShellPortMash::SetPartialMagnifierEnabled(bool enabled) {
if (GetAshConfig() == Config::MUS) {
Shell::Get()->partial_magnification_controller()->SetEnabled(enabled);
return;
}
NOTIMPLEMENTED();
}
void ShellPortMash::CreatePointerWatcherAdapter() {
// In Config::MUS PointerWatcherAdapter must be created when this function is
// called (it is order dependent), that is not the case with Config::MASH.
if (GetAshConfig() == Config::MUS) {
mus_state_->pointer_watcher_adapter =
base::MakeUnique<PointerWatcherAdapter>();
}
}
std::unique_ptr<AshWindowTreeHost> ShellPortMash::CreateAshWindowTreeHost(
const AshWindowTreeHostInitParams& init_params) {
std::unique_ptr<aura::DisplayInitParams> display_params =
base::MakeUnique<aura::DisplayInitParams>();
display_params->viewport_metrics.bounds_in_pixels =
init_params.initial_bounds;
display_params->viewport_metrics.device_scale_factor =
init_params.device_scale_factor;
display_params->viewport_metrics.ui_scale_factor =
init_params.ui_scale_factor;
display::Display mirrored_display =
Shell::Get()->display_manager()->GetMirroringDisplayById(
init_params.display_id);
if (mirrored_display.is_valid()) {
display_params->display =
base::MakeUnique<display::Display>(mirrored_display);
}
display_params->is_primary_display = true;
aura::WindowTreeHostMusInitParams aura_init_params =
window_manager_->window_manager_client()->CreateInitParamsForNewDisplay();
aura_init_params.display_id = init_params.display_id;
aura_init_params.display_init_params = std::move(display_params);
aura_init_params.use_classic_ime = !Shell::ShouldUseIMEService();
return base::MakeUnique<AshWindowTreeHostMus>(std::move(aura_init_params));
}
void ShellPortMash::OnCreatedRootWindowContainers(
RootWindowController* root_window_controller) {
// TODO: To avoid lots of IPC AddActivationParent() should take an array.
// http://crbug.com/682048.
aura::Window* root_window = root_window_controller->GetRootWindow();
for (size_t i = 0; i < kNumActivatableShellWindowIds; ++i) {
window_manager_->window_manager_client()->AddActivationParent(
root_window->GetChildById(kActivatableShellWindowIds[i]));
}
}
void ShellPortMash::OnHostsInitialized() {
display_synchronizer_ = base::MakeUnique<DisplaySynchronizer>(
window_manager_->window_manager_client());
}
std::unique_ptr<display::NativeDisplayDelegate>
ShellPortMash::CreateNativeDisplayDelegate() {
#if defined(USE_OZONE)
display::mojom::NativeDisplayDelegatePtr native_display_delegate;
if (window_manager_->connector()) {
window_manager_->connector()->BindInterface(ui::mojom::kServiceName,
&native_display_delegate);
}
return base::MakeUnique<display::ForwardingDisplayDelegate>(
std::move(native_display_delegate));
#else
// The bots compile this config, but it is never run.
CHECK(false);
return nullptr;
#endif
}
std::unique_ptr<AcceleratorController>
ShellPortMash::CreateAcceleratorController() {
if (GetAshConfig() == Config::MUS) {
DCHECK(!mus_state_->accelerator_controller_delegate);
mus_state_->accelerator_controller_delegate =
base::MakeUnique<AcceleratorControllerDelegateAura>();
return base::MakeUnique<AcceleratorController>(
mus_state_->accelerator_controller_delegate.get(), nullptr);
}
DCHECK(!mash_state_->accelerator_controller_delegate);
uint16_t accelerator_namespace_id = 0u;
const bool add_result =
window_manager_->GetNextAcceleratorNamespaceId(&accelerator_namespace_id);
// ShellPortMash is created early on, so that GetNextAcceleratorNamespaceId()
// should always succeed.
DCHECK(add_result);
mash_state_->accelerator_controller_delegate =
base::MakeUnique<AcceleratorControllerDelegateMus>(window_manager_);
mash_state_->accelerator_controller_registrar =
base ::MakeUnique<AcceleratorControllerRegistrar>(
window_manager_, accelerator_namespace_id);
return base::MakeUnique<AcceleratorController>(
mash_state_->accelerator_controller_delegate.get(),
mash_state_->accelerator_controller_registrar.get());
}
} // namespace mus
} // namespace ash