diff --git a/kwin/src/breezydesktopeffect.cpp b/kwin/src/breezydesktopeffect.cpp index 5d0f028..4b0747c 100644 --- a/kwin/src/breezydesktopeffect.cpp +++ b/kwin/src/breezydesktopeffect.cpp @@ -211,20 +211,23 @@ void BreezyDesktopEffect::reconfigure(ReconfigureFlags) setAllDisplaysDistance(BreezyDesktopConfig::allDisplaysDistance() / 100.0f); setDisplaySpacing(BreezyDesktopConfig::displaySpacing() / 1000.0f); setZoomOnFocusEnabled(BreezyDesktopConfig::zoomOnFocusEnabled()); + setSmoothFollowThreshold(BreezyDesktopConfig::smoothFollowThreshold()); + qreal horiz = BreezyDesktopConfig::displayHorizontalOffset() / 100.0f; qreal vert = BreezyDesktopConfig::displayVerticalOffset() / 100.0f; + bool offsetchanged = false; + if (!qFuzzyCompare(m_displayHorizontalOffset, horiz)) { m_displayHorizontalOffset = horiz; offsetchanged = true; } + if (!qFuzzyCompare(m_displayVerticalOffset, vert)) { m_displayVerticalOffset = vert; offsetchanged = true; } + if (offsetchanged) Q_EMIT displayOffsetChanged(); + int wrap = BreezyDesktopConfig::displayWrappingScheme(); int aaQuality = BreezyDesktopConfig::antialiasingQuality(); bool removeVD = BreezyDesktopConfig::removeVirtualDisplaysOnDisable(); bool mirrorPhysicalDisplays = BreezyDesktopConfig::mirrorPhysicalDisplays(); - bool changed = false; - if (!qFuzzyCompare(m_displayHorizontalOffset, horiz)) { m_displayHorizontalOffset = horiz; changed = true; } - if (!qFuzzyCompare(m_displayVerticalOffset, vert)) { m_displayVerticalOffset = vert; changed = true; } if (m_displayWrappingScheme != wrap) { m_displayWrappingScheme = wrap; Q_EMIT displayWrappingSchemeChanged(); } if (m_antialiasingQuality != aaQuality) { m_antialiasingQuality = aaQuality; Q_EMIT antialiasingQualityChanged(); } if (m_removeVirtualDisplaysOnDisable != removeVD) { m_removeVirtualDisplaysOnDisable = removeVD; Q_EMIT removeVirtualDisplaysOnDisableChanged(); } if (m_mirrorPhysicalDisplays != mirrorPhysicalDisplays) { m_mirrorPhysicalDisplays = mirrorPhysicalDisplays; Q_EMIT mirrorPhysicalDisplaysChanged(); } - if (changed) Q_EMIT displayOffsetChanged(); } QVariantMap BreezyDesktopEffect::initialProperties(Output *screen) @@ -432,7 +435,7 @@ void BreezyDesktopEffect::setFocusedDisplayDistance(qreal distance) { m_focusedDisplayDistance = std::clamp(distance, 0.2, m_allDisplaysDistance); Q_EMIT focusedDisplayDistanceChanged(); - if (m_smoothFollowEnabled) updateDriverDisplayDistance(m_focusedDisplayDistance); + if (m_smoothFollowEnabled) updateDriverSmoothFollowSettings(); } } @@ -674,13 +677,24 @@ void BreezyDesktopEffect::updateImuRotation() { m_smoothFollowEnabled = nextSmoothFollowEnabled; Q_EMIT smoothFollowEnabledChanged(); - if (nextSmoothFollowEnabled) updateDriverDisplayDistance(m_focusedDisplayDistance); - } else if (enabled && !wasEnabled) Q_EMIT smoothFollowEnabledChanged(); + if (nextSmoothFollowEnabled) updateDriverSmoothFollowSettings(); + } else if (enabled && !wasEnabled) { + Q_EMIT smoothFollowEnabledChanged(); + if (nextSmoothFollowEnabled) updateDriverSmoothFollowSettings(); + } } -void BreezyDesktopEffect::updateDriverDisplayDistance(float distance) { +void BreezyDesktopEffect::setSmoothFollowThreshold(float threshold) { + if (m_smoothFollowThreshold != threshold) { + m_smoothFollowThreshold = threshold; + if (m_smoothFollowEnabled) updateDriverSmoothFollowSettings(); + } +} + +void BreezyDesktopEffect::updateDriverSmoothFollowSettings() { QJsonObject flags; - flags.insert(QStringLiteral("breezy_desktop_display_distance"), distance); + flags.insert(QStringLiteral("breezy_desktop_display_distance"), m_focusedDisplayDistance); + flags.insert(QStringLiteral("breezy_desktop_follow_threshold"), m_smoothFollowThreshold); XRDriverIPC::instance().writeControlFlags(flags); } diff --git a/kwin/src/breezydesktopeffect.h b/kwin/src/breezydesktopeffect.h index 4c15f89..c5edd3d 100644 --- a/kwin/src/breezydesktopeffect.h +++ b/kwin/src/breezydesktopeffect.h @@ -133,7 +133,8 @@ namespace KWin std::function triggeredFunc); void recenter(); void toggleSmoothFollow(); - void updateDriverDisplayDistance(float distance); + void setSmoothFollowThreshold(float threshold); + void updateDriverSmoothFollowSettings(); QString m_cursorImageSource; QSize m_cursorImageSize; @@ -166,6 +167,7 @@ namespace KWin int m_antialiasingQuality = 3; // 0=None, 1=Medium, 2=High, 3=VeryHigh bool m_removeVirtualDisplaysOnDisable = true; bool m_mirrorPhysicalDisplays = false; + float m_smoothFollowThreshold = 1.0f; struct VirtualOutputInfo { Output *output = nullptr; diff --git a/kwin/src/kcm/breezydesktopeffectkcm.cpp b/kwin/src/kcm/breezydesktopeffectkcm.cpp index 5373f8c..487fc5d 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.cpp +++ b/kwin/src/kcm/breezydesktopeffectkcm.cpp @@ -116,7 +116,7 @@ BreezyDesktopEffectConfig::BreezyDesktopEffectConfig(QObject *parent, const KPlu connect(ui.kcfg_FocusedDisplayDistance, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); connect(ui.kcfg_AllDisplaysDistance, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); connect(ui.kcfg_DisplaySpacing, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); - connect(ui.kcfg_SmoothFollowThreshold, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::updateSmoothFollowThreshold); + connect(ui.kcfg_SmoothFollowThreshold, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); connect(ui.kcfg_DisplayHorizontalOffset, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); connect(ui.kcfg_DisplayVerticalOffset, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); connect(ui.kcfg_LookAheadOverride, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); @@ -519,14 +519,6 @@ void BreezyDesktopEffectConfig::updateSmoothFollowEnabled() XRDriverIPC::instance().writeControlFlags(flags); } -void BreezyDesktopEffectConfig::updateSmoothFollowThreshold() -{ - BreezyDesktopEffectConfig::save(); - QJsonObject flags; - flags.insert(QStringLiteral("breezy_desktop_follow_threshold"), ui.kcfg_SmoothFollowThreshold->value()); - XRDriverIPC::instance().writeControlFlags(flags); -} - void BreezyDesktopEffectConfig::showStatus(QLabel *label, bool success, const QString &message) { if (!label) return; QPalette pal = label->palette(); diff --git a/kwin/src/kcm/breezydesktopeffectkcm.h b/kwin/src/kcm/breezydesktopeffectkcm.h index 4f705bd..c027890 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.h +++ b/kwin/src/kcm/breezydesktopeffectkcm.h @@ -31,7 +31,6 @@ private: void updateDriverEnabled(); void updateMultitapEnabled(); void updateSmoothFollowEnabled(); - void updateSmoothFollowThreshold(); void updateUiFromConfig(); void updateUiFromDefaultConfig(); void updateConfigFromUi(); diff --git a/kwin/src/qml/BreezyDesktop.qml b/kwin/src/qml/BreezyDesktop.qml index ac017aa..6baf840 100644 --- a/kwin/src/qml/BreezyDesktop.qml +++ b/kwin/src/qml/BreezyDesktop.qml @@ -46,12 +46,12 @@ Node { if (smoothFollowEnabledChanged) { let targetDisplay; let targetProgress; - if (focusedIndex !== -1) { + if (smoothFollowEnabled && focusedIndex !== -1) { focusedDisplay = breezyDesktop.displayAtIndex(focusedIndex); targetDisplay = focusedDisplay; targetProgress = 1.0; startSmoothFollowFocusAnimation = true; - } else if (breezyDesktop.focusedMonitorIndex !== -1) { + } else if (!smoothFollowEnabled && breezyDesktop.focusedMonitorIndex !== -1) { unfocusedDisplay = breezyDesktop.displayAtIndex(breezyDesktop.focusedMonitorIndex); targetDisplay = unfocusedDisplay; targetProgress = 0.0; @@ -126,9 +126,6 @@ Node { const displayEus = displayEusVector(display); // short circuit to avoid slerping if not needed - if (display.smoothFollowTransitionProgress === 0.0) { - return displayRotationVector(display, displayEus); - } if (display.smoothFollowTransitionProgress === 1.0) { return displaySmoothFollowVector(display, displayEus, smoothFollowRotation); } @@ -197,17 +194,29 @@ Node { let continueRunning = false; const focusedDisplay = breezyDesktop.smoothFollowFocusedDisplay; if (focusedDisplay) { - const smoothFollowRotation = smoothFollowQuat(); - focusedDisplay.position = displayPosition(focusedDisplay, smoothFollowRotation); continueRunning = focusedDisplay.smoothFollowTransitionProgress > 0.0; - if (continueRunning) { + const smoothFollowRotation = smoothFollowQuat(); focusedDisplay.eulerRotation = Qt.vector3d(0, 0, 0); focusedDisplay.rotation = smoothFollowRotation; + + // When smooth follow is running, we're updating the position of the display manually + // on every frame (avoid binding to a function that uses non-notify effect properties + // imuRotations and smoothFollowOrigin). + focusedDisplay.position = displayPosition(focusedDisplay, smoothFollowRotation); } else { + focusedDisplay.rotation = Qt.quaternion(1, 0, 0, 0); focusedDisplay.eulerRotation.x = focusedDisplay.screenRotationX; focusedDisplay.eulerRotation.y = focusedDisplay.screenRotationY; focusedDisplay.eulerRotation.z = 0.0; + + // When smooth follow is done, this frame animation will no longer run so we need to + // rebind a safe function to the position property that will automatically update the + // position when delegate properties change. display properties don't often change, + // but zoomOnFocus does change monitorDistance, so we need the binding to pick that up. + focusedDisplay.position = Qt.binding(function() { + return displayRotationVector(this, displayEusVector(this)); + }.bind(focusedDisplay) ); } }