1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-14 09:42:10 -04:00

rendering: improve rendering of popouts and modals

This commit is contained in:
bbedward
2025-11-07 12:35:15 -05:00
parent 5d6c3e364d
commit 35ead280d5
4 changed files with 243 additions and 241 deletions

View File

@@ -139,12 +139,11 @@ PanelWindow {
} }
} }
Rectangle { Item {
id: contentContainer id: modalContainer
width: Theme.px(root.width, dpr) width: Theme.px(root.width, dpr)
height: Theme.px(root.height, dpr) height: Theme.px(root.height, dpr)
anchors.centerIn: undefined
x: { x: {
if (positioning === "center") { if (positioning === "center") {
return Theme.snap((root.screenWidth - width) / 2, dpr) return Theme.snap((root.screenWidth - width) / 2, dpr)
@@ -165,101 +164,93 @@ PanelWindow {
} }
return 0 return 0
} }
color: root.backgroundColor
radius: root.cornerRadius
border.color: root.borderColor
border.width: root.borderWidth
clip: false
layer.enabled: true
layer.smooth: true
layer.textureSize: Qt.size(width * Math.max(2, root.screen?.devicePixelRatio || 1), height * Math.max(2, root.screen?.devicePixelRatio || 1))
layer.samples: 4
opacity: root.shouldBeVisible ? 1 : 0
transform: [scaleTransform, motionTransform]
Scale { readonly property bool slide: root.animationType === "slide"
id: scaleTransform readonly property real offsetX: slide ? 15 : 0
readonly property real offsetY: slide ? -30 : root.animationOffset
origin.x: contentContainer.width / 2 property real animX: 0
origin.y: contentContainer.height / 2 property real animY: 0
xScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed property real scaleValue: root.animationScaleCollapsed
yScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
Behavior on xScale { onOffsetXChanged: animX = Theme.snap(root.shouldBeVisible ? 0 : offsetX, root.dpr)
NumberAnimation { onOffsetYChanged: animY = Theme.snap(root.shouldBeVisible ? 0 : offsetY, root.dpr)
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on yScale { Connections {
NumberAnimation { target: root
duration: root.animationDuration function onShouldBeVisibleChanged() {
easing.type: Easing.BezierSpline modalContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetX, root.dpr)
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve modalContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetY, root.dpr)
} modalContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed
} }
} }
Translate { Behavior on animX {
id: motionTransform
readonly property bool slide: root.animationType === "slide"
readonly property real hiddenX: slide ? 15 : 0
readonly property real hiddenY: slide ? -30 : root.animationOffset
x: Theme.snap(root.shouldBeVisible ? 0 : hiddenX, root.dpr)
y: Theme.snap(root.shouldBeVisible ? 0 : hiddenY, root.dpr)
Behavior on x {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on y {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
}
Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: animationDuration duration: root.animationDuration
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
} }
} }
FocusScope { Behavior on animY {
anchors.fill: parent NumberAnimation {
focus: root.shouldBeVisible duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on scaleValue {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Rectangle {
id: contentContainer
anchors.centerIn: parent
width: parent.width
height: parent.height
color: root.backgroundColor
radius: root.cornerRadius
border.color: root.borderColor
border.width: root.borderWidth
clip: false clip: false
layer.enabled: true
layer.smooth: false
layer.textureSize: Qt.size(width * root.dpr, height * root.dpr)
layer.textureMirroring: ShaderEffectSource.NoMirroring
opacity: root.shouldBeVisible ? 1 : 0
scale: modalContainer.scaleValue
x: Theme.snap(modalContainer.animX + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5, root.dpr)
y: Theme.snap(modalContainer.animY + (parent.height - height) * (1 - modalContainer.scaleValue) * 0.5, root.dpr)
Item { Behavior on opacity {
id: directContentWrapper NumberAnimation {
duration: animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
FocusScope {
anchors.fill: parent anchors.fill: parent
visible: root.directContent !== null focus: root.shouldBeVisible
focus: true
clip: false clip: false
Component.onCompleted: { Item {
if (root.directContent) { id: directContentWrapper
root.directContent.parent = directContentWrapper
root.directContent.anchors.fill = directContentWrapper
Qt.callLater(() => root.directContent.forceActiveFocus())
}
}
Connections { anchors.fill: parent
function onDirectContentChanged() { visible: root.directContent !== null
focus: true
clip: false
Component.onCompleted: {
if (root.directContent) { if (root.directContent) {
root.directContent.parent = directContentWrapper root.directContent.parent = directContentWrapper
root.directContent.anchors.fill = directContentWrapper root.directContent.anchors.fill = directContentWrapper
@@ -267,23 +258,33 @@ PanelWindow {
} }
} }
target: root Connections {
function onDirectContentChanged() {
if (root.directContent) {
root.directContent.parent = directContentWrapper
root.directContent.anchors.fill = directContentWrapper
Qt.callLater(() => root.directContent.forceActiveFocus())
}
}
target: root
}
} }
}
Loader { Loader {
id: contentLoader id: contentLoader
anchors.fill: parent anchors.fill: parent
active: root.directContent === null && (root.keepContentLoaded || root.shouldBeVisible || root.visible) active: root.directContent === null && (root.keepContentLoaded || root.shouldBeVisible || root.visible)
asynchronous: false asynchronous: false
focus: true focus: true
clip: false clip: false
visible: root.directContent === null visible: root.directContent === null
onLoaded: { onLoaded: {
if (item) { if (item) {
Qt.callLater(() => item.forceActiveFocus()) Qt.callLater(() => item.forceActiveFocus())
}
} }
} }
} }

View File

@@ -114,92 +114,90 @@ PanelWindow {
} }
} }
Loader { Item {
id: contentLoader id: contentContainer
x: alignedX x: alignedX
y: alignedY y: alignedY
width: alignedWidth width: alignedWidth
height: alignedHeight height: alignedHeight
active: root.visible
asynchronous: false
transformOrigin: Item.Center
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
layer.smooth: true
layer.textureSize: Qt.size(width * Math.max(2, root.screen?.devicePixelRatio || 1), height * Math.max(2, root.screen?.devicePixelRatio || 1))
layer.samples: 4
opacity: shouldBeVisible ? 1 : 0
visible: opacity > 0
transform: [scaleTransform, motionTransform]
Scale { readonly property bool barTop: SettingsData.dankBarPosition === SettingsData.Position.Top
id: scaleTransform readonly property bool barBottom: SettingsData.dankBarPosition === SettingsData.Position.Bottom
readonly property bool barLeft: SettingsData.dankBarPosition === SettingsData.Position.Left
readonly property bool barRight: SettingsData.dankBarPosition === SettingsData.Position.Right
readonly property real offsetX: barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0)
readonly property real offsetY: barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0)
origin.x: contentLoader.width / 2 property real animX: 0
origin.y: contentLoader.height / 2 property real animY: 0
xScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed property real scaleValue: root.animationScaleCollapsed
yScale: root.shouldBeVisible ? 1 : root.animationScaleCollapsed
Behavior on xScale { onOffsetXChanged: animX = Theme.snap(root.shouldBeVisible ? 0 : offsetX, root.dpr)
NumberAnimation { onOffsetYChanged: animY = Theme.snap(root.shouldBeVisible ? 0 : offsetY, root.dpr)
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on yScale { Connections {
NumberAnimation { target: root
duration: root.animationDuration function onShouldBeVisibleChanged() {
easing.type: Easing.BezierSpline contentContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetX, root.dpr)
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve contentContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : contentContainer.offsetY, root.dpr)
} contentContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed
} }
} }
Translate { Behavior on animX {
id: motionTransform
readonly property bool barTop: SettingsData.dankBarPosition === SettingsData.Position.Top
readonly property bool barBottom: SettingsData.dankBarPosition === SettingsData.Position.Bottom
readonly property bool barLeft: SettingsData.dankBarPosition === SettingsData.Position.Left
readonly property bool barRight: SettingsData.dankBarPosition === SettingsData.Position.Right
readonly property real hiddenX: barLeft ? root.animationOffset : (barRight ? -root.animationOffset : 0)
readonly property real hiddenY: barBottom ? -root.animationOffset : (barTop ? root.animationOffset : 0)
x: Theme.snap(root.shouldBeVisible ? 0 : hiddenX, root.dpr)
y: Theme.snap(root.shouldBeVisible ? 0 : hiddenY, root.dpr)
Behavior on x {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on y {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
}
Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: animationDuration duration: root.animationDuration
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
} }
} }
Behavior on animY {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Behavior on scaleValue {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
Loader {
id: contentLoader
anchors.centerIn: parent
width: parent.width
height: parent.height
active: root.visible
asynchronous: false
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
layer.smooth: false
layer.textureSize: Qt.size(width * root.dpr, height * root.dpr)
layer.textureMirroring: ShaderEffectSource.NoMirroring
opacity: shouldBeVisible ? 1 : 0
visible: opacity > 0
scale: contentContainer.scaleValue
x: Theme.snap(contentContainer.animX + (parent.width - width) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
y: Theme.snap(contentContainer.animY + (parent.height - height) * (1 - contentContainer.scaleValue) * 0.5, root.dpr)
Behavior on opacity {
NumberAnimation {
duration: animationDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: root.shouldBeVisible ? root.animationEnterCurve : root.animationExitCurve
}
}
}
} }
Item { Item {
x: alignedX parent: contentContainer
y: alignedY anchors.fill: parent
width: alignedWidth
height: alignedHeight
focus: true focus: true
Keys.onPressed: event => { Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) { if (event.key === Qt.Key_Escape) {

View File

@@ -67,27 +67,32 @@ PanelWindow {
} }
} }
StyledRect { Item {
id: contentRect id: slideContainer
layer.enabled: true
layer.smooth: true
layer.textureSize: Qt.size(width * Math.max(2, root.modelData?.devicePixelRatio || 1), height * Math.max(2, root.modelData?.devicePixelRatio || 1))
layer.samples: 4
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
width: expandable && expandedWidth ? expandedWidthValue : slideoutWidth width: expandable && expandedWidth ? expandedWidthValue : slideoutWidth
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b,
customTransparency >= 0 ? customTransparency : SettingsData.popupTransparency)
border.color: Theme.outlineMedium
border.width: 1
radius: Theme.cornerRadius
visible: isVisible || slideAnimation.running
transform: Translate { Behavior on width {
id: slideTransform NumberAnimation {
x: isVisible ? 0 : contentRect.width duration: 250
easing.type: Easing.OutCubic
}
}
StyledRect {
id: contentRect
readonly property real dpr: root.modelData?.devicePixelRatio || 1
layer.enabled: true
layer.smooth: false
layer.textureSize: Qt.size(width * dpr, height * dpr)
layer.textureMirroring: ShaderEffectSource.NoMirroring
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
x: isVisible ? 0 : parent.width
Behavior on x { Behavior on x {
NumberAnimation { NumberAnimation {
@@ -102,85 +107,84 @@ PanelWindow {
} }
} }
} }
} color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b,
customTransparency >= 0 ? customTransparency : SettingsData.popupTransparency)
border.color: Theme.outlineMedium
border.width: 1
radius: Theme.cornerRadius
visible: isVisible || slideAnimation.running
Behavior on width { Column {
NumberAnimation { id: headerColumn
duration: 250 anchors.top: parent.top
easing.type: Easing.OutCubic anchors.left: parent.left
} anchors.right: parent.right
} anchors.margins: Theme.spacingL
spacing: Theme.spacingM
Column { visible: root.title !== ""
id: headerColumn
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: Theme.spacingL
spacing: Theme.spacingM
visible: root.title !== ""
Row {
width: parent.width
height: 32
Column {
width: parent.width - buttonRow.width
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
StyledText {
text: root.title
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
}
}
Row { Row {
id: buttonRow width: parent.width
spacing: Theme.spacingXS height: 32
DankActionButton { Column {
id: expandButton width: parent.width - buttonRow.width
iconName: root.expandedWidth ? "unfold_less" : "unfold_more" spacing: Theme.spacingXS
iconSize: Theme.iconSize - 4 anchors.verticalCenter: parent.verticalCenter
iconColor: Theme.surfaceText
visible: root.expandable
onClicked: root.expandedWidth = !root.expandedWidth
transform: Rotation { StyledText {
angle: 90 text: root.title
origin.x: expandButton.width / 2 font.pixelSize: Theme.fontSizeLarge
origin.y: expandButton.height / 2 color: Theme.surfaceText
font.weight: Font.Medium
} }
} }
DankActionButton { Row {
id: closeButton id: buttonRow
iconName: "close" spacing: Theme.spacingXS
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText DankActionButton {
onClicked: root.hide() id: expandButton
iconName: root.expandedWidth ? "unfold_less" : "unfold_more"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
visible: root.expandable
onClicked: root.expandedWidth = !root.expandedWidth
transform: Rotation {
angle: 90
origin.x: expandButton.width / 2
origin.y: expandButton.height / 2
}
}
DankActionButton {
id: closeButton
iconName: "close"
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: root.hide()
}
} }
} }
} }
}
Item { Item {
id: contentContainer id: contentContainer
anchors.top: root.title !== "" ? headerColumn.bottom : parent.top anchors.top: root.title !== "" ? headerColumn.bottom : parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.topMargin: root.title !== "" ? 0 : Theme.spacingL anchors.topMargin: root.title !== "" ? 0 : Theme.spacingL
anchors.leftMargin: Theme.spacingL anchors.leftMargin: Theme.spacingL
anchors.rightMargin: Theme.spacingL anchors.rightMargin: Theme.spacingL
anchors.bottomMargin: Theme.spacingL anchors.bottomMargin: Theme.spacingL
Loader { Loader {
anchors.fill: parent anchors.fill: parent
sourceComponent: root.content sourceComponent: root.content
}
} }
} }
} }

View File

@@ -31,7 +31,6 @@ Item {
antialiasing: true antialiasing: true
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
layer.enabled: true layer.enabled: true
layer.samples: 0
ShapePath { ShapePath {
strokeColor: root.trackColor strokeColor: root.trackColor