#include <wayland-server-protocol.h>
#include <wayland-server.h>
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.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/host/wayland_seat.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/mock_wayland_platform_window_delegate.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/test_zaura_shell.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/platform_window/platform_window_init_properties.h"
Values;
namespace ui {
namespace {
constexpr uint32_t kNumberOfDisplays = …;
constexpr uint32_t kOutputWidth = …;
constexpr uint32_t kOutputHeight = …;
int GetRightX(const wl::TestOutput* output) { … }
class TestDisplayObserver : public display::DisplayObserver { … };
}
class WaylandScreenTest : public WaylandTest { … };
TEST_P(WaylandScreenTest, OutputBaseTest) { … }
TEST_P(WaylandScreenTest, EnteredOutputListAfterDisplayRemoval) { … }
TEST_P(WaylandScreenTest, MultipleOutputsAddedAndRemoved) { … }
TEST_P(WaylandScreenTest, OutputPropertyChangesMissingLogicalSize) { … }
TEST_P(WaylandScreenTest, OutputPropertyChangesPrimaryDisplayChanged) { … }
TEST_P(WaylandScreenTest, OutputPropertyChangesOverscanInsets) { … }
TEST_P(WaylandScreenTest, GetAcceleratedWidgetAtScreenPoint) { … }
TEST_P(WaylandScreenTest, GetLocalProcessWidgetAtPoint) { … }
TEST_P(WaylandScreenTest, GetDisplayMatching) { … }
TEST_P(WaylandScreenTest, GetPrimaryDisplayAfterRemoval) { … }
TEST_P(WaylandScreenTest, GetDisplayForAcceleratedWidget) { … }
TEST_P(WaylandScreenTest, GetCursorScreenPoint) { … }
TEST_P(WaylandScreenTest, SetWindowScale) { … }
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_P(WaylandScreenTest, SetWindowScaleWithoutEnteredOutput) { … }
#endif
TEST_P(WaylandScreenTest, Transform) { … }
TEST_P(WaylandScreenTest, DualOutput) { … }
TEST_P(WaylandScreenTest, OutputStateIsConsistentWhenNotifyingObservers) { … }
#if BUILDFLAG(IS_CHROMEOS_LACROS)
class WaylandAuraShellScreenTest : public WaylandScreenTest {
public:
void SetUp() override {
WaylandScreenTest::SetUp();
connection_->set_surface_submission_in_pixel_coordinates(true);
}
};
TEST_P(WaylandAuraShellScreenTest, OutputPropertyChanges) {
TestDisplayObserver observer;
platform_screen_->AddObserver(&observer);
constexpr gfx::Rect kPhysicalBounds{800, 600};
PostToServerAndWait([kPhysicalBounds](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetPhysicalAndLogicalBounds(kPhysicalBounds);
output->Flush();
});
uint32_t changed_values = display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
display::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
constexpr gfx::Rect kExpectedBounds{800, 600};
EXPECT_EQ(observer.GetDisplay().bounds(), kExpectedBounds);
constexpr gfx::Size expected_size_in_pixels{800, 600};
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), expected_size_in_pixels);
EXPECT_EQ(observer.GetDisplay().work_area(), kExpectedBounds);
constexpr gfx::Rect kNewWorkArea{10, 20, 700, 500};
const gfx::Insets expected_inset = kExpectedBounds.InsetsFrom(kNewWorkArea);
PostToServerAndWait([expected_inset](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetLogicalInsets(expected_inset);
output->Flush();
});
changed_values = display::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
EXPECT_EQ(observer.GetDisplay().bounds(), kExpectedBounds);
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), expected_size_in_pixels);
EXPECT_EQ(observer.GetDisplay().work_area(), kNewWorkArea);
constexpr int32_t kNewScaleValue = 2;
const gfx::Size scaled_logical_size =
gfx::ScaleToRoundedSize(kPhysicalBounds.size(), 1.f / kNewScaleValue);
PostToServerAndWait([&](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetLogicalSize(scaled_logical_size);
output->SetDeviceScaleFactor(kNewScaleValue);
output->Flush();
});
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(), kNewScaleValue);
const gfx::Rect scaled_bounds{400, 300};
EXPECT_EQ(observer.GetDisplay().bounds(), scaled_bounds);
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), expected_size_in_pixels);
gfx::Rect scaled_work_area(scaled_bounds);
scaled_work_area.Inset(expected_inset);
EXPECT_EQ(observer.GetDisplay().work_area(), scaled_work_area);
PostToServerAndWait([&](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetPanelTransform(WL_OUTPUT_TRANSFORM_90);
output->SetLogicalTransform(WL_OUTPUT_TRANSFORM_90);
output->ApplyLogicalTranspose();
output->Flush();
});
changed_values = display::DisplayObserver::DISPLAY_METRIC_WORK_AREA |
display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
display::DisplayObserver::DISPLAY_METRIC_ROTATION;
EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
const gfx::Rect rotated_bounds{300, 400};
EXPECT_EQ(observer.GetDisplay().bounds(), rotated_bounds);
const gfx::Size rotated_size_in_pixels{600, 800};
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), rotated_size_in_pixels);
gfx::Rect rotated_work_area(rotated_bounds);
rotated_work_area.Inset(expected_inset);
EXPECT_EQ(observer.GetDisplay().work_area(), rotated_work_area);
EXPECT_EQ(observer.GetDisplay().panel_rotation(),
display::Display::Rotation::ROTATE_270);
EXPECT_EQ(observer.GetDisplay().rotation(),
display::Display::Rotation::ROTATE_270);
platform_screen_->RemoveObserver(&observer);
}
TEST_P(WaylandAuraShellScreenTest,
OutputPropertyChangesWithPortraitPanelRotation) {
TestDisplayObserver observer;
platform_screen_->AddObserver(&observer);
constexpr gfx::Point kOrigin(50, 70);
constexpr gfx::Size kPhysicalSize(1200, 1600);
PostToServerAndWait([&](wl::TestWaylandServerThread* server) {
server->output()->SetPhysicalAndLogicalBounds({kOrigin, kPhysicalSize});
});
constexpr gfx::Insets kInsets = gfx::Insets::TLBR(10, 20, 30, 40);
const gfx::Size scaled_logical_size =
gfx::ScaleToRoundedSize(kPhysicalSize, 0.5);
PostToServerAndWait([&](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetLogicalSize(scaled_logical_size);
output->SetDeviceScaleFactor(2);
output->SetLogicalInsets(kInsets);
output->SetPanelTransform(WL_OUTPUT_TRANSFORM_90);
output->SetLogicalTransform(WL_OUTPUT_TRANSFORM_NORMAL);
output->ApplyLogicalTranspose();
output->Flush();
});
uint32_t changed_values =
display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
display::DisplayObserver::DISPLAY_METRIC_WORK_AREA |
display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
display::DisplayObserver::DISPLAY_METRIC_ROTATION;
EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
const gfx::Rect kExpectedBounds(kOrigin, gfx::Size(800, 600));
EXPECT_EQ(observer.GetDisplay().bounds(), kExpectedBounds);
const gfx::Size expected_size_in_pixels(1600, 1200);
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), expected_size_in_pixels);
gfx::Rect expected_work_area(kExpectedBounds);
expected_work_area.Inset(kInsets);
EXPECT_EQ(observer.GetDisplay().work_area(), expected_work_area);
EXPECT_EQ(observer.GetDisplay().panel_rotation(),
display::Display::Rotation::ROTATE_270);
EXPECT_EQ(observer.GetDisplay().rotation(),
display::Display::Rotation::ROTATE_0);
PostToServerAndWait([&](wl::TestWaylandServerThread* server) {
auto* output = server->output();
output->SetPanelTransform(WL_OUTPUT_TRANSFORM_180);
output->SetLogicalTransform(WL_OUTPUT_TRANSFORM_90);
output->ApplyLogicalTranspose();
output->Flush();
});
changed_values = display::DisplayObserver::DISPLAY_METRIC_BOUNDS |
display::DisplayObserver::DISPLAY_METRIC_WORK_AREA |
display::DisplayObserver::DISPLAY_METRIC_ROTATION;
EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
const gfx::Rect portrait_bounds(kOrigin, gfx::Size(600, 800));
EXPECT_EQ(observer.GetDisplay().bounds(), portrait_bounds);
const gfx::Size portrait_size_in_pixels(1200, 1600);
EXPECT_EQ(observer.GetDisplay().GetSizeInPixel(), portrait_size_in_pixels);
gfx::Rect portrait_work_area(portrait_bounds);
portrait_work_area.Inset(kInsets);
EXPECT_EQ(observer.GetDisplay().work_area(), portrait_work_area);
EXPECT_EQ(observer.GetDisplay().panel_rotation(),
display::Display::Rotation::ROTATE_180);
EXPECT_EQ(observer.GetDisplay().rotation(),
display::Display::Rotation::ROTATE_270);
platform_screen_->RemoveObserver(&observer);
}
TEST_P(WaylandAuraShellScreenTest, UseCorrectScreenBeforeEnterEvent) {
wl::TestOutput* output1 = nullptr;
wl::TestOutput* output2 = nullptr;
PostToServerAndWait([&output1](wl::TestWaylandServerThread* server) {
output1 = server->output();
ASSERT_TRUE(output1);
});
PostToServerAndWait(
[&output1, &output2](wl::TestWaylandServerThread* server) {
output2 = server->CreateAndInitializeOutput(
wl::TestOutputMetrics({GetRightX(output1), 0, 800, 600}));
output2->SetLogicalSize({400, 300});
output2->SetDeviceScaleFactor(2);
ASSERT_TRUE(output2);
});
WaitForAllDisplaysReady();
EXPECT_CALL(delegate_, OnAcceleratedWidgetAvailable(testing::_)).Times(1);
PlatformWindowInitProperties properties;
properties.bounds = gfx::Rect(GetRightX(output1), 0, 100, 100);
properties.type = PlatformWindowType::kWindow;
window_ =
delegate_.CreateWaylandWindow(connection_.get(), std::move(properties));
ASSERT_NE(widget_, gfx::kNullAcceleratedWidget);
window_->Show(false);
EXPECT_EQ(window_->root_surface()->entered_outputs().size(), 0u);
}
#endif
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
INSTANTIATE_TEST_SUITE_P(…);
#else
INSTANTIATE_TEST_SUITE_P(
XdgVersionStableTestWithAuraShell,
WaylandScreenTest,
Values(wl::ServerConfig{
.enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled}));
INSTANTIATE_TEST_SUITE_P(
XdgVersionStableTest,
WaylandAuraShellScreenTest,
Values(wl::ServerConfig{
.enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled}));
#endif
}