44 int left = physicalGeometry.x() + qRound(
region.x() * physicalGeometry.width());
45 int top = physicalGeometry.y() + qRound(
region.y() * physicalGeometry.height());
46 int right = physicalGeometry.x() + qRound((
region.x() +
region.width()) * physicalGeometry.width());
47 int bottom = physicalGeometry.y() + qRound((
region.y() +
region.height()) * physicalGeometry.height());
49 right = qMin(right, physicalGeometry.x() + physicalGeometry.width());
50 bottom = qMin(bottom, physicalGeometry.y() + physicalGeometry.height());
54 left = qMin(left, right - 1);
55 top = qMin(top, bottom - 1);
56 left = qMax(left, physicalGeometry.x());
57 top = qMax(top, physicalGeometry.y());
58 int w = qMax(1, right - left);
59 int h = qMax(1, bottom - top);
60 return QRect(left, top, w, h);
158 for (
int i = 0; i <
screens.size(); ++i) {
176 int maxScreensPerPhysical, QString* error =
nullptr)
178 auto fail = [&](
const QString& msg) {
189 if (!expectedPhysicalScreenId.isEmpty() && cfg.
physicalScreenId != expectedPhysicalScreenId) {
190 return fail(QStringLiteral(
"config physicalScreenId '%1' does not match parameter '%2'")
195 return fail(QStringLiteral(
"need at least 2 screens for subdivision, got %1").arg(cfg.
screens.size()));
198 if (maxScreensPerPhysical > 0 && cfg.
screens.size() > maxScreensPerPhysical) {
199 return fail(QStringLiteral(
"too many virtual screens %1 (max %2)")
201 .arg(maxScreensPerPhysical));
204 QSet<QString> seenIds;
205 QSet<int> seenIndices;
206 for (
const auto& def : cfg.
screens) {
207 if (!def.isValid()) {
208 return fail(QStringLiteral(
"invalid VirtualScreenDef id='%1' region=(%2,%3 %4x%5)")
212 .arg(def.region.width())
213 .arg(def.region.height()));
216 return fail(QStringLiteral(
"def.physicalScreenId '%1' does not match config '%2' for def '%3'")
220 if (def.id != expectedId) {
221 return fail(QStringLiteral(
"def.id '%1' does not match expected '%2' for index %3")
222 .arg(def.id, expectedId)
225 if (seenIds.contains(def.id)) {
226 return fail(QStringLiteral(
"duplicate def.id %1").arg(def.id));
228 seenIds.insert(def.id);
229 if (seenIndices.contains(def.index)) {
230 return fail(QStringLiteral(
"duplicate def.index %1").arg(def.index));
232 seenIndices.insert(def.index);
236 for (
int i = 0; i < cfg.
screens.size(); ++i) {
237 for (
int j = i + 1; j < cfg.
screens.size(); ++j) {
238 const QRectF intersection = cfg.
screens[i].region.intersected(cfg.
screens[j].region);
241 return fail(QStringLiteral(
"overlapping regions between '%1' and '%2'")
248 qreal totalArea = 0.0;
249 for (
const auto& def : cfg.
screens) {
250 totalArea += def.region.width() * def.region.height();
254 if (totalArea < lower) {
255 return fail(QStringLiteral(
"insufficient coverage for '%1' — total area %2 < %3")
260 if (totalArea > upper) {
261 return fail(QStringLiteral(
"excessive coverage for '%1' — total area %2 > %3")
282 for (
int i = 0; i <
screens.size(); ++i) {
285 }
else if (
screens[i].
id == idB) {
289 if (indexA < 0 || indexB < 0) {
319 if (orderedIds.size() < 2) {
322 QSet<QString> seenIds;
323 seenIds.reserve(orderedIds.size());
324 QVector<int> defIndices;
325 defIndices.reserve(orderedIds.size());
326 for (
const auto&
id : orderedIds) {
327 if (seenIds.contains(
id)) {
332 for (
int i = 0; i <
screens.size(); ++i) {
341 defIndices.append(found);
343 const int n = defIndices.size();
344 QVector<QRectF> regions;
346 for (
int idx : defIndices) {
347 regions.append(
screens[idx].region);
349 for (
int i = 0; i < n; ++i) {
350 const int src = clockwise ? (i + 1) % n : (i - 1 + n) % n;
351 screens[defIndices[i]].region = regions[src];
bool isVirtual(const QString &screenId)
Check if a screen ID is a virtual screen ID (contains "/vs:").
Definition VirtualScreenId.h:31
QString make(const QString &physicalScreenId, int index)
Construct a virtual screen ID from physical ID and index.
Definition VirtualScreenId.h:60
Definition IWindowTrackingService.h:26
Configuration for how a physical screen is subdivided into virtual screens.
Definition VirtualScreen.h:124
bool operator==(const VirtualScreenConfig &) const =default
Exact vector equality: order-sensitive (QVector::operator==) and delegates to VirtualScreenDef::opera...
bool swapRegions(const QString &idA, const QString &idB)
Swap the region fields of the two defs identified by idA and idB.
Definition VirtualScreen.h:275
static bool isValid(const VirtualScreenConfig &cfg, const QString &expectedPhysicalScreenId, int maxScreensPerPhysical, QString *error=nullptr)
Validate geometric and structural invariants for this config.
Definition VirtualScreen.h:175
bool hasSubdivisions() const
Definition VirtualScreen.h:128
QVector< VirtualScreenDef > screens
Definition VirtualScreen.h:126
bool rotateRegions(const QVector< QString > &orderedIds, bool clockwise)
Rotate the region fields through the defs identified by orderedIds.
Definition VirtualScreen.h:317
bool isEmpty() const
Definition VirtualScreen.h:132
QString physicalScreenId
Definition VirtualScreen.h:125
bool approxEqual(const VirtualScreenConfig &other) const
Tolerance-aware equivalent of operator==: compares defs pairwise using VirtualScreenDef::approxEqual.
Definition VirtualScreen.h:153
Check which edges of this virtual screen are at the physical screen boundary (vs internal edges share...
Definition VirtualScreen.h:103
bool left
Definition VirtualScreen.h:104
bool right
Definition VirtualScreen.h:106
bool bottom
Definition VirtualScreen.h:107
bool top
Definition VirtualScreen.h:105
Definition of a single virtual screen within a physical screen.
Definition VirtualScreen.h:28
QRect absoluteGeometry(const QRect &physicalGeometry) const
Compute absolute geometry from the physical screen's geometry.
Definition VirtualScreen.h:42
QString displayName
User-facing name, e.g. "Left", "Right".
Definition VirtualScreen.h:31
bool approxEqual(const VirtualScreenDef &other) const
Tolerance-aware comparison for change-detection paths that round through JSON.
Definition VirtualScreen.h:76
bool isValid() const
Check if the definition is valid: non-empty id, non-empty physicalScreenId, non-negative origin,...
Definition VirtualScreen.h:91
QString id
Full ID: "physicalId/vs:N".
Definition VirtualScreen.h:29
bool operator==(const VirtualScreenDef &) const =default
Exact bitwise equality across every field.
static constexpr qreal Tolerance
Shared tolerance for floating-point region comparisons.
Definition VirtualScreen.h:37
PhysicalEdges physicalEdges() const
Definition VirtualScreen.h:109
QRectF region
Relative geometry within physical screen (0-1)
Definition VirtualScreen.h:32
int index
Index within the physical screen's subdivision.
Definition VirtualScreen.h:33
QString physicalScreenId
Owning physical screen's stable EDID ID.
Definition VirtualScreen.h:30