This commit is contained in:
wheaney 2026-01-10 10:00:10 -08:00
parent f4fecdc3e5
commit efd652b77c
9 changed files with 191 additions and 74 deletions

View File

@ -29,6 +29,13 @@
<label>Display Spacing</label>
<description>How far apart the displays are visually (not logically)</description>
</entry>
<entry name="DisplaySize" type="Int">
<default>100</default>
<min>10</min>
<max>250</max>
<label>Display Size</label>
<description>Scale the displays in XR (percentage)</description>
</entry>
<entry name="DisplayHorizontalOffset" type="Int">
<default>0</default>
<min>-250</min>

View File

@ -243,6 +243,7 @@ void BreezyDesktopEffect::reconfigure(ReconfigureFlags)
setFocusedDisplayDistance(BreezyDesktopConfig::focusedDisplayDistance() / 100.0f);
setAllDisplaysDistance(BreezyDesktopConfig::allDisplaysDistance() / 100.0f);
setDisplaySpacing(BreezyDesktopConfig::displaySpacing() / 1000.0f);
setDisplaySize(BreezyDesktopConfig::displaySize() / 100.0f);
setZoomOnFocusEnabled(BreezyDesktopConfig::zoomOnFocusEnabled());
setSmoothFollowThreshold(BreezyDesktopConfig::smoothFollowThreshold());
@ -515,6 +516,18 @@ void BreezyDesktopEffect::setDisplaySpacing(qreal spacing) {
}
}
qreal BreezyDesktopEffect::displaySize() const {
return m_displaySize;
}
void BreezyDesktopEffect::setDisplaySize(qreal size) {
const qreal clamped = std::clamp(size, 0.5, 2.0);
if (!qFuzzyCompare(clamped, m_displaySize)) {
m_displaySize = clamped;
Q_EMIT displaySizeChanged();
}
}
qreal BreezyDesktopEffect::displayHorizontalOffset() const {
return m_displayHorizontalOffset;
}

View File

@ -38,6 +38,7 @@ namespace KWin
Q_PROPERTY(qreal focusedDisplayDistance READ focusedDisplayDistance NOTIFY focusedDisplayDistanceChanged)
Q_PROPERTY(qreal allDisplaysDistance READ allDisplaysDistance NOTIFY allDisplaysDistanceChanged)
Q_PROPERTY(qreal displaySpacing READ displaySpacing NOTIFY displaySpacingChanged)
Q_PROPERTY(qreal displaySize READ displaySize NOTIFY displaySizeChanged)
Q_PROPERTY(qreal displayHorizontalOffset READ displayHorizontalOffset NOTIFY displayOffsetChanged)
Q_PROPERTY(qreal displayVerticalOffset READ displayVerticalOffset NOTIFY displayOffsetChanged)
Q_PROPERTY(int displayWrappingScheme READ displayWrappingScheme NOTIFY displayWrappingSchemeChanged)
@ -89,6 +90,8 @@ namespace KWin
void setAllDisplaysDistance(qreal distance);
qreal displaySpacing() const;
void setDisplaySpacing(qreal spacing);
qreal displaySize() const;
void setDisplaySize(qreal size);
qreal displayHorizontalOffset() const;
qreal displayVerticalOffset() const;
int displayWrappingScheme() const;
@ -127,6 +130,7 @@ namespace KWin
void focusedDisplayDistanceChanged();
void allDisplaysDistanceChanged();
void displaySpacingChanged();
void displaySizeChanged();
void displayOffsetChanged();
void displayWrappingSchemeChanged();
void enabledStateChanged();
@ -191,6 +195,7 @@ namespace KWin
qreal m_focusedDisplayDistance = 0.85;
qreal m_allDisplaysDistance = 1.05;
qreal m_displaySpacing = 0.0;
qreal m_displaySize = 1.0;
qreal m_displayHorizontalOffset = 0.0;
qreal m_displayVerticalOffset = 0.0;
int m_displayWrappingScheme = 0; // 0=auto,1=horizontal,2=vertical,3=flat

View File

@ -330,6 +330,7 @@ BreezyDesktopEffectConfig::BreezyDesktopEffectConfig(QObject *parent, const KPlu
connect(ui.kcfg_ZoomOnFocusEnabled, &QCheckBox::toggled, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_FocusedDisplayDistance, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_AllDisplaysDistance, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_DisplaySize, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_DisplaySpacing, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_SmoothFollowThreshold, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
connect(ui.kcfg_DisplayHorizontalOffset, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save);
@ -456,6 +457,7 @@ void BreezyDesktopEffectConfig::updateUiFromConfig()
{
ui.kcfg_FocusedDisplayDistance->setValue(BreezyDesktopConfig::self()->focusedDisplayDistance());
ui.kcfg_AllDisplaysDistance->setValue(BreezyDesktopConfig::self()->allDisplaysDistance());
ui.kcfg_DisplaySize->setValue(BreezyDesktopConfig::self()->displaySize());
ui.kcfg_DisplaySpacing->setValue(BreezyDesktopConfig::self()->displaySpacing());
ui.kcfg_DisplayHorizontalOffset->setValue(BreezyDesktopConfig::self()->displayHorizontalOffset());
ui.kcfg_DisplayVerticalOffset->setValue(BreezyDesktopConfig::self()->displayVerticalOffset());
@ -492,7 +494,7 @@ void BreezyDesktopEffectConfig::checkEffectLoaded() {
QPalette pal = warn->palette();
pal.setColor(QPalette::WindowText, QColor(Qt::red));
warn->setPalette(pal);
warn->setText(tr("The Breezy Desktop KWin effect is not loaded. Please log out and back in to enable it."));
warn->setText(tr("The Breezy Desktop KWin effect is disabled or not loaded. Please check the Desktop Effects dialog. Otherwise, log out and back in to enable it."));
warn->setVisible(true);
}
}

View File

@ -151,14 +151,23 @@
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelDisplaySpacing">
<widget class="QLabel" name="labelDisplaySize">
<property name="text">
<string>Display Spacing:</string>
<string>Display Size:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSlider" name="kcfg_DisplaySpacing">
<widget class="LabeledSlider" name="kcfg_DisplaySize">
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
<property name="tickStartOffset">
<double>10</double>
</property>
<property name="tickInterval">
<double>25</double>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -168,13 +177,30 @@
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelDisplaySpacing">
<property name="text">
<string>Display Spacing:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSlider" name="kcfg_DisplaySpacing">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tracking">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="labelFollowThreshold">
<property name="text">
<string>Follow threshold:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="LabeledSlider" name="kcfg_SmoothFollowThreshold">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -196,7 +222,7 @@
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="labelVirtualDisplays">
<property name="text">
<string>Add Virtual Display:</string>
@ -209,7 +235,7 @@
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QWidget" name="widgetVirtualDisplayButtons">
<property name="visible">
<bool>false</bool>

View File

@ -17,7 +17,7 @@ Item {
property bool customBannerEnabled: effect.customBannerEnabled
property bool smoothFollowEnabled: effect.smoothFollowEnabled
property real lookAheadScanlineMs: effect.lookAheadConfig[2]
property var crossFovs: displays.diagonalToCrossFOVs(
property var fovLengths: displays.diagonalToCrossFOVs(
displays.degreeToRadian(effect.diagonalFOV),
aspectRatio
);
@ -84,7 +84,9 @@ Item {
}
function buildPerspectiveMatrix() {
const f = 1.0 / crossFovs.verticalTangent;
const verticalTangent = fovLengths.heightUnitDistance / 2.0;
const horizontalTangent = fovLengths.widthUnitDistance / 2.0;
const f = 1.0 / verticalTangent;
const nf = 1.0 / (clipNear - clipFar);
const m00 = f / aspectRatio;
const m11 = f;
@ -102,13 +104,13 @@ Item {
function applyRollingShutterShear(rates) {
// Convert to maximum shift at bottom of frame
const maxDxNdc = (rates.yaw * lookAheadScanlineMs) / crossFovs.horizontalTangent;
const maxDyNdc = -(rates.pitch * lookAheadScanlineMs) / crossFovs.verticalTangent;
const maxDxNdc = (rates.yaw * lookAheadScanlineMs) / horizontalTangent;
const maxDyNdc = -(rates.pitch * lookAheadScanlineMs) / verticalTangent;
let shx = maxDxNdc / 2.0;
let shy = maxDyNdc / 2.0;
const f = 1.0 / crossFovs.verticalTangent;
const f = 1.0 / verticalTangent;
const nf = 1.0 / (clipNear - clipFar);
const m00 = f / aspectRatio;
const m11 = f;

View File

@ -26,27 +26,26 @@ ProceduralMesh {
const fov = mesh.fovDetails;
const monitor = mesh.monitorGeometry;
const conv = fov.curvedDisplay ? mesh.fovConversionFns.curved
: mesh.fovConversionFns.flat;
const horizontalWrap = fov.monitorWrappingScheme === 'horizontal';
const verticalWrap = fov.monitorWrappingScheme === 'vertical';
const horizontalConversions = horizontalWrap && fov.curvedDisplay ? fovConversionFns.curved : fovConversionFns.flat;
const sideEdgeDistance = conv.centerToFovEdgeDistance(
fov.completeScreenDistancePixels, fov.widthPixels);
const horizontalRadians = conv.lengthToRadians(
const sideEdgeDistancePixels = horizontalConversions.centerToFovEdgeDistance(
fov.completeScreenDistancePixels, fov.sizeAdjustedWidthPixels);
const horizontalRadians = horizontalConversions.lengthToRadians(
fov.defaultDistanceHorizontalRadians,
fov.widthPixels,
sideEdgeDistance,
sideEdgeDistancePixels,
monitor.width
);
const topEdgeDistance = conv.centerToFovEdgeDistance(
fov.completeScreenDistancePixels, fov.heightPixels);
const verticalRadians = conv.lengthToRadians(
const verticalWrap = fov.monitorWrappingScheme === 'vertical';
const verticalConversions = verticalWrap && fov.curvedDisplay ? fovConversionFns.curved : fovConversionFns.flat;
const topEdgeDistancePixels = verticalConversions.centerToFovEdgeDistance(
fov.completeScreenDistancePixels, fov.sizeAdjustedHeightPixels);
const verticalRadians = verticalConversions.lengthToRadians(
fov.defaultDistanceVerticalRadians,
fov.heightPixels,
topEdgeDistance,
topEdgeDistancePixels,
monitor.height
);

View File

@ -23,17 +23,25 @@ QtObject {
return Qt.quaternion(quaternion.scalar, -quaternion.z, -quaternion.x, quaternion.y);
}
// Converts diagonal FOV in radians and aspect ratio to horizontal and vertical FOVs
// Converts diagonal FOV in radians and aspect ratio to horizontal and vertical FOV measurements
function diagonalToCrossFOVs(diagonalFOVRadians, aspectRatio) {
var diagonalTangent = Math.tan(diagonalFOVRadians / 2);
var verticalTangent = diagonalTangent / Math.sqrt(1 + aspectRatio * aspectRatio);
var horizontalTangent = verticalTangent * aspectRatio;
// first convert from a spherical FOV to a diagonal FOV on a flat plane at a unit distance of 1.0
const diagonalLengthUnitDistance = 2 * Math.tan(diagonalFOVRadians / 2);
// then convert to flat plane horizontal and vertical FOVs
const heightUnitDistance = diagonalLengthUnitDistance / Math.sqrt(1 + aspectRatio * aspectRatio);
const widthUnitDistance = heightUnitDistance * aspectRatio;
return {
diagonal: diagonalFOVRadians,
horizontal: 2 * Math.atan(horizontalTangent),
horizontalTangent: horizontalTangent,
vertical: 2 * Math.atan(verticalTangent),
verticalTangent: verticalTangent
// then convert back to spherical FOV
diagonalRadians: diagonalFOVRadians,
horizontalRadians: 2 * Math.atan(widthUnitDistance / 2),
verticalRadians: 2 * Math.atan(heightUnitDistance / 2),
// flat values are relative to a unit distance of 1.0
diagonalLengthUnitDistance,
widthUnitDistance,
heightUnitDistance
}
}
@ -50,33 +58,55 @@ QtObject {
}
}
function buildFovDetails(screens, viewportWidth, viewportHeight, viewportDiagonalFOV, lensDistanceRatio, defaultDisplayDistance, wrappingChoice) {
function buildFovDetails(screens, viewportWidth, viewportHeight, viewportDiagonalFOV, lensDistanceRatio, defaultDisplayDistance, wrappingChoice, distanceAdjustedSize) {
const aspect = viewportWidth / viewportHeight;
const crossFovs = diagonalToCrossFOVs(degreeToRadian(viewportDiagonalFOV), aspect);
const defaultDistanceVerticalRadians = 2 * Math.atan(crossFovs.verticalTangent / defaultDisplayDistance);
const defaultDistanceHorizontalRadians = 2 * Math.atan(crossFovs.horizontalTangent / defaultDisplayDistance);
// distance needed for the FOV-sized monitor to fill up the screen
const fullScreenDistance = viewportHeight / (2 * crossFovs.verticalTangent);
const lensDistancePixels = fullScreenDistance / (1.0 - lensDistanceRatio) - fullScreenDistance;
// distance of a display at the default (most zoomed out) distance, plus the lens distance constant
const lensToScreenDistance = viewportHeight / (2 * Math.tan(defaultDistanceVerticalRadians / 2));
const completeScreenDistancePixels = lensToScreenDistance + lensDistancePixels;
const fovLengths = diagonalToCrossFOVs(degreeToRadian(viewportDiagonalFOV), aspect);
let monitorWrappingScheme = actualWrapScheme(screens, viewportWidth, viewportHeight);
if (wrappingChoice === 1) monitorWrappingScheme = 'horizontal';
else if (wrappingChoice === 2) monitorWrappingScheme = 'vertical';
else if (wrappingChoice === 3) monitorWrappingScheme = 'flat';
const lensDistanceComplement = 1.0 - lensDistanceRatio;
const lensDistanceFactor = (1.0 / lensDistanceComplement) - 1.0;
const horizontalConversions = effect.curvedDisplay && monitorWrappingScheme === 'horizontal' ? fovConversionFns.curved : fovConversionFns.flat;
const verticalConversions = effect.curvedDisplay && monitorWrappingScheme === 'vertical' ? fovConversionFns.curved : fovConversionFns.flat;
const defaultDistanceVerticalRadians = verticalConversions.fovRadiansAtDistance(
fovLengths.verticalRadians,
fovLengths.heightUnitDistance,
defaultDisplayDistance
);
const defaultDistanceHorizontalRadians = horizontalConversions.fovRadiansAtDistance(
fovLengths.horizontalRadians,
fovLengths.widthUnitDistance,
defaultDisplayDistance
);
// distance needed for the FOV-sized monitor to fill up the screen, as measured from the lenses
const lensToUnitDistancePixels = viewportWidth / fovLengths.widthUnitDistance;
// distance from pivot point to lens
const lensDistancePixels = lensToUnitDistancePixels * lensDistanceFactor;
// distance from pivot point to full screen (monitor at unit distance from lens)
const fullScreenDistancePixels = lensToUnitDistancePixels + lensDistancePixels;
// distance of a display at the default (most zoomed out) distance from the pivot point
const completeScreenDistancePixels = fullScreenDistancePixels * defaultDisplayDistance;
return {
widthPixels: viewportWidth,
distanceAdjustedSize,
sizeAdjustedWidthPixels: viewportWidth * distanceAdjustedSize,
heightPixels: viewportHeight,
sizeAdjustedHeightPixels: viewportHeight * distanceAdjustedSize,
defaultDistanceVerticalRadians,
defaultDistanceHorizontalRadians,
lensDistancePixels,
fullScreenDistancePixels,
completeScreenDistancePixels,
monitorWrappingScheme: monitorWrappingScheme,
monitorWrappingScheme,
curvedDisplay: effect.curvedDisplay
};
}
@ -99,6 +129,9 @@ QtObject {
angleToLength: function(fovRadians, fovLength, screenDistance, toAngleOpposite, toAngleAdjacent) {
return toAngleOpposite / toAngleAdjacent * screenDistance;
},
fovRadiansAtDistance: function(fovRadians, unitLength, newScreenDistance) {
return 2 * Math.atan(unitLength / 2 / newScreenDistance);
},
radiansToSegments: function(screenRadians) { return 1; }
},
curved: {
@ -114,6 +147,9 @@ QtObject {
angleToLength: function(fovRadians, fovLength, screenDistance, toAngleOpposite, toAngleAdjacent) {
return fovLength / fovRadians * Math.atan2(toAngleOpposite, toAngleAdjacent);
},
fovRadiansAtDistance: function(fovRadians, unitLength, newScreenDistance) {
return fovRadians / newScreenDistance;
},
radiansToSegments: function(screenRadians) {
return Math.ceil(screenRadians * segmentsPerRadian);
}
@ -198,8 +234,12 @@ QtObject {
var conversionFns = fovDetails.curvedDisplay ? fovConversionFns.curved : fovConversionFns.flat;
if (fovDetails.monitorWrappingScheme === 'horizontal') {
var sideEdgeRadius = conversionFns.centerToFovEdgeDistance(fovDetails.completeScreenDistancePixels, fovDetails.widthPixels);
var monitorSpacingPixels = monitorSpacing * fovDetails.widthPixels;
// monitors wrap around us horizontally
var sideEdgeRadius = conversionFns.centerToFovEdgeDistance(fovDetails.completeScreenDistancePixels, fovDetails.sizeAdjustedWidthPixels);
var monitorSpacingPixels = monitorSpacing * fovDetails.sizeAdjustedWidthPixels;
// targetWidth is assumed to aleady be size adjusted
var lengthToRadianFn = function(targetWidth) {
return conversionFns.lengthToRadians(
fovDetails.defaultDistanceHorizontalRadians,
@ -209,14 +249,14 @@ QtObject {
);
};
cachedMonitorRadians[0] = -fovDetails.defaultDistanceHorizontalRadians / 2;
cachedMonitorRadians[0] = -lengthToRadianFn(fovDetails.sizeAdjustedWidthPixels) / 2;
horizontalMonitorSort(monitorDetailsList).forEach(function(obj) {
var monitorDetails = obj.monitorDetails;
var originalIndex = obj.originalIndex;
var monitorWrapDetails = monitorWrap(cachedMonitorRadians, monitorSpacingPixels, monitorDetails.x, monitorDetails.width, lengthToRadianFn);
var monitorCenterRadius = conversionFns.fovEdgeToScreenCenterDistance(sideEdgeRadius, monitorDetails.width);
var upTopPixels = -monitorDetails.y - (monitorDetails.y / fovDetails.heightPixels) * monitorSpacingPixels;
var upCenterOffsetPixels = (monitorDetails.height - fovDetails.heightPixels) / 2;
var upTopPixels = -monitorDetails.y - (monitorDetails.y / fovDetails.sizeAdjustedHeightPixels) * monitorSpacingPixels;
var upCenterOffsetPixels = (monitorDetails.height - fovDetails.sizeAdjustedHeightPixels) / 2;
var upCenterPixels = upTopPixels - upCenterOffsetPixels;
monitorPlacements.push({
@ -239,8 +279,8 @@ QtObject {
});
});
} else if (fovDetails.monitorWrappingScheme === 'vertical') {
var topEdgeRadius = conversionFns.centerToFovEdgeDistance(fovDetails.completeScreenDistancePixels, fovDetails.heightPixels);
var monitorSpacingPixels = monitorSpacing * fovDetails.heightPixels;
var topEdgeRadius = conversionFns.centerToFovEdgeDistance(fovDetails.completeScreenDistancePixels, fovDetails.sizeAdjustedHeightPixels);
var monitorSpacingPixels = monitorSpacing * fovDetails.sizeAdjustedHeightPixels;
var lengthToRadianFn = function(targetHeight) {
return conversionFns.lengthToRadians(
fovDetails.defaultDistanceVerticalRadians,
@ -250,14 +290,14 @@ QtObject {
);
};
cachedMonitorRadians[0] = -fovDetails.defaultDistanceVerticalRadians / 2;
cachedMonitorRadians[0] = -lengthToRadianFn(fovDetails.sizeAdjustedHeightPixels) / 2;
verticalMonitorSort(monitorDetailsList).forEach(function(obj) {
var monitorDetails = obj.monitorDetails;
var originalIndex = obj.originalIndex;
var monitorWrapDetails = monitorWrap(cachedMonitorRadians, monitorSpacingPixels, monitorDetails.y, monitorDetails.height, lengthToRadianFn);
var monitorCenterRadius = conversionFns.fovEdgeToScreenCenterDistance(topEdgeRadius, monitorDetails.height);
var westLeftPixels = -monitorDetails.x - (monitorDetails.x / fovDetails.widthPixels) * monitorSpacingPixels;
var westCenterOffsetPixels = (monitorDetails.width - fovDetails.widthPixels) / 2;
var westLeftPixels = -monitorDetails.x - (monitorDetails.x / fovDetails.sizeAdjustedWidthPixels) * monitorSpacingPixels;
var westCenterOffsetPixels = (monitorDetails.width - fovDetails.sizeAdjustedWidthPixels) / 2;
var westCenterPixels = westLeftPixels - westCenterOffsetPixels;
monitorPlacements.push({
@ -280,12 +320,12 @@ QtObject {
});
});
} else {
var monitorSpacingPixels = monitorSpacing * fovDetails.widthPixels;
var monitorSpacingPixels = monitorSpacing * fovDetails.sizeAdjustedWidthPixels;
monitorDetailsList.forEach(function(monitorDetails, index) {
var upTopPixels = -monitorDetails.y - (monitorDetails.y / fovDetails.heightPixels) * monitorSpacingPixels;
var westLeftPixels = -monitorDetails.x - (monitorDetails.x / fovDetails.widthPixels) * monitorSpacingPixels;
var westCenterOffsetPixels = (monitorDetails.width - fovDetails.widthPixels) / 2;
var upCenterOffsetPixels = (monitorDetails.height - fovDetails.heightPixels) / 2;
var upTopPixels = -monitorDetails.y - (monitorDetails.y / fovDetails.sizeAdjustedHeightPixels) * monitorSpacingPixels;
var westLeftPixels = -monitorDetails.x - (monitorDetails.x / fovDetails.sizeAdjustedWidthPixels) * monitorSpacingPixels;
var westCenterOffsetPixels = (monitorDetails.width - fovDetails.sizeAdjustedWidthPixels) / 2;
var upCenterOffsetPixels = (monitorDetails.height - fovDetails.sizeAdjustedHeightPixels) / 2;
var westCenterPixels = westLeftPixels - westCenterOffsetPixels;
var upCenterPixels = upTopPixels - upCenterOffsetPixels;

View File

@ -33,19 +33,41 @@ Item {
property var screens: KWinComponents.Workspace.screens.filter(function(screen) {
return mirrorPhysicalDisplays || screen.name.includes("BreezyDesktop") || supportedModels.some(model => screen.model.includes(model));
})
property var sizeAdjustedScreens: screens.map(function(screen) {
const sizeComplement = (1.0 - distanceAdjustedSize) / 2.0;
const sizeViewportOffsetX = sizeComplement * viewportResolution[0];
const sizeViewportOffsetY = sizeComplement * viewportResolution[1];
return {
geometry: {
x: screen.geometry.x * distanceAdjustedSize + sizeViewportOffsetX,
y: screen.geometry.y * distanceAdjustedSize + sizeViewportOffsetY,
width: screen.geometry.width * distanceAdjustedSize,
height: screen.geometry.height * distanceAdjustedSize
},
name: screen.name,
model: screen.model
};
})
property real distanceAdjustedSize: (effect.allDisplaysDistance - effect.lensDistanceRatio) *effect.displaySize
property var sizeAdjustedViewport: {
return {
width: viewportResolution[0] * distanceAdjustedSize,
height: viewportResolution[1] * distanceAdjustedSize
};
}
// x value for placing the viewport in the middle of all screens
property real screensXMid: {
let xMin = Number.MAX_VALUE;
let xMax = Number.MIN_VALUE;
for (let i = 0; i < screens.length; i++) {
const geometry = screens[i].geometry;
for (let i = 0; i < sizeAdjustedScreens.length; i++) {
const geometry = sizeAdjustedScreens[i].geometry;
xMin = Math.min(xMin, geometry.x);
xMax = Math.max(xMax, geometry.x + geometry.width);
}
return (xMin + xMax) / 2 - (viewportResolution[0] / 2);
return (xMin + xMax) / 2 - (sizeAdjustedViewport.width / 2);
}
// y value for placing the viewport in the middle of all screens
@ -53,13 +75,13 @@ Item {
let yMin = Number.MAX_VALUE;
let yMax = Number.MIN_VALUE;
for (let i = 0; i < screens.length; i++) {
const geometry = screens[i].geometry;
for (let i = 0; i < sizeAdjustedScreens.length; i++) {
const geometry = sizeAdjustedScreens[i].geometry;
yMin = Math.min(yMin, geometry.y);
yMax = Math.max(yMax, geometry.y + geometry.height);
}
return (yMin + yMax) / 2 - (viewportResolution[1] / 2);
return (yMin + yMax) / 2 - (sizeAdjustedViewport.height / 2);
}
Displays {
@ -67,19 +89,20 @@ Item {
}
property var fovDetails: displays.buildFovDetails(
screens,
viewportResolution[0],
viewportResolution[1],
sizeAdjustedScreens,
sizeAdjustedViewport.width,
sizeAdjustedViewport.height,
viewportDiagonalFOVDegrees,
effect.lensDistanceRatio,
effect.allDisplaysDistance,
effect.displayWrappingScheme
effect.displayWrappingScheme,
distanceAdjustedSize
)
property var monitorPlacements: {
const dx = effect.displayHorizontalOffset * viewportResolution[0];
const dy = effect.displayVerticalOffset * viewportResolution[1];
const adjustedGeometries = screens.map(screen => {
const dx = effect.displayHorizontalOffset * sizeAdjustedViewport.width;
const dy = effect.displayVerticalOffset * sizeAdjustedViewport.height;
const adjustedGeometries = sizeAdjustedScreens.map(screen => {
const g = screen.geometry;
return {
x: g.x - screensXMid + dx,