blob: 6294fba1c81db43846e3f6426748417966d96bcc [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 = ctx.host_outputs[0];
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 = ctx.host_outputs[0];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 1920);
// 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 = ctx.host_outputs[0];
EXPECT_EQ(output->x, -800);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1080);
output = ctx.host_outputs[2];
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 3000);
}
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 = ctx.host_outputs[0];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 1920);
// Act
AdvertiseOutputs(xwayland.get(), {{
.x = -800,
.y = 1080,
.width_pixels = 1920,
.height_pixels = 1080,
.transform = WL_OUTPUT_TRANSFORM_90,
.output_scale = 750,
}});
// Assert
output = ctx.host_outputs[0];
EXPECT_EQ(output->x, -800);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1440);
output = ctx.host_outputs[2];
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 3360);
}
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 = ctx.host_outputs[0];
RemoveOutput(output);
// Assert: Output is removed and others are shifted left.
output = ctx.host_outputs[0];
EXPECT_EQ(output->x, 1920);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 2000);
EXPECT_EQ(output->virt_x, 540);
// outputs has length 2.
EXPECT_EQ(ctx.host_outputs.size(), 2u);
}
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 = ctx.host_outputs[1];
RemoveOutput(output);
// Assert
output = ctx.host_outputs[0];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 2000);
EXPECT_EQ(output->virt_x, 1920);
// outputs has length 2.
EXPECT_EQ(ctx.host_outputs.size(), 2u);
}
TEST_F(X11Test, OtherOutputUnchangedAfterRemovingRightOutput) {
// Arrange: Add 2 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 = ctx.host_outputs[1];
RemoveOutput(output);
// Assert
output = ctx.host_outputs[0];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 0);
// outputs has length 1.
EXPECT_EQ(ctx.host_outputs.size(), 1u);
}
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 = ctx.host_outputs[0];
// 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_rotated_width, 1080);
EXPECT_EQ(output->virt_rotated_height, 1920);
output = ctx.host_outputs[1];
EXPECT_EQ(output->virt_x, 1080);
}
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 = ctx.host_outputs[1];
// Act: Move output on the right to be on the left of other output.
ConfigureOutput(output, {.x = -1920, .y = 700});
// Assert
output = ctx.host_outputs[0];
EXPECT_EQ(output->x, -1920);
EXPECT_EQ(output->virt_x, 0);
output = ctx.host_outputs[1];
EXPECT_EQ(output->x, 0);
EXPECT_EQ(output->virt_x, 1920);
}
} // namespace sommelier
} // namespace vm_tools