mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-04 04:42:05 -04:00
feat: Implement M3 design elevation & shadow effects
- Added global toggles in the Themes tab - Light color & directional user ovverides - Independent shadow overrides per/bar - Refactored various components to sync the updated designs
This commit is contained in:
@@ -98,7 +98,7 @@ Item {
|
||||
sourceComponent: IconImage {
|
||||
anchors.fill: parent
|
||||
source: root.iconPath
|
||||
backer.sourceSize: Qt.size(root.iconSize, root.iconSize)
|
||||
backer.sourceSize: Qt.size(root.iconSize * 2, root.iconSize * 2)
|
||||
mipmap: true
|
||||
asynchronous: true
|
||||
visible: status === Image.Ready
|
||||
|
||||
@@ -81,6 +81,8 @@ Rectangle {
|
||||
mipmap: true
|
||||
cache: true
|
||||
visible: false
|
||||
sourceSize.width: Math.max(width * 2, 128)
|
||||
sourceSize.height: Math.max(height * 2, 128)
|
||||
source: !root.shouldProbe ? root.imageSource : ""
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import "../Common/fzf.js" as Fzf
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
@@ -254,6 +253,8 @@ Item {
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
id: contentSurface
|
||||
|
||||
LayoutMirroring.enabled: I18n.isRtl
|
||||
LayoutMirroring.childrenInherit: true
|
||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
|
||||
@@ -261,12 +262,17 @@ Item {
|
||||
border.width: 2
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowBlur: 0.4
|
||||
shadowColor: Theme.shadowStrong
|
||||
shadowVerticalOffset: 4
|
||||
ElevationShadow {
|
||||
id: shadowLayer
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
level: Theme.elevationLevel2
|
||||
fallbackOffset: 4
|
||||
targetRadius: contentSurface.radius
|
||||
targetColor: contentSurface.color
|
||||
borderColor: contentSurface.border.color
|
||||
borderWidth: contentSurface.border.width
|
||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
@@ -132,16 +131,20 @@ Rectangle {
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
id: contentSurface
|
||||
color: Theme.surface
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
shadowEnabled: true
|
||||
shadowColor: Theme.shadowStrong
|
||||
shadowBlur: 0.8
|
||||
shadowHorizontalOffset: 0
|
||||
shadowVerticalOffset: 4
|
||||
ElevationShadow {
|
||||
id: shadowLayer
|
||||
anchors.fill: parent
|
||||
z: -1
|
||||
level: Theme.elevationLevel2
|
||||
fallbackOffset: 4
|
||||
targetRadius: contentSurface.radius
|
||||
targetColor: contentSurface.color
|
||||
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||
shadowEnabled: Theme.elevationEnabled
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
@@ -257,11 +256,7 @@ PanelWindow {
|
||||
scale: shouldBeVisible ? 1 : 0.9
|
||||
|
||||
property bool childHovered: false
|
||||
property real shadowBlurPx: 10
|
||||
property real shadowSpreadPx: 0
|
||||
property real shadowBaseAlpha: 0.60
|
||||
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||
readonly property real effectiveShadowAlpha: shouldBeVisible ? Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha)) : 0
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
@@ -273,38 +268,20 @@ PanelWindow {
|
||||
z: -1
|
||||
}
|
||||
|
||||
Item {
|
||||
ElevationShadow {
|
||||
id: bgShadowLayer
|
||||
anchors.fill: parent
|
||||
visible: osdContainer.popupSurfaceAlpha >= 0.95
|
||||
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||
layer.smooth: false
|
||||
z: -1
|
||||
level: Theme.elevationLevel3
|
||||
fallbackOffset: 6
|
||||
targetRadius: Theme.cornerRadius
|
||||
targetColor: Theme.surfaceContainer
|
||||
borderColor: Theme.outlineMedium
|
||||
borderWidth: 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
|
||||
|
||||
readonly property int blurMax: 64
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
id: shadowFx
|
||||
autoPaddingEnabled: true
|
||||
shadowEnabled: true
|
||||
blurEnabled: false
|
||||
maskEnabled: false
|
||||
shadowBlur: Math.max(0, Math.min(1, osdContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
||||
shadowScale: 1 + (2 * osdContainer.shadowSpreadPx) / Math.max(1, Math.min(bgShadowLayer.width, bgShadowLayer.height))
|
||||
shadowColor: {
|
||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||
return Theme.withAlpha(baseColor, osdContainer.effectiveShadowAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainer
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
import qs.Common
|
||||
@@ -31,6 +30,7 @@ Item {
|
||||
property bool backgroundInteractive: true
|
||||
property bool contentHandlesKeys: false
|
||||
property bool fullHeightSurface: false
|
||||
property bool _primeContent: false
|
||||
property bool _resizeActive: false
|
||||
property real _surfaceMarginLeft: 0
|
||||
property real _surfaceW: 0
|
||||
@@ -77,6 +77,38 @@ Item {
|
||||
|
||||
property int effectiveBarPosition: 0
|
||||
property real effectiveBarBottomGap: 0
|
||||
readonly property string autoBarShadowDirection: {
|
||||
const section = triggerSection || "center";
|
||||
switch (effectiveBarPosition) {
|
||||
case SettingsData.Position.Top:
|
||||
if (section === "left")
|
||||
return "topLeft";
|
||||
if (section === "right")
|
||||
return "topRight";
|
||||
return "top";
|
||||
case SettingsData.Position.Bottom:
|
||||
if (section === "left")
|
||||
return "bottomLeft";
|
||||
if (section === "right")
|
||||
return "bottomRight";
|
||||
return "bottom";
|
||||
case SettingsData.Position.Left:
|
||||
if (section === "left")
|
||||
return "topLeft";
|
||||
if (section === "right")
|
||||
return "bottomLeft";
|
||||
return "left";
|
||||
case SettingsData.Position.Right:
|
||||
if (section === "left")
|
||||
return "topRight";
|
||||
if (section === "right")
|
||||
return "bottomRight";
|
||||
return "right";
|
||||
default:
|
||||
return "top";
|
||||
}
|
||||
}
|
||||
readonly property string effectiveShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
||||
|
||||
// Snapshot mask geometry to prevent background damage on bar updates
|
||||
property real _frozenMaskX: 0
|
||||
@@ -89,6 +121,14 @@ Item {
|
||||
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
|
||||
}
|
||||
|
||||
function primeContent() {
|
||||
_primeContent = true;
|
||||
}
|
||||
|
||||
function clearPrimedContent() {
|
||||
_primeContent = false;
|
||||
}
|
||||
|
||||
function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
|
||||
triggerX = x;
|
||||
triggerY = y;
|
||||
@@ -152,6 +192,7 @@ Item {
|
||||
|
||||
function close() {
|
||||
shouldBeVisible = false;
|
||||
_primeContent = false;
|
||||
PopoutManager.popoutChanged();
|
||||
closeTimer.restart();
|
||||
}
|
||||
@@ -197,7 +238,11 @@ Item {
|
||||
readonly property real screenHeight: screen ? screen.height : 0
|
||||
readonly property real dpr: screen ? screen.devicePixelRatio : 1
|
||||
|
||||
readonly property real shadowBuffer: 5
|
||||
readonly property var shadowLevel: Theme.elevationLevel3
|
||||
readonly property real shadowFallbackOffset: 6
|
||||
readonly property real shadowRenderPadding: (Theme.elevationEnabled && SettingsData.popoutElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, effectiveShadowDirection, shadowFallbackOffset, 8, 16) : 0
|
||||
readonly property real shadowMotionPadding: Math.max(0, animationOffset)
|
||||
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
||||
readonly property real alignedWidth: Theme.px(popupWidth, dpr)
|
||||
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||
|
||||
@@ -257,29 +302,30 @@ Item {
|
||||
}
|
||||
})(), dpr)
|
||||
|
||||
readonly property real triggeringBarLeftExclusion: (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0
|
||||
readonly property real triggeringBarTopExclusion: (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0
|
||||
readonly property real triggeringBarRightExclusion: (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0
|
||||
readonly property real triggeringBarBottomExclusion: (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0
|
||||
|
||||
readonly property real maskX: {
|
||||
const triggeringBarX = (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? barWidth : 0;
|
||||
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
|
||||
return Math.max(triggeringBarX, adjacentLeftBar);
|
||||
return Math.max(triggeringBarLeftExclusion, adjacentLeftBar);
|
||||
}
|
||||
|
||||
readonly property real maskY: {
|
||||
const triggeringBarY = (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? barHeight : 0;
|
||||
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
|
||||
return Math.max(triggeringBarY, adjacentTopBar);
|
||||
return Math.max(triggeringBarTopExclusion, adjacentTopBar);
|
||||
}
|
||||
|
||||
readonly property real maskWidth: {
|
||||
const triggeringBarRight = (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? barWidth : 0;
|
||||
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0;
|
||||
const rightExclusion = Math.max(triggeringBarRight, adjacentRightBar);
|
||||
const rightExclusion = Math.max(triggeringBarRightExclusion, adjacentRightBar);
|
||||
return Math.max(100, screenWidth - maskX - rightExclusion);
|
||||
}
|
||||
|
||||
readonly property real maskHeight: {
|
||||
const triggeringBarBottom = (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? barHeight : 0;
|
||||
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0;
|
||||
const bottomExclusion = Math.max(triggeringBarBottom, adjacentBottomBar);
|
||||
const bottomExclusion = Math.max(triggeringBarBottomExclusion, adjacentBottomBar);
|
||||
return Math.max(100, screenHeight - maskY - bottomExclusion);
|
||||
}
|
||||
|
||||
@@ -395,7 +441,7 @@ Item {
|
||||
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
||||
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
||||
|
||||
mask: (useBackgroundWindow && _fullHeight) ? contentInputMask : null
|
||||
mask: useBackgroundWindow ? contentInputMask : null
|
||||
|
||||
Region {
|
||||
id: contentInputMask
|
||||
@@ -405,10 +451,10 @@ Item {
|
||||
Item {
|
||||
id: contentMaskRect
|
||||
visible: false
|
||||
x: contentContainer.x - root.shadowBuffer
|
||||
y: contentContainer.y - root.shadowBuffer
|
||||
width: root.alignedWidth + root.shadowBuffer * 2
|
||||
height: root.alignedHeight + root.shadowBuffer * 2
|
||||
x: contentContainer.x
|
||||
y: contentContainer.y
|
||||
width: root.alignedWidth
|
||||
height: root.alignedHeight
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -480,42 +526,20 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
ElevationShadow {
|
||||
id: shadowSource
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
radius: Theme.cornerRadius
|
||||
color: "black"
|
||||
visible: false
|
||||
opacity: contentWrapper.opacity
|
||||
scale: contentWrapper.scale
|
||||
x: contentWrapper.x
|
||||
y: contentWrapper.y
|
||||
|
||||
property real shadowBlurPx: 10
|
||||
property real shadowSpreadPx: 0
|
||||
property real shadowBaseAlpha: 0.60
|
||||
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||
readonly property int blurMax: 64
|
||||
|
||||
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
||||
layer.smooth: false
|
||||
|
||||
layer.effect: MultiEffect {
|
||||
id: shadowFx
|
||||
autoPaddingEnabled: true
|
||||
shadowEnabled: true
|
||||
blurEnabled: false
|
||||
maskEnabled: false
|
||||
shadowBlur: Math.max(0, Math.min(1, shadowSource.shadowBlurPx / shadowSource.blurMax))
|
||||
shadowScale: 1 + (2 * shadowSource.shadowSpreadPx) / Math.max(1, Math.min(shadowSource.width, shadowSource.height))
|
||||
shadowColor: {
|
||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||
return Theme.withAlpha(baseColor, shadowSource.effectiveShadowAlpha);
|
||||
}
|
||||
}
|
||||
level: root.shadowLevel
|
||||
direction: root.effectiveShadowDirection
|
||||
fallbackOffset: root.shadowFallbackOffset
|
||||
targetRadius: Theme.cornerRadius
|
||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -546,13 +570,13 @@ Item {
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||
border.color: Theme.outlineMedium
|
||||
border.width: 1
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.fill: parent
|
||||
active: shouldBeVisible || contentWindow.visible
|
||||
active: root._primeContent || shouldBeVisible || contentWindow.visible
|
||||
asynchronous: false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user