mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-08 23:02:05 -04:00
(frame): implement ConnectedModeState to better handle component sync
This commit is contained in:
@@ -19,12 +19,12 @@ Variants {
|
||||
|
||||
WindowBlur {
|
||||
targetWindow: dock
|
||||
blurEnabled: dock.effectiveBlurEnabled
|
||||
blurX: dockBackground.x + dockContainer.x + dockMouseArea.x + dockCore.x + dockSlide.x - dock.horizontalConnectorExtent
|
||||
blurY: dockBackground.y + dockContainer.y + dockMouseArea.y + dockCore.y + dockSlide.y - dock.verticalConnectorExtent
|
||||
blurWidth: dock.hasApps && dock.reveal ? dockBackground.width + dock.horizontalConnectorExtent * 2 : 0
|
||||
blurHeight: dock.hasApps && dock.reveal ? dockBackground.height + dock.verticalConnectorExtent * 2 : 0
|
||||
blurRadius: dock.surfaceRadius
|
||||
blurEnabled: dock.effectiveBlurEnabled && !SettingsData.connectedFrameModeActive
|
||||
blurX: dockBackground.x + dockContainer.x + dockMouseArea.x + dockCore.x + dockSlide.x
|
||||
blurY: dockBackground.y + dockContainer.y + dockMouseArea.y + dockCore.y + dockSlide.y
|
||||
blurWidth: dock.hasApps && dock.reveal ? dockBackground.width : 0
|
||||
blurHeight: dock.hasApps && dock.reveal ? dockBackground.height : 0
|
||||
blurRadius: Theme.isConnectedEffect ? Theme.connectedCornerRadius : dock.surfaceRadius
|
||||
}
|
||||
|
||||
WlrLayershell.namespace: "dms:dock"
|
||||
@@ -43,21 +43,15 @@ Variants {
|
||||
property real backgroundTransparency: SettingsData.dockTransparency
|
||||
property bool groupByApp: SettingsData.dockGroupByApp
|
||||
readonly property int borderThickness: SettingsData.dockBorderEnabled ? SettingsData.dockBorderThickness : 0
|
||||
readonly property string connectedBarSide: SettingsData.dockPosition === SettingsData.Position.Top ? "top"
|
||||
: SettingsData.dockPosition === SettingsData.Position.Bottom ? "bottom"
|
||||
: SettingsData.dockPosition === SettingsData.Position.Left ? "left" : "right"
|
||||
readonly property bool connectedBarActiveOnEdge: Theme.isConnectedEffect
|
||||
&& !!(dock.screen || modelData)
|
||||
&& SettingsData.getActiveBarEdgesForScreen(dock.screen || modelData).includes(connectedBarSide)
|
||||
readonly property string connectedBarSide: SettingsData.dockPosition === SettingsData.Position.Top ? "top" : SettingsData.dockPosition === SettingsData.Position.Bottom ? "bottom" : SettingsData.dockPosition === SettingsData.Position.Left ? "left" : "right"
|
||||
readonly property bool connectedBarActiveOnEdge: Theme.isConnectedEffect && !!(dock.screen || modelData) && SettingsData.getActiveBarEdgesForScreen(dock.screen || modelData).includes(connectedBarSide)
|
||||
readonly property real connectedJoinInset: {
|
||||
if (!Theme.isConnectedEffect)
|
||||
return 0;
|
||||
return connectedBarActiveOnEdge ? SettingsData.frameBarSize : SettingsData.frameThickness;
|
||||
}
|
||||
readonly property real surfaceRadius: Theme.connectedSurfaceRadius
|
||||
readonly property color surfaceColor: Theme.isConnectedEffect
|
||||
? Theme.connectedSurfaceColor
|
||||
: Theme.withAlpha(Theme.surfaceContainer, backgroundTransparency)
|
||||
readonly property color surfaceColor: Theme.isConnectedEffect ? Theme.connectedSurfaceColor : Theme.withAlpha(Theme.surfaceContainer, backgroundTransparency)
|
||||
readonly property color surfaceBorderColor: Theme.isConnectedEffect ? "transparent" : BlurService.borderColor
|
||||
readonly property real surfaceBorderWidth: Theme.isConnectedEffect ? 0 : BlurService.borderWidth
|
||||
readonly property real surfaceTopLeftRadius: Theme.isConnectedEffect && (SettingsData.dockPosition === SettingsData.Position.Top || SettingsData.dockPosition === SettingsData.Position.Left) ? 0 : surfaceRadius
|
||||
@@ -188,6 +182,51 @@ Variants {
|
||||
return placement === "left" ? seamY - height : seamY;
|
||||
}
|
||||
|
||||
// ─── ConnectedModeState sync ────────────────────────────────────────
|
||||
// Dock window origin in screen-relative coordinates (FrameWindow space).
|
||||
function _dockWindowOriginX() {
|
||||
if (!dock.isVertical)
|
||||
return 0;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Right)
|
||||
return (dock.screen ? dock.screen.width : 0) - dock.width;
|
||||
return 0;
|
||||
}
|
||||
function _dockWindowOriginY() {
|
||||
if (dock.isVertical)
|
||||
return 0;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Bottom)
|
||||
return (dock.screen ? dock.screen.height : 0) - dock.height;
|
||||
return 0;
|
||||
}
|
||||
|
||||
readonly property string _dockScreenName: dock.modelData ? dock.modelData.name : (dock.screen ? dock.screen.name : "")
|
||||
|
||||
function _syncDockChromeState() {
|
||||
if (!dock._dockScreenName)
|
||||
return;
|
||||
if (!SettingsData.connectedFrameModeActive) {
|
||||
ConnectedModeState.clearDockState(dock._dockScreenName);
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectedModeState.setDockState(dock._dockScreenName, {
|
||||
"reveal": dock.visible && (dock.reveal || slideXAnimation.running || slideYAnimation.running) && dock.hasApps,
|
||||
"barSide": dock.connectedBarSide,
|
||||
"bodyX": dock._dockWindowOriginX() + dockBackground.x + dockContainer.x + dockMouseArea.x + dockCore.x,
|
||||
"bodyY": dock._dockWindowOriginY() + dockBackground.y + dockContainer.y + dockMouseArea.y + dockCore.y,
|
||||
"bodyW": dock.hasApps ? dockBackground.width : 0,
|
||||
"bodyH": dock.hasApps ? dockBackground.height : 0,
|
||||
"slideX": dockSlide.x,
|
||||
"slideY": dockSlide.y
|
||||
});
|
||||
}
|
||||
|
||||
function _syncDockSlide() {
|
||||
if (!dock._dockScreenName || !SettingsData.connectedFrameModeActive)
|
||||
return;
|
||||
ConnectedModeState.setDockSlide(dock._dockScreenName, dockSlide.x, dockSlide.y);
|
||||
}
|
||||
|
||||
property bool contextMenuOpen: (dockVariants.contextMenu && dockVariants.contextMenu.visible && dockVariants.contextMenu.screen === modelData)
|
||||
property bool revealSticky: false
|
||||
|
||||
@@ -349,6 +388,23 @@ Variants {
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: Qt.callLater(() => dock._syncDockChromeState())
|
||||
Component.onDestruction: ConnectedModeState.clearDockState(dock._dockScreenName)
|
||||
|
||||
onRevealChanged: dock._syncDockChromeState()
|
||||
onWidthChanged: dock._syncDockChromeState()
|
||||
onHeightChanged: dock._syncDockChromeState()
|
||||
onVisibleChanged: dock._syncDockChromeState()
|
||||
onHasAppsChanged: dock._syncDockChromeState()
|
||||
onConnectedBarSideChanged: dock._syncDockChromeState()
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onConnectedFrameModeActiveChanged() {
|
||||
dock._syncDockChromeState();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onDockTransparencyChanged() {
|
||||
@@ -573,6 +629,10 @@ Variants {
|
||||
return 0;
|
||||
if (dock.reveal)
|
||||
return 0;
|
||||
if (Theme.isConnectedEffect) {
|
||||
const retractDist = dockBackground.width + SettingsData.dockSpacing + 10;
|
||||
return SettingsData.dockPosition === SettingsData.Position.Right ? retractDist : -retractDist;
|
||||
}
|
||||
const hideDistance = dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin + 10;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Right) {
|
||||
return hideDistance;
|
||||
@@ -585,6 +645,10 @@ Variants {
|
||||
return 0;
|
||||
if (dock.reveal)
|
||||
return 0;
|
||||
if (Theme.isConnectedEffect) {
|
||||
const retractDist = dockBackground.height + SettingsData.dockSpacing + 10;
|
||||
return SettingsData.dockPosition === SettingsData.Position.Bottom ? retractDist : -retractDist;
|
||||
}
|
||||
const hideDistance = dock.connectedJoinInset + dock.effectiveBarHeight + SettingsData.dockSpacing + dock.effectiveDockBottomGap + dock.effectiveDockMargin + 10;
|
||||
if (SettingsData.dockPosition === SettingsData.Position.Bottom) {
|
||||
return hideDistance;
|
||||
@@ -596,28 +660,29 @@ Variants {
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
id: slideXAnimation
|
||||
duration: Theme.isConnectedEffect
|
||||
? Theme.variantDuration(Theme.popoutAnimationDuration, dock.reveal)
|
||||
: Theme.shortDuration
|
||||
duration: Theme.isConnectedEffect ? Theme.variantDuration(Theme.popoutAnimationDuration, dock.reveal) : Theme.shortDuration
|
||||
easing.type: Theme.isConnectedEffect ? Easing.BezierSpline : Easing.OutCubic
|
||||
easing.bezierCurve: Theme.isConnectedEffect
|
||||
? (dock.reveal ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve)
|
||||
: []
|
||||
easing.bezierCurve: Theme.isConnectedEffect ? (dock.reveal ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve) : []
|
||||
onRunningChanged: if (!running) dock._syncDockChromeState()
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
id: slideYAnimation
|
||||
duration: Theme.isConnectedEffect
|
||||
? Theme.variantDuration(Theme.popoutAnimationDuration, dock.reveal)
|
||||
: Theme.shortDuration
|
||||
duration: Theme.isConnectedEffect ? Theme.variantDuration(Theme.popoutAnimationDuration, dock.reveal) : Theme.shortDuration
|
||||
easing.type: Theme.isConnectedEffect ? Easing.BezierSpline : Easing.OutCubic
|
||||
easing.bezierCurve: Theme.isConnectedEffect
|
||||
? (dock.reveal ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve)
|
||||
: []
|
||||
easing.bezierCurve: Theme.isConnectedEffect ? (dock.reveal ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve) : []
|
||||
onRunningChanged: if (!running) dock._syncDockChromeState()
|
||||
}
|
||||
}
|
||||
|
||||
onXChanged: {
|
||||
dock._syncDockSlide();
|
||||
}
|
||||
onYChanged: {
|
||||
dock._syncDockSlide();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -647,6 +712,7 @@ Variants {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: !SettingsData.connectedFrameModeActive
|
||||
color: dock.surfaceColor
|
||||
topLeftRadius: dock.surfaceTopLeftRadius
|
||||
topRightRadius: dock.surfaceTopRightRadius
|
||||
@@ -656,6 +722,7 @@ Variants {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
visible: !SettingsData.connectedFrameModeActive
|
||||
color: "transparent"
|
||||
topLeftRadius: dock.surfaceTopLeftRadius
|
||||
topRightRadius: dock.surfaceTopRightRadius
|
||||
@@ -665,26 +732,34 @@ Variants {
|
||||
border.width: dock.surfaceBorderWidth
|
||||
z: 100
|
||||
}
|
||||
|
||||
// Sync dockBackground geometry to ConnectedModeState
|
||||
onXChanged: dock._syncDockChromeState()
|
||||
onYChanged: dock._syncDockChromeState()
|
||||
onWidthChanged: dock._syncDockChromeState()
|
||||
onHeightChanged: dock._syncDockChromeState()
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect && dock.reveal
|
||||
visible: Theme.isConnectedEffect && dock.reveal && !SettingsData.connectedFrameModeActive
|
||||
barSide: dock.connectedBarSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: dock.surfaceColor
|
||||
dpr: dock._dpr
|
||||
x: Theme.snap(dock.connectorX(dockBackground.x, dockBackground.width, placement, spacing), dock._dpr)
|
||||
y: Theme.snap(dock.connectorY(dockBackground.y, dockBackground.height, placement, spacing), dock._dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
visible: Theme.isConnectedEffect && dock.reveal
|
||||
visible: Theme.isConnectedEffect && dock.reveal && !SettingsData.connectedFrameModeActive
|
||||
barSide: dock.connectedBarSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: Theme.connectedCornerRadius
|
||||
color: dock.surfaceColor
|
||||
dpr: dock._dpr
|
||||
x: Theme.snap(dock.connectorX(dockBackground.x, dockBackground.width, placement, spacing), dock._dpr)
|
||||
y: Theme.snap(dock.connectorY(dockBackground.y, dockBackground.height, placement, spacing), dock._dpr)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
PanelWindow {
|
||||
id: win
|
||||
@@ -26,8 +27,6 @@ PanelWindow {
|
||||
}
|
||||
|
||||
color: "transparent"
|
||||
|
||||
// No input — pass everything through to apps and bar
|
||||
mask: Region {}
|
||||
|
||||
readonly property var barEdges: {
|
||||
@@ -36,20 +35,50 @@ PanelWindow {
|
||||
}
|
||||
|
||||
readonly property real _dpr: CompositorService.getScreenScale(win.screen)
|
||||
readonly property bool _frameActive: SettingsData.frameEnabled
|
||||
&& SettingsData.isScreenInPreferences(win.screen, SettingsData.frameScreenPreferences)
|
||||
readonly property int _windowRegionWidth: win._regionInt(win.width)
|
||||
readonly property bool _frameActive: SettingsData.frameEnabled && SettingsData.isScreenInPreferences(win.screen, SettingsData.frameScreenPreferences)
|
||||
readonly property int _windowRegionWidth: win._regionInt(win.width)
|
||||
readonly property int _windowRegionHeight: win._regionInt(win.height)
|
||||
readonly property string _screenName: win.screen ? win.screen.name : ""
|
||||
readonly property var _dockState: ConnectedModeState.dockStates[win._screenName] || ConnectedModeState.emptyDockState
|
||||
readonly property var _dockSlide: ConnectedModeState.dockSlides[win._screenName] || ({
|
||||
"x": 0,
|
||||
"y": 0
|
||||
})
|
||||
|
||||
// ─── Connected chrome convenience properties ──────────────────────────────
|
||||
readonly property bool _connectedActive: win._frameActive && SettingsData.connectedFrameModeActive
|
||||
readonly property string _barSide: {
|
||||
const edges = win.barEdges;
|
||||
if (edges.includes("top"))
|
||||
return "top";
|
||||
if (edges.includes("bottom"))
|
||||
return "bottom";
|
||||
if (edges.includes("left"))
|
||||
return "left";
|
||||
return "right";
|
||||
}
|
||||
readonly property real _ccr: Theme.connectedCornerRadius
|
||||
readonly property real _effectivePopoutCcr: {
|
||||
const extent = win._popoutArcExtent();
|
||||
const isHoriz = ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom";
|
||||
const crossSize = isHoriz ? _popoutBodyBlurAnchor.width : _popoutBodyBlurAnchor.height;
|
||||
return Math.max(0, Math.min(win._ccr, extent, crossSize / 2));
|
||||
}
|
||||
readonly property color _surfaceColor: Theme.connectedSurfaceColor
|
||||
readonly property real _surfaceOpacity: _surfaceColor.a
|
||||
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)
|
||||
|
||||
function _regionInt(value) {
|
||||
return Math.max(0, Math.round(Theme.px(value, win._dpr)));
|
||||
}
|
||||
|
||||
readonly property int cutoutTopInset: win._regionInt(barEdges.includes("top") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutTopInset: win._regionInt(barEdges.includes("top") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutBottomInset: win._regionInt(barEdges.includes("bottom") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutLeftInset: win._regionInt(barEdges.includes("left") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutRightInset: win._regionInt(barEdges.includes("right") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutWidth: Math.max(0, win._windowRegionWidth - win.cutoutLeftInset - win.cutoutRightInset)
|
||||
readonly property int cutoutLeftInset: win._regionInt(barEdges.includes("left") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutRightInset: win._regionInt(barEdges.includes("right") ? SettingsData.frameBarSize : SettingsData.frameThickness)
|
||||
readonly property int cutoutWidth: Math.max(0, win._windowRegionWidth - win.cutoutLeftInset - win.cutoutRightInset)
|
||||
readonly property int cutoutHeight: Math.max(0, win._windowRegionHeight - win.cutoutTopInset - win.cutoutBottomInset)
|
||||
readonly property int cutoutRadius: {
|
||||
const requested = win._regionInt(SettingsData.frameRounding);
|
||||
@@ -57,7 +86,6 @@ PanelWindow {
|
||||
return Math.max(0, Math.min(requested, maxRadius));
|
||||
}
|
||||
|
||||
// Slightly expand the subtractive blur cutout at very low opacity levels
|
||||
readonly property int _blurCutoutCompensation: SettingsData.frameOpacity <= 0.2 ? 1 : 0
|
||||
readonly property int _blurCutoutLeft: Math.max(0, win.cutoutLeftInset - win._blurCutoutCompensation)
|
||||
readonly property int _blurCutoutTop: Math.max(0, win.cutoutTopInset - win._blurCutoutCompensation)
|
||||
@@ -69,7 +97,7 @@ PanelWindow {
|
||||
return Math.max(0, Math.min(requested, maxRadius));
|
||||
}
|
||||
|
||||
// Must stay visible so Region.item can resolve scene coordinates.
|
||||
// Invisible items providing scene coordinates for blur Region anchors
|
||||
Item {
|
||||
id: _blurCutout
|
||||
x: win._blurCutoutLeft
|
||||
@@ -78,48 +106,471 @@ PanelWindow {
|
||||
height: Math.max(0, win._blurCutoutBottom - win._blurCutoutTop)
|
||||
}
|
||||
|
||||
property var _frameBlurRegion: null
|
||||
Item {
|
||||
id: _popoutBodyBlurAnchor
|
||||
visible: false
|
||||
|
||||
readonly property bool _active: ConnectedModeState.popoutVisible && ConnectedModeState.popoutScreen === win._screenName
|
||||
|
||||
readonly property real _dyClamp: (ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom") ? Math.max(-ConnectedModeState.popoutBodyH, Math.min(ConnectedModeState.popoutAnimY, ConnectedModeState.popoutBodyH)) : 0
|
||||
readonly property real _dxClamp: (ConnectedModeState.popoutBarSide === "left" || ConnectedModeState.popoutBarSide === "right") ? Math.max(-ConnectedModeState.popoutBodyW, Math.min(ConnectedModeState.popoutAnimX, ConnectedModeState.popoutBodyW)) : 0
|
||||
|
||||
x: _active ? ConnectedModeState.popoutBodyX + (ConnectedModeState.popoutBarSide === "right" ? _dxClamp : 0) : 0
|
||||
y: _active ? ConnectedModeState.popoutBodyY + (ConnectedModeState.popoutBarSide === "bottom" ? _dyClamp : 0) : 0
|
||||
width: _active ? Math.max(0, ConnectedModeState.popoutBodyW - Math.abs(_dxClamp)) : 0
|
||||
height: _active ? Math.max(0, ConnectedModeState.popoutBodyH - Math.abs(_dyClamp)) : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockBodyBlurAnchor
|
||||
visible: false
|
||||
|
||||
readonly property bool _active: win._dockState.reveal && win._dockState.bodyW > 0 && win._dockState.bodyH > 0
|
||||
|
||||
x: _active ? win._dockState.bodyX + (win._dockSlide.x || 0) : 0
|
||||
y: _active ? win._dockState.bodyY + (win._dockSlide.y || 0) : 0
|
||||
width: _active ? win._dockState.bodyW : 0
|
||||
height: _active ? win._dockState.bodyH : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutBodyBlurCap
|
||||
opacity: 0
|
||||
|
||||
readonly property string _side: ConnectedModeState.popoutBarSide
|
||||
readonly property real _capThickness: win._popoutBlurCapThickness()
|
||||
readonly property bool _active: _popoutBodyBlurAnchor._active && _capThickness > 0 && _popoutBodyBlurAnchor.width > 0 && _popoutBodyBlurAnchor.height > 0
|
||||
readonly property real _capWidth: (_side === "left" || _side === "right") ? Math.min(_capThickness, _popoutBodyBlurAnchor.width) : _popoutBodyBlurAnchor.width
|
||||
readonly property real _capHeight: (_side === "top" || _side === "bottom") ? Math.min(_capThickness, _popoutBodyBlurAnchor.height) : _popoutBodyBlurAnchor.height
|
||||
|
||||
x: !_active ? 0 : (_side === "right" ? _popoutBodyBlurAnchor.x + _popoutBodyBlurAnchor.width - _capWidth : _popoutBodyBlurAnchor.x)
|
||||
y: !_active ? 0 : (_side === "bottom" ? _popoutBodyBlurAnchor.y + _popoutBodyBlurAnchor.height - _capHeight : _popoutBodyBlurAnchor.y)
|
||||
width: _active ? _capWidth : 0
|
||||
height: _active ? _capHeight : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockBodyBlurCap
|
||||
opacity: 0
|
||||
|
||||
readonly property string _side: win._dockState.barSide
|
||||
readonly property bool _active: _dockBodyBlurAnchor._active && _dockBodyBlurAnchor.width > 0 && _dockBodyBlurAnchor.height > 0
|
||||
readonly property real _capWidth: (_side === "left" || _side === "right") ? Math.min(win._dockConnectorRadius(), _dockBodyBlurAnchor.width) : _dockBodyBlurAnchor.width
|
||||
readonly property real _capHeight: (_side === "top" || _side === "bottom") ? Math.min(win._dockConnectorRadius(), _dockBodyBlurAnchor.height) : _dockBodyBlurAnchor.height
|
||||
|
||||
x: !_active ? 0 : (_side === "right" ? _dockBodyBlurAnchor.x + _dockBodyBlurAnchor.width - _capWidth : _dockBodyBlurAnchor.x)
|
||||
y: !_active ? 0 : (_side === "bottom" ? _dockBodyBlurAnchor.y + _dockBodyBlurAnchor.height - _capHeight : _dockBodyBlurAnchor.y)
|
||||
width: _active ? _capWidth : 0
|
||||
height: _active ? _capHeight : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockLeftConnectorBlurAnchor
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _dockBodyBlurAnchor._active && win._dockConnectorRadius() > 0
|
||||
readonly property real _w: win._dockConnectorWidth(0)
|
||||
readonly property real _h: win._dockConnectorHeight(0)
|
||||
|
||||
x: _active ? Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "left", 0), win._dpr) : 0
|
||||
y: _active ? Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "left", 0), win._dpr) : 0
|
||||
width: _active ? _w : 0
|
||||
height: _active ? _h : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockRightConnectorBlurAnchor
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _dockBodyBlurAnchor._active && win._dockConnectorRadius() > 0
|
||||
readonly property real _w: win._dockConnectorWidth(0)
|
||||
readonly property real _h: win._dockConnectorHeight(0)
|
||||
|
||||
x: _active ? Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "right", 0), win._dpr) : 0
|
||||
y: _active ? Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "right", 0), win._dpr) : 0
|
||||
width: _active ? _w : 0
|
||||
height: _active ? _h : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockLeftConnectorCutout
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _dockLeftConnectorBlurAnchor.width > 0 && _dockLeftConnectorBlurAnchor.height > 0
|
||||
readonly property string _arcCorner: win._connectorArcCorner(win._dockState.barSide, "left")
|
||||
|
||||
x: _active ? win._connectorCutoutX(_dockLeftConnectorBlurAnchor.x, _dockLeftConnectorBlurAnchor.width, _arcCorner, win._dockConnectorRadius()) : 0
|
||||
y: _active ? win._connectorCutoutY(_dockLeftConnectorBlurAnchor.y, _dockLeftConnectorBlurAnchor.height, _arcCorner, win._dockConnectorRadius()) : 0
|
||||
width: _active ? win._dockConnectorRadius() * 2 : 0
|
||||
height: _active ? win._dockConnectorRadius() * 2 : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockRightConnectorCutout
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _dockRightConnectorBlurAnchor.width > 0 && _dockRightConnectorBlurAnchor.height > 0
|
||||
readonly property string _arcCorner: win._connectorArcCorner(win._dockState.barSide, "right")
|
||||
|
||||
x: _active ? win._connectorCutoutX(_dockRightConnectorBlurAnchor.x, _dockRightConnectorBlurAnchor.width, _arcCorner, win._dockConnectorRadius()) : 0
|
||||
y: _active ? win._connectorCutoutY(_dockRightConnectorBlurAnchor.y, _dockRightConnectorBlurAnchor.height, _arcCorner, win._dockConnectorRadius()) : 0
|
||||
width: _active ? win._dockConnectorRadius() * 2 : 0
|
||||
height: _active ? win._dockConnectorRadius() * 2 : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutLeftConnectorBlurAnchor
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: win._popoutArcVisible()
|
||||
readonly property real _w: win._popoutConnectorWidth(0)
|
||||
readonly property real _h: win._popoutConnectorHeight(0)
|
||||
|
||||
x: _active ? Theme.snap(win._popoutConnectorX(ConnectedModeState.popoutBodyX, ConnectedModeState.popoutBodyW, "left", 0), win._dpr) : 0
|
||||
y: _active ? Theme.snap(win._popoutConnectorY(ConnectedModeState.popoutBodyY, ConnectedModeState.popoutBodyH, "left", 0), win._dpr) : 0
|
||||
width: _active ? _w : 0
|
||||
height: _active ? _h : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutRightConnectorBlurAnchor
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: win._popoutArcVisible()
|
||||
readonly property real _w: win._popoutConnectorWidth(0)
|
||||
readonly property real _h: win._popoutConnectorHeight(0)
|
||||
|
||||
x: _active ? Theme.snap(win._popoutConnectorX(ConnectedModeState.popoutBodyX, ConnectedModeState.popoutBodyW, "right", 0), win._dpr) : 0
|
||||
y: _active ? Theme.snap(win._popoutConnectorY(ConnectedModeState.popoutBodyY, ConnectedModeState.popoutBodyH, "right", 0), win._dpr) : 0
|
||||
width: _active ? _w : 0
|
||||
height: _active ? _h : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutLeftConnectorCutout
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _popoutLeftConnectorBlurAnchor.width > 0 && _popoutLeftConnectorBlurAnchor.height > 0
|
||||
readonly property string _arcCorner: win._connectorArcCorner(ConnectedModeState.popoutBarSide, "left")
|
||||
|
||||
x: _active ? win._connectorCutoutX(_popoutLeftConnectorBlurAnchor.x, _popoutLeftConnectorBlurAnchor.width, _arcCorner) : 0
|
||||
y: _active ? win._connectorCutoutY(_popoutLeftConnectorBlurAnchor.y, _popoutLeftConnectorBlurAnchor.height, _arcCorner) : 0
|
||||
width: _active ? win._effectivePopoutCcr * 2 : 0
|
||||
height: _active ? win._effectivePopoutCcr * 2 : 0
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _popoutRightConnectorCutout
|
||||
opacity: 0
|
||||
|
||||
readonly property bool _active: _popoutRightConnectorBlurAnchor.width > 0 && _popoutRightConnectorBlurAnchor.height > 0
|
||||
readonly property string _arcCorner: win._connectorArcCorner(ConnectedModeState.popoutBarSide, "right")
|
||||
|
||||
x: _active ? win._connectorCutoutX(_popoutRightConnectorBlurAnchor.x, _popoutRightConnectorBlurAnchor.width, _arcCorner) : 0
|
||||
y: _active ? win._connectorCutoutY(_popoutRightConnectorBlurAnchor.y, _popoutRightConnectorBlurAnchor.height, _arcCorner) : 0
|
||||
width: _active ? win._effectivePopoutCcr * 2 : 0
|
||||
height: _active ? win._effectivePopoutCcr * 2 : 0
|
||||
}
|
||||
|
||||
Region {
|
||||
id: _staticBlurRegion
|
||||
x: 0
|
||||
y: 0
|
||||
width: win._windowRegionWidth
|
||||
height: win._windowRegionHeight
|
||||
|
||||
// Frame cutout (always active when frame is on)
|
||||
Region {
|
||||
item: _blurCutout
|
||||
intersection: Intersection.Subtract
|
||||
radius: win._blurCutoutRadius
|
||||
}
|
||||
|
||||
// ── Connected popout blur regions ──
|
||||
Region {
|
||||
item: _popoutBodyBlurAnchor
|
||||
readonly property string _bs: ConnectedModeState.popoutBarSide
|
||||
topLeftRadius: (_bs === "top" || _bs === "left") ? win._effectivePopoutCcr : win._surfaceRadius
|
||||
topRightRadius: (_bs === "top" || _bs === "right") ? win._effectivePopoutCcr : win._surfaceRadius
|
||||
bottomLeftRadius: (_bs === "bottom" || _bs === "left") ? win._effectivePopoutCcr : win._surfaceRadius
|
||||
bottomRightRadius: (_bs === "bottom" || _bs === "right") ? win._effectivePopoutCcr : win._surfaceRadius
|
||||
}
|
||||
Region {
|
||||
item: _popoutBodyBlurCap
|
||||
}
|
||||
Region {
|
||||
item: _popoutLeftConnectorBlurAnchor
|
||||
Region {
|
||||
item: _popoutLeftConnectorCutout
|
||||
intersection: Intersection.Subtract
|
||||
radius: win._effectivePopoutCcr
|
||||
}
|
||||
}
|
||||
Region {
|
||||
item: _popoutRightConnectorBlurAnchor
|
||||
Region {
|
||||
item: _popoutRightConnectorCutout
|
||||
intersection: Intersection.Subtract
|
||||
radius: win._effectivePopoutCcr
|
||||
}
|
||||
}
|
||||
|
||||
// ── Connected dock blur regions ──
|
||||
Region {
|
||||
item: _dockBodyBlurAnchor
|
||||
radius: win._dockBodyBlurRadius()
|
||||
}
|
||||
Region {
|
||||
item: _dockBodyBlurCap
|
||||
}
|
||||
Region {
|
||||
item: _dockLeftConnectorBlurAnchor
|
||||
radius: win._dockConnectorRadius()
|
||||
Region {
|
||||
item: _dockLeftConnectorCutout
|
||||
intersection: Intersection.Subtract
|
||||
radius: win._dockConnectorRadius()
|
||||
}
|
||||
}
|
||||
Region {
|
||||
item: _dockRightConnectorBlurAnchor
|
||||
radius: win._dockConnectorRadius()
|
||||
Region {
|
||||
item: _dockRightConnectorCutout
|
||||
intersection: Intersection.Subtract
|
||||
radius: win._dockConnectorRadius()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Connector position helpers (mirror DankPopout / Dock logic) ──────────
|
||||
|
||||
function _popoutConnectorWidth(spacing) {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return (barSide === "top" || barSide === "bottom") ? win._effectivePopoutCcr : (spacing + win._effectivePopoutCcr);
|
||||
}
|
||||
|
||||
function _popoutConnectorHeight(spacing) {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return (barSide === "top" || barSide === "bottom") ? (spacing + win._effectivePopoutCcr) : win._effectivePopoutCcr;
|
||||
}
|
||||
|
||||
function _popoutConnectorX(baseX, bodyWidth, placement, spacing) {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
const seamX = (barSide === "top" || barSide === "bottom") ? (placement === "left" ? baseX : baseX + bodyWidth) : (barSide === "left" ? baseX : baseX + bodyWidth);
|
||||
const w = _popoutConnectorWidth(spacing);
|
||||
if (barSide === "top" || barSide === "bottom")
|
||||
return placement === "left" ? seamX - w : seamX;
|
||||
return barSide === "left" ? seamX : seamX - w;
|
||||
}
|
||||
|
||||
function _popoutConnectorY(baseY, bodyHeight, placement, spacing) {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
const seamY = barSide === "top" ? baseY : barSide === "bottom" ? baseY + bodyHeight : (placement === "left" ? baseY : baseY + bodyHeight);
|
||||
const h = _popoutConnectorHeight(spacing);
|
||||
if (barSide === "top")
|
||||
return seamY;
|
||||
if (barSide === "bottom")
|
||||
return seamY - h;
|
||||
return placement === "left" ? seamY - h : seamY;
|
||||
}
|
||||
|
||||
function _dockBodyBlurRadius() {
|
||||
return _dockBodyBlurAnchor._active ? Math.max(0, Math.min(win._surfaceRadius, _dockBodyBlurAnchor.width / 2, _dockBodyBlurAnchor.height / 2)) : win._surfaceRadius;
|
||||
}
|
||||
|
||||
function _dockConnectorRadius() {
|
||||
if (!_dockBodyBlurAnchor._active)
|
||||
return win._ccr;
|
||||
const dockSide = win._dockState.barSide;
|
||||
const thickness = (dockSide === "left" || dockSide === "right") ? _dockBodyBlurAnchor.width : _dockBodyBlurAnchor.height;
|
||||
const bodyRadius = win._dockBodyBlurRadius();
|
||||
const maxConnectorRadius = Math.max(0, thickness - bodyRadius - win._seamOverlap);
|
||||
return Math.max(0, Math.min(win._ccr, bodyRadius, maxConnectorRadius));
|
||||
}
|
||||
|
||||
function _dockConnectorWidth(spacing) {
|
||||
const isVert = win._dockState.barSide === "left" || win._dockState.barSide === "right";
|
||||
const radius = win._dockConnectorRadius();
|
||||
return isVert ? (spacing + radius) : radius;
|
||||
}
|
||||
|
||||
function _dockConnectorHeight(spacing) {
|
||||
const isVert = win._dockState.barSide === "left" || win._dockState.barSide === "right";
|
||||
const radius = win._dockConnectorRadius();
|
||||
return isVert ? radius : (spacing + radius);
|
||||
}
|
||||
|
||||
function _dockConnectorX(baseX, bodyWidth, placement, spacing) {
|
||||
const dockSide = win._dockState.barSide;
|
||||
const isVert = dockSide === "left" || dockSide === "right";
|
||||
const seamX = !isVert ? (placement === "left" ? baseX : baseX + bodyWidth) : (dockSide === "left" ? baseX : baseX + bodyWidth);
|
||||
const w = _dockConnectorWidth(spacing);
|
||||
if (!isVert)
|
||||
return placement === "left" ? seamX - w : seamX;
|
||||
return dockSide === "left" ? seamX : seamX - w;
|
||||
}
|
||||
|
||||
function _dockConnectorY(baseY, bodyHeight, placement, spacing) {
|
||||
const dockSide = win._dockState.barSide;
|
||||
const seamY = dockSide === "top" ? baseY : dockSide === "bottom" ? baseY + bodyHeight : (placement === "left" ? baseY : baseY + bodyHeight);
|
||||
const h = _dockConnectorHeight(spacing);
|
||||
if (dockSide === "top")
|
||||
return seamY;
|
||||
if (dockSide === "bottom")
|
||||
return seamY - h;
|
||||
return placement === "left" ? seamY - h : seamY;
|
||||
}
|
||||
|
||||
function _popoutFillOverlapX() {
|
||||
return (ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom") ? win._seamOverlap : 0;
|
||||
}
|
||||
|
||||
function _popoutFillOverlapY() {
|
||||
return (ConnectedModeState.popoutBarSide === "left" || ConnectedModeState.popoutBarSide === "right") ? win._seamOverlap : 0;
|
||||
}
|
||||
|
||||
function _dockFillOverlapX() {
|
||||
return (win._dockState.barSide === "top" || win._dockState.barSide === "bottom") ? win._seamOverlap : 0;
|
||||
}
|
||||
|
||||
function _dockFillOverlapY() {
|
||||
return (win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._seamOverlap : 0;
|
||||
}
|
||||
|
||||
function _popoutArcExtent() {
|
||||
return (ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "bottom") ? _popoutBodyBlurAnchor.height : _popoutBodyBlurAnchor.width;
|
||||
}
|
||||
|
||||
function _popoutArcVisible() {
|
||||
if (!_popoutBodyBlurAnchor._active || _popoutBodyBlurAnchor.width <= 0 || _popoutBodyBlurAnchor.height <= 0)
|
||||
return false;
|
||||
return win._popoutArcExtent() >= win._ccr * (1 + win._ccr * 0.02);
|
||||
}
|
||||
|
||||
function _popoutBlurCapThickness() {
|
||||
const extent = win._popoutArcExtent();
|
||||
return Math.max(0, Math.min(win._effectivePopoutCcr, extent - win._surfaceRadius));
|
||||
}
|
||||
|
||||
function _popoutChromeX() {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return ConnectedModeState.popoutBodyX - ((barSide === "top" || barSide === "bottom") ? win._effectivePopoutCcr : 0);
|
||||
}
|
||||
|
||||
function _popoutChromeY() {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return ConnectedModeState.popoutBodyY - ((barSide === "left" || barSide === "right") ? win._effectivePopoutCcr : 0);
|
||||
}
|
||||
|
||||
function _popoutChromeWidth() {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return ConnectedModeState.popoutBodyW + ((barSide === "top" || barSide === "bottom") ? win._effectivePopoutCcr * 2 : 0);
|
||||
}
|
||||
|
||||
function _popoutChromeHeight() {
|
||||
const barSide = ConnectedModeState.popoutBarSide;
|
||||
return ConnectedModeState.popoutBodyH + ((barSide === "left" || barSide === "right") ? win._effectivePopoutCcr * 2 : 0);
|
||||
}
|
||||
|
||||
function _popoutClipX() {
|
||||
return _popoutBodyBlurAnchor.x - win._popoutChromeX() - win._popoutFillOverlapX();
|
||||
}
|
||||
|
||||
function _popoutClipY() {
|
||||
return _popoutBodyBlurAnchor.y - win._popoutChromeY() - win._popoutFillOverlapY();
|
||||
}
|
||||
|
||||
function _popoutClipWidth() {
|
||||
return _popoutBodyBlurAnchor.width + win._popoutFillOverlapX() * 2;
|
||||
}
|
||||
|
||||
function _popoutClipHeight() {
|
||||
return _popoutBodyBlurAnchor.height + win._popoutFillOverlapY() * 2;
|
||||
}
|
||||
|
||||
function _popoutBodyXInClip() {
|
||||
return (ConnectedModeState.popoutBarSide === "left" ? _popoutBodyBlurAnchor._dxClamp : 0) - win._popoutFillOverlapX();
|
||||
}
|
||||
|
||||
function _popoutBodyYInClip() {
|
||||
return (ConnectedModeState.popoutBarSide === "top" ? _popoutBodyBlurAnchor._dyClamp : 0) - win._popoutFillOverlapY();
|
||||
}
|
||||
|
||||
function _popoutBodyFullWidth() {
|
||||
return ConnectedModeState.popoutBodyW + win._popoutFillOverlapX() * 2;
|
||||
}
|
||||
|
||||
function _popoutBodyFullHeight() {
|
||||
return ConnectedModeState.popoutBodyH + win._popoutFillOverlapY() * 2;
|
||||
}
|
||||
|
||||
function _dockChromeX() {
|
||||
const dockSide = win._dockState.barSide;
|
||||
return _dockBodyBlurAnchor.x - ((dockSide === "top" || dockSide === "bottom") ? win._dockConnectorRadius() : 0);
|
||||
}
|
||||
|
||||
function _dockChromeY() {
|
||||
const dockSide = win._dockState.barSide;
|
||||
return _dockBodyBlurAnchor.y - ((dockSide === "left" || dockSide === "right") ? win._dockConnectorRadius() : 0);
|
||||
}
|
||||
|
||||
function _dockChromeWidth() {
|
||||
const dockSide = win._dockState.barSide;
|
||||
return _dockBodyBlurAnchor.width + ((dockSide === "top" || dockSide === "bottom") ? win._dockConnectorRadius() * 2 : 0);
|
||||
}
|
||||
|
||||
function _dockChromeHeight() {
|
||||
const dockSide = win._dockState.barSide;
|
||||
return _dockBodyBlurAnchor.height + ((dockSide === "left" || dockSide === "right") ? win._dockConnectorRadius() * 2 : 0);
|
||||
}
|
||||
|
||||
function _dockBodyXInChrome() {
|
||||
return ((win._dockState.barSide === "top" || win._dockState.barSide === "bottom") ? win._dockConnectorRadius() : 0) - win._dockFillOverlapX();
|
||||
}
|
||||
|
||||
function _dockBodyYInChrome() {
|
||||
return ((win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._dockConnectorRadius() : 0) - win._dockFillOverlapY();
|
||||
}
|
||||
|
||||
function _connectorArcCorner(barSide, placement) {
|
||||
if (barSide === "top")
|
||||
return placement === "left" ? "bottomLeft" : "bottomRight";
|
||||
if (barSide === "bottom")
|
||||
return placement === "left" ? "topLeft" : "topRight";
|
||||
if (barSide === "left")
|
||||
return placement === "left" ? "topRight" : "bottomRight";
|
||||
return placement === "left" ? "topLeft" : "bottomLeft";
|
||||
}
|
||||
|
||||
function _connectorCutoutX(connectorX, connectorWidth, arcCorner, radius) {
|
||||
const r = radius === undefined ? win._effectivePopoutCcr : radius;
|
||||
return (arcCorner === "topLeft" || arcCorner === "bottomLeft") ? connectorX - r : connectorX + connectorWidth - r;
|
||||
}
|
||||
|
||||
function _connectorCutoutY(connectorY, connectorHeight, arcCorner, radius) {
|
||||
const r = radius === undefined ? win._effectivePopoutCcr : radius;
|
||||
return (arcCorner === "topLeft" || arcCorner === "topRight") ? connectorY - r : connectorY + connectorHeight - r;
|
||||
}
|
||||
|
||||
// ─── Blur build / teardown ────────────────────────────────────────────────
|
||||
|
||||
function _buildBlur() {
|
||||
_teardownBlur();
|
||||
// Follow the global blur toggle
|
||||
if (!BlurService.enabled || !SettingsData.frameBlurEnabled || !win._frameActive || !win.visible)
|
||||
return;
|
||||
try {
|
||||
const region = Qt.createQmlObject(
|
||||
'import QtQuick; import Quickshell; Region {' +
|
||||
' property Item cutoutItem;' +
|
||||
' property int cutoutRadius: 0;' +
|
||||
' Region {' +
|
||||
' item: cutoutItem;' +
|
||||
' intersection: Intersection.Subtract;' +
|
||||
' radius: cutoutRadius;' +
|
||||
' }' +
|
||||
'}',
|
||||
win, "FrameBlurRegion");
|
||||
|
||||
region.x = Qt.binding(() => 0);
|
||||
region.y = Qt.binding(() => 0);
|
||||
region.width = Qt.binding(() => win._windowRegionWidth);
|
||||
region.height = Qt.binding(() => win._windowRegionHeight);
|
||||
region.cutoutItem = _blurCutout;
|
||||
region.cutoutRadius = Qt.binding(() => win._blurCutoutRadius);
|
||||
|
||||
win.BackgroundEffect.blurRegion = region;
|
||||
win._frameBlurRegion = region;
|
||||
if (!BlurService.enabled || !SettingsData.frameBlurEnabled || !win._frameActive || !win.visible) {
|
||||
win.BackgroundEffect.blurRegion = null;
|
||||
return;
|
||||
}
|
||||
win.BackgroundEffect.blurRegion = _staticBlurRegion;
|
||||
} catch (e) {
|
||||
console.warn("FrameWindow: Failed to create blur region:", e);
|
||||
console.warn("FrameWindow: Failed to set blur region:", e);
|
||||
}
|
||||
}
|
||||
|
||||
function _teardownBlur() {
|
||||
if (!win._frameBlurRegion)
|
||||
return;
|
||||
try {
|
||||
win.BackgroundEffect.blurRegion = null;
|
||||
} catch (e) {}
|
||||
win._frameBlurRegion.destroy();
|
||||
win._frameBlurRegion = null;
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -130,24 +581,44 @@ PanelWindow {
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onFrameBlurEnabledChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameEnabledChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameThicknessChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameBarSizeChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameOpacityChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameRoundingChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameScreenPreferencesChanged() { _blurRebuildTimer.restart(); }
|
||||
function onBarConfigsChanged() { _blurRebuildTimer.restart(); }
|
||||
function onFrameBlurEnabledChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameEnabledChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameThicknessChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameBarSizeChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameOpacityChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameRoundingChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onFrameScreenPreferencesChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onBarConfigsChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
function onConnectedFrameModeActiveChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BlurService
|
||||
function onEnabledChanged() { _blurRebuildTimer.restart(); }
|
||||
function onEnabledChanged() {
|
||||
_blurRebuildTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
win._frameBlurRegion = null;
|
||||
_blurRebuildTimer.restart();
|
||||
} else {
|
||||
_teardownBlur();
|
||||
@@ -157,6 +628,8 @@ PanelWindow {
|
||||
Component.onCompleted: Qt.callLater(() => win._buildBlur())
|
||||
Component.onDestruction: win._teardownBlur()
|
||||
|
||||
// ─── Frame border ─────────────────────────────────────────────────────────
|
||||
|
||||
FrameBorder {
|
||||
anchors.fill: parent
|
||||
visible: win._frameActive
|
||||
@@ -166,4 +639,132 @@ PanelWindow {
|
||||
cutoutRightInset: win.cutoutRightInset
|
||||
cutoutRadius: win.cutoutRadius
|
||||
}
|
||||
|
||||
// ─── Connected chrome fills ───────────────────────────────────────────────
|
||||
|
||||
Item {
|
||||
id: _connectedChrome
|
||||
anchors.fill: parent
|
||||
visible: win._connectedActive
|
||||
|
||||
Item {
|
||||
id: _popoutChrome
|
||||
visible: ConnectedModeState.popoutVisible && ConnectedModeState.popoutScreen === win._screenName
|
||||
x: win._popoutChromeX()
|
||||
y: win._popoutChromeY()
|
||||
width: win._popoutChromeWidth()
|
||||
height: win._popoutChromeHeight()
|
||||
opacity: win._surfaceOpacity
|
||||
layer.enabled: opacity < 1
|
||||
layer.smooth: false
|
||||
|
||||
Item {
|
||||
id: _popoutClip
|
||||
x: win._popoutClipX()
|
||||
y: win._popoutClipY()
|
||||
width: win._popoutClipWidth()
|
||||
height: win._popoutClipHeight()
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: _popoutFill
|
||||
x: win._popoutBodyXInClip()
|
||||
y: win._popoutBodyYInClip()
|
||||
width: win._popoutBodyFullWidth()
|
||||
height: win._popoutBodyFullHeight()
|
||||
color: win._opaqueSurfaceColor
|
||||
z: 1
|
||||
topLeftRadius: (ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "left") ? 0 : win._surfaceRadius
|
||||
topRightRadius: (ConnectedModeState.popoutBarSide === "top" || ConnectedModeState.popoutBarSide === "right") ? 0 : win._surfaceRadius
|
||||
bottomLeftRadius: (ConnectedModeState.popoutBarSide === "bottom" || ConnectedModeState.popoutBarSide === "left") ? 0 : win._surfaceRadius
|
||||
bottomRightRadius: (ConnectedModeState.popoutBarSide === "bottom" || ConnectedModeState.popoutBarSide === "right") ? 0 : win._surfaceRadius
|
||||
}
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connPopoutLeft
|
||||
visible: win._popoutArcVisible()
|
||||
barSide: ConnectedModeState.popoutBarSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: win._effectivePopoutCcr
|
||||
color: win._opaqueSurfaceColor
|
||||
edgeStrokeWidth: win._seamOverlap
|
||||
edgeStrokeColor: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._popoutConnectorX(ConnectedModeState.popoutBodyX, ConnectedModeState.popoutBodyW, "left", 0) - _popoutChrome.x, win._dpr)
|
||||
y: Theme.snap(win._popoutConnectorY(ConnectedModeState.popoutBodyY, ConnectedModeState.popoutBodyH, "left", 0) - _popoutChrome.y, win._dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connPopoutRight
|
||||
visible: win._popoutArcVisible()
|
||||
barSide: ConnectedModeState.popoutBarSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: win._effectivePopoutCcr
|
||||
color: win._opaqueSurfaceColor
|
||||
edgeStrokeWidth: win._seamOverlap
|
||||
edgeStrokeColor: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._popoutConnectorX(ConnectedModeState.popoutBodyX, ConnectedModeState.popoutBodyW, "right", 0) - _popoutChrome.x, win._dpr)
|
||||
y: Theme.snap(win._popoutConnectorY(ConnectedModeState.popoutBodyY, ConnectedModeState.popoutBodyH, "right", 0) - _popoutChrome.y, win._dpr)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: _dockChrome
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
x: win._dockChromeX()
|
||||
y: win._dockChromeY()
|
||||
width: win._dockChromeWidth()
|
||||
height: win._dockChromeHeight()
|
||||
opacity: win._surfaceOpacity
|
||||
layer.enabled: opacity < 1
|
||||
layer.smooth: false
|
||||
|
||||
Rectangle {
|
||||
id: _dockFill
|
||||
x: win._dockBodyXInChrome()
|
||||
y: win._dockBodyYInChrome()
|
||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapX() * 2
|
||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapY() * 2
|
||||
color: win._opaqueSurfaceColor
|
||||
z: 1
|
||||
|
||||
readonly property string _dockSide: win._dockState.barSide
|
||||
readonly property real _dockRadius: win._dockBodyBlurRadius()
|
||||
topLeftRadius: (_dockSide === "top" || _dockSide === "left") ? 0 : _dockRadius
|
||||
topRightRadius: (_dockSide === "top" || _dockSide === "right") ? 0 : _dockRadius
|
||||
bottomLeftRadius: (_dockSide === "bottom" || _dockSide === "left") ? 0 : _dockRadius
|
||||
bottomRightRadius: (_dockSide === "bottom" || _dockSide === "right") ? 0 : _dockRadius
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockLeft
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "left"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "left", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "left", 0) - _dockChrome.y, win._dpr)
|
||||
}
|
||||
|
||||
ConnectedCorner {
|
||||
id: _connDockRight
|
||||
visible: _dockBodyBlurAnchor._active
|
||||
barSide: win._dockState.barSide
|
||||
placement: "right"
|
||||
spacing: 0
|
||||
connectorRadius: win._dockConnectorRadius()
|
||||
color: win._opaqueSurfaceColor
|
||||
dpr: win._dpr
|
||||
x: Theme.snap(win._dockConnectorX(_dockBodyBlurAnchor.x, _dockBodyBlurAnchor.width, "right", 0) - _dockChrome.x, win._dpr)
|
||||
y: Theme.snap(win._dockConnectorY(_dockBodyBlurAnchor.y, _dockBodyBlurAnchor.height, "right", 0) - _dockChrome.y, win._dpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,9 @@ Item {
|
||||
settingKey: "frameRounding"
|
||||
tags: ["frame", "border", "rounding", "radius", "corner"]
|
||||
text: I18n.tr("Border Radius")
|
||||
description: SettingsData.connectedFrameModeActive
|
||||
? I18n.tr("Controls the radius of the frame and all connected popout, dock, and modal surfaces while Connected Mode is active")
|
||||
: I18n.tr("Controls the frame border radius. This also becomes the connected surface radius whenever Connected Mode is active")
|
||||
unit: "px"
|
||||
minimum: 0
|
||||
maximum: 100
|
||||
|
||||
@@ -11,9 +11,7 @@ import qs.Modules.Settings.Widgets
|
||||
Item {
|
||||
id: themeColorsTab
|
||||
|
||||
readonly property bool connectedFrameModeActive: SettingsData.frameEnabled
|
||||
&& SettingsData.motionEffect === 1
|
||||
&& SettingsData.directionalAnimationMode === 3
|
||||
readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
|
||||
property var cachedIconThemes: SettingsData.availableIconThemes
|
||||
property var cachedCursorThemes: SettingsData.availableCursorThemes
|
||||
property var cachedMatugenSchemes: Theme.availableMatugenSchemes.map(option => option.label)
|
||||
@@ -1639,7 +1637,9 @@ Item {
|
||||
tags: ["corner", "radius", "rounded", "square"]
|
||||
settingKey: "cornerRadius"
|
||||
text: I18n.tr("Corner Radius")
|
||||
description: I18n.tr("0 = square corners")
|
||||
description: themeColorsTab.connectedFrameModeActive
|
||||
? I18n.tr("Controls general UI rounding. Connected frame popouts, docks, and modal surfaces follow Border Radius in the Frame tab while Connected Frame mode is active")
|
||||
: I18n.tr("0 = square corners")
|
||||
value: SettingsData.cornerRadius
|
||||
minimum: 0
|
||||
maximum: 32
|
||||
|
||||
Reference in New Issue
Block a user