910e62b5创建于 1月15日历史提交
// Copyright 2016 The Chromium Authors
// 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 "base/memory/raw_ptr.h"

#include <utility>

#include "ash/host/ash_window_tree_host_delegate.h"
#include "ash/host/root_window_transformer.h"
#include "ash/host/transformer_helper.h"
#include "base/feature_list.h"
#include "base/trace_event/trace_event.h"
#include "ui/aura/null_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_platform.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/geometry/transform.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace ash {

class ScopedEnableUnadjustedMouseEventsOzone
    : public aura::ScopedEnableUnadjustedMouseEvents {
 public:
  explicit ScopedEnableUnadjustedMouseEventsOzone(
      ui::InputController* input_controller)
      : input_controller_(input_controller) {
    input_controller_->SuspendMouseAcceleration();
  }

  ~ScopedEnableUnadjustedMouseEventsOzone() override {
    input_controller_->EndMouseAccelerationSuspension();
  }

 private:
  raw_ptr<ui::InputController> input_controller_;
};

AshWindowTreeHostPlatform::AshWindowTreeHostPlatform(
    ui::PlatformWindowInitProperties properties,
    AshWindowTreeHostDelegate* delegate)
    : aura::WindowTreeHostPlatform(std::move(properties),
                                   std::make_unique<aura::Window>(nullptr)),
      delegate_(delegate),
      transformer_helper_(this),
      input_controller_(
          ui::OzonePlatform::GetInstance()->GetInputController()) {
  DCHECK(delegate_);
  CommonInit();
}

AshWindowTreeHostPlatform::AshWindowTreeHostPlatform(
    std::unique_ptr<ui::PlatformWindow> platform_window,
    AshWindowTreeHostDelegate* delegate,
    size_t compositor_memory_limit_mb)
    : aura::WindowTreeHostPlatform(std::make_unique<aura::Window>(nullptr)),
      delegate_(delegate),
      transformer_helper_(this) {
  DCHECK(delegate_);
  CreateCompositor(/* force_software_compositor */ false,
                   /* use_external_begin_frame_control */ false,
                   /* enable_compositing_based_throttling */ false,
                   compositor_memory_limit_mb);
  SetPlatformWindow(std::move(platform_window));
  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;

  last_cursor_confine_bounds_in_pixels_ =
      GetRootTransform().MapRect(bounds_in_root);
  platform_window()->ConfineCursorToBounds(
      last_cursor_confine_bounds_in_pixels_);
}

gfx::Rect AshWindowTreeHostPlatform::GetLastCursorConfineBoundsInPixels()
    const {
  return last_cursor_confine_bounds_in_pixels_;
}

void AshWindowTreeHostPlatform::UpdateCursorConfig() {
  const display::Display* display = delegate_->GetDisplayById(GetDisplayId());
  if (!display) {
    LOG(ERROR)
        << "While updating cursor config, could not find display with id="
        << GetDisplayId();
    return;
  }

  // Scale all motion on High-DPI displays.
  float scale = display->device_scale_factor();

  if (!display->IsInternal())
    scale *= 1.2;

  ui::CursorController::GetInstance()->SetCursorConfigForWindow(
      GetAcceleratedWidget(), display->panel_rotation(), scale);
}

void AshWindowTreeHostPlatform::ClearCursorConfig() {
  ui::CursorController::GetInstance()->ClearCursorConfigForWindow(
      GetAcceleratedWidget());
}

void AshWindowTreeHostPlatform::UpdateRootWindowSize() {
  aura::WindowTreeHostPlatform::UpdateRootWindowSize();
}

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::GetTransformedRootWindowBoundsFromPixelSize(
    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) {
  WindowTreeHostPlatform::SetBoundsInPixels(bounds);
  ConfineCursorToRootWindow();
}

void AshWindowTreeHostPlatform::CommonInit() {
  transformer_helper_.Init();
}

void AshWindowTreeHostPlatform::SetTapToClickPaused(bool state) {
  // Temporarily pause tap-to-click when the cursor is hidden.
  ui::OzonePlatform::GetInstance()->GetInputController()->SetTapToClickPaused(
      state);
}

std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
AshWindowTreeHostPlatform::RequestUnadjustedMovement() {
  return std::make_unique<ScopedEnableUnadjustedMouseEventsOzone>(
      input_controller_);
}

void AshWindowTreeHostPlatform::OnDamageRect(const gfx::Rect& damage_rect) {
  if (ignore_platform_damage_rect_for_test_) {
    return;
  }
  return aura::WindowTreeHostPlatform::OnDamageRect(damage_rect);
}

void AshWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
  TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
  if (event->IsLocatedEvent())
    TranslateLocatedEvent(event->AsLocatedEvent());
  return aura::WindowTreeHostPlatform::DispatchEvent(event);
}

}  // namespace ash