blob: 61fc38925d8a9af80e08157fcad23495c4759830 [file] [log] [blame]
// Copyright 2024 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_GFX_X_RANDR_OUTPUT_MANAGER_H_
#define UI_GFX_X_RANDR_OUTPUT_MANAGER_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/component_export.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/x/randr.h"
namespace x11 {
// Wrapper class for the XRRScreenResources struct.
class COMPONENT_EXPORT(X11) ScreenResources {
public:
ScreenResources();
~ScreenResources();
bool Refresh(x11::RandR* randr, x11::Window window);
x11::RandR::Mode GetIdForMode(const std::string& name);
x11::RandR::GetScreenResourcesCurrentReply* get();
private:
std::unique_ptr<x11::RandR::GetScreenResourcesCurrentReply> resources_;
};
// Encapsulates basic configuration properties for a single RandR monitor.
class COMPONENT_EXPORT(X11) RandRMonitorConfig {
public:
using ScreenId = int64_t;
RandRMonitorConfig(std::optional<ScreenId> id,
gfx::Rect rect,
gfx::Vector2d dpi);
RandRMonitorConfig(const RandRMonitorConfig& other);
RandRMonitorConfig& operator=(const RandRMonitorConfig& other);
bool operator==(const RandRMonitorConfig& rhs) const;
std::optional<ScreenId> id() const { return id_; }
const gfx::Rect& rect() const { return rect_; }
const gfx::Vector2d& dpi() const { return dpi_; }
private:
// An opaque ID used to identify this monitor. Unset when the ID is unknown,
// for example, when a caller is setting a new layout and the screen ID
// does not exist yet.
std::optional<ScreenId> id_;
gfx::Rect rect_;
gfx::Vector2d dpi_;
};
// Encapsulates a set of monitors to represent an entire screen layout.
struct COMPONENT_EXPORT(X11) RandRMonitorLayout {
RandRMonitorLayout();
RandRMonitorLayout(const RandRMonitorLayout&);
explicit RandRMonitorLayout(std::vector<RandRMonitorConfig> configs);
RandRMonitorLayout& operator=(const RandRMonitorLayout&);
~RandRMonitorLayout();
bool operator==(const RandRMonitorLayout& rhs) const;
std::vector<RandRMonitorConfig> configs;
std::optional<int64_t> primary_screen_id;
};
// Attaches an arbitrary pointer to a monitor config for internal tracking
// purposes.
struct COMPONENT_EXPORT(X11) RandRMonitorConfigWithContext {
x11::RandRMonitorConfig config;
raw_ptr<void> context;
};
// Structure to hold data which describes changes between two layouts.
struct COMPONENT_EXPORT(X11) DisplayLayoutDiff {
DisplayLayoutDiff();
DisplayLayoutDiff(
x11::RandRMonitorLayout new_displays,
std::vector<RandRMonitorConfigWithContext> updated_displays,
std::vector<RandRMonitorConfigWithContext> removed_displays);
DisplayLayoutDiff(const DisplayLayoutDiff&);
~DisplayLayoutDiff();
x11::RandRMonitorLayout new_displays;
std::vector<RandRMonitorConfigWithContext> updated_displays;
std::vector<RandRMonitorConfigWithContext> removed_displays;
};
// Calculates the difference between the current display layout and the new
// display layout. Displays are matched using the screen ID.
COMPONENT_EXPORT(X11)
DisplayLayoutDiff CalculateDisplayLayoutDiff(
const std::vector<RandRMonitorConfigWithContext>& current_displays,
const x11::RandRMonitorLayout& new_layout);
// Manages modes and layout of RandR outputs.
class COMPONENT_EXPORT(X11) RandROutputManager final {
public:
// `output_name_prefix` is used when creating new RandR outputs. Optionally
// override the default mode dot clock with `default_mode_dot_clock`.
explicit RandROutputManager(
std::string output_name_prefix,
uint32_t default_mode_dot_clock = 60 * 1e6 /* Realistic default */);
~RandROutputManager();
// Attempts to get the current list of XRandR monitors from the current
// connection. Returns true on success in which case `list` is populated with
// the monitors. Returns false otherwise.
bool TryGetCurrentMonitors(std::vector<x11::RandR::MonitorInfo>& list);
// Obtains the current RandR layout.
RandRMonitorLayout GetLayout();
// Adjusts outputs to match the specified layout.
void SetLayout(const RandRMonitorLayout& layout);
// Removes the existing mode from the output and replaces it with the new
// size. Returns the new mode ID, or None (0) on failure.
x11::RandR::Mode UpdateMode(x11::RandR::Output output, int width, int height);
// Remove the specified mode from the output, and delete it. If the mode is in
// use, it is not deleted.
// |name| should be set to GetModeNameForOutput(output). The parameter is to
// avoid creating the mode name twice.
void DeleteMode(x11::RandR::Output output, const std::string& name);
// Add a mode matching the specified resolution and switch to it.
void SetResolutionForOutput(x11::RandR::Output output,
const gfx::Size& dimensions,
const gfx::Vector2d& dpi);
private:
using OutputInfoList = std::vector<
std::pair<x11::RandR::Output, x11::RandR::GetOutputInfoReply>>;
OutputInfoList GetDisabledOutputs();
std::string GetModeNameForOutput(x11::RandR::Output output);
raw_ptr<x11::Connection> connection_ = nullptr;
const raw_ptr<x11::RandR> randr_ = nullptr;
x11::Window root_;
ScreenResources resources_;
bool has_randr_;
std::string output_name_prefix_;
const uint32_t default_mode_dot_clock_;
};
} // namespace x11
#endif // UI_GFX_X_RANDR_OUTPUT_MANAGER_H_