Fix how display distances are bound so it tracks the UI smoothly

This commit is contained in:
wheaney 2025-09-02 21:24:49 -07:00
parent 7a810bb1bc
commit 6c5f08611e
5 changed files with 40 additions and 24 deletions

View File

@ -301,7 +301,7 @@ qreal BreezyDesktopEffect::focusedDisplayDistance() const {
void BreezyDesktopEffect::setFocusedDisplayDistance(qreal distance) {
if (distance != m_focusedDisplayDistance) {
m_focusedDisplayDistance = std::clamp(distance, 0.2, m_allDisplaysDistance);
Q_EMIT displayDistanceChanged();
Q_EMIT focusedDisplayDistanceChanged();
}
}
@ -312,7 +312,7 @@ qreal BreezyDesktopEffect::allDisplaysDistance() const {
void BreezyDesktopEffect::setAllDisplaysDistance(qreal distance) {
if (distance != m_allDisplaysDistance) {
m_allDisplaysDistance = std::clamp(distance, m_focusedDisplayDistance, 2.5);
Q_EMIT displayDistanceChanged();
Q_EMIT allDisplaysDistanceChanged();
}
}

View File

@ -24,8 +24,8 @@ namespace KWin
Q_PROPERTY(QPointF cursorPos READ cursorPos NOTIFY cursorPosChanged)
Q_PROPERTY(QList<qreal> lookAheadConfig READ lookAheadConfig NOTIFY devicePropertiesChanged)
Q_PROPERTY(QList<quint32> displayResolution READ displayResolution NOTIFY devicePropertiesChanged)
Q_PROPERTY(qreal focusedDisplayDistance READ focusedDisplayDistance NOTIFY displayDistanceChanged)
Q_PROPERTY(qreal allDisplaysDistance READ allDisplaysDistance NOTIFY displayDistanceChanged)
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 diagonalFOV READ diagonalFOV NOTIFY devicePropertiesChanged)
Q_PROPERTY(qreal lensDistanceRatio READ lensDistanceRatio NOTIFY devicePropertiesChanged)
@ -77,7 +77,8 @@ namespace KWin
void updateCursorPos();
Q_SIGNALS:
void displayDistanceChanged();
void focusedDisplayDistanceChanged();
void allDisplaysDistanceChanged();
void displaySpacingChanged();
void enabledStateChanged();
void zoomOnFocusChanged();

View File

@ -25,10 +25,10 @@ Node {
Repeater3D {
id: breezyDesktopDisplays
model: screens.length
model: breezyDesktop.screens.length
delegate: BreezyDesktopDisplay {
screen: screens[index]
monitorPlacement: monitorPlacements[index]
screen: breezyDesktop.screens[index]
monitorPlacement: breezyDesktop.monitorPlacements[index]
property real monitorDistance: effect.allDisplaysDistance
property real targetDistance: effect.allDisplaysDistance
property real screenRotationY: displays.radianToDegree(monitorPlacement.rotationAngleRadians.y)
@ -81,30 +81,45 @@ Node {
);
}
const focusedDisplay = focusedIndex !== -1 ? breezyDesktop.displayAtIndex(focusedIndex) : null;
if (focusedIndex !== breezyDesktop.focusedMonitorIndex) {
const unfocusedIndex = breezyDesktop.focusedMonitorIndex;
const focusedDisplay = focusedIndex !== -1 ? breezyDesktop.displayAtIndex(focusedIndex) : null;
const allDisplaysDistanceBinding = Qt.binding(function() { return effect.allDisplaysDistance; });
const focusedDisplayDistanceBinding = Qt.binding(function() { return effect.focusedDisplayDistance; });
if (focusedDisplay === null) {
zoomOutAnimation.target = breezyDesktop.displayAtIndex(breezyDesktop.focusedMonitorIndex);
zoomOutAnimation.target.targetDistance = zoomOutAnimation.to;
const unfocusedDisplay = breezyDesktop.displayAtIndex(unfocusedIndex);
zoomOutAnimation.target = unfocusedDisplay;
zoomOutAnimation.target.targetDistance = effect.allDisplaysDistance;
zoomOutAnimation.onFinished.connect(function() {
unfocusedDisplay.monitorDistance = allDisplaysDistanceBinding;
});
zoomOutAnimation.start();
} else {
if (breezyDesktop.focusedMonitorIndex === -1) {
if (unfocusedIndex === -1) {
zoomInAnimation.target = focusedDisplay;
focusedDisplay.targetDistance = zoomInAnimation.to;
focusedDisplay.targetDistance = effect.focusedDisplayDistance;
zoomInAnimation.onFinished.connect(function() {
focusedDisplay.monitorDistance = focusedDisplayDistanceBinding;
});
zoomInAnimation.start();
} else {
const focusedDisplay = breezyDesktop.displayAtIndex(focusedIndex);
zoomInSeqAnimation.target = focusedDisplay;
focusedDisplay.targetDistance = zoomInSeqAnimation.to;
zoomOutSeqAnimation.target = breezyDesktop.displayAtIndex(breezyDesktop.focusedMonitorIndex);
zoomOutSeqAnimation.target.targetDistance = zoomOutSeqAnimation.to;
focusedDisplay.targetDistance = effect.focusedDisplayDistance;
const unfocusedDisplay = breezyDesktop.displayAtIndex(unfocusedIndex);
zoomOutSeqAnimation.target = unfocusedDisplay;
zoomOutSeqAnimation.target.targetDistance = effect.allDisplaysDistance;
zoomOnFocusSequence.onFinished.connect(function() {
focusedDisplay.monitorDistance = focusedDisplayDistanceBinding;
unfocusedDisplay.monitorDistance = allDisplaysDistanceBinding;
});
zoomOnFocusSequence.start();
}
}
breezyDesktop.focusedMonitorIndex = focusedIndex;
} else if (focusedDisplay !== null && focusedDisplay.targetDistance !== effect.focusedDisplayDistance) {
// user is changing the focused display distance setting, so just move it to match
focusedDisplay.monitorDistance = effect.focusedDisplayDistance;
focusedDisplay.targetDistance = effect.focusedDisplayDistance;
}
}
}

View File

@ -48,11 +48,11 @@ QtObject {
}
}
function fovDetails(screens, viewportWidth, viewportHeight, viewportDiagonalFOV, lensDistanceRatio) {
function fovDetails(screens, viewportWidth, viewportHeight, viewportDiagonalFOV, lensDistanceRatio, defaultDisplayDistanace) {
const aspect = viewportWidth / viewportHeight;
const fovRadians = diagonalToCrossFOVs(degreeToRadian(viewportDiagonalFOV), aspect);
const defaultDistanceVerticalRadians = 2 * Math.atan(Math.tan(fovRadians.vertical / 2) / effect.allDisplaysDistance);
const defaultDistanceHorizontalRadians = 2 * Math.atan(Math.tan(fovRadians.horizontal / 2) / effect.allDisplaysDistance);
const defaultDistanceVerticalRadians = 2 * Math.atan(Math.tan(fovRadians.vertical / 2) / defaultDisplayDistanace);
const defaultDistanceHorizontalRadians = 2 * Math.atan(Math.tan(fovRadians.horizontal / 2) / defaultDisplayDistanace);
// distance needed for the FOV-sized monitor to fill up the screen
const fullScreenDistance = viewportHeight / 2 / Math.tan(fovRadians.vertical / 2);

View File

@ -61,7 +61,7 @@ Item {
id: displays
}
property var fovDetails: displays.fovDetails(screens, viewportResolution[0], viewportResolution[1], viewportDiagonalFOVDegrees, effect.lensDistanceRatio)
property var fovDetails: displays.fovDetails(screens, viewportResolution[0], viewportResolution[1], viewportDiagonalFOVDegrees, effect.lensDistanceRatio, effect.allDisplaysDistance)
property var monitorPlacements: {
const adjustedGeometries = screens.map(screen => {