mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-06-10 13:13:29 -04:00
Refactor shadow handling & improve connected chrome rendering
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -19,7 +18,12 @@ Item {
|
|||||||
property real bottomRightRadius: targetRadius
|
property real bottomRightRadius: targetRadius
|
||||||
property color borderColor: "transparent"
|
property color borderColor: "transparent"
|
||||||
property real borderWidth: 0
|
property real borderWidth: 0
|
||||||
property bool useCustomSource: false
|
|
||||||
|
// Rounded-rect geometry within the item; defaults fill the item.
|
||||||
|
property real sourceX: 0
|
||||||
|
property real sourceY: 0
|
||||||
|
property real sourceWidth: width
|
||||||
|
property real sourceHeight: height
|
||||||
|
|
||||||
property bool shadowEnabled: Theme.elevationEnabled
|
property bool shadowEnabled: Theme.elevationEnabled
|
||||||
property real shadowBlurPx: level && level.blurPx !== undefined ? level.blurPx : 0
|
property real shadowBlurPx: level && level.blurPx !== undefined ? level.blurPx : 0
|
||||||
@@ -28,36 +32,26 @@ Item {
|
|||||||
property real shadowOffsetY: Theme.elevationOffsetYFor(level, direction, fallbackOffset)
|
property real shadowOffsetY: Theme.elevationOffsetYFor(level, direction, fallbackOffset)
|
||||||
property color shadowColor: Theme.elevationShadowColor(level)
|
property color shadowColor: Theme.elevationShadowColor(level)
|
||||||
property real shadowOpacity: 1
|
property real shadowOpacity: 1
|
||||||
property real blurMax: Theme.elevationBlurMax
|
|
||||||
|
|
||||||
property alias sourceRect: sourceRect
|
readonly property var _ambient: Theme.elevationAmbient(level)
|
||||||
|
readonly property real _pad: shadowEnabled ? Math.ceil(Math.max(shadowBlurPx + shadowSpreadPx + Math.max(Math.abs(shadowOffsetX), Math.abs(shadowOffsetY)), _ambient.blurPx + _ambient.spreadPx) + 2) : 0
|
||||||
|
|
||||||
layer.enabled: shadowEnabled
|
// Fill + border + key/ambient shadows drawn analytically on one oversized
|
||||||
|
// quad — no FBO, no blur passes.
|
||||||
layer.effect: MultiEffect {
|
ShaderEffect {
|
||||||
autoPaddingEnabled: true
|
|
||||||
shadowEnabled: true
|
|
||||||
blurEnabled: false
|
|
||||||
maskEnabled: false
|
|
||||||
shadowBlur: Math.max(0, Math.min(1, root.shadowBlurPx / Math.max(1, root.blurMax)))
|
|
||||||
shadowScale: 1 + (2 * root.shadowSpreadPx) / Math.max(1, Math.min(root.width, root.height))
|
|
||||||
shadowHorizontalOffset: root.shadowOffsetX
|
|
||||||
shadowVerticalOffset: root.shadowOffsetY
|
|
||||||
blurMax: root.blurMax
|
|
||||||
shadowColor: root.shadowColor
|
|
||||||
shadowOpacity: root.shadowOpacity
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: sourceRect
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: !root.useCustomSource
|
anchors.margins: -root._pad
|
||||||
topLeftRadius: root.topLeftRadius
|
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/elevation_rect.frag.qsb")
|
||||||
topRightRadius: root.topRightRadius
|
|
||||||
bottomLeftRadius: root.bottomLeftRadius
|
property real widthPx: width
|
||||||
bottomRightRadius: root.bottomRightRadius
|
property real heightPx: height
|
||||||
color: root.targetColor
|
property real borderWidth: root.borderWidth
|
||||||
border.color: root.borderColor
|
property vector4d rectPx: Qt.vector4d(root._pad + root.sourceX, root._pad + root.sourceY, root.sourceWidth, root.sourceHeight)
|
||||||
border.width: root.borderWidth
|
property vector4d cornerRadius: Qt.vector4d(root.topLeftRadius, root.topRightRadius, root.bottomRightRadius, root.bottomLeftRadius)
|
||||||
|
property vector4d fillColor: Qt.vector4d(root.targetColor.r, root.targetColor.g, root.targetColor.b, root.targetColor.a)
|
||||||
|
property vector4d borderColor: Qt.vector4d(root.borderColor.r, root.borderColor.g, root.borderColor.b, root.borderColor.a)
|
||||||
|
property vector4d shadowColor: Qt.vector4d(root.shadowColor.r, root.shadowColor.g, root.shadowColor.b, root.shadowEnabled ? root.shadowColor.a * root.shadowOpacity : 0)
|
||||||
|
property vector4d shadowParam: Qt.vector4d(Math.max(0, root.shadowBlurPx), root.shadowSpreadPx, root.shadowOffsetX, root.shadowOffsetY)
|
||||||
|
property vector4d ambientParam: Qt.vector4d(root._ambient.blurPx, root._ambient.spreadPx, root.shadowEnabled ? root._ambient.alpha * root.shadowOpacity : 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -911,6 +911,19 @@ Singleton {
|
|||||||
}
|
}
|
||||||
return Qt.rgba(r, g, b, alpha);
|
return Qt.rgba(r, g, b, alpha);
|
||||||
}
|
}
|
||||||
|
// Non-directional ambient layer of the M3 two-part shadow model (key +
|
||||||
|
// ambient). Derived from the key level so user intensity/opacity settings
|
||||||
|
// scale both layers together.
|
||||||
|
function elevationAmbient(level) {
|
||||||
|
const blur = (level && level.blurPx !== undefined) ? Math.max(0, level.blurPx) : 0;
|
||||||
|
const alpha = ((level && level.alpha !== undefined) ? level.alpha : 0.3) * 0.5;
|
||||||
|
return {
|
||||||
|
blurPx: blur * 1.75,
|
||||||
|
spreadPx: 1,
|
||||||
|
alpha: alpha
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function elevationTintOpacity(level) {
|
function elevationTintOpacity(level) {
|
||||||
if (!level)
|
if (!level)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Item {
|
|||||||
// M3 elevation shadow — Level 2 baseline (navigation bar), with per-bar override support
|
// M3 elevation shadow — Level 2 baseline (navigation bar), with per-bar override support
|
||||||
readonly property bool hasPerBarOverride: (barConfig?.shadowIntensity ?? 0) > 0
|
readonly property bool hasPerBarOverride: (barConfig?.shadowIntensity ?? 0) > 0
|
||||||
readonly property var elevLevel: Theme.elevationLevel2
|
readonly property var elevLevel: Theme.elevationLevel2
|
||||||
readonly property bool shadowEnabled: !BlurService.enabled && ((Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || hasPerBarOverride)
|
readonly property bool shadowEnabled: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || hasPerBarOverride
|
||||||
readonly property string autoBarShadowDirection: isTop ? "top" : (isBottom ? "bottom" : (isLeft ? "left" : (isRight ? "right" : "top")))
|
readonly property string autoBarShadowDirection: isTop ? "top" : (isBottom ? "bottom" : (isLeft ? "left" : (isRight ? "right" : "top")))
|
||||||
readonly property string globalShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
readonly property string globalShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
||||||
readonly property string perBarShadowDirectionMode: barConfig?.shadowDirectionMode ?? "inherit"
|
readonly property string perBarShadowDirectionMode: barConfig?.shadowDirectionMode ?? "inherit"
|
||||||
@@ -207,7 +207,6 @@ Item {
|
|||||||
shadowOffsetX: root.shadowOffsetX
|
shadowOffsetX: root.shadowOffsetX
|
||||||
shadowOffsetY: root.shadowOffsetY
|
shadowOffsetY: root.shadowOffsetY
|
||||||
shadowColor: root.shadowColor
|
shadowColor: root.shadowColor
|
||||||
blurMax: Theme.elevationBlurMax
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
|||||||
@@ -1237,13 +1237,7 @@ BasePill {
|
|||||||
fallbackOffset: 6
|
fallbackOffset: 6
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
targetRadius: Theme.cornerRadius
|
targetRadius: Theme.cornerRadius
|
||||||
sourceRect.antialiasing: true
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
|
||||||
sourceRect.smooth: true
|
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && !BlurService.enabled
|
|
||||||
layer.smooth: true
|
|
||||||
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
|
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
|
||||||
layer.samples: 4
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -1689,11 +1683,7 @@ BasePill {
|
|||||||
fallbackOffset: 6
|
fallbackOffset: 6
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
targetRadius: Theme.cornerRadius
|
targetRadius: Theme.cornerRadius
|
||||||
sourceRect.antialiasing: true
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && !BlurService.enabled
|
|
||||||
layer.smooth: true
|
|
||||||
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
|
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ Item {
|
|||||||
borderColor: volumePanel.border.color
|
borderColor: volumePanel.border.color
|
||||||
borderWidth: volumePanel.border.width
|
borderWidth: volumePanel.border.width
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
shadowEnabled: Theme.elevationEnabled && !BlurService.enabled
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -272,7 +272,7 @@ Item {
|
|||||||
borderColor: audioDevicesPanel.border.color
|
borderColor: audioDevicesPanel.border.color
|
||||||
borderWidth: audioDevicesPanel.border.width
|
borderWidth: audioDevicesPanel.border.width
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
shadowEnabled: Theme.elevationEnabled && !BlurService.enabled
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -444,7 +444,7 @@ Item {
|
|||||||
borderColor: playersPanel.border.color
|
borderColor: playersPanel.border.color
|
||||||
borderWidth: playersPanel.border.width
|
borderWidth: playersPanel.border.width
|
||||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
shadowEnabled: Theme.elevationEnabled && !BlurService.enabled
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Shapes
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
// Frame perimeter ring: the full window rectangle with a rounded-rectangle
|
// Frame perimeter ring: the full window rectangle with a rounded-rectangle
|
||||||
// cutout. Drawn as a single even-odd Shape so the ring is one primitive: no
|
// cutout, rendered as a signed-distance field with analytic antialiasing.
|
||||||
// full-output mask textures, and a translucent fill never double-blends at the
|
// One primitive: no full-output mask textures, no corner double-blend, crisp
|
||||||
// corners.
|
// edges at any scale without an FBO.
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
@@ -20,42 +19,14 @@ Item {
|
|||||||
required property real cutoutRadius
|
required property real cutoutRadius
|
||||||
property color borderColor: Qt.rgba(SettingsData.effectiveFrameColor.r, SettingsData.effectiveFrameColor.g, SettingsData.effectiveFrameColor.b, SettingsData.frameOpacity)
|
property color borderColor: Qt.rgba(SettingsData.effectiveFrameColor.r, SettingsData.effectiveFrameColor.g, SettingsData.effectiveFrameColor.b, SettingsData.frameOpacity)
|
||||||
|
|
||||||
// Path elements can't reference `parent`; expose cutout edges as root props.
|
ShaderEffect {
|
||||||
readonly property real _left: cutoutLeftInset
|
|
||||||
readonly property real _top: cutoutTopInset
|
|
||||||
readonly property real _right: width - cutoutRightInset
|
|
||||||
readonly property real _bottom: height - cutoutBottomInset
|
|
||||||
readonly property real _radius: Math.max(0, Math.min(cutoutRadius, (_right - _left) / 2, (_bottom - _top) / 2))
|
|
||||||
|
|
||||||
Shape {
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
asynchronous: false
|
fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/frame_arc.frag.qsb")
|
||||||
preferredRendererType: Shape.CurveRenderer
|
|
||||||
antialiasing: true
|
|
||||||
|
|
||||||
ShapePath {
|
property real widthPx: width
|
||||||
fillColor: root.borderColor
|
property real heightPx: height
|
||||||
strokeWidth: -1
|
property real cutoutRadius: root.cutoutRadius
|
||||||
fillRule: ShapePath.OddEvenFill
|
property vector4d cutout: Qt.vector4d(root.cutoutLeftInset, root.cutoutTopInset, root.width - root.cutoutRightInset, root.height - root.cutoutBottomInset)
|
||||||
|
property vector4d surfaceColor: Qt.vector4d(root.borderColor.r, root.borderColor.g, root.borderColor.b, root.borderColor.a)
|
||||||
// Outer rectangle (window edge, square corners)
|
|
||||||
startX: 0
|
|
||||||
startY: 0
|
|
||||||
PathLine { x: root.width; y: 0 }
|
|
||||||
PathLine { x: root.width; y: root.height }
|
|
||||||
PathLine { x: 0; y: root.height }
|
|
||||||
PathLine { x: 0; y: 0 }
|
|
||||||
|
|
||||||
// Inner rounded-rectangle cutout (second subpath → even-odd hole)
|
|
||||||
PathMove { x: root._left + root._radius; y: root._top }
|
|
||||||
PathLine { x: root._right - root._radius; y: root._top }
|
|
||||||
PathArc { x: root._right; y: root._top + root._radius; radiusX: root._radius; radiusY: root._radius }
|
|
||||||
PathLine { x: root._right; y: root._bottom - root._radius }
|
|
||||||
PathArc { x: root._right - root._radius; y: root._bottom; radiusX: root._radius; radiusY: root._radius }
|
|
||||||
PathLine { x: root._left + root._radius; y: root._bottom }
|
|
||||||
PathArc { x: root._left; y: root._bottom - root._radius; radiusX: root._radius; radiusY: root._radius }
|
|
||||||
PathLine { x: root._left; y: root._top + root._radius }
|
|
||||||
PathArc { x: root._left + root._radius; y: root._top; radiusX: root._radius; radiusY: root._radius }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
|
||||||
import "../../Common/ConnectorGeometry.js" as ConnectorGeometry
|
import "../../Common/ConnectorGeometry.js" as ConnectorGeometry
|
||||||
import "../../Common/ConnectedSurfaceGeometry.js" as SurfaceGeometry
|
import "../../Common/ConnectedSurfaceGeometry.js" as SurfaceGeometry
|
||||||
|
|
||||||
@@ -70,11 +68,8 @@ PanelWindow {
|
|||||||
readonly property real _ccr: Theme.connectedCornerRadius
|
readonly property real _ccr: Theme.connectedCornerRadius
|
||||||
|
|
||||||
readonly property bool _popoutHorizontal: SurfaceGeometry.isHorizontal(win._popoutDescriptor.barSide)
|
readonly property bool _popoutHorizontal: SurfaceGeometry.isHorizontal(win._popoutDescriptor.barSide)
|
||||||
readonly property bool _notifHorizontal: ConnectorGeometry.isHorizontal(win._notifState.barSide)
|
|
||||||
readonly property bool _modalHorizontal: ConnectorGeometry.isHorizontal(win._modalState.barSide)
|
readonly property bool _modalHorizontal: ConnectorGeometry.isHorizontal(win._modalState.barSide)
|
||||||
readonly property bool _dockHorizontal: ConnectorGeometry.isHorizontal(win._dockState.barSide)
|
|
||||||
readonly property var _popoutBodyGeometry: SurfaceGeometry.animatedBodyRect(win._popoutDescriptor, win._dpr)
|
readonly property var _popoutBodyGeometry: SurfaceGeometry.animatedBodyRect(win._popoutDescriptor, win._dpr)
|
||||||
readonly property var _popoutStaticBodyGeometry: SurfaceGeometry.bodyRect(win._popoutDescriptor, win._dpr)
|
|
||||||
readonly property var _modalBodyGeometry: SurfaceGeometry.animatedBodyRect(win._modalDescriptor, win._dpr)
|
readonly property var _modalBodyGeometry: SurfaceGeometry.animatedBodyRect(win._modalDescriptor, win._dpr)
|
||||||
readonly property var _notifBodyGeometry: SurfaceGeometry.bodyRect(win._notifDescriptor, win._dpr)
|
readonly property var _notifBodyGeometry: SurfaceGeometry.bodyRect(win._notifDescriptor, win._dpr)
|
||||||
readonly property var _dockBodyGeometry: SurfaceGeometry.translatedBodyRect(win._dockDescriptor, win._dpr)
|
readonly property var _dockBodyGeometry: SurfaceGeometry.translatedBodyRect(win._dockDescriptor, win._dpr)
|
||||||
@@ -97,12 +92,6 @@ PanelWindow {
|
|||||||
return Math.max(0, Math.min(win._ccr, bodyRadius, maxConnectorRadius));
|
return Math.max(0, Math.min(win._ccr, bodyRadius, maxConnectorRadius));
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real _popoutFillOverlapXValue: win._popoutHorizontal ? win._seamOverlap : 0
|
|
||||||
readonly property real _popoutFillOverlapYValue: (win._popoutState.barSide === "left" || win._popoutState.barSide === "right") ? win._seamOverlap : 0
|
|
||||||
readonly property real _dockFillOverlapXValue: win._dockHorizontal ? win._seamOverlap : 0
|
|
||||||
readonly property real _dockFillOverlapYValue: (win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._seamOverlap : 0
|
|
||||||
readonly property real _dockJoinOverlapXValue: ConnectorGeometry.isVertical(win._dockState.barSide) ? win._seamOverlap : 0
|
|
||||||
readonly property real _dockJoinOverlapYValue: ConnectorGeometry.isHorizontal(win._dockState.barSide) ? win._seamOverlap : 0
|
|
||||||
readonly property real _notifSideUnderlapValue: ConnectorGeometry.isVertical(win._notifState.barSide) ? win._seamOverlap : 0
|
readonly property real _notifSideUnderlapValue: ConnectorGeometry.isVertical(win._notifState.barSide) ? win._seamOverlap : 0
|
||||||
readonly property real _notifStartUnderlapValue: win._notifState.omitStartConnector ? win._seamOverlap : 0
|
readonly property real _notifStartUnderlapValue: win._notifState.omitStartConnector ? win._seamOverlap : 0
|
||||||
readonly property real _notifEndUnderlapValue: win._notifState.omitEndConnector ? win._seamOverlap : 0
|
readonly property real _notifEndUnderlapValue: win._notifState.omitEndConnector ? win._seamOverlap : 0
|
||||||
@@ -118,7 +107,6 @@ PanelWindow {
|
|||||||
readonly property real _effectivePopoutFarEndCcr: win._popoutRadii.farEnd
|
readonly property real _effectivePopoutFarEndCcr: win._popoutRadii.farEnd
|
||||||
readonly property real _effectivePopoutMaxCcr: Math.max(win._effectivePopoutStartCcr, win._effectivePopoutEndCcr)
|
readonly property real _effectivePopoutMaxCcr: Math.max(win._effectivePopoutStartCcr, win._effectivePopoutEndCcr)
|
||||||
readonly property real _effectivePopoutFarExtent: Math.max(win._effectivePopoutFarStartCcr, win._effectivePopoutFarEndCcr)
|
readonly property real _effectivePopoutFarExtent: Math.max(win._effectivePopoutFarStartCcr, win._effectivePopoutFarEndCcr)
|
||||||
readonly property var _popoutChromeGeometry: SurfaceGeometry.chromeBounds(win._popoutStaticBodyGeometry, win._popoutDescriptor.barSide, win._effectivePopoutStartCcr, win._effectivePopoutEndCcr, 0, win._dpr)
|
|
||||||
readonly property var _notifNearRadii: SurfaceGeometry.connectorRadii(win._notifDescriptor, win._notifBodyGeometry, win._ccr, win._surfaceRadius, win._dpr, true)
|
readonly property var _notifNearRadii: SurfaceGeometry.connectorRadii(win._notifDescriptor, win._notifBodyGeometry, win._ccr, win._surfaceRadius, win._dpr, true)
|
||||||
readonly property var _notifFarRadii: SurfaceGeometry.connectorRadii(win._notifDescriptor, win._notifBodyScene(), win._ccr, win._surfaceRadius, win._dpr, true)
|
readonly property var _notifFarRadii: SurfaceGeometry.connectorRadii(win._notifDescriptor, win._notifBodyScene(), win._ccr, win._surfaceRadius, win._dpr, true)
|
||||||
readonly property real _effectiveNotifCcr: win._notifNearRadii.near
|
readonly property real _effectiveNotifCcr: win._notifNearRadii.near
|
||||||
@@ -137,20 +125,16 @@ PanelWindow {
|
|||||||
readonly property real _effectiveModalFarStartCcr: win._modalRadii.farStart
|
readonly property real _effectiveModalFarStartCcr: win._modalRadii.farStart
|
||||||
readonly property real _effectiveModalFarEndCcr: win._modalRadii.farEnd
|
readonly property real _effectiveModalFarEndCcr: win._modalRadii.farEnd
|
||||||
readonly property real _effectiveModalFarExtent: Math.max(win._effectiveModalFarStartCcr, win._effectiveModalFarEndCcr)
|
readonly property real _effectiveModalFarExtent: Math.max(win._effectiveModalFarStartCcr, win._effectiveModalFarEndCcr)
|
||||||
readonly property var _dockChromeGeometry: SurfaceGeometry.chromeBounds(win._dockBodyGeometry, win._dockDescriptor.barSide, win._dockConnectorRadiusValue, win._dockConnectorRadiusValue, 0, win._dpr)
|
|
||||||
readonly property color _surfaceColor: Theme.connectedSurfaceColor
|
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 _surfaceRadius: Theme.connectedSurfaceRadius
|
||||||
readonly property real _seamOverlap: Theme.hairline(win._dpr)
|
readonly property real _seamOverlap: Theme.hairline(win._dpr)
|
||||||
readonly property bool _disableLayer: Quickshell.env("DMS_DISABLE_LAYER") === "true" || Quickshell.env("DMS_DISABLE_LAYER") === "1"
|
readonly property bool _disableLayer: Quickshell.env("DMS_DISABLE_LAYER") === "true" || Quickshell.env("DMS_DISABLE_LAYER") === "1"
|
||||||
// The connected silhouette is drawn directly as one translucent Shape; the
|
// Both elevation states render through the SDF shader; this only toggles
|
||||||
// full-output layer/FBO is allocated only when it must source the elevation
|
// the shadow term inside it.
|
||||||
// shadow. Translucency no longer needs a flatten (single primitive).
|
|
||||||
readonly property bool _elevationShadow: win._connectedActive && Theme.elevationEnabled && !win._disableLayer
|
readonly property bool _elevationShadow: win._connectedActive && Theme.elevationEnabled && !win._disableLayer
|
||||||
// Active surfaces packed into four fixed SDF-shader slots. Each near (bar)
|
// Active surfaces packed into four fixed SDF-shader slots. Each near (bar)
|
||||||
// edge is clamped to the cutout edge so the smooth-min connector attaches
|
// edge is clamped to the cutout edge so the smooth-min connector attaches
|
||||||
// there; connR (the smin radius) is the connector fillet.
|
// there; the per-corner smin radius is that corner's junction fillet.
|
||||||
readonly property var _sdfSlots: {
|
readonly property var _sdfSlots: {
|
||||||
const T = win.cutoutTopInset;
|
const T = win.cutoutTopInset;
|
||||||
const L = win.cutoutLeftInset;
|
const L = win.cutoutLeftInset;
|
||||||
@@ -177,44 +161,54 @@ PanelWindow {
|
|||||||
if (i < src.length) {
|
if (i < src.length) {
|
||||||
const s = src[i];
|
const s = src[i];
|
||||||
const b = clampNear(s.side, s.body);
|
const b = clampNear(s.side, s.body);
|
||||||
// smin radius = the near connector fillet only; an omitted
|
|
||||||
// connector contributes no flare (its corner just rounds).
|
|
||||||
const connR = Math.max(s.radii.startCr, s.radii.endCr);
|
|
||||||
const active = b.width > 0 && b.height > 0 ? 1 : 0;
|
const active = b.width > 0 && b.height > 0 ? 1 : 0;
|
||||||
// A bar-side corner is sharp only where its connector is present;
|
// Map start/end (left/top, right/bottom) onto corners
|
||||||
// an omitted connector (farStart/farEnd set) keeps that corner
|
// (tl,tr,br,bl): bar-side corners take their near connector
|
||||||
// rounded. Far corners always round. (start=left/top, end=right/bottom.)
|
// fillet, far corners always take the far fillet so a body
|
||||||
const bodyR = s.radii.surfaceRadius;
|
// meeting a perpendicular border joins with an arc (smin is
|
||||||
|
// inert when nothing is within k). A bar-side corner is sharp
|
||||||
|
// where its connector is present; an omitted connector makes
|
||||||
|
// its far corner sharp instead (the far-cap join).
|
||||||
|
const sc = s.radii.startCr, ec = s.radii.endCr;
|
||||||
|
// Clamp the far fillet to the body extent so it cannot flare
|
||||||
|
// back across a shallow body into the bar mid-animation.
|
||||||
|
const extent = (s.side === "top" || s.side === "bottom") ? b.height : b.width;
|
||||||
|
const fc = Math.min(s.radii.farCr, extent);
|
||||||
const omitS = s.radii.farStartCr > 0;
|
const omitS = s.radii.farStartCr > 0;
|
||||||
const omitE = s.radii.farEndCr > 0;
|
const omitE = s.radii.farEndCr > 0;
|
||||||
let tl = bodyR, tr = bodyR, br = bodyR, bl = bodyR;
|
const bodyR = s.radii.surfaceRadius;
|
||||||
|
const nearS = omitS ? bodyR : 0, nearE = omitE ? bodyR : 0;
|
||||||
|
const farS = omitS ? 0 : bodyR, farE = omitE ? 0 : bodyR;
|
||||||
|
// An omitted bar-side corner sits flush against the border, so
|
||||||
|
// it keeps a nonzero fillet (a zero k hard-joins the coincident
|
||||||
|
// edges and shows a half-coverage hairline along the seam).
|
||||||
|
const kS = omitS ? fc : sc, kE = omitE ? fc : ec;
|
||||||
|
let ks, cr;
|
||||||
if (s.side === "top") {
|
if (s.side === "top") {
|
||||||
if (!omitS) tl = 0;
|
ks = [kS, kE, fc, fc];
|
||||||
if (!omitE) tr = 0;
|
cr = [nearS, nearE, farE, farS];
|
||||||
} else if (s.side === "bottom") {
|
} else if (s.side === "bottom") {
|
||||||
if (!omitS) bl = 0;
|
ks = [fc, fc, kE, kS];
|
||||||
if (!omitE) br = 0;
|
cr = [farS, farE, nearE, nearS];
|
||||||
} else if (s.side === "left") {
|
} else if (s.side === "left") {
|
||||||
if (!omitS) tl = 0;
|
ks = [kS, fc, fc, kE];
|
||||||
if (!omitE) bl = 0;
|
cr = [nearS, farS, farE, nearE];
|
||||||
} else {
|
} else {
|
||||||
if (!omitS) tr = 0;
|
ks = [fc, kS, kE, fc];
|
||||||
if (!omitE) br = 0;
|
cr = [farS, nearS, nearE, farE];
|
||||||
}
|
}
|
||||||
out.push({
|
out.push({
|
||||||
"rect": Qt.vector4d(b.x, b.y, b.width, b.height),
|
"rect": Qt.vector4d(b.x, b.y, b.width, b.height),
|
||||||
"corner": Qt.vector4d(tl, tr, br, bl),
|
"corner": Qt.vector4d(cr[0], cr[1], cr[2], cr[3]),
|
||||||
"param": Qt.vector4d(connR, active, 0, 0)
|
"k": Qt.vector4d(ks[0], ks[1], ks[2], ks[3]),
|
||||||
|
"param": Qt.vector4d(active, 0, 0, 0)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
out.push({"rect": Qt.vector4d(0, 0, 0, 0), "corner": Qt.vector4d(0, 0, 0, 0), "param": Qt.vector4d(0, 0, 0, 0)});
|
out.push({"rect": Qt.vector4d(0, 0, 0, 0), "corner": Qt.vector4d(0, 0, 0, 0), "k": Qt.vector4d(0, 0, 0, 0), "param": Qt.vector4d(0, 0, 0, 0)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
property bool _surfaceRefreshNeedsLayerRecreate: false
|
|
||||||
property bool _surfaceLayerRecoveryActive: false
|
|
||||||
|
|
||||||
function _regionInt(value) {
|
function _regionInt(value) {
|
||||||
return Math.max(0, Math.round(Theme.px(value, win._dpr)));
|
return Math.max(0, Math.round(Theme.px(value, win._dpr)));
|
||||||
}
|
}
|
||||||
@@ -1067,96 +1061,14 @@ PanelWindow {
|
|||||||
return Math.max(0, Math.min(win._effectiveModalCcr, extent - win._surfaceRadius));
|
return Math.max(0, Math.min(win._effectiveModalCcr, extent - win._surfaceRadius));
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
function _popoutBlurCapThickness() {
|
||||||
const extent = win._popoutArcExtent;
|
const extent = win._popoutArcExtent;
|
||||||
return Math.max(0, Math.min(win._effectivePopoutMaxCcr, extent - win._surfaceRadius));
|
return Math.max(0, Math.min(win._effectivePopoutMaxCcr, extent - win._surfaceRadius));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _popoutChromeX() {
|
|
||||||
return win._popoutChromeGeometry.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutChromeY() {
|
|
||||||
return win._popoutChromeGeometry.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutChromeWidth() {
|
|
||||||
return win._popoutChromeGeometry.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutChromeHeight() {
|
|
||||||
return win._popoutChromeGeometry.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutClipX() {
|
|
||||||
return _popoutBodyBlurAnchor.x - win._popoutChromeX() - win._popoutFillOverlapXValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutClipY() {
|
|
||||||
return _popoutBodyBlurAnchor.y - win._popoutChromeY() - win._popoutFillOverlapYValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutClipWidth() {
|
|
||||||
return _popoutBodyBlurAnchor.width + win._popoutFillOverlapXValue * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutClipHeight() {
|
|
||||||
return _popoutBodyBlurAnchor.height + win._popoutFillOverlapYValue * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutShapeBodyOffsetX() {
|
|
||||||
const side = win._popoutState.barSide;
|
|
||||||
if (ConnectorGeometry.isHorizontal(side))
|
|
||||||
return win._effectivePopoutStartCcr;
|
|
||||||
return side === "right" ? win._effectivePopoutFarExtent : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutShapeBodyOffsetY() {
|
|
||||||
const side = win._popoutState.barSide;
|
|
||||||
if (ConnectorGeometry.isHorizontal(side))
|
|
||||||
return side === "bottom" ? win._effectivePopoutFarExtent : 0;
|
|
||||||
return win._effectivePopoutStartCcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutShapeWidth() {
|
|
||||||
const side = win._popoutState.barSide;
|
|
||||||
if (ConnectorGeometry.isHorizontal(side))
|
|
||||||
return win._popoutClipWidth() + win._effectivePopoutStartCcr + win._effectivePopoutEndCcr;
|
|
||||||
return win._popoutClipWidth() + win._effectivePopoutFarExtent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutShapeHeight() {
|
|
||||||
const side = win._popoutState.barSide;
|
|
||||||
if (ConnectorGeometry.isHorizontal(side))
|
|
||||||
return win._popoutClipHeight() + win._effectivePopoutFarExtent;
|
|
||||||
return win._popoutClipHeight() + win._effectivePopoutStartCcr + win._effectivePopoutEndCcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutBodyXInClip() {
|
|
||||||
return (win._popoutState.barSide === "left" ? _popoutBodyBlurAnchor._dxClamp : 0) - win._popoutFillOverlapXValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutBodyYInClip() {
|
|
||||||
return (win._popoutState.barSide === "top" ? _popoutBodyBlurAnchor._dyClamp : 0) - win._popoutFillOverlapYValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutBodyFullWidth() {
|
|
||||||
return win._popoutState.bodyW + win._popoutFillOverlapXValue * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _popoutBodyFullHeight() {
|
|
||||||
return win._popoutState.bodyH + win._popoutFillOverlapYValue * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Active connected surfaces fed to the unified silhouette path. Raw animated
|
// Active connected surfaces fed to the unified silhouette path. Raw animated
|
||||||
// body rects (no seam/fill overlap); the builder anchors each to the cutout
|
// body rects (no seam/fill overlap); the builder anchors each to the cutout
|
||||||
// edge. Connector radii match what each ConnectedShape would receive.
|
// edge. Connector radii use the same per-surface helpers as the blur regions.
|
||||||
function _unifiedSurfaces() {
|
function _unifiedSurfaces() {
|
||||||
const arr = [];
|
const arr = [];
|
||||||
const p = win._popoutBodyGeometry;
|
const p = win._popoutBodyGeometry;
|
||||||
@@ -1165,6 +1077,7 @@ PanelWindow {
|
|||||||
"side": win._popoutDescriptor.barSide,
|
"side": win._popoutDescriptor.barSide,
|
||||||
"body": {"x": p.x, "y": p.y, "width": p.width, "height": p.height},
|
"body": {"x": p.x, "y": p.y, "width": p.width, "height": p.height},
|
||||||
"radii": {
|
"radii": {
|
||||||
|
"farCr": win._effectivePopoutFarCcr,
|
||||||
"startCr": win._effectivePopoutStartCcr,
|
"startCr": win._effectivePopoutStartCcr,
|
||||||
"endCr": win._effectivePopoutEndCcr,
|
"endCr": win._effectivePopoutEndCcr,
|
||||||
"farStartCr": win._effectivePopoutFarStartCcr,
|
"farStartCr": win._effectivePopoutFarStartCcr,
|
||||||
@@ -1178,6 +1091,7 @@ PanelWindow {
|
|||||||
"side": win._modalDescriptor.barSide,
|
"side": win._modalDescriptor.barSide,
|
||||||
"body": {"x": m.x, "y": m.y, "width": m.width, "height": m.height},
|
"body": {"x": m.x, "y": m.y, "width": m.width, "height": m.height},
|
||||||
"radii": {
|
"radii": {
|
||||||
|
"farCr": win._effectiveModalFarCcr,
|
||||||
"startCr": win._effectiveModalStartCcr,
|
"startCr": win._effectiveModalStartCcr,
|
||||||
"endCr": win._effectiveModalEndCcr,
|
"endCr": win._effectiveModalEndCcr,
|
||||||
"farStartCr": win._effectiveModalFarStartCcr,
|
"farStartCr": win._effectiveModalFarStartCcr,
|
||||||
@@ -1191,6 +1105,7 @@ PanelWindow {
|
|||||||
"side": win._notifDescriptor.barSide,
|
"side": win._notifDescriptor.barSide,
|
||||||
"body": {"x": n.x, "y": n.y, "width": n.width, "height": n.height},
|
"body": {"x": n.x, "y": n.y, "width": n.width, "height": n.height},
|
||||||
"radii": {
|
"radii": {
|
||||||
|
"farCr": win._effectiveNotifFarCcr,
|
||||||
"startCr": win._effectiveNotifStartCcr,
|
"startCr": win._effectiveNotifStartCcr,
|
||||||
"endCr": win._effectiveNotifEndCcr,
|
"endCr": win._effectiveNotifEndCcr,
|
||||||
"farStartCr": win._effectiveNotifFarStartCcr,
|
"farStartCr": win._effectiveNotifFarStartCcr,
|
||||||
@@ -1204,6 +1119,7 @@ PanelWindow {
|
|||||||
"side": win._dockDescriptor.barSide,
|
"side": win._dockDescriptor.barSide,
|
||||||
"body": {"x": dk.x, "y": dk.y, "width": dk.width, "height": dk.height},
|
"body": {"x": dk.x, "y": dk.y, "width": dk.width, "height": dk.height},
|
||||||
"radii": {
|
"radii": {
|
||||||
|
"farCr": win._dockConnectorRadiusValue,
|
||||||
"startCr": win._dockConnectorRadiusValue,
|
"startCr": win._dockConnectorRadiusValue,
|
||||||
"endCr": win._dockConnectorRadiusValue,
|
"endCr": win._dockConnectorRadiusValue,
|
||||||
"farStartCr": 0,
|
"farStartCr": 0,
|
||||||
@@ -1214,38 +1130,6 @@ PanelWindow {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _dockChromeX() {
|
|
||||||
return win._dockChromeGeometry.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockChromeY() {
|
|
||||||
return win._dockChromeGeometry.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockChromeWidth() {
|
|
||||||
return win._dockChromeGeometry.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockChromeHeight() {
|
|
||||||
return win._dockChromeGeometry.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockBodyXInChrome() {
|
|
||||||
return (ConnectorGeometry.isHorizontal(win._dockState.barSide) ? win._dockConnectorRadiusValue : 0) - win._dockFillOverlapXValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockBodyYInChrome() {
|
|
||||||
return ((win._dockState.barSide === "left" || win._dockState.barSide === "right") ? win._dockConnectorRadiusValue : 0) - win._dockFillOverlapYValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockJoinOverlapXOffset() {
|
|
||||||
return win._dockState.barSide === "left" ? -win._dockJoinOverlapXValue : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _dockJoinOverlapYOffset() {
|
|
||||||
return win._dockState.barSide === "top" ? -win._dockJoinOverlapYValue : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _farConnectorBarSide(sourceSide, placement) {
|
function _farConnectorBarSide(sourceSide, placement) {
|
||||||
if (sourceSide === "top" || sourceSide === "bottom")
|
if (sourceSide === "top" || sourceSide === "bottom")
|
||||||
return placement === "left" ? "left" : "right";
|
return placement === "left" ? "left" : "right";
|
||||||
@@ -1317,28 +1201,13 @@ PanelWindow {
|
|||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _scheduleSurfaceRefresh(recreateLayer) {
|
function _scheduleSurfaceRefresh() {
|
||||||
if (recreateLayer)
|
|
||||||
_surfaceRefreshNeedsLayerRecreate = true;
|
|
||||||
surfaceRefreshAction.restart();
|
surfaceRefreshAction.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _runSurfaceRefresh() {
|
function _runSurfaceRefresh() {
|
||||||
if (!win.visible)
|
if (!win.visible)
|
||||||
return;
|
return;
|
||||||
if (_surfaceRefreshNeedsLayerRecreate) {
|
|
||||||
_surfaceRefreshNeedsLayerRecreate = false;
|
|
||||||
if (win._elevationShadow) {
|
|
||||||
_surfaceLayerRecoveryActive = true;
|
|
||||||
surfaceLayerRestoreAction.restart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_requestContentUpdate();
|
|
||||||
_republishFrameBlur();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _finishSurfaceLayerRecovery() {
|
|
||||||
_surfaceLayerRecoveryActive = false;
|
|
||||||
_requestContentUpdate();
|
_requestContentUpdate();
|
||||||
_republishFrameBlur();
|
_republishFrameBlur();
|
||||||
}
|
}
|
||||||
@@ -1348,11 +1217,6 @@ PanelWindow {
|
|||||||
onTriggered: win._runSurfaceRefresh()
|
onTriggered: win._runSurfaceRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
DeferredAction {
|
|
||||||
id: surfaceLayerRestoreAction
|
|
||||||
onTriggered: win._finishSurfaceLayerRecovery()
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
function onFrameBlurEnabledChanged() {
|
function onFrameBlurEnabledChanged() {
|
||||||
@@ -1397,41 +1261,33 @@ PanelWindow {
|
|||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
win._scheduleBlurRebuild();
|
win._scheduleBlurRebuild();
|
||||||
win._scheduleSurfaceRefresh(false);
|
win._scheduleSurfaceRefresh();
|
||||||
} else {
|
} else {
|
||||||
surfaceRefreshAction.cancel();
|
surfaceRefreshAction.cancel();
|
||||||
surfaceLayerRestoreAction.cancel();
|
|
||||||
_surfaceLayerRecoveryActive = false;
|
|
||||||
_surfaceRefreshNeedsLayerRecreate = false;
|
|
||||||
_teardownBlur();
|
_teardownBlur();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
on_SurfaceRevisionChanged: win._scheduleSurfaceRefresh(false)
|
on_SurfaceRevisionChanged: win._scheduleSurfaceRefresh()
|
||||||
|
|
||||||
onResourcesLost: {
|
onResourcesLost: {
|
||||||
blurRebuildAction.cancel();
|
blurRebuildAction.cancel();
|
||||||
surfaceRefreshAction.cancel();
|
surfaceRefreshAction.cancel();
|
||||||
surfaceLayerRestoreAction.cancel();
|
|
||||||
_surfaceRefreshNeedsLayerRecreate = true;
|
|
||||||
if (win._elevationShadow)
|
|
||||||
_surfaceLayerRecoveryActive = true;
|
|
||||||
win._teardownBlur();
|
win._teardownBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
onWindowConnected: {
|
onWindowConnected: {
|
||||||
win._scheduleSurfaceRefresh(true);
|
win._scheduleSurfaceRefresh();
|
||||||
win._scheduleBlurRebuild();
|
win._scheduleBlurRebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
win._scheduleBlurRebuild();
|
win._scheduleBlurRebuild();
|
||||||
win._scheduleSurfaceRefresh(false);
|
win._scheduleSurfaceRefresh();
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
Component.onDestruction: {
|
||||||
blurRebuildAction.cancel();
|
blurRebuildAction.cancel();
|
||||||
surfaceRefreshAction.cancel();
|
surfaceRefreshAction.cancel();
|
||||||
surfaceLayerRestoreAction.cancel();
|
|
||||||
win._teardownBlur();
|
win._teardownBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,258 +1301,41 @@ PanelWindow {
|
|||||||
cutoutRadius: win.cutoutRadius
|
cutoutRadius: win.cutoutRadius
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
// The entire connected silhouette (frame ring + every active chrome) as one
|
||||||
id: _connectedSurfaceLayer
|
// SDF in a fragment shader. Analytic fwidth AA → crisp at any scale, no FBO;
|
||||||
|
// the smooth-min radius is the connector. The elevation shadow is derived
|
||||||
|
// from the same distance field, so elevation-on needs no grouping layer.
|
||||||
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: win._connectedActive
|
visible: win._connectedActive
|
||||||
// Elevation-off draws the silhouette directly at the surface color, so
|
fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/connected_arc.frag.qsb")
|
||||||
// group opacity is 1. Elevation-on draws children opaque and applies the
|
|
||||||
// surface alpha to the whole group beneath the shadow.
|
|
||||||
opacity: win._elevationShadow ? win._surfaceOpacity : 1
|
|
||||||
// FBO is allocated only to source the elevation shadow.
|
|
||||||
layer.enabled: win._elevationShadow && !win._surfaceLayerRecoveryActive
|
|
||||||
layer.smooth: false
|
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
readonly property var _level: Theme.elevationLevel2
|
||||||
readonly property var level: Theme.elevationLevel2
|
readonly property color _shadowTint: Theme.elevationShadowColor(_level)
|
||||||
readonly property real _shadowBlur: Theme.elevationEnabled ? (level && level.blurPx !== undefined ? level.blurPx : 0) : 0
|
readonly property var _ambient: Theme.elevationAmbient(_level)
|
||||||
readonly property real _shadowSpread: Theme.elevationEnabled ? (level && level.spreadPx !== undefined ? level.spreadPx : 0) : 0
|
property real widthPx: width
|
||||||
|
property real heightPx: height
|
||||||
autoPaddingEnabled: true
|
property real cutoutRadius: win.cutoutRadius
|
||||||
blurEnabled: false
|
property vector4d cutout: Qt.vector4d(win.cutoutLeftInset, win.cutoutTopInset, win.width - win.cutoutRightInset, win.height - win.cutoutBottomInset)
|
||||||
maskEnabled: false
|
property vector4d surfaceColor: Qt.vector4d(win._surfaceColor.r, win._surfaceColor.g, win._surfaceColor.b, win._surfaceColor.a)
|
||||||
|
property vector4d shadowColor: Qt.vector4d(_shadowTint.r, _shadowTint.g, _shadowTint.b, win._elevationShadow ? _shadowTint.a : 0)
|
||||||
shadowEnabled: !win._disableLayer && Theme.elevationEnabled
|
property vector4d shadowParam: Qt.vector4d(Math.max(0, _level.blurPx), Math.max(0, _level.spreadPx), Theme.elevationOffsetXFor(_level, Theme.elevationLightDirection, 4), Theme.elevationOffsetYFor(_level, Theme.elevationLightDirection, 4))
|
||||||
shadowBlur: Math.max(0, Math.min(1, _shadowBlur / Math.max(1, Theme.elevationBlurMax)))
|
property vector4d ambientParam: Qt.vector4d(_ambient.blurPx, _ambient.spreadPx, win._elevationShadow ? _ambient.alpha : 0, 0)
|
||||||
shadowScale: 1 + (2 * _shadowSpread) / Math.max(1, Math.min(_connectedSurfaceLayer.width, _connectedSurfaceLayer.height))
|
property vector4d chromeRect0: win._sdfSlots[0].rect
|
||||||
shadowHorizontalOffset: Theme.elevationOffsetXFor(level, Theme.elevationLightDirection, 4)
|
property vector4d chromeCorner0: win._sdfSlots[0].corner
|
||||||
shadowVerticalOffset: Theme.elevationOffsetYFor(level, Theme.elevationLightDirection, 4)
|
property vector4d chromeK0: win._sdfSlots[0].k
|
||||||
shadowColor: Theme.elevationShadowColor(level)
|
property vector4d chromeParam0: win._sdfSlots[0].param
|
||||||
shadowOpacity: 1
|
property vector4d chromeRect1: win._sdfSlots[1].rect
|
||||||
}
|
property vector4d chromeCorner1: win._sdfSlots[1].corner
|
||||||
|
property vector4d chromeK1: win._sdfSlots[1].k
|
||||||
// Elevation-off: the entire connected silhouette (frame ring + every
|
property vector4d chromeParam1: win._sdfSlots[1].param
|
||||||
// active chrome) as one SDF in a fragment shader. Analytic fwidth AA →
|
property vector4d chromeRect2: win._sdfSlots[2].rect
|
||||||
// crisp at any scale, no FBO; the smooth-min radius is the connector.
|
property vector4d chromeCorner2: win._sdfSlots[2].corner
|
||||||
ShaderEffect {
|
property vector4d chromeK2: win._sdfSlots[2].k
|
||||||
anchors.fill: parent
|
property vector4d chromeParam2: win._sdfSlots[2].param
|
||||||
visible: win._connectedActive && !win._elevationShadow
|
property vector4d chromeRect3: win._sdfSlots[3].rect
|
||||||
fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/connected_arc.frag.qsb")
|
property vector4d chromeCorner3: win._sdfSlots[3].corner
|
||||||
|
property vector4d chromeK3: win._sdfSlots[3].k
|
||||||
property real widthPx: width
|
property vector4d chromeParam3: win._sdfSlots[3].param
|
||||||
property real heightPx: height
|
|
||||||
property real cutoutRadius: win.cutoutRadius
|
|
||||||
property vector4d cutout: Qt.vector4d(win.cutoutLeftInset, win.cutoutTopInset, win.width - win.cutoutRightInset, win.height - win.cutoutBottomInset)
|
|
||||||
property vector4d surfaceColor: Qt.vector4d(win._surfaceColor.r, win._surfaceColor.g, win._surfaceColor.b, win._surfaceColor.a)
|
|
||||||
property vector4d chromeRect0: win._sdfSlots[0].rect
|
|
||||||
property vector4d chromeCorner0: win._sdfSlots[0].corner
|
|
||||||
property vector4d chromeParam0: win._sdfSlots[0].param
|
|
||||||
property vector4d chromeRect1: win._sdfSlots[1].rect
|
|
||||||
property vector4d chromeCorner1: win._sdfSlots[1].corner
|
|
||||||
property vector4d chromeParam1: win._sdfSlots[1].param
|
|
||||||
property vector4d chromeRect2: win._sdfSlots[2].rect
|
|
||||||
property vector4d chromeCorner2: win._sdfSlots[2].corner
|
|
||||||
property vector4d chromeParam2: win._sdfSlots[2].param
|
|
||||||
property vector4d chromeRect3: win._sdfSlots[3].rect
|
|
||||||
property vector4d chromeCorner3: win._sdfSlots[3].corner
|
|
||||||
property vector4d chromeParam3: win._sdfSlots[3].param
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elevation-on: opaque children flattened in the FBO so the MultiEffect
|
|
||||||
// can derive one shadow; the layer applies the surface alpha.
|
|
||||||
FrameBorder {
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: win._elevationShadow
|
|
||||||
borderColor: win._opaqueSurfaceColor
|
|
||||||
cutoutTopInset: win.cutoutTopInset
|
|
||||||
cutoutBottomInset: win.cutoutBottomInset
|
|
||||||
cutoutLeftInset: win.cutoutLeftInset
|
|
||||||
cutoutRightInset: win.cutoutRightInset
|
|
||||||
cutoutRadius: win.cutoutRadius
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _connectedChrome
|
|
||||||
anchors.fill: parent
|
|
||||||
visible: win._elevationShadow
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _popoutChrome
|
|
||||||
visible: win._popoutState.visible && win._popoutState.screen === win._screenName
|
|
||||||
x: win._popoutChromeX()
|
|
||||||
y: win._popoutChromeY()
|
|
||||||
width: win._popoutChromeWidth()
|
|
||||||
height: win._popoutChromeHeight()
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _popoutClip
|
|
||||||
x: win._popoutClipX() - win._popoutShapeBodyOffsetX()
|
|
||||||
y: win._popoutClipY() - win._popoutShapeBodyOffsetY()
|
|
||||||
width: win._popoutShapeWidth()
|
|
||||||
height: win._popoutShapeHeight()
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
ConnectedShape {
|
|
||||||
id: _popoutShape
|
|
||||||
visible: _popoutBodyBlurAnchor._active && _popoutBodyBlurAnchor.width > 0 && _popoutBodyBlurAnchor.height > 0
|
|
||||||
barSide: win._popoutState.barSide
|
|
||||||
bodyWidth: win._popoutClipWidth()
|
|
||||||
bodyHeight: win._popoutClipHeight()
|
|
||||||
connectorRadius: win._effectivePopoutCcr
|
|
||||||
startConnectorRadius: win._effectivePopoutStartCcr
|
|
||||||
endConnectorRadius: win._effectivePopoutEndCcr
|
|
||||||
farStartConnectorRadius: win._effectivePopoutFarStartCcr
|
|
||||||
farEndConnectorRadius: win._effectivePopoutFarEndCcr
|
|
||||||
surfaceRadius: win._surfaceRadius
|
|
||||||
fillColor: win._opaqueSurfaceColor
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _dockChrome
|
|
||||||
visible: _dockBodyBlurAnchor._active
|
|
||||||
x: win._dockChromeX()
|
|
||||||
y: win._dockChromeY()
|
|
||||||
width: win._dockChromeWidth()
|
|
||||||
height: win._dockChromeHeight()
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: _dockFill
|
|
||||||
x: win._dockBodyXInChrome() + win._dockJoinOverlapXOffset()
|
|
||||||
y: win._dockBodyYInChrome() + win._dockJoinOverlapYOffset()
|
|
||||||
width: _dockBodyBlurAnchor.width + win._dockFillOverlapXValue * 2 + win._dockJoinOverlapXValue
|
|
||||||
height: _dockBodyBlurAnchor.height + win._dockFillOverlapYValue * 2 + win._dockJoinOverlapYValue
|
|
||||||
color: win._opaqueSurfaceColor
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
readonly property string _dockSide: win._dockState.barSide
|
|
||||||
readonly property real _dockRadius: win._dockBodyBlurRadiusValue
|
|
||||||
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._dockConnectorRadiusValue
|
|
||||||
color: win._opaqueSurfaceColor
|
|
||||||
dpr: win._dpr
|
|
||||||
x: Theme.snap(_dockLeftConnectorBlurAnchor.x - _dockChrome.x, win._dpr)
|
|
||||||
y: Theme.snap(_dockLeftConnectorBlurAnchor.y - _dockChrome.y, win._dpr)
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectedCorner {
|
|
||||||
id: _connDockRight
|
|
||||||
visible: _dockBodyBlurAnchor._active
|
|
||||||
barSide: win._dockState.barSide
|
|
||||||
placement: "right"
|
|
||||||
spacing: 0
|
|
||||||
connectorRadius: win._dockConnectorRadiusValue
|
|
||||||
color: win._opaqueSurfaceColor
|
|
||||||
dpr: win._dpr
|
|
||||||
x: Theme.snap(_dockRightConnectorBlurAnchor.x - _dockChrome.x, win._dpr)
|
|
||||||
y: Theme.snap(_dockRightConnectorBlurAnchor.y - _dockChrome.y, win._dpr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _notifChrome
|
|
||||||
visible: win._elevationShadow && _notifBodySceneBlurAnchor._active
|
|
||||||
|
|
||||||
readonly property string _notifSide: win._notifState.barSide
|
|
||||||
readonly property bool _isHoriz: _notifSide === "top" || _notifSide === "bottom"
|
|
||||||
readonly property real _startCcr: win._effectiveNotifStartCcr
|
|
||||||
readonly property real _endCcr: win._effectiveNotifEndCcr
|
|
||||||
readonly property real _farExtent: win._effectiveNotifFarExtent
|
|
||||||
readonly property real _bodyW: Theme.snap(_notifBodySceneBlurAnchor.width, win._dpr)
|
|
||||||
readonly property real _bodyH: Theme.snap(_notifBodySceneBlurAnchor.height, win._dpr)
|
|
||||||
readonly property var _geometry: SurfaceGeometry.chromeBounds(_notifBodySceneBlurAnchor, _notifSide, _startCcr, _endCcr, _farExtent, win._dpr)
|
|
||||||
|
|
||||||
z: _isHoriz ? 0 : -1
|
|
||||||
x: _geometry.x
|
|
||||||
y: _geometry.y
|
|
||||||
width: _geometry.width
|
|
||||||
height: _geometry.height
|
|
||||||
|
|
||||||
ConnectedShape {
|
|
||||||
visible: _notifBodySceneBlurAnchor._active && _notifBodySceneBlurAnchor.width > 0 && _notifBodySceneBlurAnchor.height > 0
|
|
||||||
barSide: _notifChrome._notifSide
|
|
||||||
bodyWidth: _notifChrome._bodyW
|
|
||||||
bodyHeight: _notifChrome._bodyH
|
|
||||||
connectorRadius: win._effectiveNotifCcr
|
|
||||||
startConnectorRadius: _notifChrome._startCcr
|
|
||||||
endConnectorRadius: _notifChrome._endCcr
|
|
||||||
farStartConnectorRadius: win._effectiveNotifFarStartCcr
|
|
||||||
farEndConnectorRadius: win._effectiveNotifFarEndCcr
|
|
||||||
surfaceRadius: win._surfaceRadius
|
|
||||||
fillColor: win._opaqueSurfaceColor
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bar-side-bounded clip so modal chrome retracts behind the bar on exit
|
|
||||||
// instead of sliding over bar widgets (mirrors the popout `_popoutClip`).
|
|
||||||
Item {
|
|
||||||
id: _modalClip
|
|
||||||
visible: win._elevationShadow && _modalBodyBlurAnchor._active
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
readonly property string _modalSide: win._modalState.barSide
|
|
||||||
readonly property real _inset: _modalBodyBlurAnchor._active && win.screen ? SettingsData.frameEdgeInsetForSide(win.screen, _modalSide) : 0
|
|
||||||
readonly property real _topBound: _modalSide === "top" ? _inset : 0
|
|
||||||
readonly property real _bottomBound: _modalSide === "bottom" ? (win.height - _inset) : win.height
|
|
||||||
readonly property real _leftBound: _modalSide === "left" ? _inset : 0
|
|
||||||
readonly property real _rightBound: _modalSide === "right" ? (win.width - _inset) : win.width
|
|
||||||
|
|
||||||
x: _leftBound
|
|
||||||
y: _topBound
|
|
||||||
width: Math.max(0, _rightBound - _leftBound)
|
|
||||||
height: Math.max(0, _bottomBound - _topBound)
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: _modalChrome
|
|
||||||
|
|
||||||
readonly property string _modalSide: win._modalState.barSide
|
|
||||||
readonly property bool _isHoriz: _modalSide === "top" || _modalSide === "bottom"
|
|
||||||
readonly property real _startCcr: win._effectiveModalStartCcr
|
|
||||||
readonly property real _endCcr: win._effectiveModalEndCcr
|
|
||||||
readonly property real _farExtent: win._effectiveModalFarExtent
|
|
||||||
readonly property real _bodyW: Theme.snap(_modalBodyBlurAnchor.width, win._dpr)
|
|
||||||
readonly property real _bodyH: Theme.snap(_modalBodyBlurAnchor.height, win._dpr)
|
|
||||||
readonly property var _geometry: SurfaceGeometry.chromeBounds(_modalBodyBlurAnchor, _modalSide, _startCcr, _endCcr, _farExtent, win._dpr)
|
|
||||||
|
|
||||||
x: Theme.snap(_geometry.x - _modalClip.x, win._dpr)
|
|
||||||
y: Theme.snap(_geometry.y - _modalClip.y, win._dpr)
|
|
||||||
width: _geometry.width
|
|
||||||
height: _geometry.height
|
|
||||||
|
|
||||||
ConnectedShape {
|
|
||||||
visible: _modalBodyBlurAnchor._active && _modalChrome._bodyW > 0 && _modalChrome._bodyH > 0
|
|
||||||
barSide: _modalChrome._modalSide
|
|
||||||
bodyWidth: _modalChrome._bodyW
|
|
||||||
bodyHeight: _modalChrome._bodyH
|
|
||||||
connectorRadius: win._effectiveModalCcr
|
|
||||||
startConnectorRadius: _modalChrome._startCcr
|
|
||||||
endConnectorRadius: _modalChrome._endCcr
|
|
||||||
farStartConnectorRadius: win._effectiveModalFarStartCcr
|
|
||||||
farEndConnectorRadius: win._effectiveModalFarEndCcr
|
|
||||||
surfaceRadius: win._surfaceRadius
|
|
||||||
fillColor: win._opaqueSurfaceColor
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Rectangle {
|
|||||||
height: baseCardHeight + contentItem.extraHeight
|
height: baseCardHeight + contentItem.extraHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
clip: false
|
clip: false
|
||||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !BlurService.enabled
|
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
|
|
||||||
ElevationShadow {
|
ElevationShadow {
|
||||||
id: shadowLayer
|
id: shadowLayer
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Rectangle {
|
|||||||
readonly property real targetHeight: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
readonly property real targetHeight: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
||||||
radius: connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
radius: connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||||
scale: (cardHoverHandler.hovered ? 1.004 : 1.0) * listLevelAdjacentScaleInfluence
|
scale: (cardHoverHandler.hovered ? 1.004 : 1.0) * listLevelAdjacentScaleInfluence
|
||||||
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !BlurService.enabled
|
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
readonly property var shadowElevation: Theme.elevationLevel1
|
readonly property var shadowElevation: Theme.elevationLevel1
|
||||||
readonly property real baseShadowBlurPx: (shadowElevation && shadowElevation.blurPx !== undefined) ? shadowElevation.blurPx : 4
|
readonly property real baseShadowBlurPx: (shadowElevation && shadowElevation.blurPx !== undefined) ? shadowElevation.blurPx : 4
|
||||||
readonly property real hoverShadowBlurBoost: cardHoverHandler.hovered ? Math.min(2, baseShadowBlurPx * 0.25) : 0
|
readonly property real hoverShadowBlurBoost: cardHoverHandler.hovered ? Math.min(2, baseShadowBlurPx * 0.25) : 0
|
||||||
|
|||||||
@@ -641,21 +641,15 @@ PanelWindow {
|
|||||||
shadowOffsetY: content.shadowOffsetY
|
shadowOffsetY: content.shadowOffsetY
|
||||||
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
||||||
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed && !win.connectedFrameMode
|
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed && !win.connectedFrameMode
|
||||||
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
|
||||||
|
|
||||||
sourceRect.anchors.fill: undefined
|
sourceX: content.shadowRenderPadding + content.cardInset
|
||||||
sourceRect.x: content.shadowRenderPadding + content.cardInset
|
sourceY: content.shadowRenderPadding + content.cardInset
|
||||||
sourceRect.y: content.shadowRenderPadding + content.cardInset
|
sourceWidth: Math.max(0, content.width - (content.cardInset * 2))
|
||||||
sourceRect.width: Math.max(0, content.width - (content.cardInset * 2))
|
sourceHeight: Math.max(0, content.height - (content.cardInset * 2))
|
||||||
sourceRect.height: Math.max(0, content.height - (content.cardInset * 2))
|
targetRadius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
||||||
sourceRect.radius: win.connectedFrameMode ? Theme.connectedSurfaceRadius : Theme.cornerRadius
|
targetColor: win.connectedFrameMode ? Theme.floatingSurface : Theme.readableSurface
|
||||||
sourceRect.color: win.connectedFrameMode ? Theme.floatingSurface : Theme.readableSurface
|
borderColor: win.notificationData && win.notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
||||||
sourceRect.antialiasing: true
|
borderWidth: win.notificationData && win.notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
||||||
sourceRect.layer.enabled: false
|
|
||||||
sourceRect.layer.textureSize: Qt.size(0, 0)
|
|
||||||
sourceRect.border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
|
||||||
sourceRect.border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep critical accent outside shadow rendering so connected mode still shows it.
|
// Keep critical accent outside shadow rendering so connected mode still shows it.
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
// (an inverted rounded rectangle) smooth-unioned with each active chrome
|
// (an inverted rounded rectangle) smooth-unioned with each active chrome
|
||||||
// (popout/modal, dock, notification). The smooth-min radius IS the connector
|
// (popout/modal, dock, notification). The smooth-min radius IS the connector
|
||||||
// fillet. Antialiasing is analytic via fwidth -> crisp at any scale, no FBO.
|
// fillet. Antialiasing is analytic via fwidth -> crisp at any scale, no FBO.
|
||||||
|
// The elevation shadow samples the same field at the light offset, so both
|
||||||
|
// elevation states render in this one pass.
|
||||||
|
|
||||||
layout(location = 0) in vec2 qt_TexCoord0;
|
layout(location = 0) in vec2 qt_TexCoord0;
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
@@ -16,19 +18,27 @@ layout(std140, binding = 0) uniform buf {
|
|||||||
float cutoutRadius;
|
float cutoutRadius;
|
||||||
vec4 cutout; // inner cutout edges in px: x=left y=top z=right w=bottom
|
vec4 cutout; // inner cutout edges in px: x=left y=top z=right w=bottom
|
||||||
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||||
// Up to four chrome slots. rect = x,y,w,h (px). corner = per-corner radii
|
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||||
// (topLeft, topRight, bottomRight, bottomLeft). param = connectorR, active, 0, 0
|
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||||
|
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||||
|
// Up to four chrome slots. rect = x,y,w,h (px). corner = per-corner radii,
|
||||||
|
// k = per-corner junction fillet radii (both topLeft, topRight, bottomRight,
|
||||||
|
// bottomLeft; a corner is sharp exactly where its k > 0). param = active, 0, 0, 0
|
||||||
vec4 chromeRect0;
|
vec4 chromeRect0;
|
||||||
vec4 chromeCorner0;
|
vec4 chromeCorner0;
|
||||||
|
vec4 chromeK0;
|
||||||
vec4 chromeParam0;
|
vec4 chromeParam0;
|
||||||
vec4 chromeRect1;
|
vec4 chromeRect1;
|
||||||
vec4 chromeCorner1;
|
vec4 chromeCorner1;
|
||||||
|
vec4 chromeK1;
|
||||||
vec4 chromeParam1;
|
vec4 chromeParam1;
|
||||||
vec4 chromeRect2;
|
vec4 chromeRect2;
|
||||||
vec4 chromeCorner2;
|
vec4 chromeCorner2;
|
||||||
|
vec4 chromeK2;
|
||||||
vec4 chromeParam2;
|
vec4 chromeParam2;
|
||||||
vec4 chromeRect3;
|
vec4 chromeRect3;
|
||||||
vec4 chromeCorner3;
|
vec4 chromeCorner3;
|
||||||
|
vec4 chromeK3;
|
||||||
vec4 chromeParam3;
|
vec4 chromeParam3;
|
||||||
} ubuf;
|
} ubuf;
|
||||||
|
|
||||||
@@ -64,9 +74,13 @@ float chromeDist(vec2 px, vec4 rect, vec4 corner) {
|
|||||||
return sdRoundBox4(px, c, rect.zw * 0.5, corner);
|
return sdRoundBox4(px, c, rect.zw * 0.5, corner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
// Per-corner junction fillet radius, selected by chrome-rect quadrant.
|
||||||
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
float chromeK(vec2 px, vec4 rect, vec4 ks) {
|
||||||
|
vec2 p = px - (rect.xy + rect.zw * 0.5);
|
||||||
|
return (p.x >= 0.0) ? (p.y >= 0.0 ? ks.z : ks.y) : (p.y >= 0.0 ? ks.w : ks.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sceneDist(vec2 px) {
|
||||||
// Frame ring: inside the screen rect AND outside the rounded cutout (hole).
|
// Frame ring: inside the screen rect AND outside the rounded cutout (hole).
|
||||||
vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5;
|
vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5;
|
||||||
float dOuter = sdBox(px, sc, sc);
|
float dOuter = sdBox(px, sc, sc);
|
||||||
@@ -75,18 +89,35 @@ void main() {
|
|||||||
float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius);
|
float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius);
|
||||||
float d = max(dOuter, -dCut);
|
float d = max(dOuter, -dCut);
|
||||||
|
|
||||||
// Smooth-union the active chrome surfaces; smin radius = connector fillet.
|
// Smooth-union the active chrome surfaces; smin radius = junction fillet.
|
||||||
if (ubuf.chromeParam0.y > 0.5)
|
if (ubuf.chromeParam0.x > 0.5)
|
||||||
d = smin(d, chromeDist(px, ubuf.chromeRect0, ubuf.chromeCorner0), ubuf.chromeParam0.x);
|
d = smin(d, chromeDist(px, ubuf.chromeRect0, ubuf.chromeCorner0), chromeK(px, ubuf.chromeRect0, ubuf.chromeK0));
|
||||||
if (ubuf.chromeParam1.y > 0.5)
|
if (ubuf.chromeParam1.x > 0.5)
|
||||||
d = smin(d, chromeDist(px, ubuf.chromeRect1, ubuf.chromeCorner1), ubuf.chromeParam1.x);
|
d = smin(d, chromeDist(px, ubuf.chromeRect1, ubuf.chromeCorner1), chromeK(px, ubuf.chromeRect1, ubuf.chromeK1));
|
||||||
if (ubuf.chromeParam2.y > 0.5)
|
if (ubuf.chromeParam2.x > 0.5)
|
||||||
d = smin(d, chromeDist(px, ubuf.chromeRect2, ubuf.chromeCorner2), ubuf.chromeParam2.x);
|
d = smin(d, chromeDist(px, ubuf.chromeRect2, ubuf.chromeCorner2), chromeK(px, ubuf.chromeRect2, ubuf.chromeK2));
|
||||||
if (ubuf.chromeParam3.y > 0.5)
|
if (ubuf.chromeParam3.x > 0.5)
|
||||||
d = smin(d, chromeDist(px, ubuf.chromeRect3, ubuf.chromeCorner3), ubuf.chromeParam3.x);
|
d = smin(d, chromeDist(px, ubuf.chromeRect3, ubuf.chromeCorner3), chromeK(px, ubuf.chromeRect3, ubuf.chromeK3));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||||
|
float d = sceneDist(px);
|
||||||
float fw = max(fwidth(d), 1e-4);
|
float fw = max(fwidth(d), 1e-4);
|
||||||
float cov = 1.0 - smoothstep(-fw, fw, d);
|
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||||
float a = ubuf.surfaceColor.a * cov * ubuf.qt_Opacity;
|
// Opaque silhouette over shadow, then the surface alpha applied to the
|
||||||
fragColor = vec4(ubuf.surfaceColor.rgb * a, a);
|
// whole result — matches the old flattened-FBO + group-opacity look.
|
||||||
|
vec4 col = vec4(ubuf.surfaceColor.rgb, 1.0) * cov;
|
||||||
|
if (ubuf.shadowColor.a > 0.0) {
|
||||||
|
float dk = sceneDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||||
|
float bk = max(ubuf.shadowParam.x, fw);
|
||||||
|
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||||
|
// Ambient wrap reuses the field already computed for the silhouette.
|
||||||
|
float ba = max(ubuf.ambientParam.x, fw);
|
||||||
|
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||||
|
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||||
|
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - col.a));
|
||||||
|
}
|
||||||
|
fragColor = col * (ubuf.surfaceColor.a * ubuf.qt_Opacity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
// Popout-local connected chrome as a signed-distance field: the body rounded
|
||||||
|
// rect smooth-unioned against the bar-edge half-plane, so the connector
|
||||||
|
// fillets form analytically — the SDF twin of the old ConnectedShape +
|
||||||
|
// ConnectedCorner + MultiEffect FBO. Key + ambient shadows sample the same
|
||||||
|
// field; shadow is masked outside the silhouette.
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 qt_TexCoord0;
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform buf {
|
||||||
|
mat4 qt_Matrix;
|
||||||
|
float qt_Opacity;
|
||||||
|
float widthPx;
|
||||||
|
float heightPx;
|
||||||
|
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||||
|
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||||
|
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||||
|
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||||
|
vec4 bodyRect; // body rounded rect in item px: x, y, w, h
|
||||||
|
vec4 cornerRadius; // topLeft, topRight, bottomRight, bottomLeft
|
||||||
|
vec4 edgeParam; // x = bar side (0 top, 1 bottom, 2 left, 3 right), y = fillet k
|
||||||
|
} ubuf;
|
||||||
|
|
||||||
|
// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft).
|
||||||
|
float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) {
|
||||||
|
p -= c;
|
||||||
|
float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x);
|
||||||
|
rr = min(rr, min(hs.x, hs.y));
|
||||||
|
vec2 q = abs(p) - hs + rr;
|
||||||
|
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Circular smooth-min: blends two SDFs with a fillet of radius k.
|
||||||
|
float smin(float a, float b, float k) {
|
||||||
|
if (k <= 0.0)
|
||||||
|
return min(a, b);
|
||||||
|
return max(k, min(a, b)) - length(max(vec2(k) - vec2(a, b), vec2(0.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float sceneDist(vec2 px) {
|
||||||
|
// Bar edge as a half-plane whose interior lies off-item, on the bar's
|
||||||
|
// side; only its fillet contribution is visible.
|
||||||
|
float side = ubuf.edgeParam.x;
|
||||||
|
float dEdge = side < 0.5 ? px.y
|
||||||
|
: side < 1.5 ? (ubuf.heightPx - px.y)
|
||||||
|
: side < 2.5 ? px.x
|
||||||
|
: (ubuf.widthPx - px.x);
|
||||||
|
vec2 hs = ubuf.bodyRect.zw * 0.5;
|
||||||
|
float dBody = sdRoundBox4(px, ubuf.bodyRect.xy + hs, hs, ubuf.cornerRadius);
|
||||||
|
return smin(dEdge, dBody, ubuf.edgeParam.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||||
|
float d = sceneDist(px);
|
||||||
|
float fw = max(fwidth(d), 1e-4);
|
||||||
|
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||||
|
vec4 col = vec4(ubuf.surfaceColor.rgb, 1.0) * cov;
|
||||||
|
if (ubuf.shadowColor.a > 0.0) {
|
||||||
|
float dk = sceneDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||||
|
float bk = max(ubuf.shadowParam.x, fw);
|
||||||
|
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||||
|
float ba = max(ubuf.ambientParam.x, fw);
|
||||||
|
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||||
|
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||||
|
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - col.a));
|
||||||
|
}
|
||||||
|
fragColor = col * (ubuf.surfaceColor.a * ubuf.qt_Opacity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
// Standalone elevation surface as a signed-distance field: one quad draws the
|
||||||
|
// rounded-rect fill, its border, and the M3 two-part shadow (directional key +
|
||||||
|
// non-directional ambient) analytically — no FBO, no blur passes. The shadow
|
||||||
|
// is masked to outside the silhouette, so translucent fills never get
|
||||||
|
// interior darkening.
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 qt_TexCoord0;
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform buf {
|
||||||
|
mat4 qt_Matrix;
|
||||||
|
float qt_Opacity;
|
||||||
|
float widthPx;
|
||||||
|
float heightPx;
|
||||||
|
float borderWidth;
|
||||||
|
vec4 rectPx; // rounded rect in item px: x, y, w, h
|
||||||
|
vec4 cornerRadius; // topLeft, topRight, bottomRight, bottomLeft
|
||||||
|
vec4 fillColor; // straight (non-premultiplied) rgba
|
||||||
|
vec4 borderColor; // straight rgba
|
||||||
|
vec4 shadowColor; // straight rgba; a = 0 disables both shadow terms
|
||||||
|
vec4 shadowParam; // key: x = blur px, y = spread px, z,w = offset px
|
||||||
|
vec4 ambientParam; // ambient: x = blur px, y = spread px, z = alpha
|
||||||
|
} ubuf;
|
||||||
|
|
||||||
|
// Per-corner rounded box. r = (topLeft, topRight, bottomRight, bottomLeft).
|
||||||
|
float sdRoundBox4(vec2 p, vec2 c, vec2 hs, vec4 r) {
|
||||||
|
p -= c;
|
||||||
|
float rr = (p.x >= 0.0) ? (p.y >= 0.0 ? r.z : r.y) : (p.y >= 0.0 ? r.w : r.x);
|
||||||
|
rr = min(rr, min(hs.x, hs.y));
|
||||||
|
vec2 q = abs(p) - hs + rr;
|
||||||
|
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - rr;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rectDist(vec2 px) {
|
||||||
|
vec2 hs = ubuf.rectPx.zw * 0.5;
|
||||||
|
return sdRoundBox4(px, ubuf.rectPx.xy + hs, hs, ubuf.cornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||||
|
float d = rectDist(px);
|
||||||
|
float fw = max(fwidth(d), 1e-4);
|
||||||
|
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||||
|
// Qt Rectangle semantics: border band on the rim, fill inset inside it.
|
||||||
|
float covInner = 1.0 - smoothstep(-fw, fw, d + ubuf.borderWidth);
|
||||||
|
vec4 col = vec4(ubuf.fillColor.rgb, 1.0) * (ubuf.fillColor.a * covInner)
|
||||||
|
+ vec4(ubuf.borderColor.rgb, 1.0) * (ubuf.borderColor.a * max(0.0, cov - covInner));
|
||||||
|
if (ubuf.shadowColor.a > 0.0) {
|
||||||
|
float dk = rectDist(px - ubuf.shadowParam.zw) - ubuf.shadowParam.y;
|
||||||
|
float bk = max(ubuf.shadowParam.x, fw);
|
||||||
|
float covK = 1.0 - smoothstep(-bk, bk, dk);
|
||||||
|
float ba = max(ubuf.ambientParam.x, fw);
|
||||||
|
float covA = 1.0 - smoothstep(-ba, ba, d - ubuf.ambientParam.y);
|
||||||
|
float sh = 1.0 - (1.0 - covK * ubuf.shadowColor.a) * (1.0 - covA * ubuf.ambientParam.z);
|
||||||
|
col += vec4(ubuf.shadowColor.rgb, 1.0) * (sh * (1.0 - cov));
|
||||||
|
}
|
||||||
|
fragColor = col * ubuf.qt_Opacity;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
// Frame perimeter ring as a signed-distance field: the window rectangle minus
|
||||||
|
// a rounded-rectangle cutout. Antialiasing is analytic via fwidth -> crisp at
|
||||||
|
// any scale, no FBO and no mask textures.
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 qt_TexCoord0;
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform buf {
|
||||||
|
mat4 qt_Matrix;
|
||||||
|
float qt_Opacity;
|
||||||
|
float widthPx;
|
||||||
|
float heightPx;
|
||||||
|
float cutoutRadius;
|
||||||
|
vec4 cutout; // inner cutout edges in px: x=left y=top z=right w=bottom
|
||||||
|
vec4 surfaceColor; // straight (non-premultiplied) rgba
|
||||||
|
} ubuf;
|
||||||
|
|
||||||
|
float sdBox(vec2 p, vec2 c, vec2 hs) {
|
||||||
|
vec2 q = abs(p - c) - hs;
|
||||||
|
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdRoundBox(vec2 p, vec2 c, vec2 hs, float r) {
|
||||||
|
r = min(r, min(hs.x, hs.y));
|
||||||
|
vec2 q = abs(p - c) - hs + r;
|
||||||
|
return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 px = qt_TexCoord0 * vec2(ubuf.widthPx, ubuf.heightPx);
|
||||||
|
vec2 sc = vec2(ubuf.widthPx, ubuf.heightPx) * 0.5;
|
||||||
|
float dOuter = sdBox(px, sc, sc);
|
||||||
|
vec2 cutC = vec2((ubuf.cutout.x + ubuf.cutout.z) * 0.5, (ubuf.cutout.y + ubuf.cutout.w) * 0.5);
|
||||||
|
vec2 cutH = vec2((ubuf.cutout.z - ubuf.cutout.x) * 0.5, (ubuf.cutout.w - ubuf.cutout.y) * 0.5);
|
||||||
|
float dCut = sdRoundBox(px, cutC, cutH, ubuf.cutoutRadius);
|
||||||
|
float d = max(dOuter, -dCut);
|
||||||
|
|
||||||
|
float fw = max(fwidth(d), 1e-4);
|
||||||
|
float cov = 1.0 - smoothstep(-fw, fw, d);
|
||||||
|
float a = ubuf.surfaceColor.a * cov * ubuf.qt_Opacity;
|
||||||
|
fragColor = vec4(ubuf.surfaceColor.rgb * a, a);
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -289,8 +289,6 @@ PanelWindow {
|
|||||||
borderColor: Theme.outlineMedium
|
borderColor: Theme.outlineMedium
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
layer.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
|
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import Quickshell
|
|||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import "../Common/ConnectorGeometry.js" as ConnectorGeometry
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -568,6 +567,20 @@ Item {
|
|||||||
return Math.abs(value - bound) <= Math.max(1, Theme.hairline(root.dpr) * 2);
|
return Math.abs(value - bound) <= Math.max(1, Theme.hairline(root.dpr) * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Snap a frame-perpendicular position flush to the frame bound when it
|
||||||
|
// lands within the connector radius: a gap smaller than the radius cannot
|
||||||
|
// form the close-gap arc and renders as a pinched wedge instead.
|
||||||
|
function _snapNearFrameBound(value, minBound, maxBound, minIsFrame, maxIsFrame) {
|
||||||
|
if (!root.usesConnectedSurfaceChrome || !root.closeFrameGapsActive)
|
||||||
|
return value;
|
||||||
|
const snapDist = Theme.connectedCornerRadius;
|
||||||
|
if (maxIsFrame && value < maxBound && maxBound - value < snapDist && maxBound - value <= value - minBound)
|
||||||
|
return maxBound;
|
||||||
|
if (minIsFrame && value > minBound && value - minBound < snapDist)
|
||||||
|
return minBound;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
function _closeGapClampedToFrameSide(side) {
|
function _closeGapClampedToFrameSide(side) {
|
||||||
if (!root.closeFrameGapsActive)
|
if (!root.closeFrameGapsActive)
|
||||||
return false;
|
return false;
|
||||||
@@ -714,9 +727,11 @@ Item {
|
|||||||
return Math.max(edgeGapLeft, Math.min(screenWidth - popupWidth - popupGap, anchorX - popupWidth));
|
return Math.max(edgeGapLeft, Math.min(screenWidth - popupWidth - popupGap, anchorX - popupWidth));
|
||||||
default:
|
default:
|
||||||
const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2);
|
const rawX = triggerX + (triggerWidth / 2) - (popupWidth / 2);
|
||||||
const minX = Math.max(edgeGapLeft, adjacentBarClearance(adjacentBarInfo.leftBar));
|
const clearLeft = adjacentBarClearance(adjacentBarInfo.leftBar);
|
||||||
const maxX = screenWidth - popupWidth - Math.max(edgeGapRight, adjacentBarClearance(adjacentBarInfo.rightBar));
|
const clearRight = adjacentBarClearance(adjacentBarInfo.rightBar);
|
||||||
return Math.max(minX, Math.min(maxX, rawX));
|
const minX = Math.max(edgeGapLeft, clearLeft);
|
||||||
|
const maxX = screenWidth - popupWidth - Math.max(edgeGapRight, clearRight);
|
||||||
|
return _snapNearFrameBound(Math.max(minX, Math.min(maxX, rawX)), minX, maxX, edgeGapLeft >= clearLeft, edgeGapRight >= clearRight);
|
||||||
}
|
}
|
||||||
})(), dpr)
|
})(), dpr)
|
||||||
|
|
||||||
@@ -735,9 +750,11 @@ Item {
|
|||||||
return Math.max(popupGap, Math.min(screenHeight - popupHeight - edgeGapBottom, anchorY));
|
return Math.max(popupGap, Math.min(screenHeight - popupHeight - edgeGapBottom, anchorY));
|
||||||
default:
|
default:
|
||||||
const rawY = triggerY - (popupHeight / 2);
|
const rawY = triggerY - (popupHeight / 2);
|
||||||
const minY = Math.max(edgeGapTop, adjacentBarClearance(adjacentBarInfo.topBar));
|
const clearTop = adjacentBarClearance(adjacentBarInfo.topBar);
|
||||||
const maxY = screenHeight - popupHeight - Math.max(edgeGapBottom, adjacentBarClearance(adjacentBarInfo.bottomBar));
|
const clearBottom = adjacentBarClearance(adjacentBarInfo.bottomBar);
|
||||||
return Math.max(minY, Math.min(maxY, rawY));
|
const minY = Math.max(edgeGapTop, clearTop);
|
||||||
|
const maxY = screenHeight - popupHeight - Math.max(edgeGapBottom, clearBottom);
|
||||||
|
return _snapNearFrameBound(Math.max(minY, Math.min(maxY, rawY)), minY, maxY, edgeGapTop >= clearTop, edgeGapBottom >= clearBottom);
|
||||||
}
|
}
|
||||||
})(), dpr)
|
})(), dpr)
|
||||||
|
|
||||||
@@ -1024,22 +1041,13 @@ Item {
|
|||||||
|
|
||||||
ElevationShadow {
|
ElevationShadow {
|
||||||
id: shadowSource
|
id: shadowSource
|
||||||
readonly property real connectorExtent: root.usesConnectedSurfaceChrome ? Theme.connectedCornerRadius : 0
|
visible: !root.usesConnectedSurfaceChrome
|
||||||
readonly property real extraLeft: root.usesConnectedSurfaceChrome && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
width: rollOutAdjuster.baseWidth
|
||||||
readonly property real extraRight: root.usesConnectedSurfaceChrome && (contentContainer.barTop || contentContainer.barBottom) ? connectorExtent : 0
|
height: rollOutAdjuster.baseHeight
|
||||||
readonly property real extraTop: root.usesConnectedSurfaceChrome && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
|
||||||
readonly property real extraBottom: root.usesConnectedSurfaceChrome && (contentContainer.barLeft || contentContainer.barRight) ? connectorExtent : 0
|
|
||||||
readonly property real bodyX: extraLeft
|
|
||||||
readonly property real bodyY: extraTop
|
|
||||||
readonly property real bodyWidth: rollOutAdjuster.baseWidth
|
|
||||||
readonly property real bodyHeight: rollOutAdjuster.baseHeight
|
|
||||||
|
|
||||||
width: rollOutAdjuster.baseWidth + extraLeft + extraRight
|
|
||||||
height: rollOutAdjuster.baseHeight + extraTop + extraBottom
|
|
||||||
opacity: contentWrapper.publishedOpacity
|
opacity: contentWrapper.publishedOpacity
|
||||||
scale: contentWrapper.scale
|
scale: contentWrapper.scale
|
||||||
x: contentWrapper.x - extraLeft
|
x: contentWrapper.x
|
||||||
y: contentWrapper.y - extraTop
|
y: contentWrapper.y
|
||||||
level: root.shadowLevel
|
level: root.shadowLevel
|
||||||
direction: root.effectiveShadowDirection
|
direction: root.effectiveShadowDirection
|
||||||
fallbackOffset: root.shadowFallbackOffset
|
fallbackOffset: root.shadowFallbackOffset
|
||||||
@@ -1051,49 +1059,53 @@ Item {
|
|||||||
targetColor: contentContainer.surfaceColor
|
targetColor: contentContainer.surfaceColor
|
||||||
borderColor: contentContainer.surfaceBorderColor
|
borderColor: contentContainer.surfaceBorderColor
|
||||||
borderWidth: contentContainer.surfaceBorderWidth
|
borderWidth: contentContainer.surfaceBorderWidth
|
||||||
useCustomSource: root.usesConnectedSurfaceChrome
|
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive) && !root.frameOwnsConnectedChrome
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive) && !root.frameOwnsConnectedChrome
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
// Local connected chrome (body + connector fillets joined to
|
||||||
|
// the bar edge) and its shadow as one SDF quad — no FBO.
|
||||||
|
Item {
|
||||||
|
id: localChrome
|
||||||
|
visible: root.usesLocalConnectedSurfaceChrome
|
||||||
|
|
||||||
|
readonly property real extraLeft: (contentContainer.barTop || contentContainer.barBottom) ? Theme.connectedCornerRadius : 0
|
||||||
|
readonly property real extraTop: (contentContainer.barLeft || contentContainer.barRight) ? Theme.connectedCornerRadius : 0
|
||||||
|
|
||||||
|
readonly property bool shadowsOn: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
||||||
|
readonly property real shadowBlurPx: root.shadowLevel && root.shadowLevel.blurPx !== undefined ? root.shadowLevel.blurPx : 0
|
||||||
|
readonly property real shadowSpreadPx: root.shadowLevel && root.shadowLevel.spreadPx !== undefined ? root.shadowLevel.spreadPx : 0
|
||||||
|
readonly property real shadowOffsetX: Theme.elevationOffsetXFor(root.shadowLevel, root.effectiveShadowDirection, root.shadowFallbackOffset)
|
||||||
|
readonly property real shadowOffsetY: Theme.elevationOffsetYFor(root.shadowLevel, root.effectiveShadowDirection, root.shadowFallbackOffset)
|
||||||
|
readonly property color shadowTint: Theme.elevationShadowColor(root.shadowLevel)
|
||||||
|
readonly property var ambient: Theme.elevationAmbient(root.shadowLevel)
|
||||||
|
readonly property real pad: shadowsOn ? Math.ceil(Math.max(shadowBlurPx + shadowSpreadPx + Math.max(Math.abs(shadowOffsetX), Math.abs(shadowOffsetY)), ambient.blurPx + ambient.spreadPx) + 2) : 0
|
||||||
|
|
||||||
|
width: rollOutAdjuster.baseWidth + extraLeft * 2
|
||||||
|
height: rollOutAdjuster.baseHeight + extraTop * 2
|
||||||
|
opacity: contentWrapper.publishedOpacity
|
||||||
|
scale: contentWrapper.scale
|
||||||
|
x: contentWrapper.x - extraLeft
|
||||||
|
y: contentWrapper.y - extraTop
|
||||||
|
|
||||||
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: root.usesLocalConnectedSurfaceChrome
|
// Shadow overflow pads every side except the bar
|
||||||
clip: false
|
// edge, where the silhouette must end flush.
|
||||||
|
anchors.topMargin: contentContainer.barTop ? 0 : -localChrome.pad
|
||||||
|
anchors.bottomMargin: contentContainer.barBottom ? 0 : -localChrome.pad
|
||||||
|
anchors.leftMargin: contentContainer.barLeft ? 0 : -localChrome.pad
|
||||||
|
anchors.rightMargin: contentContainer.barRight ? 0 : -localChrome.pad
|
||||||
|
fragmentShader: Qt.resolvedUrl("../Shaders/qsb/connected_chrome.frag.qsb")
|
||||||
|
|
||||||
Rectangle {
|
property real widthPx: width
|
||||||
x: shadowSource.bodyX
|
property real heightPx: height
|
||||||
y: shadowSource.bodyY
|
property vector4d surfaceColor: Qt.vector4d(contentContainer.surfaceColor.r, contentContainer.surfaceColor.g, contentContainer.surfaceColor.b, contentContainer.surfaceColor.a)
|
||||||
width: shadowSource.bodyWidth
|
property vector4d shadowColor: Qt.vector4d(localChrome.shadowTint.r, localChrome.shadowTint.g, localChrome.shadowTint.b, localChrome.shadowsOn ? localChrome.shadowTint.a : 0)
|
||||||
height: shadowSource.bodyHeight
|
property vector4d shadowParam: Qt.vector4d(Math.max(0, localChrome.shadowBlurPx), localChrome.shadowSpreadPx, localChrome.shadowOffsetX, localChrome.shadowOffsetY)
|
||||||
topLeftRadius: contentContainer.surfaceTopLeftRadius
|
property vector4d ambientParam: Qt.vector4d(localChrome.ambient.blurPx, localChrome.ambient.spreadPx, localChrome.shadowsOn ? localChrome.ambient.alpha : 0, 0)
|
||||||
topRightRadius: contentContainer.surfaceTopRightRadius
|
property vector4d bodyRect: Qt.vector4d((contentContainer.barLeft ? 0 : localChrome.pad) + localChrome.extraLeft, (contentContainer.barTop ? 0 : localChrome.pad) + localChrome.extraTop, rollOutAdjuster.baseWidth, rollOutAdjuster.baseHeight)
|
||||||
bottomLeftRadius: contentContainer.surfaceBottomLeftRadius
|
property vector4d cornerRadius: Qt.vector4d(contentContainer.surfaceTopLeftRadius, contentContainer.surfaceTopRightRadius, contentContainer.surfaceBottomRightRadius, contentContainer.surfaceBottomLeftRadius)
|
||||||
bottomRightRadius: contentContainer.surfaceBottomRightRadius
|
property vector4d edgeParam: Qt.vector4d(contentContainer.barTop ? 0 : (contentContainer.barBottom ? 1 : (contentContainer.barLeft ? 2 : 3)), Theme.connectedCornerRadius, 0, 0)
|
||||||
color: contentContainer.surfaceColor
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectedCorner {
|
|
||||||
visible: root.usesConnectedSurfaceChrome
|
|
||||||
barSide: contentContainer.connectedBarSide
|
|
||||||
placement: "left"
|
|
||||||
spacing: 0
|
|
||||||
connectorRadius: Theme.connectedCornerRadius
|
|
||||||
color: contentContainer.surfaceColor
|
|
||||||
dpr: root.dpr
|
|
||||||
x: Theme.snap(ConnectorGeometry.connectorX(contentContainer.connectedBarSide, shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing, Theme.connectedCornerRadius), root.dpr)
|
|
||||||
y: Theme.snap(ConnectorGeometry.connectorY(contentContainer.connectedBarSide, shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing, Theme.connectedCornerRadius), root.dpr)
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectedCorner {
|
|
||||||
visible: root.usesConnectedSurfaceChrome
|
|
||||||
barSide: contentContainer.connectedBarSide
|
|
||||||
placement: "right"
|
|
||||||
spacing: 0
|
|
||||||
connectorRadius: Theme.connectedCornerRadius
|
|
||||||
color: contentContainer.surfaceColor
|
|
||||||
dpr: root.dpr
|
|
||||||
x: Theme.snap(ConnectorGeometry.connectorX(contentContainer.connectedBarSide, shadowSource.bodyX, shadowSource.bodyWidth, placement, spacing, Theme.connectedCornerRadius), root.dpr)
|
|
||||||
y: Theme.snap(ConnectorGeometry.connectorY(contentContainer.connectedBarSide, shadowSource.bodyY, shadowSource.bodyHeight, placement, spacing, Theme.connectedCornerRadius), root.dpr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user