// 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 <wayland-server.h>
#include <memory>

#include "base/strings/stringprintf.h"
#include "base/test/scoped_command_line.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/display.h"
#include "ui/display/display_observer.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_output.h"
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_screen.h"
#include "ui/ozone/platform/wayland/test/mock_pointer.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h"
#include "ui/ozone/platform/wayland/test/test_output.h"
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/platform_window/platform_window_init_properties.h"

using ::testing::Values;

namespace ui {

namespace {

constexpr uint32_t kNumberOfDisplays = 1;
constexpr uint32_t kOutputWidth = 1024;
constexpr uint32_t kOutputHeight = 768;

class TestDisplayObserver : public display::DisplayObserver {
 public:
  TestDisplayObserver() {}
  ~TestDisplayObserver() override {}

  display::Display GetDisplay() { return std::move(display_); }
  display::Display GetRemovedDisplay() { return std::move(removed_display_); }
  uint32_t GetAndClearChangedMetrics() {
    uint32_t changed_metrics = changed_metrics_;
    changed_metrics_ = 0;
    return changed_metrics;
  }

  // display::DisplayObserver:
  void OnDisplayAdded(const display::Display& new_display) override {
    display_ = new_display;
  }

  void OnDisplayRemoved(const display::Display& old_display) override {
    removed_display_ = old_display;
  }

  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t changed_metrics) override {
    changed_metrics_ = changed_metrics;
    display_ = display;
  }

 private:
  uint32_t changed_metrics_ = 0;
  display::Display display_;
  display::Display removed_display_;

  DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver);
};

}  // namespace

class WaylandScreenTest : public WaylandTest {
 public:
  WaylandScreenTest() = default;
  ~WaylandScreenTest() override = default;

  void SetUp() override {
    output_ = server_.output();

    WaylandTest::SetUp();

    output_->SetRect({kOutputWidth, kOutputHeight});
    output_->SetScale(1);
    output_->Flush();
    Sync();

    output_manager_ = connection_->wayland_output_manager();
    ASSERT_TRUE(output_manager_);

    EXPECT_TRUE(output_manager_->IsOutputReady());
    platform_screen_ = output_manager_->CreateWaylandScreen();
  }

 protected:
  std::unique_ptr<WaylandWindow> CreateWaylandWindowWithProperties(
      const gfx::Rect& bounds,
      PlatformWindowType window_type,
      gfx::AcceleratedWidget parent_widget,
      MockPlatformWindowDelegate* delegate) {
    PlatformWindowInitProperties properties;
    properties.bounds = bounds;
    properties.type = window_type;
    properties.parent_widget = parent_widget;
    return WaylandWindow::Create(delegate, connection_.get(),
                                 std::move(properties));
  }

  void ValidateTheDisplayForWidget(gfx::AcceleratedWidget widget,
                                   int64_t expected_display_id) {
    display::Display display_for_widget =
        platform_screen_->GetDisplayForAcceleratedWidget(widget);
    EXPECT_EQ(display_for_widget.id(), expected_display_id);
  }

  wl::TestOutput* output_ = nullptr;
  WaylandOutputManager* output_manager_ = nullptr;

  std::unique_ptr<WaylandScreen> platform_screen_;

 private:
  DISALLOW_COPY_AND_ASSIGN(WaylandScreenTest);
};

// Tests whether a primary output has been initialized before PlatformScreen is
// created.
TEST_P(WaylandScreenTest, OutputBaseTest) {
  // IsPrimaryOutputReady and PlatformScreen creation is done in the
  // initialization part of the tests.

  // Ensure there is only one display, which is the primary one.
  auto& all_displays = platform_screen_->GetAllDisplays();
  EXPECT_EQ(all_displays.size(), kNumberOfDisplays);

  // Ensure the size property of the primary display.
  EXPECT_EQ(platform_screen_->GetPrimaryDisplay().bounds(),
            gfx::Rect(0, 0, kOutputWidth, kOutputHeight));
}

TEST_P(WaylandScreenTest, MultipleOutputsAddedAndRemoved) {
  TestDisplayObserver observer;
  platform_screen_->AddObserver(&observer);

  const int64_t old_primary_display_id =
      platform_screen_->GetPrimaryDisplay().id();
  gfx::Rect output1_rect = server_.output()->GetRect();

  // Add a second display.
  wl::TestOutput* output2 = server_.CreateAndInitializeOutput();

  Sync();

  // The second display is located to the right of first display like
  // | || |.
  gfx::Rect output2_rect(output1_rect.width(), 0, 800, 600);
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  // Ensure that second display is not a primary one and have a different id.
  int64_t added_display_id = observer.GetDisplay().id();
  EXPECT_NE(platform_screen_->GetPrimaryDisplay().id(), added_display_id);

  output2->DestroyGlobal();

  Sync();

  // Ensure that removed display has correct id.
  int64_t removed_display_id = observer.GetRemovedDisplay().id();
  EXPECT_EQ(added_display_id, removed_display_id);

  // Create another display again.
  output2 = server_.CreateAndInitializeOutput();

  Sync();

  // Updates rect again.
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  // The newly added display is not a primary yet.
  added_display_id = observer.GetDisplay().id();
  EXPECT_NE(platform_screen_->GetPrimaryDisplay().id(), added_display_id);

  // Now, rearrange displays so that second display becomes the primary one.
  output1_rect = gfx::Rect(1024, 0, 1024, 768);
  output_->SetRect(output1_rect);
  output_->Flush();

  output2_rect = gfx::Rect(0, 0, 1024, 768);
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  // Ensure that output2 is now the primary one.
  EXPECT_EQ(platform_screen_->GetPrimaryDisplay().id(), added_display_id);

  // Remove the primary display now.
  output2->DestroyGlobal();

  Sync();

  // Ensure that output1 is a primary display now.
  EXPECT_EQ(platform_screen_->GetPrimaryDisplay().id(), old_primary_display_id);
  // Ensure that the removed display was the one, which was a primary display.
  EXPECT_EQ(observer.GetRemovedDisplay().id(), added_display_id);

  platform_screen_->RemoveObserver(&observer);
}

TEST_P(WaylandScreenTest, OutputPropertyChanges) {
  TestDisplayObserver observer;
  platform_screen_->AddObserver(&observer);

  gfx::Rect new_rect{100, 100};
  output_->SetRect(new_rect);
  output_->Flush();

  Sync();

  uint32_t changed_values = display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
                            display::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
  EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
  EXPECT_EQ(observer.GetDisplay().bounds(), new_rect);

  const int32_t new_scale_value = 2;
  output_->SetScale(new_scale_value);
  output_->Flush();

  Sync();

  changed_values =
      display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
      display::DisplayObserver::DISPLAY_METRIC_WORK_AREA |
      display::DisplayObserver::DISPLAY_METRIC_BOUNDS;
  EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
  EXPECT_EQ(observer.GetDisplay().device_scale_factor(), new_scale_value);
  EXPECT_EQ(observer.GetDisplay().bounds(), gfx::Rect(50, 50));

  platform_screen_->RemoveObserver(&observer);
}

TEST_P(WaylandScreenTest, GetAcceleratedWidgetAtScreenPoint) {
  // Now, send enter event for the surface, which was created before.
  wl::MockSurface* surface = server_.GetObject<wl::MockSurface>(
      window_->root_surface()->GetSurfaceId());
  ASSERT_TRUE(surface);
  wl_surface_send_enter(surface->resource(), output_->resource());

  Sync();

  // If there is no focused window (focus is set whenever a pointer enters any
  // of the windows), there must be kNullAcceleratedWidget returned. There is no
  // real way to determine what window is located on a certain screen point in
  // Wayland.
  gfx::AcceleratedWidget widget_at_screen_point =
      platform_screen_->GetAcceleratedWidgetAtScreenPoint(gfx::Point(10, 10));
  EXPECT_EQ(widget_at_screen_point, gfx::kNullAcceleratedWidget);

  // Set a focus to the main window. Now, that focused window must be returned.
  window_->SetPointerFocus(true);
  widget_at_screen_point =
      platform_screen_->GetAcceleratedWidgetAtScreenPoint(gfx::Point(10, 10));
  EXPECT_EQ(widget_at_screen_point, window_->GetWidget());

  // Getting a widget at a screen point outside its bounds, must result in a
  // null widget.
  const gfx::Rect window_bounds = window_->GetBounds();
  widget_at_screen_point = platform_screen_->GetAcceleratedWidgetAtScreenPoint(
      gfx::Point(window_bounds.width() + 1, window_bounds.height() + 1));
  EXPECT_EQ(widget_at_screen_point, gfx::kNullAcceleratedWidget);

  MockPlatformWindowDelegate delegate;
  auto menu_window_bounds =
      gfx::Rect(window_->GetBounds().width() - 10,
                window_->GetBounds().height() - 10, 100, 100);
  std::unique_ptr<WaylandWindow> menu_window =
      CreateWaylandWindowWithProperties(menu_window_bounds,
                                        PlatformWindowType::kMenu,
                                        window_->GetWidget(), &delegate);

  Sync();

  // Imagine the mouse enters a menu window, which is located on top of the main
  // window, and gathers focus.
  window_->SetPointerFocus(false);
  menu_window->SetPointerFocus(true);
  widget_at_screen_point =
      platform_screen_->GetAcceleratedWidgetAtScreenPoint(gfx::Point(
          menu_window->GetBounds().x() + 1, menu_window->GetBounds().y() + 1));
  EXPECT_EQ(widget_at_screen_point, menu_window->GetWidget());

  // Whenever a mouse pointer leaves the menu window, the accelerated widget
  // of that focused window must be returned.
  window_->SetPointerFocus(true);
  menu_window->SetPointerFocus(false);
  widget_at_screen_point =
      platform_screen_->GetAcceleratedWidgetAtScreenPoint(gfx::Point(0, 0));
  EXPECT_EQ(widget_at_screen_point, window_->GetWidget());

  // Reset the focus to avoid crash on dtor as long as there is no real pointer
  // object.
  window_->SetPointerFocus(false);

  // Part 2: test that the window is found when display's scale changes.
  // Update scale.
  output_->SetScale(2);
  output_->Flush();

  Sync();

  auto menu_bounds_px = menu_window->GetBounds();
  // Translate the point to dip.
  auto point_in_screen =
      gfx::ScaleToRoundedPoint(menu_bounds_px.origin(), 1.f / 2);
  menu_window->SetPointerFocus(true);
  widget_at_screen_point =
      platform_screen_->GetAcceleratedWidgetAtScreenPoint(point_in_screen);
  EXPECT_EQ(widget_at_screen_point, menu_window->GetWidget());
}

TEST_P(WaylandScreenTest, GetLocalProcessWidgetAtPoint) {
  gfx::Point point(10, 10);
  EXPECT_EQ(platform_screen_->GetLocalProcessWidgetAtPoint(point, {}),
            gfx::kNullAcceleratedWidget);

  // Set a focus to the main window. Now, that focused window must be returned.
  window_->SetPointerFocus(true);
  EXPECT_EQ(platform_screen_->GetLocalProcessWidgetAtPoint(point, {}),
            window_->GetWidget());

  // Null widget must be returned when the focused window is part of the
  // |ignore| list.
  gfx::AcceleratedWidget w = window_->GetWidget();
  EXPECT_EQ(
      platform_screen_->GetLocalProcessWidgetAtPoint(point, {w - 1, w, w + 1}),
      gfx::kNullAcceleratedWidget);

  // Reset the focus to avoid crash on dtor as long as there is no real pointer
  // object.
  window_->SetPointerFocus(false);
}

TEST_P(WaylandScreenTest, GetDisplayMatching) {
  TestDisplayObserver observer;
  platform_screen_->AddObserver(&observer);

  const display::Display primary_display =
      platform_screen_->GetPrimaryDisplay();

  wl::TestOutput* output2 = server_.CreateAndInitializeOutput();

  Sync();

  // Place it on the right side of the primary display.
  const gfx::Rect output2_rect =
      gfx::Rect(primary_display.bounds().width(), 0, 1024, 768);
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  const display::Display second_display = observer.GetDisplay();
  EXPECT_EQ(second_display.bounds(), output2_rect);

  // We have two displays: display1(0:0,1024x768) and display2(1024:0,1024x768).
  EXPECT_EQ(
      primary_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)).id());
  EXPECT_EQ(
      second_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1024, 0, 10, 10)).id());

  // More pixels on second display.
  EXPECT_EQ(
      second_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1020, 0, 10, 10)).id());

  // More pixels on first display.
  EXPECT_EQ(
      primary_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1018, 0, 10, 10)).id());

  // Half pixels on second and half on primary.
  EXPECT_EQ(
      primary_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1019, 0, 10, 10)).id());

  // Place second display 700 pixels below along y axis (1024:700,1024x768)
  output2->SetRect(
      gfx::Rect(gfx::Point(output2_rect.x(), output2_rect.y() + 700),
                output2_rect.size()));
  output2->Flush();

  Sync();

  // The match rect is located outside the displays. Primary display must be
  // returned.
  EXPECT_EQ(
      primary_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1024, 0, 10, 10)).id());

  // At least some of the pixels are located on the display.
  EXPECT_EQ(
      primary_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1023, 0, 10, 10)).id());

  // Most of pixels are located on second display.
  EXPECT_EQ(
      second_display.id(),
      platform_screen_->GetDisplayMatching(gfx::Rect(1023, 695, 10, 10)).id());

  // Empty rect results in primary display.
  EXPECT_EQ(primary_display.id(),
            platform_screen_->GetDisplayMatching(gfx::Rect(0, 0, 0, 0)).id());

  platform_screen_->RemoveObserver(&observer);
  output2->DestroyGlobal();
  Sync();
}

TEST_P(WaylandScreenTest, GetDisplayForAcceleratedWidget) {
  TestDisplayObserver observer;
  platform_screen_->AddObserver(&observer);

  const display::Display primary_display =
      platform_screen_->GetPrimaryDisplay();

  // Create an additional display.
  wl::TestOutput* output2 = server_.CreateAndInitializeOutput();

  Sync();

  // Place it on the right side of the primary
  // display.
  const gfx::Rect output2_rect =
      gfx::Rect(primary_display.bounds().width(), 0, 1024, 768);
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  const display::Display secondary_display = observer.GetDisplay();
  EXPECT_EQ(secondary_display.bounds(), output2_rect);

  const gfx::AcceleratedWidget widget = window_->GetWidget();
  // There must be a primary display used if the window has not received an
  // enter event yet.
  ValidateTheDisplayForWidget(widget, primary_display.id());

  // Now, send enter event for the surface, which was created before.
  wl::MockSurface* surface = server_.GetObject<wl::MockSurface>(
      window_->root_surface()->GetSurfaceId());
  ASSERT_TRUE(surface);
  wl_surface_send_enter(surface->resource(), output_->resource());

  Sync();

  // The id of the entered display must correspond to the primary output.
  ValidateTheDisplayForWidget(widget, primary_display.id());

  Sync();

  // Enter the second output now.
  wl_surface_send_enter(surface->resource(), output2->resource());

  Sync();

  // The id of the entered display must still correspond to the primary output.
  ValidateTheDisplayForWidget(widget, primary_display.id());

  // Leave the first output.
  wl_surface_send_leave(surface->resource(), output_->resource());

  Sync();

  // The id of the entered display must correspond to the second output.
  ValidateTheDisplayForWidget(widget, secondary_display.id());

  // Leaving the same output twice (check comment in
  // WaylandWindow::OnEnteredOutputIdRemoved), must be ok and nothing must
  // change.
  wl_surface_send_leave(surface->resource(), output_->resource());

  Sync();

  // The id of the entered display must correspond to the second output.
  ValidateTheDisplayForWidget(widget, secondary_display.id());

  output2->DestroyGlobal();
  Sync();
}

TEST_P(WaylandScreenTest, GetCursorScreenPoint) {
  MockPlatformWindowDelegate delegate;
  std::unique_ptr<WaylandWindow> second_window =
      CreateWaylandWindowWithProperties(gfx::Rect(0, 0, 1920, 1080),
                                        PlatformWindowType::kWindow,
                                        gfx::kNullAcceleratedWidget, &delegate);

  auto* surface = server_.GetObject<wl::MockSurface>(
      window_->root_surface()->GetSurfaceId());
  ASSERT_TRUE(surface);

  // Announce pointer capability so that WaylandPointer is created on the client
  // side.
  wl_seat_send_capabilities(server_.seat()->resource(),
                            WL_SEAT_CAPABILITY_POINTER);

  Sync();

  wl::MockPointer* pointer = server_.seat()->pointer();
  ASSERT_TRUE(pointer);

  uint32_t serial = 0;
  uint32_t time = 1002;
  wl_pointer_send_enter(pointer->resource(), ++serial, surface->resource(), 0,
                        0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(10),
                         wl_fixed_from_int(20));

  Sync();

  // WaylandScreen must return the last pointer location.
  EXPECT_EQ(gfx::Point(10, 20), platform_screen_->GetCursorScreenPoint());

  auto* second_surface = server_.GetObject<wl::MockSurface>(
      second_window->root_surface()->GetSurfaceId());
  ASSERT_TRUE(second_surface);
  // Now, leave the first surface and enter second one.
  wl_pointer_send_leave(pointer->resource(), ++serial, surface->resource());
  wl_pointer_send_enter(pointer->resource(), ++serial,
                        second_surface->resource(), 0, 0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(20),
                         wl_fixed_from_int(10));

  Sync();

  // WaylandScreen must return the last pointer location.
  EXPECT_EQ(gfx::Point(20, 10), platform_screen_->GetCursorScreenPoint());

  // Clear pointer focus.
  wl_pointer_send_leave(pointer->resource(), ++serial,
                        second_surface->resource());

  Sync();

  // WaylandScreen must return a point, which is located outside of bounds of
  // any window. Basically, it means that it takes the largest window and adds
  // 10 pixels to its width and height, and returns the value.
  const gfx::Rect second_window_bounds = second_window->GetBounds();
  // A second window has largest bounds. Thus, these bounds must be taken as a
  // ground for the point outside any of the surfaces.
  ASSERT_TRUE(window_->GetBounds() < second_window_bounds);
  EXPECT_EQ(gfx::Point(second_window_bounds.width() + 10,
                       second_window_bounds.height() + 10),
            platform_screen_->GetCursorScreenPoint());

  // Create a menu window now and ensure cursor position is always sent in
  // regards to that window bounds.
  std::unique_ptr<WaylandWindow> menu_window =
      CreateWaylandWindowWithProperties(
          gfx::Rect(second_window_bounds.width() - 10,
                    second_window_bounds.height() - 10, 10, 20),
          PlatformWindowType::kMenu, second_window->GetWidget(), &delegate);

  Sync();

  auto* menu_surface = server_.GetObject<wl::MockSurface>(
      menu_window->root_surface()->GetSurfaceId());
  ASSERT_TRUE(menu_surface);

  wl_pointer_send_enter(pointer->resource(), ++serial, menu_surface->resource(),
                        0, 0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(2),
                         wl_fixed_from_int(1));

  Sync();

  // The cursor screen point must be converted to the top-level window
  // coordinates as long as Wayland doesn't provide global coordinates of
  // surfaces and Chromium assumes those windows are always located at origin
  // (0,0). For more information, check the comment in
  // WaylandWindow::UpdateCursorPositionFromEvent.
  EXPECT_EQ(gfx::Point(1912, 1071), platform_screen_->GetCursorScreenPoint());

  // Leave the menu window and enter the top level window.
  wl_pointer_send_leave(pointer->resource(), ++serial,
                        menu_surface->resource());
  wl_pointer_send_enter(pointer->resource(), ++serial,
                        second_surface->resource(), 0, 0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(1912),
                         wl_fixed_from_int(1071));

  Sync();

  // WaylandWindow::UpdateCursorPositionFromEvent mustn't convert this point,
  // because it has already been located on the top-level window.
  EXPECT_EQ(gfx::Point(1912, 1071), platform_screen_->GetCursorScreenPoint());

  wl_pointer_send_leave(pointer->resource(), ++serial,
                        second_surface->resource());

  // Now, create a nested menu window and make sure that the cursor screen point
  // still has been correct. The location of the window is on the right side of
  // the main menu window.
  const gfx::Rect menu_window_bounds = menu_window->GetBounds();
  std::unique_ptr<WaylandWindow> nested_menu_window =
      CreateWaylandWindowWithProperties(
          gfx::Rect(menu_window_bounds.x() + menu_window_bounds.width(),
                    menu_window_bounds.y() + 2, 10, 20),
          PlatformWindowType::kMenu, second_window->GetWidget(), &delegate);

  Sync();

  auto* nested_menu_surface = server_.GetObject<wl::MockSurface>(
      nested_menu_window->root_surface()->GetSurfaceId());
  ASSERT_TRUE(nested_menu_surface);

  wl_pointer_send_enter(pointer->resource(), ++serial,
                        nested_menu_surface->resource(), 0, 0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(2),
                         wl_fixed_from_int(3));

  Sync();

  EXPECT_EQ(gfx::Point(1922, 1075), platform_screen_->GetCursorScreenPoint());

  // Leave the nested surface and enter main menu surface. The cursor screen
  // point still must be reported correctly.
  wl_pointer_send_leave(pointer->resource(), ++serial,
                        nested_menu_surface->resource());
  wl_pointer_send_enter(pointer->resource(), ++serial, menu_surface->resource(),
                        0, 0);
  wl_pointer_send_motion(pointer->resource(), ++time, wl_fixed_from_int(2),
                         wl_fixed_from_int(1));

  Sync();

  EXPECT_EQ(gfx::Point(1912, 1071), platform_screen_->GetCursorScreenPoint());
}

// Checks that the surface that backs the window receives new scale of the
// output that it is in.
TEST_P(WaylandScreenTest, SetWindowScale) {
  // Place the window onto the output.
  wl_surface_send_enter(surface_->resource(), output_->resource());

  // Change the scale of the output.  Windows looking into that output must get
  // the new scale and update scale of their buffers.  The default UI scale
  // equals the output scale.
  const int32_t kTripleScale = 3;
  output_->SetScale(kTripleScale);
  output_->Flush();

  Sync();

  EXPECT_EQ(window_->window_scale(), kTripleScale);
  EXPECT_EQ(window_->ui_scale_, kTripleScale);

  // Now simulate the --force-device-scale-factor=1.5
  const float kForcedUIScale = 1.5;
  base::test::ScopedCommandLine command_line;
  command_line.GetProcessCommandLine()->AppendSwitchASCII(
      switches::kForceDeviceScaleFactor,
      base::StringPrintf("%.1f", kForcedUIScale));
  display::Display::ResetForceDeviceScaleFactorForTesting();

  // Change the scale of the output again.  Windows must update scale of
  // their buffers but the UI scale must get the forced value.
  const int32_t kDoubleScale = 2;
  // Question ourselves before questioning others!
  EXPECT_NE(kForcedUIScale, kDoubleScale);
  output_->SetScale(kDoubleScale);
  output_->Flush();

  Sync();

  EXPECT_EQ(window_->window_scale(), kDoubleScale);
  EXPECT_EQ(window_->ui_scale_, kForcedUIScale);

  display::Display::ResetForceDeviceScaleFactorForTesting();
}

// Tests that WaylandScreen updates list of displays with additional fractional
// scale by taking only decimal part of it and updating the displays using their
// existing scale + fractional part. This fractional part comes from GNOME's
// accessibility feature called "Large Text".
TEST_P(WaylandScreenTest, SetAdditionalScale) {
  TestDisplayObserver observer;
  platform_screen_->AddObserver(&observer);

  const display::Display primary_display =
      platform_screen_->GetPrimaryDisplay();

  wl::TestOutput* output2 = server_.CreateAndInitializeOutput();

  Sync();

  // Place it on the right side of the primary display.
  const gfx::Rect output2_rect =
      gfx::Rect(primary_display.bounds().width(), 0, 1024, 768);
  output2->SetRect(output2_rect);
  output2->Flush();

  Sync();

  const std::vector<float> scales = {0.2, 0.7, 1.3, 1.6, 1.8, 2.3, 2.9, 3.5};
  // Pretend GNOME updates scale and sets fractional scale (Large Text feature).
  for (auto scale : scales) {
    platform_screen_->SetDeviceScaleFactor(scale);
    for (auto& display : platform_screen_->GetAllDisplays()) {
      float whole = 0;
      // WaylandScreen will get decimal part and use the integer part provided
      // by wl_output.
      float expected_scale = std::modf(scale, &whole) + 1.f;
      EXPECT_EQ(expected_scale, display.device_scale_factor());
    }
  }
}

namespace {

class LazilyConfiguredScreenTest
    : public WaylandTest,
      public wl::TestWaylandServerThread::OutputDelegate {
 public:
  LazilyConfiguredScreenTest() = default;
  LazilyConfiguredScreenTest(const LazilyConfiguredScreenTest&) = delete;
  LazilyConfiguredScreenTest& operator=(const LazilyConfiguredScreenTest&) =
      delete;
  ~LazilyConfiguredScreenTest() override = default;

  void SetUp() override {
    // Being the server's output delegate allows LazilyConfiguredScreenTest to
    // manipulate wl_outputs during the server's global objects initialization
    // phase. See SetupOutputs() function below.
    server_.set_output_delegate(this);

    WaylandTest::SetUp();

    output_manager_ = connection_->wayland_output_manager();
    ASSERT_TRUE(output_manager_);
  }

  void TearDown() override {
    WaylandTest::TearDown();
    server_.set_output_delegate(nullptr);
  }

 protected:
  // wl::TestWaylandServerThread::OutputDelegate:
  void SetupOutputs(wl::TestOutput* primary) override {
    // Keep the first wl_output announced "unconfigured" and just caches it for
    // now, so we can exercise WaylandOutputManager::IsOutputReady() function
    // when wl_output events come in unordered.
    primary_output_ = primary;

    // Create/announce a second wl_output object and makes it the first one to
    // get configuration events (eg: geometry, done, etc). This is achieved by
    // setting its bounds here.
    aux_output_ = server_.CreateAndInitializeOutput();
    aux_output_->SetRect({0, 0, 800, 600});
  }

  wl::TestOutput* primary_output_ = nullptr;
  wl::TestOutput* aux_output_ = nullptr;
  WaylandOutputManager* output_manager_ = nullptr;
  bool auto_configure;
};

}  // namespace

// Ensures WaylandOutputManager and WaylandScreen properly handle scenarios
// where multiple wl_output objects are announced but not "configured" (ie:
// size, position, mode, etc sent to client) at bind time.
TEST_P(LazilyConfiguredScreenTest, DualOutput) {
  // Ensure WaylandScreen got properly created and fed with a single display
  // object, ie: |aux_output_| at server side.
  EXPECT_TRUE(output_manager_->IsOutputReady());
  EXPECT_TRUE(screen_);
  EXPECT_EQ(1u, screen_->GetAllDisplays().size());
  Sync();

  // Send wl_output configuration events for the first advertised wl_output
  // object. ie: |primary_output_| at server side.
  primary_output_->SetRect({800, 0, kOutputWidth, kOutputHeight});
  primary_output_->SetScale(1);
  primary_output_->Flush();
  Sync();

  // And make sure it makes its way into the WaylandScreen's display list at
  // client side.
  EXPECT_EQ(2u, screen_->GetAllDisplays().size());
}

INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
                         WaylandScreenTest,
                         Values(wl::ServerConfig{
                             .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
                         WaylandScreenTest,
                         Values(wl::ServerConfig{
                             .shell_version = wl::ShellVersion::kV6}));
INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest,
                         LazilyConfiguredScreenTest,
                         Values(wl::ServerConfig{
                             .shell_version = wl::ShellVersion::kStable}));
INSTANTIATE_TEST_SUITE_P(XdgVersionV6Test,
                         LazilyConfiguredScreenTest,
                         Values(wl::ServerConfig{
                             .shell_version = wl::ShellVersion::kV6}));

}  // namespace ui
