blob: fb6924f80a444cd100e31f6b67eff664aca4d044 [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/host/ash_window_tree_host_platform.h"
#include <utility>
#include "ash/host/root_window_transformer.h"
#include "ash/host/transformer_helper.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/window_factory.h"
#include "ash/ws/window_service_owner.h"
#include "base/feature_list.h"
#include "base/trace_event/trace_event.h"
#include "services/ws/event_queue.h"
#include "services/ws/public/cpp/input_devices/input_device_controller_client.h"
#include "services/ws/public/mojom/window_manager.mojom.h"
#include "services/ws/window_service.h"
#include "ui/aura/mus/input_method_mus.h"
#include "ui/aura/null_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/event_sink.h"
#include "ui/events/null_event_targeter.h"
#include "ui/events/ozone/chromeos/cursor_controller.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/transform.h"
#include "ui/platform_window/mojo/ime_type_converters.h"
#include "ui/platform_window/platform_ime_controller.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/platform_window/text_input_state.h"
namespace ash {
namespace {
// String passed to Compositor to identify who is submitting compositor frames.
// Used by telemetry.
const char* kTraceEnvironmentName = "ash";
} // namespace
AshWindowTreeHostPlatform::AshWindowTreeHostPlatform(
ui::PlatformWindowInitProperties properties)
: aura::WindowTreeHostPlatform(
std::move(properties),
window_factory::NewWindow(),
::features::IsUsingWindowService() ? kTraceEnvironmentName : nullptr),
transformer_helper_(this) {
CommonInit();
}
AshWindowTreeHostPlatform::AshWindowTreeHostPlatform()
: aura::WindowTreeHostPlatform(window_factory::NewWindow()),
transformer_helper_(this) {
CreateCompositor(
viz::FrameSinkId(),
/* force_software_compositor */ false,
/* external_begin_frame_client */ nullptr,
/* are_events_in_pixels */ true,
::features::IsUsingWindowService() ? kTraceEnvironmentName : nullptr);
CommonInit();
}
AshWindowTreeHostPlatform::~AshWindowTreeHostPlatform() = default;
void AshWindowTreeHostPlatform::ConfineCursorToRootWindow() {
if (!allow_confine_cursor())
return;
gfx::Rect confined_bounds(GetBoundsInPixels().size());
confined_bounds.Inset(transformer_helper_.GetHostInsets());
last_cursor_confine_bounds_in_pixels_ = confined_bounds;
platform_window()->ConfineCursorToBounds(confined_bounds);
}
void AshWindowTreeHostPlatform::ConfineCursorToBoundsInRoot(
const gfx::Rect& bounds_in_root) {
if (!allow_confine_cursor())
return;
gfx::RectF bounds_f(bounds_in_root);
GetRootTransform().TransformRect(&bounds_f);
last_cursor_confine_bounds_in_pixels_ = gfx::ToEnclosingRect(bounds_f);
platform_window()->ConfineCursorToBounds(
last_cursor_confine_bounds_in_pixels_);
}
gfx::Rect AshWindowTreeHostPlatform::GetLastCursorConfineBoundsInPixels()
const {
return last_cursor_confine_bounds_in_pixels_;
}
void AshWindowTreeHostPlatform::SetCursorConfig(
const display::Display& display,
display::Display::Rotation rotation) {
// Scale all motion on High-DPI displays.
float scale = display.device_scale_factor();
if (!display.IsInternal())
scale *= 1.2;
ui::CursorController::GetInstance()->SetCursorConfigForWindow(
GetAcceleratedWidget(), rotation, scale);
}
void AshWindowTreeHostPlatform::ClearCursorConfig() {
ui::CursorController::GetInstance()->ClearCursorConfigForWindow(
GetAcceleratedWidget());
}
void AshWindowTreeHostPlatform::UpdateTextInputState(
ui::mojom::TextInputStatePtr state) {
SetTextInputState(std::move(state));
}
void AshWindowTreeHostPlatform::UpdateImeVisibility(
bool visible,
ui::mojom::TextInputStatePtr state) {
SetImeVisibility(visible, std::move(state));
}
void AshWindowTreeHostPlatform::SetRootWindowTransformer(
std::unique_ptr<RootWindowTransformer> transformer) {
transformer_helper_.SetRootWindowTransformer(std::move(transformer));
ConfineCursorToRootWindow();
}
gfx::Insets AshWindowTreeHostPlatform::GetHostInsets() const {
return transformer_helper_.GetHostInsets();
}
aura::WindowTreeHost* AshWindowTreeHostPlatform::AsWindowTreeHost() {
return this;
}
void AshWindowTreeHostPlatform::PrepareForShutdown() {
// Block the root window from dispatching events because it is weird for a
// ScreenPositionClient not to be attached to the root window and for
// ui::EventHandlers to be unable to convert the event's location to screen
// coordinates.
window()->SetEventTargeter(std::make_unique<aura::NullWindowTargeter>());
// Do anything platform specific necessary before shutdown (eg. stop
// listening for configuration XEvents).
platform_window()->PrepareForShutdown();
}
void AshWindowTreeHostPlatform::SetRootTransform(
const gfx::Transform& transform) {
transformer_helper_.SetTransform(transform);
}
gfx::Transform AshWindowTreeHostPlatform::GetRootTransform() const {
return transformer_helper_.GetTransform();
}
gfx::Transform AshWindowTreeHostPlatform::GetInverseRootTransform() const {
return transformer_helper_.GetInverseTransform();
}
gfx::Rect AshWindowTreeHostPlatform::GetTransformedRootWindowBoundsInPixels(
const gfx::Size& host_size_in_pixels) const {
return transformer_helper_.GetTransformedWindowBounds(host_size_in_pixels);
}
void AshWindowTreeHostPlatform::OnCursorVisibilityChangedNative(bool show) {
SetTapToClickPaused(!show);
}
void AshWindowTreeHostPlatform::SetBoundsInPixels(
const gfx::Rect& bounds,
const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) {
WindowTreeHostPlatform::SetBoundsInPixels(bounds,
local_surface_id_allocation);
ConfineCursorToRootWindow();
}
void AshWindowTreeHostPlatform::CommonInit() {
transformer_helper_.Init();
event_queue_ =
Shell::Get()->window_service_owner()->window_service()->event_queue();
if (!::features::IsMultiProcessMash())
return;
input_method_ = std::make_unique<aura::InputMethodMus>(this, this);
input_method_->Init(Shell::Get()->connector());
SetSharedInputMethod(input_method_.get());
}
void AshWindowTreeHostPlatform::SetTapToClickPaused(bool state) {
ws::InputDeviceControllerClient* input_device_controller_client =
Shell::Get()->shell_delegate()->GetInputDeviceControllerClient();
if (!input_device_controller_client)
return; // Happens in tests.
// Temporarily pause tap-to-click when the cursor is hidden.
input_device_controller_client->SetTapToClickPaused(state);
}
bool AshWindowTreeHostPlatform::ShouldSendKeyEventToIme() {
// Don't send key events to IME if they are going to go to a remote client.
// Remote clients handle forwarding to IME (as necessary).
aura::Window* target = window()->targeter()->FindTargetForKeyEvent(window());
return !target || !ws::WindowService::IsProxyWindow(target);
}
void AshWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
if (event->IsLocatedEvent())
TranslateLocatedEvent(event->AsLocatedEvent());
return aura::WindowTreeHostPlatform::DispatchEvent(event);
}
ui::EventDispatchDetails AshWindowTreeHostPlatform::DeliverEventToSink(
ui::Event* event) {
// Queue the event if needed, or deliver it directly to the sink.
auto result = event_queue_->DeliverOrQueueEvent(this, event);
return result.value_or(ui::EventDispatchDetails());
}
void AshWindowTreeHostPlatform::SetTextInputState(
ui::mojom::TextInputStatePtr state) {
ui::PlatformImeController* ime =
platform_window()->GetPlatformImeController();
if (ime)
ime->UpdateTextInputState(state.To<ui::TextInputState>());
}
void AshWindowTreeHostPlatform::SetImeVisibility(
bool visible,
ui::mojom::TextInputStatePtr state) {
if (!state.is_null())
SetTextInputState(std::move(state));
ui::PlatformImeController* ime =
platform_window()->GetPlatformImeController();
if (ime)
ime->SetImeVisibility(visible);
}
} // namespace ash