diff --git a/quickshell/Common/ConnectedModeState.qml b/quickshell/Common/ConnectedModeState.qml index 64685f48..ed3474eb 100644 --- a/quickshell/Common/ConnectedModeState.qml +++ b/quickshell/Common/ConnectedModeState.qml @@ -91,6 +91,14 @@ Singleton { return true; } + function setPopoutAnim(claimId, animX, animY) { + if (!hasPopoutOwner(claimId)) + return false; + popoutAnimX = animX; + popoutAnimY = animY; + return true; + } + function _cloneDockStates() { const next = {}; for (const screenName in dockStates) diff --git a/quickshell/Modules/Dock/Dock.qml b/quickshell/Modules/Dock/Dock.qml index 875bf9f3..6bf67756 100644 --- a/quickshell/Modules/Dock/Dock.qml +++ b/quickshell/Modules/Dock/Dock.qml @@ -227,6 +227,20 @@ Variants { ConnectedModeState.setDockSlide(dock._dockScreenName, dockSlide.x, dockSlide.y); } + property bool _slideSyncPending: false + function _queueSlideSync() { + if (!SettingsData.connectedFrameModeActive) + return; + if (_slideSyncPending) + return; + _slideSyncPending = true; + Qt.callLater(dock._flushSlideSync); + } + function _flushSlideSync() { + _slideSyncPending = false; + dock._syncDockSlide(); + } + property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData) property bool revealSticky: false @@ -677,12 +691,8 @@ Variants { } } - onXChanged: { - dock._syncDockSlide(); - } - onYChanged: { - dock._syncDockSlide(); - } + onXChanged: dock._queueSlideSync() + onYChanged: dock._queueSlideSync() } Item { diff --git a/quickshell/Modules/Frame/FrameWindow.qml b/quickshell/Modules/Frame/FrameWindow.qml index e5c8ed85..ea6a0384 100644 --- a/quickshell/Modules/Frame/FrameWindow.qml +++ b/quickshell/Modules/Frame/FrameWindow.qml @@ -77,6 +77,7 @@ PanelWindow { readonly property color _opaqueSurfaceColor: Qt.rgba(_surfaceColor.r, _surfaceColor.g, _surfaceColor.b, 1) readonly property real _surfaceRadius: Theme.connectedSurfaceRadius readonly property real _seamOverlap: Theme.hairline(win._dpr) + readonly property bool _disableLayer: Quickshell.env("DMS_DISABLE_LAYER") === "true" || Quickshell.env("DMS_DISABLE_LAYER") === "1" function _regionInt(value) { return Math.max(0, Math.round(Theme.px(value, win._dpr))); @@ -794,7 +795,8 @@ PanelWindow { anchors.fill: parent visible: win._connectedActive opacity: win._surfaceOpacity - layer.enabled: true // Always need a layer to apply Shadow or Opacity in MultiEffect, or at least if elevationEnabled/opacity < 1 + // Skip FBO when neither elevation nor alpha blend is active + layer.enabled: (!win._disableLayer && Theme.elevationEnabled) || win._surfaceOpacity < 1 layer.smooth: false layer.effect: MultiEffect { @@ -806,7 +808,7 @@ PanelWindow { blurEnabled: false maskEnabled: false - shadowEnabled: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" + shadowEnabled: !win._disableLayer && Theme.elevationEnabled shadowBlur: Math.max(0, Math.min(1, _shadowBlur / Math.max(1, Theme.elevationBlurMax))) shadowScale: 1 + (2 * _shadowSpread) / Math.max(1, Math.min(_connectedSurfaceLayer.width, _connectedSurfaceLayer.height)) shadowHorizontalOffset: Theme.elevationOffsetXFor(level, Theme.elevationLightDirection, 4) diff --git a/quickshell/Widgets/DankPopout.qml b/quickshell/Widgets/DankPopout.qml index 4f4befdd..75f8ad26 100644 --- a/quickshell/Widgets/DankPopout.qml +++ b/quickshell/Widgets/DankPopout.qml @@ -195,6 +195,9 @@ Item { readonly property real contentAnimX: contentContainer.animX readonly property real contentAnimY: contentContainer.animY + property bool _animSyncPending: false + property bool _fullSyncPending: false + // ─── ConnectedModeState sync ──────────────────────────────────────────── function _syncPopoutChromeState() { if (!root.frameOwnsConnectedChrome) { @@ -212,11 +215,41 @@ Item { _publishConnectedChromeState(contentWindow.visible && !ConnectedModeState.hasPopoutOwner(_chromeClaimId)); } - onAlignedXChanged: _syncPopoutChromeState() - onAlignedYChanged: _syncPopoutChromeState() - onAlignedWidthChanged: _syncPopoutChromeState() - onContentAnimXChanged: _syncPopoutChromeState() - onContentAnimYChanged: _syncPopoutChromeState() + function _flushAnimSync() { + _animSyncPending = false; + if (!root.frameOwnsConnectedChrome || !_chromeClaimId) + return; + if (!contentWindow.visible && !shouldBeVisible) + return; + ConnectedModeState.setPopoutAnim(_chromeClaimId, contentContainer.animX, contentContainer.animY); + } + + function _queueAnimSync() { + if (!root.frameOwnsConnectedChrome || !_chromeClaimId) + return; + if (_animSyncPending) + return; + _animSyncPending = true; + Qt.callLater(root._flushAnimSync); + } + + function _flushFullSync() { + _fullSyncPending = false; + _syncPopoutChromeState(); + } + + function _queueFullSync() { + if (_fullSyncPending) + return; + _fullSyncPending = true; + Qt.callLater(root._flushFullSync); + } + + onAlignedXChanged: _queueFullSync() + onAlignedYChanged: _queueFullSync() + onAlignedWidthChanged: _queueFullSync() + onContentAnimXChanged: _queueAnimSync() + onContentAnimYChanged: _queueAnimSync() onScreenChanged: _syncPopoutChromeState() onEffectiveBarPositionChanged: _syncPopoutChromeState()