blob: 7978057d0aa64da19b347030557cfe83182d690d [file] [log] [blame]
// Copyright 2018 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 "services/ui/ws2/window_service.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/service_manager/public/cpp/bind_source_info.h"
#include "services/ui/common/switches.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "services/ui/ws2/event_injector.h"
#include "services/ui/ws2/gpu_interface_provider.h"
#include "services/ui/ws2/remoting_event_injector.h"
#include "services/ui/ws2/screen_provider.h"
#include "services/ui/ws2/server_window.h"
#include "services/ui/ws2/user_activity_monitor.h"
#include "services/ui/ws2/window_server_test_impl.h"
#include "services/ui/ws2/window_service_delegate.h"
#include "services/ui/ws2/window_service_observer.h"
#include "services/ui/ws2/window_tree.h"
#include "services/ui/ws2/window_tree_factory.h"
#include "ui/aura/env.h"
#include "ui/base/mojo/clipboard_host.h"
#include "ui/wm/core/shadow_types.h"
namespace ui {
namespace ws2 {
WindowService::WindowService(
WindowServiceDelegate* delegate,
std::unique_ptr<GpuInterfaceProvider> gpu_interface_provider,
aura::client::FocusClient* focus_client,
bool decrement_client_ids,
aura::Env* env)
: delegate_(delegate),
env_(env ? env : aura::Env::GetInstance()),
gpu_interface_provider_(std::move(gpu_interface_provider)),
screen_provider_(std::make_unique<ScreenProvider>()),
focus_client_(focus_client),
user_activity_monitor_(std::make_unique<UserActivityMonitor>(env_)),
next_client_id_(decrement_client_ids ? kInitialClientIdDecrement
: kInitialClientId),
decrement_client_ids_(decrement_client_ids),
ime_registrar_(&ime_driver_) {
DCHECK(focus_client); // A |focus_client| must be provided.
// MouseLocationManager is necessary for providing the shared memory with the
// location of the mouse to clients.
aura::Env::GetInstance()->CreateMouseLocationManager();
input_device_server_.RegisterAsObserver();
// This property should be registered by the PropertyConverter constructor,
// but that would create a dependency cycle between ui/wm and ui/aura.
property_converter_.RegisterPrimitiveProperty(
::wm::kShadowElevationKey,
ui::mojom::WindowManager::kShadowElevation_Property,
aura::PropertyConverter::CreateAcceptAnyValueCallback());
}
WindowService::~WindowService() {
// WindowTreeFactory owns WindowTrees created by way of WindowTreeFactory.
// Deleting it should ensure there are no WindowTrees left. Additionally,
// WindowTree makes use of ScreenProvider, so we need to ensure all the
// WindowTrees are destroyed before ScreenProvider.
window_tree_factory_.reset();
DCHECK(window_trees_.empty());
}
ServerWindow* WindowService::GetServerWindowForWindowCreateIfNecessary(
aura::Window* window) {
ServerWindow* server_window = ServerWindow::GetMayBeNull(window);
if (server_window)
return server_window;
const viz::FrameSinkId frame_sink_id =
ClientWindowId(kWindowServerClientId, next_window_id_++);
CHECK_NE(0u, next_window_id_);
const bool is_top_level = false;
return ServerWindow::Create(window, nullptr, frame_sink_id, is_top_level);
}
std::unique_ptr<WindowTree> WindowService::CreateWindowTree(
mojom::WindowTreeClient* window_tree_client,
const std::string& client_name) {
const ClientSpecificId client_id =
decrement_client_ids_ ? next_client_id_-- : next_client_id_++;
CHECK_NE(kInvalidClientId, next_client_id_);
CHECK_NE(kWindowServerClientId, next_client_id_);
auto window_tree = std::make_unique<WindowTree>(
this, client_id, window_tree_client, client_name);
window_trees_.insert(window_tree.get());
return window_tree;
}
void WindowService::SetFrameDecorationValues(
const gfx::Insets& client_area_insets,
int max_title_bar_button_width) {
screen_provider_->SetFrameDecorationValues(client_area_insets,
max_title_bar_button_width);
}
void WindowService::SetDisplayForNewWindows(int64_t display_id) {
screen_provider_->SetDisplayForNewWindows(display_id);
}
// static
bool WindowService::HasRemoteClient(const aura::Window* window) {
return ServerWindow::GetMayBeNull(window);
}
void WindowService::AddObserver(WindowServiceObserver* observer) {
observers_.AddObserver(observer);
}
void WindowService::RemoveObserver(WindowServiceObserver* observer) {
observers_.RemoveObserver(observer);
}
void WindowService::OnFirstSurfaceActivation(const std::string& client_name) {
if (surface_activation_callback_)
std::move(surface_activation_callback_).Run(client_name);
}
void WindowService::OnWillDestroyWindowTree(WindowTree* tree) {
for (WindowServiceObserver& observer : observers_)
observer.OnWillDestroyClient(tree->client_id());
window_trees_.erase(tree);
}
bool WindowService::RequestClose(aura::Window* window) {
ServerWindow* server_window = ServerWindow::GetMayBeNull(window);
if (!server_window || !server_window->IsTopLevel())
return false;
server_window->owning_window_tree()->RequestClose(server_window);
return true;
}
void WindowService::OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) {
screen_provider_->DisplayMetricsChanged(display, changed_metrics);
}
std::string WindowService::GetIdForDebugging(aura::Window* window) {
ServerWindow* server_window = ServerWindow::GetMayBeNull(window);
if (!server_window)
return std::string();
return server_window->GetIdForDebugging();
}
void WindowService::OnStart() {
test_config_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseTestConfig);
event_injector_ = std::make_unique<EventInjector>(this);
window_tree_factory_ = std::make_unique<WindowTreeFactory>(this);
registry_.AddInterface(base::BindRepeating(
&WindowService::BindClipboardHostRequest, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&EventInjector::AddBinding, base::Unretained(event_injector_.get())));
registry_.AddInterface(base::BindRepeating(
&WindowService::BindImeRegistrarRequest, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&WindowService::BindImeDriverRequest, base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&WindowService::BindInputDeviceServerRequest, base::Unretained(this)));
registry_.AddInterface(
base::BindRepeating(&WindowService::BindRemotingEventInjectorRequest,
base::Unretained(this)));
registry_.AddInterface(base::BindRepeating(
&WindowService::BindUserActivityMonitorRequest, base::Unretained(this)));
registry_with_source_info_.AddInterface<mojom::WindowTreeFactory>(
base::BindRepeating(&WindowService::BindWindowTreeFactoryRequest,
base::Unretained(this)));
// |gpu_interface_provider_| may be null in tests.
if (gpu_interface_provider_) {
gpu_interface_provider_->RegisterGpuInterfaces(&registry_);
#if defined(USE_OZONE)
gpu_interface_provider_->RegisterOzoneGpuInterfaces(&registry_);
#endif
}
if (test_config_) {
registry_.AddInterface<mojom::WindowServerTest>(base::BindRepeating(
&WindowService::BindWindowServerTestRequest, base::Unretained(this)));
}
}
void WindowService::OnBindInterface(
const service_manager::BindSourceInfo& remote_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle) {
if (!registry_with_source_info_.TryBindInterface(interface_name, &handle,
remote_info)) {
registry_.BindInterface(interface_name, std::move(handle));
}
}
void WindowService::SetSurfaceActivationCallback(
base::OnceCallback<void(const std::string&)> callback) {
// Surface activation callbacks are expensive, and allowed only in tests.
DCHECK(test_config_);
DCHECK(surface_activation_callback_.is_null() || callback.is_null());
surface_activation_callback_ = std::move(callback);
}
void WindowService::BindClipboardHostRequest(
mojom::ClipboardHostRequest request) {
if (!clipboard_host_)
clipboard_host_ = std::make_unique<ClipboardHost>();
clipboard_host_->AddBinding(std::move(request));
}
void WindowService::BindImeRegistrarRequest(
mojom::IMERegistrarRequest request) {
ime_registrar_.AddBinding(std::move(request));
}
void WindowService::BindImeDriverRequest(mojom::IMEDriverRequest request) {
ime_driver_.AddBinding(std::move(request));
}
void WindowService::BindInputDeviceServerRequest(
mojom::InputDeviceServerRequest request) {
input_device_server_.AddBinding(std::move(request));
}
void WindowService::BindRemotingEventInjectorRequest(
mojom::RemotingEventInjectorRequest request) {
if (!remoting_event_injector_ && delegate_->GetSystemInputInjector()) {
remoting_event_injector_ = std::make_unique<RemotingEventInjector>(
delegate_->GetSystemInputInjector());
}
if (remoting_event_injector_)
remoting_event_injector_->AddBinding(std::move(request));
}
void WindowService::BindUserActivityMonitorRequest(
mojom::UserActivityMonitorRequest request) {
user_activity_monitor_->AddBinding(std::move(request));
}
void WindowService::BindWindowServerTestRequest(
mojom::WindowServerTestRequest request) {
if (!test_config_)
return;
mojo::MakeStrongBinding(std::make_unique<WindowServerTestImpl>(this),
std::move(request));
}
void WindowService::BindWindowTreeFactoryRequest(
mojom::WindowTreeFactoryRequest request,
const service_manager::BindSourceInfo& source_info) {
window_tree_factory_->AddBinding(std::move(request),
source_info.identity.name());
}
} // namespace ws2
} // namespace ui