1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/host/wayland_output.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/wayland/wayland_display_util.h"
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/xdg_output.h"
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
using ::testing::Values;
namespace ui {
namespace {
class MockWaylandOutputDelegate : public WaylandOutput::Delegate {
public:
MOCK_METHOD(void,
OnOutputHandleMetrics,
(const WaylandOutput::Metrics& metrics),
(override));
};
} // namespace
using WaylandOutputTest = WaylandTestSimple;
// Tests that name and description fall back to ones in the WaylandOutput if
// XDGOutput is not created.
TEST_F(WaylandOutputTest, NameAndDescriptionFallback) {
constexpr char kWlOutputName[] = "kWlOutputName";
constexpr char kWlOutputDescription[] = "kWlOutputDescription";
constexpr char kXDGOutputName[] = "kXDGOutputName";
constexpr char kXDGOutputDescription[] = "kXDGOutputDescription";
auto* const output_manager = connection_->wayland_output_manager();
ASSERT_TRUE(output_manager);
auto* wl_output = output_manager->GetPrimaryOutput();
ASSERT_TRUE(wl_output);
EXPECT_FALSE(wl_output->xdg_output_);
wl_output->name_ = kWlOutputName;
wl_output->description_ = kWlOutputDescription;
// We only test trivial stuff here so it is okay to create an output that is
// not backed with a real object.
wl_output->xdg_output_ = std::make_unique<XDGOutput>(nullptr);
wl_output->xdg_output_->name_ = kXDGOutputName;
wl_output->xdg_output_->description_ = kXDGOutputDescription;
wl_output->xdg_output_->is_ready_ = true;
wl_output->is_ready_ = true;
wl_output->UpdateMetrics();
EXPECT_EQ(wl_output->GetMetrics().name, kXDGOutputName);
EXPECT_EQ(wl_output->GetMetrics().description, kXDGOutputDescription);
wl_output->xdg_output_.reset();
wl_output->UpdateMetrics();
EXPECT_EQ(wl_output->GetMetrics().name, kWlOutputName);
EXPECT_EQ(wl_output->GetMetrics().description, kWlOutputDescription);
}
// Test that if using xdg output (and supports_viewporter_surface_scaling is
// enabled) the scale factor is calculated as the ratio of physical size to
// logical size as long as it is more than 1, otherwise it is set to 1.
TEST_F(WaylandOutputTest, ScaleFactorCalculation) {
auto* const output_manager = connection_->wayland_output_manager();
ASSERT_TRUE(output_manager);
auto* wl_output = output_manager->GetPrimaryOutput();
ASSERT_TRUE(wl_output);
EXPECT_FALSE(wl_output->xdg_output_);
connection_->set_supports_viewporter_surface_scaling(true);
ASSERT_TRUE(connection_->supports_viewporter_surface_scaling());
constexpr float kWlOutputScale = 2.f;
constexpr int kLogicalSideLength = 50;
float compositor_scale = 3.f;
wl_output->xdg_output_ = std::make_unique<XDGOutput>(nullptr);
wl_output->xdg_output_->logical_size_ =
gfx::Size(kLogicalSideLength, kLogicalSideLength);
wl_output->physical_size_ = gfx::Size(compositor_scale * kLogicalSideLength,
compositor_scale * kLogicalSideLength);
wl_output->scale_factor_ = kWlOutputScale;
wl_output->is_ready_ = true;
wl_output->xdg_output_->is_ready_ = true;
// Scale factor should be calculated from physical and logical sizes.
wl_output->UpdateMetrics();
EXPECT_EQ(compositor_scale, wl_output->scale_factor());
// As the calculated value is less than one, the scale factor should be
// clamped to 1.
compositor_scale = 0.5f;
wl_output->physical_size_ = gfx::Size(compositor_scale * kLogicalSideLength,
compositor_scale * kLogicalSideLength);
wl_output->UpdateMetrics();
EXPECT_EQ(1, wl_output->scale_factor());
}
// Test scale factor falls back to wl_output::scale instead of being calculated
// as the ratio of physical size to logical size when xdg_output is not ready or
// if supports_viewporter_surface_scaling is disabled.
TEST_F(WaylandOutputTest, ScaleFactorFallback) {
auto* const output_manager = connection_->wayland_output_manager();
ASSERT_TRUE(output_manager);
auto* wl_output = output_manager->GetPrimaryOutput();
ASSERT_TRUE(wl_output);
EXPECT_FALSE(wl_output->xdg_output_);
EXPECT_FALSE(connection_->supports_viewporter_surface_scaling());
// We only test trivial stuff here so it is okay to create an output that is
// not backed with a real object.
constexpr float kDefaultScaleFactor = 2.f;
wl_output->xdg_output_ = std::make_unique<XDGOutput>(nullptr);
wl_output->xdg_output_->logical_size_ = gfx::Size(100, 200);
wl_output->physical_size_ = gfx::Size(250, 500);
wl_output->scale_factor_ = kDefaultScaleFactor;
// When wl_output is ready but xdg_output is not yet ready, scale_factor
// should fall back to the value sent in wl_output::scale.
wl_output->is_ready_ = true;
wl_output->xdg_output_->is_ready_ = false;
wl_output->UpdateMetrics();
EXPECT_EQ(kDefaultScaleFactor, wl_output->scale_factor());
// If xdg_output is ready but supports_viewporter_surface_scaling is
// false, scale_factor should fall back to the value sent in wl_output::scale.
wl_output->xdg_output_->is_ready_ = true;
wl_output->UpdateMetrics();
EXPECT_EQ(kDefaultScaleFactor, wl_output->scale_factor());
}
// Test that if using xdg output and viewporter surface scaling is enabled
// the scale factor calculation based on xdg-output's logical size is no-op when
// physical and logical sizes are equal.
//
// Regression test for https://crbug.com/339681887.
TEST_F(WaylandOutputTest, ScaleFactorCalculationNoop) {
auto* const output_manager = connection_->wayland_output_manager();
ASSERT_TRUE(output_manager);
auto* wl_output = output_manager->GetPrimaryOutput();
ASSERT_TRUE(wl_output);
EXPECT_FALSE(wl_output->xdg_output_);
connection_->set_supports_viewporter_surface_scaling(true);
ASSERT_TRUE(connection_->supports_viewporter_surface_scaling());
constexpr float kWlOutputScale = 3.f;
wl_output->xdg_output_ = std::make_unique<XDGOutput>(nullptr);
wl_output->xdg_output_->logical_size_ = gfx::Size(100, 100);
wl_output->physical_size_ = gfx::Size(100, 100);
wl_output->scale_factor_ = kWlOutputScale;
// Since the logical size is the same as physical size, scale_factor should
// fall back to the value sent in wl_output::scale.
wl_output->is_ready_ = true;
wl_output->xdg_output_->is_ready_ = true;
wl_output->UpdateMetrics();
EXPECT_EQ(kWlOutputScale, wl_output->scale_factor());
}
TEST_F(WaylandOutputTest, WaylandOutputIsReady) {
auto* output_manager = connection_->wayland_output_manager();
const auto* primary_output = output_manager->GetPrimaryOutput();
// Create a new output but suppress metrics.
wl::TestOutput* test_output = nullptr;
PostToServerAndWait([&test_output](wl::TestWaylandServerThread* server) {
test_output = server->CreateAndInitializeOutput(
wl::TestOutputMetrics({0, 0, 800, 600}));
ASSERT_TRUE(test_output);
test_output->set_suppress_implicit_flush(true);
});
const auto& all_outputs = output_manager->GetAllOutputs();
ASSERT_EQ(2u, all_outputs.size());
// Get the newly created WaylandOutput.
auto pair_it = std::ranges::find_if_not(all_outputs, [&](auto& pair) {
return pair.first == primary_output->output_id();
});
ASSERT_NE(all_outputs.end(), pair_it);
const auto* new_output = pair_it->second.get();
EXPECT_NE(nullptr, new_output);
// The output should not be marked ready since metrics and specifically the
// wl_output.done event has not yet been received.
EXPECT_FALSE(new_output->IsReady());
// Flush metrics and the output should enter the ready state.
PostToServerAndWait([&test_output](wl::TestWaylandServerThread* server) {
test_output->Flush();
});
EXPECT_TRUE(new_output->IsReady());
}
} // namespace ui
|