chromium/components/exo/test/exo_test_helper.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/exo/test/exo_test_helper.h"

#include <memory>

#include "ash/public/cpp/shell_window_ids.h"
#include "ash/wm/desks/desks_util.h"
#include "ash/wm/window_positioner.h"
#include "ash/wm/window_positioning_utils.h"
#include "components/exo/buffer.h"
#include "components/exo/client_controlled_shell_surface.h"
#include "components/exo/display.h"
#include "components/exo/input_method_surface.h"
#include "components/exo/surface.h"
#include "components/exo/toast_surface.h"
#include "components/exo/wm_helper.h"
#include "components/exo/xdg_shell_surface.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/aura/env.h"
#include "ui/compositor/compositor.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/views/widget/widget.h"

namespace exo {
namespace test {

ClientControlledShellSurfaceDelegate::ClientControlledShellSurfaceDelegate(
    ClientControlledShellSurface* shell_surface,
    bool delay_commit)
    : shell_surface_(shell_surface), delay_commit_(delay_commit) {}
ClientControlledShellSurfaceDelegate::~ClientControlledShellSurfaceDelegate() =
    default;

void ClientControlledShellSurfaceDelegate::OnGeometryChanged(
    const gfx::Rect& geometry) {}
void ClientControlledShellSurfaceDelegate::OnStateChanged(
    chromeos::WindowStateType old_state,
    chromeos::WindowStateType new_state) {
  switch (new_state) {
    case chromeos::WindowStateType::kNormal:
    case chromeos::WindowStateType::kDefault:
      shell_surface_->SetRestored();
      break;
    case chromeos::WindowStateType::kMinimized:
      shell_surface_->SetMinimized();
      break;
    case chromeos::WindowStateType::kMaximized:
      shell_surface_->SetMaximized();
      break;
    case chromeos::WindowStateType::kFullscreen:
      shell_surface_->SetFullscreen(true, display::kInvalidDisplayId);
      break;
    case chromeos::WindowStateType::kPinned:
      shell_surface_->SetPinned(chromeos::WindowPinType::kPinned);
      break;
    case chromeos::WindowStateType::kTrustedPinned:
      shell_surface_->SetPinned(chromeos::WindowPinType::kTrustedPinned);
      break;
    default:
      NOTIMPLEMENTED();
      break;
  }
  Commit();
}
void ClientControlledShellSurfaceDelegate::OnBoundsChanged(
    chromeos::WindowStateType current_state,
    chromeos::WindowStateType requested_state,
    int64_t display_id,
    const gfx::Rect& bounds_in_screen,
    bool is_resize,
    int bounds_change,
    bool is_adjusted_bounds) {
  ASSERT_TRUE(display_id != display::kInvalidDisplayId);

  auto* window_state =
      ash::WindowState::Get(shell_surface_->GetWidget()->GetNativeWindow());

  if (!shell_surface_->host_window()->GetRootWindow())
    return;

  display::Display target_display;
  const display::Screen* screen = display::Screen::GetScreen();

  if (!screen->GetDisplayWithDisplayId(display_id, &target_display)) {
    return;
  }

  // Don't change the bounds in maximize/fullscreen/pinned state.
  if (window_state->IsMaximizedOrFullscreenOrPinned() &&
      requested_state == window_state->GetStateType()) {
    return;
  }

  gfx::Rect bounds_in_display(bounds_in_screen);
  bounds_in_display.Offset(-target_display.bounds().OffsetFromOrigin());
  shell_surface_->SetBounds(display_id, bounds_in_display);

  if (requested_state != window_state->GetStateType()) {
    DCHECK(requested_state == chromeos::WindowStateType::kPrimarySnapped ||
           requested_state == chromeos::WindowStateType::kSecondarySnapped);

    if (requested_state == chromeos::WindowStateType::kPrimarySnapped)
      shell_surface_->SetSnapPrimary(chromeos::kDefaultSnapRatio);
    else
      shell_surface_->SetSnapSecondary(chromeos::kDefaultSnapRatio);
  }

  Commit();
}
void ClientControlledShellSurfaceDelegate::OnDragStarted(int component) {}
void ClientControlledShellSurfaceDelegate::OnDragFinished(int x,
                                                          int y,
                                                          bool canceled) {}
void ClientControlledShellSurfaceDelegate::OnZoomLevelChanged(
    ZoomChange zoom_change) {}

void ClientControlledShellSurfaceDelegate::Commit() {
  if (!delay_commit_)
    shell_surface_->OnSurfaceCommit();
}

////////////////////////////////////////////////////////////////////////////////
// ExoTestHelper, public:

ExoTestHelper::ExoTestHelper() {
  ash::window_positioner::DisableAutoPositioning(true);
}

ExoTestHelper::~ExoTestHelper() {}

// static
std::unique_ptr<gfx::GpuMemoryBuffer> ExoTestHelper::CreateGpuMemoryBuffer(
    const gfx::Size& size,
    gfx::BufferFormat format) {
  return aura::Env::GetInstance()
      ->context_factory()
      ->GetGpuMemoryBufferManager()
      ->CreateGpuMemoryBuffer(size, format, gfx::BufferUsage::GPU_READ,
                              gpu::kNullSurfaceHandle, nullptr);
}

// static
std::unique_ptr<Buffer> ExoTestHelper::CreateBuffer(
    ShellSurfaceBase* shell_surface,
    gfx::BufferFormat format) {
  return CreateBuffer(
      shell_surface->GetWidget()->GetWindowBoundsInScreen().size(), format);
}

// static
std::unique_ptr<Buffer> ExoTestHelper::CreateBuffer(
    gfx::Size buffer_size,
    gfx::BufferFormat buffer_format,
    bool is_overlay_candidate) {
  return Buffer::CreateBuffer(buffer_size, buffer_format,
                              gfx::BufferUsage::GPU_READ, "ExoTestHelper",
                              gpu::kNullSurfaceHandle,
                              /*shutdown_event=*/nullptr, is_overlay_candidate);
}

// static
std::unique_ptr<Buffer> ExoTestHelper::CreateBufferFromGMBHandle(
    gfx::GpuMemoryBufferHandle handle,
    gfx::Size buffer_size,
    gfx::BufferFormat buffer_format) {
  return Buffer::CreateBufferFromGMBHandle(
      std::move(handle), buffer_size, buffer_format, gfx::BufferUsage::GPU_READ,
      /*query_type=*/GL_COMMANDS_COMPLETED_CHROMIUM, /*use_zero_copy=*/true,
      /*is_overlay_candidate=*/false, /*y_invert=*/false);
}

std::unique_ptr<InputMethodSurface> ExoTestHelper::CreateInputMethodSurface(
    Surface* surface,
    InputMethodSurfaceManager* surface_manager,
    bool default_scale_cancellation) {
  auto shell_surface = std::make_unique<InputMethodSurface>(
      surface_manager, surface, default_scale_cancellation);

  shell_surface->set_delegate(
      std::make_unique<ClientControlledShellSurfaceDelegate>(
          shell_surface.get()));

  return shell_surface;
}

std::unique_ptr<ToastSurface> ExoTestHelper::CreateToastSurface(
    Surface* surface,
    ToastSurfaceManager* surface_manager,
    bool default_scale_cancellation) {
  auto shell_surface = std::make_unique<ToastSurface>(
      surface_manager, surface, default_scale_cancellation);

  shell_surface->set_delegate(
      std::make_unique<ClientControlledShellSurfaceDelegate>(
          shell_surface.get()));

  return shell_surface;
}

}  // namespace test
}  // namespace exo