blob: 55539fd9fa95790a04dc985b114eece0bc050b6f [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_OUTPUT_H_
#define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_OUTPUT_H_
#include <cstdint>
#include <ostream>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/wayland/common/wayland_object.h"
namespace ui {
class WaylandConnection;
class WaylandWpColorManagementOutput;
class WaylandWpColorManager;
class XDGOutput;
// WaylandOutput objects keep track of wl_output information received through
// the Wayland protocol, along with other related protocol extensions, such as,
// xdg-output.
class WaylandOutput : public wl::GlobalObjectRegistrar<WaylandOutput> {
public:
// Instances of this class are identified by an 32-bit unsigned int value,
// corresponding to its global wl_output object 'name' value. On
// wayland-linux, it is mostly used interchangeably with WaylandScreen's
// `display::Display::id1` property, which is an int64_t instead, though it is
// worth bearing in mind they are slightly different, under the hood.
using Id = uint32_t;
static constexpr char kInterfaceName[] = "wl_output";
static void Instantiate(WaylandConnection* connection,
wl_registry* registry,
uint32_t name,
const std::string& interface,
uint32_t version);
// All parameters are in DIP screen coordinates/units except |physical_size|,
// which is in physical pixels.
struct Metrics {
// TODO(aluh): Remove explicit constructors/destructor to enable aggregate
// initialization if chromium-style check for complex struct is removed.
// See:
// https://groups.google.com/a/google.com/g/chromeos-chatty-eng/c/nM1_QC6qcuA
Metrics();
Metrics(Id output_id,
int64_t display_id,
gfx::Point origin,
gfx::Size logical_size,
gfx::Size physical_size,
gfx::Insets insets,
gfx::Insets physical_overscan_insets,
float scale_factor,
int32_t panel_transform,
int32_t logical_transform,
const std::string& description);
Metrics(const Metrics&);
Metrics& operator=(const Metrics&);
Metrics(Metrics&&);
Metrics& operator=(Metrics&&);
~Metrics();
bool operator==(const Metrics&) const = default;
Id output_id = 0;
int64_t display_id = -1;
gfx::Point origin;
gfx::Size logical_size;
gfx::Size physical_size;
// Work area insets in DIP.
gfx::Insets insets;
// Overscan insets in physical pixels.
gfx::Insets physical_overscan_insets;
float scale_factor = 0.0;
int32_t panel_transform = 0;
int32_t logical_transform = 0;
std::string name;
std::string description;
void DumpState(std::ostream& out) const;
};
class Delegate {
public:
virtual void OnOutputHandleMetrics(const Metrics& metrics) = 0;
protected:
virtual ~Delegate() = default;
};
WaylandOutput(Id output_id, wl_output* output, WaylandConnection* connection);
WaylandOutput(const WaylandOutput&) = delete;
WaylandOutput& operator=(const WaylandOutput&) = delete;
~WaylandOutput();
void Initialize(Delegate* delegate);
void InitializeXdgOutput(zxdg_output_manager_v1* manager);
void InitializeWpColorManagementOutput(WaylandWpColorManager* manager);
const Metrics& GetMetrics() const;
void SetMetrics(const Metrics& metrics);
// TODO(tuluk): Metrics getters below are rendundant and should be replaced
// with calls to GetMetrics().
Id output_id() const { return output_id_; }
float scale_factor() const;
WaylandWpColorManagementOutput* wp_color_management_output() const {
return wp_color_management_output_.get();
}
// Returns true if the output has all the state information available
// necessary to represent its associated display. This information arrives
// asynchronously via events across potentially multiple wayland objects.
bool IsReady() const;
wl_output* get_output() { return output_.get(); }
void SetScaleFactorForTesting(float scale_factor);
void TriggerDelegateNotifications();
void DumpState(std::ostream& out) const;
void set_delegate_for_testing(Delegate* delegate) { delegate_ = delegate; }
XDGOutput* xdg_output_for_testing() { return xdg_output_.get(); }
private:
FRIEND_TEST_ALL_PREFIXES(WaylandOutputTest, NameAndDescriptionFallback);
FRIEND_TEST_ALL_PREFIXES(WaylandOutputTest, ScaleFactorCalculation);
FRIEND_TEST_ALL_PREFIXES(WaylandOutputTest, ScaleFactorFallback);
FRIEND_TEST_ALL_PREFIXES(WaylandOutputTest, ScaleFactorCalculationNoop);
static constexpr int32_t kDefaultScaleFactor = 1;
// Called when the wl_output.done event is received and atomically updates
// `metrics_` based on the previously received output state events.
void UpdateMetrics();
// wl_output_listener callbacks:
static void OnGeometry(void* data,
wl_output* output,
int32_t x,
int32_t y,
int32_t physical_width,
int32_t physical_height,
int32_t subpixel,
const char* make,
const char* model,
int32_t output_transform);
static void OnMode(void* data,
wl_output* output,
uint32_t flags,
int32_t width,
int32_t height,
int32_t refresh);
static void OnDone(void* data, wl_output* output);
static void OnScale(void* data, wl_output* output, int32_t factor);
static void OnName(void* data, wl_output* output, const char* name);
static void OnDescription(void* data,
wl_output* output,
const char* description);
// Tracks whether this wl_output is considered "ready". I.e. it has received
// all of its relevant state from the server followed by a wl_output.done
// event.
bool is_ready_ = false;
// Metrics represents the current state of the display represented by this
// output object. This state is updated atomically after the client has
// received the wl_output.done event.
Metrics metrics_;
const Id output_id_ = 0;
wl::Object<wl_output> output_;
std::unique_ptr<XDGOutput> xdg_output_;
std::unique_ptr<WaylandWpColorManagementOutput> wp_color_management_output_;
float scale_factor_ = kDefaultScaleFactor;
int32_t panel_transform_ = WL_OUTPUT_TRANSFORM_NORMAL;
// Origin of the output in DIP screen coordinate.
gfx::Point origin_;
// Size of the output in physical pixels.
gfx::Size physical_size_;
// Fallback name and description.
// The XDG output specification suggests using it as the primary source of
// the information about the output. Two attributes below are used if
// xdg_output_ is not present.
// See https://wayland.app/protocols/xdg-output-unstable-v1
std::string name_;
std::string description_;
raw_ptr<Delegate> delegate_ = nullptr;
raw_ptr<WaylandConnection> connection_ = nullptr;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_OUTPUT_H_