blob: fd7ea843052822c6d35c53f0f8ff5b9f1eead0c4 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "testing/x11-test-base.h"
namespace vm_tools {
namespace sommelier {
using X11Test = X11TestBase;
TEST_F(X11Test, OutputScaleAndTransformAreApplied) {
// Arrange/Act: Advertise a fake output with no scaling.
AdvertiseOutputs(xwayland.get(),
{{.width_pixels = 1920, .height_pixels = 1080}});
struct sl_host_output* output = nullptr;
// Assert: Dimensions are unchanged.
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->virt_rotated_width, 1920);
EXPECT_EQ(output->virt_rotated_height, 1080);
// Act: Change the user defined zoom factor to be 150%.
ConfigureOutput(output, {.output_scale = 1500});
// Assert: Dimensions scaled up.
EXPECT_EQ(output->virt_rotated_width, 1280);
EXPECT_EQ(output->virt_rotated_height, 720);
// Act: Change zoom factor to be 80% and rotate.
ConfigureOutput(output,
{.transform = WL_OUTPUT_TRANSFORM_90, .output_scale = 800});
// Assert: Dimensions are scaled down and rotated dimensions are set.
EXPECT_EQ(output->virt_rotated_width, 1350);
EXPECT_EQ(output->virt_rotated_height, 2400);
}
TEST_F(X11DirectScaleTest,
AddingMultipleOutputsPositionsCorrectlyInDirectScale) {
// Act: Advertise two outputs together.
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920,
.y = 0,
.width_pixels = 1920,
.height_pixels = 1080,
.output_scale = 1250},
};
AdvertiseOutputs(xwayland.get(), configs);
struct sl_host_output* output = nullptr;
// Assert: Outputs are positioned correctly in logical space.
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 1920);
EXPECT_EQ(output->virt_y, 0);
// Advertise another output to the left.
AdvertiseOutputs(xwayland.get(), {{.x = -800,
.y = 1080,
.width_pixels = 1920,
.height_pixels = 1080,
.transform = WL_OUTPUT_TRANSFORM_90}});
// Assert: Outputs are positioned correctly in logical space.
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, -800);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1080);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next->next, output, link);
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 3000);
EXPECT_EQ(output->virt_y, 0);
}
TEST_F(X11Test, AddingMultipleOutputsPositionsCorrectly) {
// Act: Advertise outputs.
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920,
.y = 0,
.width_pixels = 1920,
.height_pixels = 1080,
.output_scale = 1250},
};
AdvertiseOutputs(xwayland.get(), configs);
struct sl_host_output* output = nullptr;
// Assert: Outputs are positioned correctly in logical space.
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 1920);
EXPECT_EQ(output->virt_y, 0);
// Act
AdvertiseOutputs(xwayland.get(), {{
.x = -800,
.y = 1080,
.width_pixels = 1920,
.height_pixels = 1080,
.transform = WL_OUTPUT_TRANSFORM_90,
.output_scale = 750,
}});
// Assert
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, -800);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1440);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next->next, output, link);
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 3360);
EXPECT_EQ(output->virt_y, 0);
}
TEST_F(X11Test, OutputsPositionedCorrectlyAfterRemovingLeftOutput) {
// Arrange: Add 3 outputs.
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920,
.y = 0,
.width_pixels = 1920,
.height_pixels = 1080,
.transform = WL_OUTPUT_TRANSFORM_90,
.output_scale = 2000},
{.x = 2000, .y = 1080, .width_pixels = 1920, .height_pixels = 1080},
};
AdvertiseOutputs(xwayland.get(), configs);
// Act: remove the leftmost output.
struct sl_host_output* output = nullptr;
output = wl_container_of(ctx.host_outputs.next, output, link);
RemoveOutput(output);
// Assert: Output is removed and others are shifted left.
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 2000);
EXPECT_EQ(output->virt_x, 540);
EXPECT_EQ(output->virt_y, 0);
// outputs has length 2.
EXPECT_EQ(ctx.host_outputs.next->next, ctx.host_outputs.prev);
}
TEST_F(X11Test, OutputsPositionedCorrectlyAfterRemovingMiddleOutput) {
// Arrange: Add 3 outputs.
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920,
.y = 0,
.width_pixels = 1920,
.height_pixels = 1080,
.transform = WL_OUTPUT_TRANSFORM_90,
.output_scale = 2000},
{.x = 2000, .y = 1080, .width_pixels = 1920, .height_pixels = 1080},
};
AdvertiseOutputs(xwayland.get(), configs);
// Act: Remove the middle output;
struct sl_host_output* output = nullptr;
output = wl_container_of(ctx.host_outputs.next->next, output, link);
RemoveOutput(output);
// Assert
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 2000);
EXPECT_EQ(output->virt_x, 1920);
EXPECT_EQ(output->virt_y, 0);
// outputs has length 2.
EXPECT_EQ(ctx.host_outputs.next->next, ctx.host_outputs.prev);
}
TEST_F(X11Test, OtherOutputUnchangedAfterRemovingRightOutput) {
// Arrange: Add 3 outputs.
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920, .y = 0}};
AdvertiseOutputs(xwayland.get(), configs);
// Act: Remove the rightmost output.
struct sl_host_output* output = nullptr;
output = wl_container_of(ctx.host_outputs.next->next, output, link);
RemoveOutput(output);
// Assert
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
// outputs has length 1.
EXPECT_EQ(ctx.host_outputs.next, ctx.host_outputs.prev);
}
TEST_F(X11Test, RotatingOutputsShiftsNeighbouringOutputs) {
// Arrange
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920},
};
AdvertiseOutputs(xwayland.get(), configs);
struct sl_host_output* output = nullptr;
output = wl_container_of(ctx.host_outputs.next, output, link);
// Act: Rotate output by 270 degrees.
ConfigureOutput(output, {.transform = WL_OUTPUT_TRANSFORM_270});
// Assert: Output is rotated and next output is shifted left.
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
EXPECT_EQ(output->virt_rotated_width, 1080);
EXPECT_EQ(output->virt_rotated_height, 1920);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->virt_x, 1080);
EXPECT_EQ(output->virt_y, 0);
}
TEST_F(X11Test, MovingOutputsShiftsOutputs) {
// Arrange
std::vector<OutputConfig> configs = {
{.x = 0, .y = 0, .width_pixels = 1920, .height_pixels = 1080},
{.x = 1920, .width_pixels = 1920, .height_pixels = 1080},
};
AdvertiseOutputs(xwayland.get(), configs);
struct sl_host_output* output = nullptr;
output = wl_container_of(ctx.host_outputs.next->next, output, link);
// Act: Move output on the right to be on the left of other output.
ConfigureOutput(output, {.x = -1920, .y = 700});
// Assert
output = wl_container_of(ctx.host_outputs.next, output, link);
EXPECT_EQ(output->x, -1920);
EXPECT_EQ(output->virt_x, 0);
EXPECT_EQ(output->virt_y, 0);
output = wl_container_of(ctx.host_outputs.next->next, output, link);
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1920);
EXPECT_EQ(output->virt_y, 0);
}
} // namespace sommelier
} // namespace vm_tools