mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-11 08:12:09 -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:
54
quickshell/Common/ElevationShadow.qml
Normal file
54
quickshell/Common/ElevationShadow.qml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var level: Theme.elevationLevel2
|
||||||
|
property string direction: Theme.elevationLightDirection
|
||||||
|
property real fallbackOffset: 4
|
||||||
|
|
||||||
|
property color targetColor: "white"
|
||||||
|
property real targetRadius: Theme.cornerRadius
|
||||||
|
property color borderColor: "transparent"
|
||||||
|
property real borderWidth: 0
|
||||||
|
|
||||||
|
property bool shadowEnabled: Theme.elevationEnabled
|
||||||
|
property real shadowBlurPx: level && level.blurPx !== undefined ? level.blurPx : 0
|
||||||
|
property real shadowSpreadPx: level && level.spreadPx !== undefined ? level.spreadPx : 0
|
||||||
|
property real shadowOffsetX: Theme.elevationOffsetXFor(level, direction, fallbackOffset)
|
||||||
|
property real shadowOffsetY: Theme.elevationOffsetYFor(level, direction, fallbackOffset)
|
||||||
|
property color shadowColor: Theme.elevationShadowColor(level)
|
||||||
|
property real shadowOpacity: 1
|
||||||
|
property real blurMax: Theme.elevationBlurMax
|
||||||
|
|
||||||
|
property alias sourceRect: sourceRect
|
||||||
|
|
||||||
|
layer.enabled: shadowEnabled
|
||||||
|
|
||||||
|
layer.effect: MultiEffect {
|
||||||
|
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
|
||||||
|
radius: root.targetRadius
|
||||||
|
color: root.targetColor
|
||||||
|
border.color: root.borderColor
|
||||||
|
border.width: root.borderWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import "settings/SettingsStore.js" as Store
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int settingsConfigVersion: 5
|
readonly property int settingsConfigVersion: 6
|
||||||
|
|
||||||
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true"
|
||||||
|
|
||||||
@@ -166,6 +166,24 @@ Singleton {
|
|||||||
property int modalCustomAnimationDuration: 150
|
property int modalCustomAnimationDuration: 150
|
||||||
property bool enableRippleEffects: true
|
property bool enableRippleEffects: true
|
||||||
onEnableRippleEffectsChanged: saveSettings()
|
onEnableRippleEffectsChanged: saveSettings()
|
||||||
|
property bool m3ElevationEnabled: true
|
||||||
|
onM3ElevationEnabledChanged: saveSettings()
|
||||||
|
property int m3ElevationIntensity: 12
|
||||||
|
onM3ElevationIntensityChanged: saveSettings()
|
||||||
|
property int m3ElevationOpacity: 30
|
||||||
|
onM3ElevationOpacityChanged: saveSettings()
|
||||||
|
property string m3ElevationColorMode: "default"
|
||||||
|
onM3ElevationColorModeChanged: saveSettings()
|
||||||
|
property string m3ElevationLightDirection: "top"
|
||||||
|
onM3ElevationLightDirectionChanged: saveSettings()
|
||||||
|
property string m3ElevationCustomColor: "#000000"
|
||||||
|
onM3ElevationCustomColorChanged: saveSettings()
|
||||||
|
property bool modalElevationEnabled: true
|
||||||
|
onModalElevationEnabledChanged: saveSettings()
|
||||||
|
property bool popoutElevationEnabled: true
|
||||||
|
onPopoutElevationEnabledChanged: saveSettings()
|
||||||
|
property bool barElevationEnabled: true
|
||||||
|
onBarElevationEnabledChanged: saveSettings()
|
||||||
property string wallpaperFillMode: "Fill"
|
property string wallpaperFillMode: "Fill"
|
||||||
property bool blurredWallpaperLayer: false
|
property bool blurredWallpaperLayer: false
|
||||||
property bool blurWallpaperOnOverview: false
|
property bool blurWallpaperOnOverview: false
|
||||||
@@ -609,7 +627,7 @@ Singleton {
|
|||||||
"scrollYBehavior": "workspace",
|
"scrollYBehavior": "workspace",
|
||||||
"shadowIntensity": 0,
|
"shadowIntensity": 0,
|
||||||
"shadowOpacity": 60,
|
"shadowOpacity": 60,
|
||||||
"shadowColorMode": "text",
|
"shadowColorMode": "default",
|
||||||
"shadowCustomColor": "#000000",
|
"shadowCustomColor": "#000000",
|
||||||
"clickThrough": false
|
"clickThrough": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -673,6 +673,232 @@ Singleton {
|
|||||||
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
property color shadowMedium: Qt.rgba(0, 0, 0, 0.08)
|
||||||
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
property color shadowStrong: Qt.rgba(0, 0, 0, 0.3)
|
||||||
|
|
||||||
|
readonly property bool elevationEnabled: typeof SettingsData !== "undefined" && (SettingsData.m3ElevationEnabled ?? true)
|
||||||
|
readonly property real elevationBlurMax: typeof SettingsData !== "undefined" && SettingsData.m3ElevationIntensity !== undefined ? Math.min(128, Math.max(32, SettingsData.m3ElevationIntensity * 2)) : 64
|
||||||
|
|
||||||
|
readonly property real _elevMult: typeof SettingsData !== "undefined" && SettingsData.m3ElevationIntensity !== undefined ? SettingsData.m3ElevationIntensity / 12 : 1
|
||||||
|
readonly property real _opMult: typeof SettingsData !== "undefined" && SettingsData.m3ElevationOpacity !== undefined ? SettingsData.m3ElevationOpacity / 60 : 1
|
||||||
|
function normalizeElevationDirection(direction) {
|
||||||
|
switch (direction) {
|
||||||
|
case "top":
|
||||||
|
case "topLeft":
|
||||||
|
case "topRight":
|
||||||
|
case "bottom":
|
||||||
|
case "bottomLeft":
|
||||||
|
case "bottomRight":
|
||||||
|
case "left":
|
||||||
|
case "right":
|
||||||
|
case "autoBar":
|
||||||
|
return direction;
|
||||||
|
default:
|
||||||
|
return "top";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property string elevationLightDirection: {
|
||||||
|
if (typeof SettingsData === "undefined" || !SettingsData.m3ElevationLightDirection)
|
||||||
|
return "top";
|
||||||
|
switch (SettingsData.m3ElevationLightDirection) {
|
||||||
|
case "autoBar":
|
||||||
|
case "top":
|
||||||
|
case "topLeft":
|
||||||
|
case "topRight":
|
||||||
|
case "bottom":
|
||||||
|
return SettingsData.m3ElevationLightDirection;
|
||||||
|
default:
|
||||||
|
return "top";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property real _elevDiagRatio: 0.55
|
||||||
|
readonly property string _globalElevationDirForTokens: {
|
||||||
|
const normalized = normalizeElevationDirection(elevationLightDirection);
|
||||||
|
return normalized === "autoBar" ? "top" : normalized;
|
||||||
|
}
|
||||||
|
readonly property real _elevDirX: {
|
||||||
|
switch (_globalElevationDirForTokens) {
|
||||||
|
case "topLeft":
|
||||||
|
case "bottomLeft":
|
||||||
|
case "left":
|
||||||
|
return 1;
|
||||||
|
case "topRight":
|
||||||
|
case "bottomRight":
|
||||||
|
case "right":
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property real _elevDirY: {
|
||||||
|
switch (_globalElevationDirForTokens) {
|
||||||
|
case "bottom":
|
||||||
|
case "bottomLeft":
|
||||||
|
case "bottomRight":
|
||||||
|
return -1;
|
||||||
|
case "left":
|
||||||
|
case "right":
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property real _elevDirXScale: (_globalElevationDirForTokens === "left" || _globalElevationDirForTokens === "right") ? 1 : _elevDiagRatio
|
||||||
|
|
||||||
|
readonly property var elevationLevel1: ({
|
||||||
|
blurPx: 4 * _elevMult,
|
||||||
|
offsetX: 1 * _elevMult * _elevDirXScale * _elevDirX,
|
||||||
|
offsetY: 1 * _elevMult * _elevDirY,
|
||||||
|
spreadPx: 0,
|
||||||
|
alpha: 0.2 * _opMult
|
||||||
|
})
|
||||||
|
readonly property var elevationLevel2: ({
|
||||||
|
blurPx: 8 * _elevMult,
|
||||||
|
offsetX: 4 * _elevMult * _elevDirXScale * _elevDirX,
|
||||||
|
offsetY: 4 * _elevMult * _elevDirY,
|
||||||
|
spreadPx: 0,
|
||||||
|
alpha: 0.25 * _opMult
|
||||||
|
})
|
||||||
|
readonly property var elevationLevel3: ({
|
||||||
|
blurPx: 12 * _elevMult,
|
||||||
|
offsetX: 6 * _elevMult * _elevDirXScale * _elevDirX,
|
||||||
|
offsetY: 6 * _elevMult * _elevDirY,
|
||||||
|
spreadPx: 0,
|
||||||
|
alpha: 0.3 * _opMult
|
||||||
|
})
|
||||||
|
readonly property var elevationLevel4: ({
|
||||||
|
blurPx: 16 * _elevMult,
|
||||||
|
offsetX: 8 * _elevMult * _elevDirXScale * _elevDirX,
|
||||||
|
offsetY: 8 * _elevMult * _elevDirY,
|
||||||
|
spreadPx: 0,
|
||||||
|
alpha: 0.3 * _opMult
|
||||||
|
})
|
||||||
|
readonly property var elevationLevel5: ({
|
||||||
|
blurPx: 20 * _elevMult,
|
||||||
|
offsetX: 10 * _elevMult * _elevDirXScale * _elevDirX,
|
||||||
|
offsetY: 10 * _elevMult * _elevDirY,
|
||||||
|
spreadPx: 0,
|
||||||
|
alpha: 0.3 * _opMult
|
||||||
|
})
|
||||||
|
|
||||||
|
function elevationOffsetMagnitude(level, fallback, direction) {
|
||||||
|
if (!level) {
|
||||||
|
return fallback !== undefined ? Math.abs(fallback) : 0;
|
||||||
|
}
|
||||||
|
const yMag = Math.abs(level.offsetY !== undefined ? level.offsetY : 0);
|
||||||
|
if (yMag > 0)
|
||||||
|
return yMag;
|
||||||
|
const xMag = Math.abs(level.offsetX !== undefined ? level.offsetX : 0);
|
||||||
|
if (xMag > 0) {
|
||||||
|
if (direction === "left" || direction === "right")
|
||||||
|
return xMag;
|
||||||
|
return xMag / _elevDiagRatio;
|
||||||
|
}
|
||||||
|
return fallback !== undefined ? Math.abs(fallback) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationOffsetXFor(level, direction, fallback) {
|
||||||
|
const dir = normalizeElevationDirection(direction || elevationLightDirection);
|
||||||
|
const mag = elevationOffsetMagnitude(level, fallback, dir);
|
||||||
|
switch (dir) {
|
||||||
|
case "topLeft":
|
||||||
|
case "bottomLeft":
|
||||||
|
return mag * _elevDiagRatio;
|
||||||
|
case "topRight":
|
||||||
|
case "bottomRight":
|
||||||
|
return -mag * _elevDiagRatio;
|
||||||
|
case "left":
|
||||||
|
return mag;
|
||||||
|
case "right":
|
||||||
|
return -mag;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationOffsetYFor(level, direction, fallback) {
|
||||||
|
const dir = normalizeElevationDirection(direction || elevationLightDirection);
|
||||||
|
const mag = elevationOffsetMagnitude(level, fallback, dir);
|
||||||
|
switch (dir) {
|
||||||
|
case "bottom":
|
||||||
|
case "bottomLeft":
|
||||||
|
case "bottomRight":
|
||||||
|
return -mag;
|
||||||
|
case "left":
|
||||||
|
case "right":
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return mag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationOffsetX(level, fallback) {
|
||||||
|
return elevationOffsetXFor(level, elevationLightDirection, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationOffsetY(level, fallback) {
|
||||||
|
return elevationOffsetYFor(level, elevationLightDirection, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationRenderPadding(level, direction, fallbackOffset, extraPadding, minPadding) {
|
||||||
|
const dir = direction !== undefined ? direction : elevationLightDirection;
|
||||||
|
const blur = (level && level.blurPx !== undefined) ? Math.max(0, level.blurPx) : 0;
|
||||||
|
const spread = (level && level.spreadPx !== undefined) ? Math.max(0, level.spreadPx) : 0;
|
||||||
|
const fallback = fallbackOffset !== undefined ? fallbackOffset : 0;
|
||||||
|
const extra = extraPadding !== undefined ? extraPadding : 8;
|
||||||
|
const minPad = minPadding !== undefined ? minPadding : 16;
|
||||||
|
const offsetX = Math.abs(elevationOffsetXFor(level, dir, fallback));
|
||||||
|
const offsetY = Math.abs(elevationOffsetYFor(level, dir, fallback));
|
||||||
|
return Math.max(minPad, blur + spread + Math.max(offsetX, offsetY) + extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
function elevationShadowColor(level) {
|
||||||
|
const alpha = (level && level.alpha !== undefined) ? level.alpha : 0.3;
|
||||||
|
let r = 0;
|
||||||
|
let g = 0;
|
||||||
|
let b = 0;
|
||||||
|
|
||||||
|
if (typeof SettingsData !== "undefined") {
|
||||||
|
const mode = SettingsData.m3ElevationColorMode || "default";
|
||||||
|
if (mode === "default") {
|
||||||
|
r = 0;
|
||||||
|
g = 0;
|
||||||
|
b = 0;
|
||||||
|
} else if (mode === "text") {
|
||||||
|
r = surfaceText.r;
|
||||||
|
g = surfaceText.g;
|
||||||
|
b = surfaceText.b;
|
||||||
|
} else if (mode === "primary") {
|
||||||
|
r = primary.r;
|
||||||
|
g = primary.g;
|
||||||
|
b = primary.b;
|
||||||
|
} else if (mode === "surfaceVariant") {
|
||||||
|
r = surfaceVariant.r;
|
||||||
|
g = surfaceVariant.g;
|
||||||
|
b = surfaceVariant.b;
|
||||||
|
} else if (mode === "custom" && SettingsData.m3ElevationCustomColor) {
|
||||||
|
const c = Qt.color(SettingsData.m3ElevationCustomColor);
|
||||||
|
r = c.r;
|
||||||
|
g = c.g;
|
||||||
|
b = c.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Qt.rgba(r, g, b, alpha);
|
||||||
|
}
|
||||||
|
function elevationTintOpacity(level) {
|
||||||
|
if (!level)
|
||||||
|
return 0;
|
||||||
|
if (level === elevationLevel1)
|
||||||
|
return 0.05;
|
||||||
|
if (level === elevationLevel2)
|
||||||
|
return 0.08;
|
||||||
|
if (level === elevationLevel3)
|
||||||
|
return 0.11;
|
||||||
|
if (level === elevationLevel4)
|
||||||
|
return 0.12;
|
||||||
|
if (level === elevationLevel5)
|
||||||
|
return 0.14;
|
||||||
|
return 0.08;
|
||||||
|
}
|
||||||
|
|
||||||
readonly property var animationDurations: [
|
readonly property var animationDurations: [
|
||||||
{
|
{
|
||||||
"shorter": 0,
|
"shorter": 0,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ var SPEC = {
|
|||||||
widgetColorMode: { def: "default" },
|
widgetColorMode: { def: "default" },
|
||||||
controlCenterTileColorMode: { def: "primary" },
|
controlCenterTileColorMode: { def: "primary" },
|
||||||
buttonColorMode: { def: "primary" },
|
buttonColorMode: { def: "primary" },
|
||||||
cornerRadius: { def: 12, onChange: "updateCompositorLayout" },
|
cornerRadius: { def: 16, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
niriLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" },
|
niriLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" },
|
||||||
@@ -47,6 +47,15 @@ var SPEC = {
|
|||||||
modalAnimationSpeed: { def: 1 },
|
modalAnimationSpeed: { def: 1 },
|
||||||
modalCustomAnimationDuration: { def: 150 },
|
modalCustomAnimationDuration: { def: 150 },
|
||||||
enableRippleEffects: { def: true },
|
enableRippleEffects: { def: true },
|
||||||
|
m3ElevationEnabled: { def: true },
|
||||||
|
m3ElevationIntensity: { def: 12 },
|
||||||
|
m3ElevationOpacity: { def: 30 },
|
||||||
|
m3ElevationColorMode: { def: "default" },
|
||||||
|
m3ElevationLightDirection: { def: "top" },
|
||||||
|
m3ElevationCustomColor: { def: "#000000" },
|
||||||
|
modalElevationEnabled: { def: true },
|
||||||
|
popoutElevationEnabled: { def: true },
|
||||||
|
barElevationEnabled: { def: true },
|
||||||
wallpaperFillMode: { def: "Fill" },
|
wallpaperFillMode: { def: "Fill" },
|
||||||
blurredWallpaperLayer: { def: false },
|
blurredWallpaperLayer: { def: false },
|
||||||
blurWallpaperOnOverview: { def: false },
|
blurWallpaperOnOverview: { def: false },
|
||||||
@@ -432,7 +441,7 @@ var SPEC = {
|
|||||||
scrollYBehavior: "workspace",
|
scrollYBehavior: "workspace",
|
||||||
shadowIntensity: 0,
|
shadowIntensity: 0,
|
||||||
shadowOpacity: 60,
|
shadowOpacity: 60,
|
||||||
shadowColorMode: "text",
|
shadowColorMode: "default",
|
||||||
shadowCustomColor: "#000000",
|
shadowCustomColor: "#000000",
|
||||||
clickThrough: false
|
clickThrough: false
|
||||||
}], onChange: "updateBarConfigs"
|
}], onChange: "updateBarConfigs"
|
||||||
|
|||||||
@@ -229,6 +229,25 @@ function migrateToVersion(obj, targetVersion) {
|
|||||||
settings.configVersion = 5;
|
settings.configVersion = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentVersion < 6) {
|
||||||
|
console.info("Migrating settings from version", currentVersion, "to version 6");
|
||||||
|
|
||||||
|
if (settings.barElevationEnabled === undefined) {
|
||||||
|
var legacyBars = Array.isArray(settings.barConfigs) ? settings.barConfigs : [];
|
||||||
|
var hadLegacyBarShadowEnabled = false;
|
||||||
|
for (var j = 0; j < legacyBars.length; j++) {
|
||||||
|
var legacyIntensity = Number(legacyBars[j] && legacyBars[j].shadowIntensity);
|
||||||
|
if (!isNaN(legacyIntensity) && legacyIntensity > 0) {
|
||||||
|
hadLegacyBarShadowEnabled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.barElevationEnabled = hadLegacyBarShadowEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.configVersion = 6;
|
||||||
|
}
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ Item {
|
|||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||||
property color backgroundColor: Theme.surfaceContainer
|
property color backgroundColor: Theme.surfaceContainer
|
||||||
property color borderColor: Theme.outlineMedium
|
property color borderColor: Theme.outlineMedium
|
||||||
property real borderWidth: 1
|
property real borderWidth: 0
|
||||||
property real cornerRadius: Theme.cornerRadius
|
property real cornerRadius: Theme.cornerRadius
|
||||||
property bool enableShadow: false
|
property bool enableShadow: true
|
||||||
property alias modalFocusScope: focusScope
|
property alias modalFocusScope: focusScope
|
||||||
property bool shouldBeVisible: false
|
property bool shouldBeVisible: false
|
||||||
property bool shouldHaveFocus: shouldBeVisible
|
property bool shouldHaveFocus: shouldBeVisible
|
||||||
@@ -142,7 +142,11 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real shadowBuffer: 5
|
readonly property var shadowLevel: Theme.elevationLevel3
|
||||||
|
readonly property real shadowFallbackOffset: 6
|
||||||
|
readonly property real shadowRenderPadding: (root.enableShadow && Theme.elevationEnabled && SettingsData.modalElevationEnabled) ? Theme.elevationRenderPadding(shadowLevel, Theme.elevationLightDirection, shadowFallbackOffset, 8, 16) : 0
|
||||||
|
readonly property real shadowMotionPadding: animationType === "slide" ? 30 : Math.max(0, animationOffset)
|
||||||
|
readonly property real shadowBuffer: Theme.snap(shadowRenderPadding + shadowMotionPadding, dpr)
|
||||||
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
|
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
|
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
|
||||||
|
|
||||||
@@ -377,12 +381,16 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
ElevationShadow {
|
||||||
|
id: modalShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: root.backgroundColor
|
level: root.shadowLevel
|
||||||
border.color: root.borderColor
|
fallbackOffset: root.shadowFallbackOffset
|
||||||
border.width: root.borderWidth
|
targetRadius: root.cornerRadius
|
||||||
radius: root.cornerRadius
|
targetColor: root.backgroundColor
|
||||||
|
borderColor: root.borderColor
|
||||||
|
borderWidth: root.borderWidth
|
||||||
|
shadowEnabled: root.enableShadow && Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
FocusScope {
|
FocusScope {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -75,7 +76,7 @@ Item {
|
|||||||
return Theme.primary;
|
return Theme.primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 1
|
readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0
|
||||||
|
|
||||||
signal dialogClosed
|
signal dialogClosed
|
||||||
|
|
||||||
@@ -390,12 +391,16 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
ElevationShadow {
|
||||||
|
id: launcherShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: root.backgroundColor
|
level: Theme.elevationLevel3
|
||||||
border.color: root.borderColor
|
fallbackOffset: 6
|
||||||
border.width: root.borderWidth
|
targetColor: root.backgroundColor
|
||||||
radius: root.cornerRadius
|
borderColor: root.borderColor
|
||||||
|
borderWidth: root.borderWidth
|
||||||
|
targetRadius: root.cornerRadius
|
||||||
|
shadowEnabled: Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
layerNamespace: "dms:control-center"
|
layerNamespace: "dms:control-center"
|
||||||
fullHeightSurface: true
|
fullHeightSurface: false
|
||||||
|
|
||||||
property string expandedSection: ""
|
property string expandedSection: ""
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import QtQuick.Shapes
|
import QtQuick.Shapes
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -53,15 +52,43 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real shadowIntensity: barConfig?.shadowIntensity ?? 0
|
// M3 elevation shadow — Level 2 baseline (navigation bar), with per-bar override support
|
||||||
readonly property bool shadowEnabled: shadowIntensity > 0
|
readonly property bool hasPerBarOverride: (barConfig?.shadowIntensity ?? 0) > 0
|
||||||
readonly property int blurMax: 64
|
readonly property var elevLevel: Theme.elevationLevel2
|
||||||
readonly property real shadowBlurPx: shadowIntensity * 0.2
|
readonly property bool shadowEnabled: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || hasPerBarOverride
|
||||||
readonly property real shadowBlur: Math.max(0, Math.min(1, shadowBlurPx / blurMax))
|
readonly property string autoBarShadowDirection: isTop ? "top" : (isBottom ? "bottom" : (isLeft ? "left" : (isRight ? "right" : "top")))
|
||||||
readonly property real shadowOpacity: (barConfig?.shadowOpacity ?? 60) / 100
|
readonly property string globalShadowDirection: Theme.elevationLightDirection === "autoBar" ? autoBarShadowDirection : Theme.elevationLightDirection
|
||||||
readonly property string shadowColorMode: barConfig?.shadowColorMode ?? "text"
|
readonly property string perBarShadowDirectionMode: barConfig?.shadowDirectionMode ?? "inherit"
|
||||||
readonly property color shadowBaseColor: {
|
readonly property string perBarManualShadowDirection: {
|
||||||
switch (shadowColorMode) {
|
switch (barConfig?.shadowDirection) {
|
||||||
|
case "top":
|
||||||
|
case "topLeft":
|
||||||
|
case "topRight":
|
||||||
|
case "bottom":
|
||||||
|
return barConfig.shadowDirection;
|
||||||
|
default:
|
||||||
|
return "top";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readonly property string effectiveShadowDirection: {
|
||||||
|
if (!hasPerBarOverride)
|
||||||
|
return globalShadowDirection;
|
||||||
|
switch (perBarShadowDirectionMode) {
|
||||||
|
case "autoBar":
|
||||||
|
return autoBarShadowDirection;
|
||||||
|
case "manual":
|
||||||
|
return perBarManualShadowDirection === "autoBar" ? autoBarShadowDirection : perBarManualShadowDirection;
|
||||||
|
default:
|
||||||
|
return globalShadowDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-bar override values (when barConfig.shadowIntensity > 0)
|
||||||
|
readonly property real overrideBlurPx: (barConfig?.shadowIntensity ?? 0) * 0.2
|
||||||
|
readonly property real overrideOpacity: (barConfig?.shadowOpacity ?? 60) / 100
|
||||||
|
readonly property string overrideColorMode: barConfig?.shadowColorMode ?? "default"
|
||||||
|
readonly property color overrideBaseColor: {
|
||||||
|
switch (overrideColorMode) {
|
||||||
case "surface":
|
case "surface":
|
||||||
return Theme.surface;
|
return Theme.surface;
|
||||||
case "primary":
|
case "primary":
|
||||||
@@ -71,10 +98,16 @@ Item {
|
|||||||
case "custom":
|
case "custom":
|
||||||
return barConfig?.shadowCustomColor ?? "#000000";
|
return barConfig?.shadowCustomColor ?? "#000000";
|
||||||
default:
|
default:
|
||||||
return Theme.surfaceText;
|
return "#000000";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readonly property color shadowColor: Theme.withAlpha(shadowBaseColor, shadowOpacity * barWindow._backgroundAlpha)
|
|
||||||
|
// Resolved values — per-bar override wins if set, otherwise use global M3 elevation
|
||||||
|
readonly property real shadowBlurPx: hasPerBarOverride ? overrideBlurPx : (elevLevel.blurPx ?? 8)
|
||||||
|
readonly property color shadowColor: hasPerBarOverride ? Theme.withAlpha(overrideBaseColor, overrideOpacity) : Theme.elevationShadowColor(elevLevel)
|
||||||
|
readonly property real shadowOffsetMagnitude: hasPerBarOverride ? (overrideBlurPx * 0.5) : Theme.elevationOffsetMagnitude(elevLevel, 4, effectiveShadowDirection)
|
||||||
|
readonly property real shadowOffsetX: Theme.elevationOffsetXFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)
|
||||||
|
readonly property real shadowOffsetY: Theme.elevationOffsetYFor(hasPerBarOverride ? null : elevLevel, effectiveShadowDirection, shadowOffsetMagnitude)
|
||||||
|
|
||||||
readonly property string mainPath: generatePathForPosition(width, height)
|
readonly property string mainPath: generatePathForPosition(width, height)
|
||||||
readonly property string borderFullPath: generateBorderFullPath(width, height)
|
readonly property string borderFullPath: generateBorderFullPath(width, height)
|
||||||
@@ -118,42 +151,28 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
ElevationShadow {
|
||||||
id: shadowLoader
|
id: barShadow
|
||||||
anchors.fill: parent
|
visible: root.shadowEnabled && root.width > 0 && root.height > 0
|
||||||
active: root.shadowEnabled && mainPathCorrectShape
|
|
||||||
asynchronous: false
|
|
||||||
sourceComponent: Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
layer.enabled: true
|
// Size to the bar's rectangular body, excluding gothic wing extensions
|
||||||
layer.smooth: true
|
x: root.isRight ? root.wing : 0
|
||||||
layer.samples: 8
|
y: root.isBottom ? root.wing : 0
|
||||||
layer.textureSize: Qt.size(Math.round(width * barWindow._dpr * 2), Math.round(height * barWindow._dpr * 2))
|
width: axis.isVertical ? (parent.width - root.wing) : parent.width
|
||||||
layer.effect: MultiEffect {
|
height: axis.isVertical ? parent.height : (parent.height - root.wing)
|
||||||
shadowEnabled: true
|
|
||||||
shadowBlur: root.shadowBlur
|
|
||||||
shadowColor: root.shadowColor
|
|
||||||
shadowVerticalOffset: root.isTop ? root.shadowBlurPx * 0.5 : (root.isBottom ? -root.shadowBlurPx * 0.5 : 0)
|
|
||||||
shadowHorizontalOffset: root.isLeft ? root.shadowBlurPx * 0.5 : (root.isRight ? -root.shadowBlurPx * 0.5 : 0)
|
|
||||||
autoPaddingEnabled: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Shape {
|
shadowEnabled: root.shadowEnabled
|
||||||
anchors.fill: parent
|
level: root.hasPerBarOverride ? null : root.elevLevel
|
||||||
preferredRendererType: Shape.CurveRenderer
|
direction: root.effectiveShadowDirection
|
||||||
|
fallbackOffset: 4
|
||||||
|
targetRadius: root.rt
|
||||||
|
targetColor: barWindow._bgColor
|
||||||
|
|
||||||
ShapePath {
|
shadowBlurPx: root.shadowBlurPx
|
||||||
fillColor: barWindow._bgColor
|
shadowOffsetX: root.shadowOffsetX
|
||||||
strokeColor: "transparent"
|
shadowOffsetY: root.shadowOffsetY
|
||||||
strokeWidth: 0
|
shadowColor: root.shadowColor
|
||||||
|
blurMax: Theme.elevationBlurMax
|
||||||
PathSvg {
|
|
||||||
path: root.mainPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
|
|||||||
@@ -140,6 +140,20 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
readonly property real _dpr: CompositorService.getScreenScale(barWindow.screen)
|
||||||
|
|
||||||
|
// Shadow buffer: extra window space for shadow to render beyond bar bounds
|
||||||
|
readonly property bool _shadowActive: (Theme.elevationEnabled && (typeof SettingsData !== "undefined" ? (SettingsData.barElevationEnabled ?? true) : false)) || (barConfig?.shadowIntensity ?? 0) > 0
|
||||||
|
readonly property real _shadowBuffer: {
|
||||||
|
if (!_shadowActive)
|
||||||
|
return 0;
|
||||||
|
const hasOverride = (barConfig?.shadowIntensity ?? 0) > 0;
|
||||||
|
if (hasOverride) {
|
||||||
|
const blur = (barConfig.shadowIntensity ?? 0) * 0.2;
|
||||||
|
const offset = blur * 0.5;
|
||||||
|
return Theme.snap(Math.max(16, blur + offset + 8), _dpr);
|
||||||
|
}
|
||||||
|
return Theme.snap(Theme.elevationRenderPadding(Theme.elevationLevel2, "top", 4, 8, 16), _dpr);
|
||||||
|
}
|
||||||
|
|
||||||
property string screenName: modelData.name
|
property string screenName: modelData.name
|
||||||
|
|
||||||
property bool hasMaximizedToplevel: false
|
property bool hasMaximizedToplevel: false
|
||||||
@@ -354,8 +368,8 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
screen: modelData
|
screen: modelData
|
||||||
implicitHeight: !isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) : 0
|
implicitHeight: !isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) + _shadowBuffer : 0
|
||||||
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) : 0
|
implicitWidth: isVertical ? Theme.px(effectiveBarThickness + effectiveSpacing + ((barConfig?.gothCornersEnabled ?? false) && !hasMaximizedToplevel ? _wingR : 0), _dpr) + _shadowBuffer : 0
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
property var nativeInhibitor: null
|
property var nativeInhibitor: null
|
||||||
|
|||||||
@@ -178,8 +178,9 @@ BasePill {
|
|||||||
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = parent.mapToItem(null, 0, 0);
|
const globalPos = parent.mapToItem(null, 0, 0);
|
||||||
const currentScreen = root.parentScreen || Screen;
|
const currentScreen = root.parentScreen || Screen;
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, parent.width);
|
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
||||||
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen);
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, parent.width, root.barSpacing, barPosition, root.barConfig);
|
||||||
|
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen, barPosition, root.barThickness, root.barSpacing, root.barConfig);
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
@@ -334,8 +335,9 @@ BasePill {
|
|||||||
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
if (root.popoutTarget && root.popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = mapToItem(null, 0, 0);
|
const globalPos = mapToItem(null, 0, 0);
|
||||||
const currentScreen = root.parentScreen || Screen;
|
const currentScreen = root.parentScreen || Screen;
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, root.width);
|
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
||||||
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen);
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, root.barThickness, root.width, root.barSpacing, barPosition, root.barConfig);
|
||||||
|
root.popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, root.section, currentScreen, barPosition, root.barThickness, root.barSpacing, root.barConfig);
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -940,9 +940,10 @@ BasePill {
|
|||||||
}
|
}
|
||||||
})(), overflowMenu.dpr)
|
})(), overflowMenu.dpr)
|
||||||
|
|
||||||
property real shadowBlurPx: 10
|
readonly property var elev: Theme.elevationLevel2
|
||||||
property real shadowSpreadPx: 0
|
property real shadowBlurPx: elev && elev.blurPx !== undefined ? elev.blurPx : 8
|
||||||
property real shadowBaseAlpha: 0.60
|
property real shadowSpreadPx: elev && elev.spreadPx !== undefined ? elev.spreadPx : 0
|
||||||
|
property real shadowBaseAlpha: elev && elev.alpha !== undefined ? elev.alpha : 0.25
|
||||||
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
|
|
||||||
@@ -963,37 +964,26 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
ElevationShadow {
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
layer.enabled: true
|
level: menuContainer.elev
|
||||||
|
fallbackOffset: 4
|
||||||
|
shadowBlurPx: menuContainer.shadowBlurPx
|
||||||
|
shadowSpreadPx: menuContainer.shadowSpreadPx
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
|
targetRadius: Theme.cornerRadius
|
||||||
|
sourceRect.antialiasing: true
|
||||||
|
sourceRect.smooth: true
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
layer.smooth: true
|
layer.smooth: true
|
||||||
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
|
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
layer.samples: 4
|
layer.samples: 4
|
||||||
|
|
||||||
readonly property int blurMax: 64
|
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
|
||||||
autoPaddingEnabled: true
|
|
||||||
shadowEnabled: true
|
|
||||||
blurEnabled: false
|
|
||||||
maskEnabled: false
|
|
||||||
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / bgShadowLayer.blurMax))
|
|
||||||
shadowScale: 1 + (2 * menuContainer.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, menuContainer.effectiveShadowAlpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
antialiasing: true
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
@@ -1412,9 +1402,10 @@ BasePill {
|
|||||||
}
|
}
|
||||||
})(), menuWindow.dpr)
|
})(), menuWindow.dpr)
|
||||||
|
|
||||||
property real shadowBlurPx: 10
|
readonly property var elev: Theme.elevationLevel2
|
||||||
property real shadowSpreadPx: 0
|
property real shadowBlurPx: elev && elev.blurPx !== undefined ? elev.blurPx : 8
|
||||||
property real shadowBaseAlpha: 0.60
|
property real shadowSpreadPx: elev && elev.spreadPx !== undefined ? elev.spreadPx : 0
|
||||||
|
property real shadowBaseAlpha: elev && elev.alpha !== undefined ? elev.alpha : 0.25
|
||||||
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
||||||
|
|
||||||
@@ -1435,35 +1426,24 @@ BasePill {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
ElevationShadow {
|
||||||
id: menuBgShadowLayer
|
id: menuBgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
layer.enabled: true
|
level: menuContainer.elev
|
||||||
|
fallbackOffset: 4
|
||||||
|
shadowBlurPx: menuContainer.shadowBlurPx
|
||||||
|
shadowSpreadPx: menuContainer.shadowSpreadPx
|
||||||
|
shadowColor: {
|
||||||
|
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
||||||
|
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
||||||
|
}
|
||||||
|
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
|
targetRadius: Theme.cornerRadius
|
||||||
|
sourceRect.antialiasing: true
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
layer.smooth: true
|
layer.smooth: true
|
||||||
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
|
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
readonly property int blurMax: 64
|
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
|
||||||
autoPaddingEnabled: true
|
|
||||||
shadowEnabled: true
|
|
||||||
blurEnabled: false
|
|
||||||
maskEnabled: false
|
|
||||||
shadowBlur: Math.max(0, Math.min(1, menuContainer.shadowBlurPx / menuBgShadowLayer.blurMax))
|
|
||||||
shadowScale: 1 + (2 * menuContainer.shadowSpreadPx) / Math.max(1, Math.min(menuBgShadowLayer.width, menuBgShadowLayer.height))
|
|
||||||
shadowColor: {
|
|
||||||
const baseColor = Theme.isLightMode ? Qt.rgba(0, 0, 0, 1) : Theme.surfaceContainerHighest;
|
|
||||||
return Theme.withAlpha(baseColor, menuContainer.effectiveShadowAlpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
antialiasing: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QsMenuAnchor {
|
QsMenuAnchor {
|
||||||
|
|||||||
@@ -177,8 +177,9 @@ BasePill {
|
|||||||
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
||||||
const globalPos = root.visualContent.mapToItem(null, 0, 0);
|
const globalPos = root.visualContent.mapToItem(null, 0, 0);
|
||||||
const currentScreen = parentScreen || Screen;
|
const currentScreen = parentScreen || Screen;
|
||||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, root.visualWidth);
|
const barPosition = root.axis?.edge === "left" ? 2 : (root.axis?.edge === "right" ? 3 : (root.axis?.edge === "top" ? 0 : 1));
|
||||||
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen);
|
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, root.visualWidth, root.barSpacing, barPosition, root.barConfig);
|
||||||
|
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen, barPosition, barThickness, root.barSpacing, root.barConfig);
|
||||||
}
|
}
|
||||||
root.clicked();
|
root.clicked();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,14 +89,18 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
id: volumeShadowLayer
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowHorizontalOffset: 0
|
z: -1
|
||||||
shadowVerticalOffset: 8
|
level: Theme.elevationLevel2
|
||||||
shadowBlur: 1.0
|
fallbackOffset: 4
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
targetRadius: volumePanel.radius
|
||||||
shadowOpacity: 0.7
|
targetColor: volumePanel.color
|
||||||
|
borderColor: volumePanel.border.color
|
||||||
|
borderWidth: volumePanel.border.width
|
||||||
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -223,14 +227,18 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
id: audioDevicesShadowLayer
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowHorizontalOffset: 0
|
z: -1
|
||||||
shadowVerticalOffset: 8
|
level: Theme.elevationLevel2
|
||||||
shadowBlur: 1.0
|
fallbackOffset: 4
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
targetRadius: audioDevicesPanel.radius
|
||||||
shadowOpacity: 0.7
|
targetColor: audioDevicesPanel.color
|
||||||
|
borderColor: audioDevicesPanel.border.color
|
||||||
|
borderWidth: audioDevicesPanel.border.width
|
||||||
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -373,14 +381,18 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
id: playersShadowLayer
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowHorizontalOffset: 0
|
z: -1
|
||||||
shadowVerticalOffset: 8
|
level: Theme.elevationLevel2
|
||||||
shadowBlur: 1.0
|
fallbackOffset: 4
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.4)
|
targetRadius: playersPanel.radius
|
||||||
shadowOpacity: 0.7
|
targetColor: playersPanel.color
|
||||||
|
borderColor: playersPanel.border.color
|
||||||
|
borderWidth: playersPanel.border.width
|
||||||
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -529,14 +529,15 @@ Item {
|
|||||||
onClicked: activePlayer && activePlayer.togglePlaying()
|
onClicked: activePlayer && activePlayer.togglePlaying()
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
anchors.fill: parent
|
||||||
shadowEnabled: true
|
z: -1
|
||||||
shadowHorizontalOffset: 0
|
level: Theme.elevationLevel1
|
||||||
shadowVerticalOffset: 0
|
fallbackOffset: 1
|
||||||
shadowBlur: 1.0
|
targetRadius: parent.radius
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.3)
|
targetColor: parent.color
|
||||||
shadowOpacity: 0.3
|
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,14 +241,15 @@ Item {
|
|||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
layer.enabled: true
|
layer.enabled: Theme.elevationEnabled
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: true
|
shadowEnabled: Theme.elevationEnabled
|
||||||
shadowHorizontalOffset: 0
|
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel1)
|
||||||
shadowVerticalOffset: 4
|
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel1, 1)
|
||||||
shadowBlur: 0.8
|
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined ? Theme.elevationLevel1.blurPx : 4) / Theme.elevationBlurMax)) : 0
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
blurMax: Theme.elevationBlurMax
|
||||||
shadowOpacity: 0.2
|
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1)
|
||||||
|
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,14 +813,14 @@ Item {
|
|||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
|
||||||
|
|
||||||
layer.enabled: true
|
layer.enabled: Theme.elevationEnabled
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: true
|
shadowEnabled: Theme.elevationEnabled
|
||||||
shadowHorizontalOffset: 0
|
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
|
||||||
shadowVerticalOffset: 4
|
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
|
||||||
shadowBlur: 0.8
|
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
blurMax: Theme.elevationBlurMax
|
||||||
shadowOpacity: 0.2
|
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -834,14 +835,14 @@ Item {
|
|||||||
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
|
||||||
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
|
||||||
|
|
||||||
layer.enabled: true
|
layer.enabled: Theme.elevationEnabled
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: true
|
shadowEnabled: Theme.elevationEnabled
|
||||||
shadowHorizontalOffset: 0
|
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
|
||||||
shadowVerticalOffset: 4
|
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
|
||||||
shadowBlur: 0.8
|
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
blurMax: Theme.elevationBlurMax
|
||||||
shadowOpacity: 0.2
|
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -30,7 +31,21 @@ Rectangle {
|
|||||||
width: parent ? parent.width : 400
|
width: parent ? parent.width : 400
|
||||||
height: baseCardHeight + contentItem.extraHeight
|
height: baseCardHeight + contentItem.extraHeight
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
clip: true
|
clip: false
|
||||||
|
readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
|
|
||||||
|
ElevationShadow {
|
||||||
|
id: shadowLayer
|
||||||
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
level: Theme.elevationLevel1
|
||||||
|
fallbackOffset: 1
|
||||||
|
targetRadius: root.radius
|
||||||
|
targetColor: root.color
|
||||||
|
borderColor: root.border.color
|
||||||
|
borderWidth: root.border.width
|
||||||
|
shadowEnabled: root.shadowsAllowed
|
||||||
|
}
|
||||||
|
|
||||||
color: {
|
color: {
|
||||||
if (isSelected && keyboardNavigationActive)
|
if (isSelected && keyboardNavigationActive)
|
||||||
@@ -49,7 +64,7 @@ Rectangle {
|
|||||||
return 1.5;
|
return 1.5;
|
||||||
if (historyItem.urgency === 2)
|
if (historyItem.urgency === 2)
|
||||||
return 2;
|
return 2;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
|
|||||||
@@ -232,6 +232,11 @@ Item {
|
|||||||
height: parent.height - filterChips.height - Theme.spacingS
|
height: parent.height - filterChips.height - Theme.spacingS
|
||||||
clip: true
|
clip: true
|
||||||
spacing: Theme.spacingS
|
spacing: Theme.spacingS
|
||||||
|
readonly property real horizontalShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
||||||
|
readonly property real verticalShadowGutter: Theme.snap(Math.max(Theme.spacingS, 8), 1)
|
||||||
|
readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
||||||
|
topMargin: verticalShadowGutter
|
||||||
|
bottomMargin: verticalShadowGutter
|
||||||
|
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
id: historyModel
|
id: historyModel
|
||||||
@@ -263,13 +268,14 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: historyCard.height
|
height: historyCard.height + historyListView.delegateShadowGutter
|
||||||
clip: true
|
clip: false
|
||||||
|
|
||||||
HistoryNotificationCard {
|
HistoryNotificationCard {
|
||||||
id: historyCard
|
id: historyCard
|
||||||
width: parent.width
|
width: Math.max(0, parent.width - (historyListView.horizontalShadowGutter * 2))
|
||||||
x: delegateRoot.swipeOffset
|
y: historyListView.delegateShadowGutter / 2
|
||||||
|
x: historyListView.horizontalShadowGutter + delegateRoot.swipeOffset
|
||||||
historyItem: modelData
|
historyItem: modelData
|
||||||
isSelected: root.keyboardActive && root.selectedIndex === index
|
isSelected: root.keyboardActive && root.selectedIndex === index
|
||||||
keyboardNavigationActive: root.keyboardActive
|
keyboardNavigationActive: root.keyboardActive
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ DankListView {
|
|||||||
property real swipingCardOffset: 0
|
property real swipingCardOffset: 0
|
||||||
property real __pendingStableHeight: 0
|
property real __pendingStableHeight: 0
|
||||||
property real __heightUpdateThreshold: 20
|
property real __heightUpdateThreshold: 20
|
||||||
|
readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0
|
||||||
|
readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1)
|
||||||
|
readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1)
|
||||||
|
readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1)
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
@@ -56,21 +60,26 @@ DankListView {
|
|||||||
let delta = 0;
|
let delta = 0;
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const item = itemAtIndex(i);
|
const item = itemAtIndex(i);
|
||||||
if (item && item.children[0] && item.children[0].isAnimating)
|
if (item && item.children[0] && item.children[0].isAnimating) {
|
||||||
delta += item.children[0].targetHeight - item.height;
|
const targetDelegateHeight = item.children[0].targetHeight + listView.delegateShadowGutter;
|
||||||
|
delta += targetDelegateHeight - item.height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const targetHeight = contentHeight + delta;
|
const targetHeight = contentHeight + delta;
|
||||||
// During expansion, always update immediately without threshold check
|
// During expansion, always update immediately without threshold check
|
||||||
stableContentHeight = targetHeight;
|
stableContentHeight = targetHeight;
|
||||||
} else {
|
} else {
|
||||||
__pendingStableHeight = contentHeight;
|
__pendingStableHeight = contentHeight;
|
||||||
heightUpdateDebounce.restart();
|
heightUpdateDebounce.stop();
|
||||||
|
stableContentHeight = __pendingStableHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
model: NotificationService.groupedNotifications
|
model: NotificationService.groupedNotifications
|
||||||
spacing: Theme.spacingL
|
spacing: Theme.spacingL
|
||||||
|
topMargin: shadowVerticalGutter
|
||||||
|
bottomMargin: shadowVerticalGutter
|
||||||
|
|
||||||
onIsUserScrollingChanged: {
|
onIsUserScrollingChanged: {
|
||||||
if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
|
if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) {
|
||||||
@@ -134,8 +143,7 @@ DankListView {
|
|||||||
readonly property real dismissThreshold: width * 0.35
|
readonly property real dismissThreshold: width * 0.35
|
||||||
property bool __delegateInitialized: false
|
property bool __delegateInitialized: false
|
||||||
|
|
||||||
readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 &&
|
readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 && (index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1)
|
||||||
(index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1)
|
|
||||||
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0
|
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0
|
||||||
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
|
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0
|
||||||
readonly property real swipeFadeStartOffset: width * 0.75
|
readonly property real swipeFadeStartOffset: width * 0.75
|
||||||
@@ -149,13 +157,14 @@ DankListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
width: ListView.view.width
|
width: ListView.view.width
|
||||||
height: notificationCard.height
|
height: notificationCard.height + listView.delegateShadowGutter
|
||||||
clip: notificationCard.isAnimating
|
clip: false
|
||||||
|
|
||||||
NotificationCard {
|
NotificationCard {
|
||||||
id: notificationCard
|
id: notificationCard
|
||||||
width: parent.width
|
width: Math.max(0, parent.width - (listView.shadowHorizontalGutter * 2))
|
||||||
x: delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence
|
y: listView.delegateShadowGutter / 2
|
||||||
|
x: listView.shadowHorizontalGutter + delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence
|
||||||
listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence
|
listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence
|
||||||
listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe
|
listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe
|
||||||
notificationGroup: modelData
|
notificationGroup: modelData
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -38,7 +39,14 @@ Rectangle {
|
|||||||
height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight)
|
||||||
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: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
scale: (cardHoverHandler.hovered ? 1.01 : 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"
|
||||||
|
readonly property var shadowElevation: Theme.elevationLevel1
|
||||||
|
readonly property real baseShadowBlurPx: (shadowElevation && shadowElevation.blurPx !== undefined) ? shadowElevation.blurPx : 4
|
||||||
|
readonly property real hoverShadowBlurBoost: cardHoverHandler.hovered ? Math.min(2, baseShadowBlurPx * 0.25) : 0
|
||||||
|
property real shadowBlurPx: shadowsAllowed ? (baseShadowBlurPx + hoverShadowBlurBoost) : 0
|
||||||
|
property real shadowOffsetXPx: shadowsAllowed ? Theme.elevationOffsetX(shadowElevation) : 0
|
||||||
|
property real shadowOffsetYPx: shadowsAllowed ? (Theme.elevationOffsetY(shadowElevation, 1) + (cardHoverHandler.hovered ? 0.35 : 0)) : 0
|
||||||
property bool __initialized: false
|
property bool __initialized: false
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -56,6 +64,27 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on shadowBlurPx {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on shadowOffsetXPx {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on shadowOffsetYPx {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Behavior on border.color {
|
Behavior on border.color {
|
||||||
enabled: root.__initialized
|
enabled: root.__initialized
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
@@ -95,14 +124,31 @@ Rectangle {
|
|||||||
if (notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical) {
|
if (notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
clip: true
|
clip: false
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: cardHoverHandler
|
id: cardHoverHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ElevationShadow {
|
||||||
|
id: shadowLayer
|
||||||
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
level: root.shadowElevation
|
||||||
|
targetRadius: root.radius
|
||||||
|
targetColor: root.color
|
||||||
|
borderColor: root.border.color
|
||||||
|
borderWidth: root.border.width
|
||||||
|
shadowBlurPx: root.shadowBlurPx
|
||||||
|
shadowSpreadPx: 0
|
||||||
|
shadowOffsetX: root.shadowOffsetXPx
|
||||||
|
shadowOffsetY: root.shadowOffsetYPx
|
||||||
|
shadowColor: root.shadowElevation ? Theme.elevationShadowColor(root.shadowElevation) : "transparent"
|
||||||
|
shadowEnabled: root.shadowsAllowed
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
@@ -304,8 +350,13 @@ Rectangle {
|
|||||||
|
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
if (!parent.hoveredLink && (parent.hasMoreText || descriptionExpanded)) {
|
||||||
|
root.userInitiatedExpansion = true;
|
||||||
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
const messageId = (notificationGroup && notificationGroup.latestNotification && notificationGroup.latestNotification.notification && notificationGroup.latestNotification.notification.id) ? (notificationGroup.latestNotification.notification.id + "_desc") : "";
|
||||||
NotificationService.toggleMessageExpansion(messageId);
|
NotificationService.toggleMessageExpansion(messageId);
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (root && !root.isAnimating)
|
||||||
|
root.userInitiatedExpansion = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,9 +470,7 @@ Rectangle {
|
|||||||
id: delegateRect
|
id: delegateRect
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
readonly property bool isAdjacentToSwipe: root.swipingNotificationIndex !== -1 &&
|
readonly property bool isAdjacentToSwipe: root.swipingNotificationIndex !== -1 && (expandedDelegateWrapper.index === root.swipingNotificationIndex - 1 || expandedDelegateWrapper.index === root.swipingNotificationIndex + 1)
|
||||||
(expandedDelegateWrapper.index === root.swipingNotificationIndex - 1 ||
|
|
||||||
expandedDelegateWrapper.index === root.swipingNotificationIndex + 1)
|
|
||||||
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? root.swipingNotificationOffset * 0.10 : 0
|
readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? root.swipingNotificationOffset * 0.10 : 0
|
||||||
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(root.swipingNotificationOffset) / width * 0.02 : 1.0
|
readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(root.swipingNotificationOffset) / width * 0.02 : 1.0
|
||||||
|
|
||||||
@@ -605,7 +654,12 @@ Rectangle {
|
|||||||
|
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) {
|
if (!parent.hoveredLink && (bodyText.hasMoreText || messageExpanded)) {
|
||||||
|
root.userInitiatedExpansion = true;
|
||||||
NotificationService.toggleMessageExpansion(modelData?.notification?.id || "");
|
NotificationService.toggleMessageExpansion(modelData?.notification?.id || "");
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (root && !root.isAnimating)
|
||||||
|
root.userInitiatedExpansion = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,22 @@ DankPopout {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
layerNamespace: "dms:notification-center-popout"
|
layerNamespace: "dms:notification-center-popout"
|
||||||
fullHeightSurface: true
|
fullHeightSurface: false
|
||||||
|
|
||||||
property bool notificationHistoryVisible: false
|
property bool notificationHistoryVisible: false
|
||||||
property var triggerScreen: null
|
property var triggerScreen: null
|
||||||
property real stablePopupHeight: 400
|
property real stablePopupHeight: 400
|
||||||
property real _lastAlignedContentHeight: -1
|
property real _lastAlignedContentHeight: -1
|
||||||
|
property bool _pendingSizedOpen: false
|
||||||
|
|
||||||
function updateStablePopupHeight() {
|
function updateStablePopupHeight() {
|
||||||
const item = contentLoader.item;
|
const item = contentLoader.item;
|
||||||
|
if (item && !root.shouldBeVisible) {
|
||||||
|
const notificationList = findChild(item, "notificationList");
|
||||||
|
if (notificationList && typeof notificationList.forceLayout === "function") {
|
||||||
|
notificationList.forceLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
const target = item ? Theme.px(item.implicitHeight, dpr) : 400;
|
const target = item ? Theme.px(item.implicitHeight, dpr) : 400;
|
||||||
if (Math.abs(target - _lastAlignedContentHeight) < 0.5)
|
if (Math.abs(target - _lastAlignedContentHeight) < 0.5)
|
||||||
return;
|
return;
|
||||||
@@ -26,7 +33,7 @@ DankPopout {
|
|||||||
NotificationKeyboardController {
|
NotificationKeyboardController {
|
||||||
id: keyboardController
|
id: keyboardController
|
||||||
listView: null
|
listView: null
|
||||||
isOpen: notificationHistoryVisible
|
isOpen: root.shouldBeVisible
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
notificationHistoryVisible = false;
|
notificationHistoryVisible = false;
|
||||||
}
|
}
|
||||||
@@ -40,20 +47,42 @@ DankPopout {
|
|||||||
suspendShadowWhileResizing: false
|
suspendShadowWhileResizing: false
|
||||||
|
|
||||||
screen: triggerScreen
|
screen: triggerScreen
|
||||||
shouldBeVisible: notificationHistoryVisible
|
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
notificationHistoryVisible = !notificationHistoryVisible;
|
notificationHistoryVisible = !notificationHistoryVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openSized() {
|
||||||
|
if (!notificationHistoryVisible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
primeContent();
|
||||||
|
if (contentLoader.item) {
|
||||||
|
updateStablePopupHeight();
|
||||||
|
_pendingSizedOpen = false;
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (!notificationHistoryVisible)
|
||||||
|
return;
|
||||||
|
updateStablePopupHeight();
|
||||||
|
open();
|
||||||
|
clearPrimedContent();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pendingSizedOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
onBackgroundClicked: {
|
onBackgroundClicked: {
|
||||||
notificationHistoryVisible = false;
|
notificationHistoryVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onNotificationHistoryVisibleChanged: {
|
onNotificationHistoryVisibleChanged: {
|
||||||
if (notificationHistoryVisible) {
|
if (notificationHistoryVisible) {
|
||||||
open();
|
openSized();
|
||||||
} else {
|
} else {
|
||||||
|
_pendingSizedOpen = false;
|
||||||
|
clearPrimedContent();
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,6 +111,17 @@ DankPopout {
|
|||||||
target: contentLoader
|
target: contentLoader
|
||||||
function onLoaded() {
|
function onLoaded() {
|
||||||
root.updateStablePopupHeight();
|
root.updateStablePopupHeight();
|
||||||
|
if (root._pendingSizedOpen && root.notificationHistoryVisible) {
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (!root._pendingSizedOpen || !root.notificationHistoryVisible)
|
||||||
|
return;
|
||||||
|
root.updateStablePopupHeight();
|
||||||
|
root._pendingSizedOpen = false;
|
||||||
|
root.open();
|
||||||
|
root.clearPrimedContent();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (root.shouldBeVisible)
|
if (root.shouldBeVisible)
|
||||||
Qt.callLater(root.setupKeyboardNavigation);
|
Qt.callLater(root.setupKeyboardNavigation);
|
||||||
}
|
}
|
||||||
@@ -139,7 +179,8 @@ DankPopout {
|
|||||||
baseHeight += Theme.spacingM * 2;
|
baseHeight += Theme.spacingM * 2;
|
||||||
|
|
||||||
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
|
const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0;
|
||||||
let listHeight = notificationHeader.currentTab === 0 ? notificationList.stableContentHeight : Math.max(200, NotificationService.historyList.length * 80);
|
const currentListHeight = root.shouldBeVisible ? notificationList.stableContentHeight : notificationList.listContentHeight;
|
||||||
|
let listHeight = notificationHeader.currentTab === 0 ? currentListHeight : Math.max(200, NotificationService.historyList.length * 80);
|
||||||
if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) {
|
if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) {
|
||||||
listHeight = 200;
|
listHeight = 200;
|
||||||
}
|
}
|
||||||
@@ -233,13 +274,21 @@ DankPopout {
|
|||||||
expanded: notificationHeader.showSettings
|
expanded: notificationHeader.showSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardNavigatedNotificationList {
|
Item {
|
||||||
id: notificationList
|
|
||||||
objectName: "notificationList"
|
|
||||||
visible: notificationHeader.currentTab === 0
|
visible: notificationHeader.currentTab === 0
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
|
height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2
|
||||||
cardAnimateExpansion: true
|
|
||||||
|
KeyboardNavigatedNotificationList {
|
||||||
|
id: notificationList
|
||||||
|
objectName: "notificationList"
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: -shadowHorizontalGutter
|
||||||
|
anchors.rightMargin: -shadowHorizontalGutter
|
||||||
|
anchors.topMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
||||||
|
anchors.bottomMargin: -(shadowVerticalGutter + delegateShadowGutter / 2)
|
||||||
|
cardAnimateExpansion: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryNotificationList {
|
HistoryNotificationList {
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ PanelWindow {
|
|||||||
WlrLayershell.exclusiveZone: -1
|
WlrLayershell.exclusiveZone: -1
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
implicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380
|
readonly property real contentImplicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380
|
||||||
implicitHeight: {
|
readonly property real contentImplicitHeight: {
|
||||||
if (SettingsData.notificationPopupPrivacyMode && !descriptionExpanded)
|
if (SettingsData.notificationPopupPrivacyMode && !descriptionExpanded)
|
||||||
return basePopupHeightPrivacy;
|
return basePopupHeightPrivacy;
|
||||||
if (!descriptionExpanded)
|
if (!descriptionExpanded)
|
||||||
@@ -130,6 +130,8 @@ PanelWindow {
|
|||||||
return basePopupHeight + bodyTextHeight - collapsedBodyHeight;
|
return basePopupHeight + bodyTextHeight - collapsedBodyHeight;
|
||||||
return basePopupHeight;
|
return basePopupHeight;
|
||||||
}
|
}
|
||||||
|
implicitWidth: contentImplicitWidth + (windowShadowPad * 2)
|
||||||
|
implicitHeight: contentImplicitHeight + (windowShadowPad * 2)
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
Behavior on implicitHeight {
|
||||||
enabled: !exiting && !_isDestroying
|
enabled: !exiting && !_isDestroying
|
||||||
@@ -182,11 +184,15 @@ PanelWindow {
|
|||||||
property bool isTopCenter: SettingsData.notificationPopupPosition === -1
|
property bool isTopCenter: SettingsData.notificationPopupPosition === -1
|
||||||
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
|
property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter
|
||||||
property bool isCenterPosition: isTopCenter || isBottomCenter
|
property bool isCenterPosition: isTopCenter || isBottomCenter
|
||||||
|
readonly property real maxPopupShadowBlurPx: Math.max((Theme.elevationLevel3 && Theme.elevationLevel3.blurPx !== undefined) ? Theme.elevationLevel3.blurPx : 12, (Theme.elevationLevel4 && Theme.elevationLevel4.blurPx !== undefined) ? Theme.elevationLevel4.blurPx : 16)
|
||||||
|
readonly property real maxPopupShadowOffsetXPx: Math.max(Math.abs(Theme.elevationOffsetX(Theme.elevationLevel3)), Math.abs(Theme.elevationOffsetX(Theme.elevationLevel4)))
|
||||||
|
readonly property real maxPopupShadowOffsetYPx: Math.max(Math.abs(Theme.elevationOffsetY(Theme.elevationLevel3, 6)), Math.abs(Theme.elevationOffsetY(Theme.elevationLevel4, 8)))
|
||||||
|
readonly property real windowShadowPad: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled ? Theme.snap(Math.max(16, maxPopupShadowBlurPx + Math.max(maxPopupShadowOffsetXPx, maxPopupShadowOffsetYPx) + 8), dpr) : 0
|
||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
anchors.bottom: true
|
anchors.left: true
|
||||||
anchors.left: SettingsData.notificationPopupPosition === SettingsData.Position.Left || SettingsData.notificationPopupPosition === SettingsData.Position.Bottom
|
anchors.bottom: false
|
||||||
anchors.right: SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Right
|
anchors.right: false
|
||||||
|
|
||||||
mask: contentInputMask
|
mask: contentInputMask
|
||||||
|
|
||||||
@@ -205,10 +211,10 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
margins {
|
margins {
|
||||||
top: _storedTopMargin
|
top: getWindowTopMargin()
|
||||||
bottom: _storedBottomMargin
|
bottom: 0
|
||||||
left: getLeftMargin()
|
left: getWindowLeftMargin()
|
||||||
right: getRightMargin()
|
right: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBarInfo() {
|
function getBarInfo() {
|
||||||
@@ -250,7 +256,7 @@ PanelWindow {
|
|||||||
|
|
||||||
function getLeftMargin() {
|
function getLeftMargin() {
|
||||||
if (isCenterPosition)
|
if (isCenterPosition)
|
||||||
return screen ? (screen.width - implicitWidth) / 2 : 0;
|
return screen ? (screen.width - alignedWidth) / 2 : 0;
|
||||||
|
|
||||||
const popupPos = SettingsData.notificationPopupPosition;
|
const popupPos = SettingsData.notificationPopupPosition;
|
||||||
const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom;
|
const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom;
|
||||||
@@ -274,23 +280,56 @@ PanelWindow {
|
|||||||
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
|
return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getContentX() {
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const popupPos = SettingsData.notificationPopupPosition;
|
||||||
|
const barLeft = getLeftMargin();
|
||||||
|
const barRight = getRightMargin();
|
||||||
|
|
||||||
|
if (isCenterPosition)
|
||||||
|
return Theme.snap((screen.width - alignedWidth) / 2, dpr);
|
||||||
|
if (popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom)
|
||||||
|
return Theme.snap(barLeft, dpr);
|
||||||
|
return Theme.snap(screen.width - alignedWidth - barRight, dpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContentY() {
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const popupPos = SettingsData.notificationPopupPosition;
|
||||||
|
const barTop = getTopMargin();
|
||||||
|
const barBottom = getBottomMargin();
|
||||||
|
const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left;
|
||||||
|
if (isTop)
|
||||||
|
return Theme.snap(barTop, dpr);
|
||||||
|
return Theme.snap(screen.height - alignedHeight - barBottom, dpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindowLeftMargin() {
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
return Theme.snap(getContentX() - windowShadowPad, dpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindowTopMargin() {
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
return Theme.snap(getContentY() - windowShadowPad, dpr);
|
||||||
|
}
|
||||||
|
|
||||||
readonly property bool screenValid: win.screen && !_isDestroying
|
readonly property bool screenValid: win.screen && !_isDestroying
|
||||||
readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1
|
readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1
|
||||||
readonly property real alignedWidth: Theme.px(implicitWidth, dpr)
|
readonly property real alignedWidth: Theme.px(Math.max(0, implicitWidth - (windowShadowPad * 2)), dpr)
|
||||||
readonly property real alignedHeight: Theme.px(implicitHeight, dpr)
|
readonly property real alignedHeight: Theme.px(Math.max(0, implicitHeight - (windowShadowPad * 2)), dpr)
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
x: Theme.snap((win.width - alignedWidth) / 2, dpr)
|
x: Theme.snap(windowShadowPad, dpr)
|
||||||
y: {
|
y: Theme.snap(windowShadowPad, dpr)
|
||||||
const isTop = isTopCenter || SettingsData.notificationPopupPosition === SettingsData.Position.Top || SettingsData.notificationPopupPosition === SettingsData.Position.Left;
|
|
||||||
if (isTop) {
|
|
||||||
return Theme.snap(screenY, dpr);
|
|
||||||
} else {
|
|
||||||
return Theme.snap(win.height - alignedHeight - screenY, dpr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
width: alignedWidth
|
width: alignedWidth
|
||||||
height: alignedHeight
|
height: alignedHeight
|
||||||
visible: !win._finalized
|
visible: !win._finalized
|
||||||
@@ -313,12 +352,13 @@ PanelWindow {
|
|||||||
readonly property bool swipeActive: swipeDragHandler.active
|
readonly property bool swipeActive: swipeDragHandler.active
|
||||||
property bool swipeDismissing: false
|
property bool swipeDismissing: false
|
||||||
|
|
||||||
readonly property real radiusForShadow: Theme.cornerRadius
|
readonly property bool shadowsAllowed: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled
|
||||||
property real shadowBlurPx: SettingsData.notificationPopupShadowEnabled ? ((2 + radiusForShadow * 0.2) * (cardHoverHandler.hovered ? 1.2 : 1)) : 0
|
readonly property var elevLevel: cardHoverHandler.hovered ? Theme.elevationLevel4 : Theme.elevationLevel3
|
||||||
property real shadowSpreadPx: SettingsData.notificationPopupShadowEnabled ? (radiusForShadow * (cardHoverHandler.hovered ? 0.06 : 0)) : 0
|
readonly property real cardInset: Theme.snap(4, win.dpr)
|
||||||
property real shadowBaseAlpha: 0.35
|
readonly property real shadowRenderPadding: shadowsAllowed ? Theme.snap(Math.max(16, shadowBlurPx + Math.max(Math.abs(shadowOffsetX), Math.abs(shadowOffsetY)) + 8), win.dpr) : 0
|
||||||
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
property real shadowBlurPx: shadowsAllowed ? (elevLevel && elevLevel.blurPx !== undefined ? elevLevel.blurPx : 12) : 0
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
property real shadowOffsetX: shadowsAllowed ? Theme.elevationOffsetX(elevLevel) : 0
|
||||||
|
property real shadowOffsetY: shadowsAllowed ? Theme.elevationOffsetY(elevLevel, 6) : 0
|
||||||
|
|
||||||
Behavior on shadowBlurPx {
|
Behavior on shadowBlurPx {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -327,50 +367,50 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on shadowSpreadPx {
|
Behavior on shadowOffsetX {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
easing.type: Theme.standardEasing
|
easing.type: Theme.standardEasing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Behavior on shadowOffsetY {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Theme.shortDuration
|
||||||
|
easing.type: Theme.standardEasing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElevationShadow {
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.snap(4, win.dpr)
|
anchors.margins: -content.shadowRenderPadding
|
||||||
layer.enabled: !win._isDestroying && win.screenValid
|
level: content.elevLevel
|
||||||
layer.smooth: false
|
fallbackOffset: 6
|
||||||
|
shadowBlurPx: content.shadowBlurPx
|
||||||
|
shadowOffsetX: content.shadowOffsetX
|
||||||
|
shadowOffsetY: content.shadowOffsetY
|
||||||
|
shadowColor: content.shadowsAllowed && content.elevLevel ? Theme.elevationShadowColor(content.elevLevel) : "transparent"
|
||||||
|
shadowEnabled: !win._isDestroying && win.screenValid && content.shadowsAllowed
|
||||||
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
||||||
|
|
||||||
readonly property int blurMax: 64
|
sourceRect.anchors.fill: undefined
|
||||||
|
sourceRect.x: content.shadowRenderPadding + content.cardInset
|
||||||
layer.effect: MultiEffect {
|
sourceRect.y: content.shadowRenderPadding + content.cardInset
|
||||||
id: shadowFx
|
sourceRect.width: Math.max(0, content.width - (content.cardInset * 2))
|
||||||
autoPaddingEnabled: true
|
sourceRect.height: Math.max(0, content.height - (content.cardInset * 2))
|
||||||
shadowEnabled: SettingsData.notificationPopupShadowEnabled
|
sourceRect.radius: Theme.cornerRadius
|
||||||
blurEnabled: false
|
sourceRect.color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
maskEnabled: false
|
sourceRect.border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
||||||
shadowBlur: Math.max(0, Math.min(1, content.shadowBlurPx / bgShadowLayer.blurMax))
|
sourceRect.border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
||||||
shadowScale: 1 + (2 * content.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, content.effectiveShadowAlpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: shadowShapeSource
|
x: bgShadowLayer.sourceRect.x
|
||||||
anchors.fill: parent
|
y: bgShadowLayer.sourceRect.y
|
||||||
radius: Theme.cornerRadius
|
width: bgShadowLayer.sourceRect.width
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
height: bgShadowLayer.sourceRect.height
|
||||||
border.color: notificationData && notificationData.urgency === NotificationUrgency.Critical ? Theme.withAlpha(Theme.primary, 0.3) : Theme.withAlpha(Theme.outline, 0.08)
|
radius: bgShadowLayer.sourceRect.radius
|
||||||
border.width: notificationData && notificationData.urgency === NotificationUrgency.Critical ? 2 : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
radius: shadowShapeSource.radius
|
|
||||||
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
|
visible: notificationData && notificationData.urgency === NotificationUrgency.Critical
|
||||||
opacity: 1
|
opacity: 1
|
||||||
clip: true
|
clip: true
|
||||||
@@ -399,7 +439,7 @@ PanelWindow {
|
|||||||
Item {
|
Item {
|
||||||
id: backgroundContainer
|
id: backgroundContainer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: Theme.snap(4, win.dpr)
|
anchors.margins: content.cardInset
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
|
|||||||
@@ -878,12 +878,17 @@ Item {
|
|||||||
x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0
|
x: hoveredButton ? hoveredButton.mapToItem(aboutTab, hoveredButton.width / 2, 0).x - width / 2 : 0
|
||||||
y: hoveredButton ? communityIcons.mapToItem(aboutTab, 0, 0).y - height - 8 : 0
|
y: hoveredButton ? communityIcons.mapToItem(aboutTab, 0, 0).y - height - 8 : 0
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
anchors.fill: parent
|
||||||
shadowEnabled: true
|
z: -1
|
||||||
shadowOpacity: 0.15
|
level: Theme.elevationLevel1
|
||||||
shadowVerticalOffset: 2
|
fallbackOffset: 1
|
||||||
shadowBlur: 0.5
|
targetRadius: communityTooltip.radius
|
||||||
|
targetColor: communityTooltip.color
|
||||||
|
borderColor: communityTooltip.border.color
|
||||||
|
borderWidth: communityTooltip.border.width
|
||||||
|
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _isBarActive(c) {
|
function _isBarActive(c) {
|
||||||
if (!c.enabled) return false;
|
if (!c.enabled)
|
||||||
|
return false;
|
||||||
const prefs = c.screenPreferences || ["all"];
|
const prefs = c.screenPreferences || ["all"];
|
||||||
if (prefs.length > 0) return true;
|
if (prefs.length > 0)
|
||||||
|
return true;
|
||||||
return (c.showOnLastDisplay ?? true) && Quickshell.screens.length === 1;
|
return (c.showOnLastDisplay ?? true) && Quickshell.screens.length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +66,8 @@ Item {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const hasHorizontal = configs.some(c => {
|
const hasHorizontal = configs.some(c => {
|
||||||
if (!_isBarActive(c)) return false;
|
if (!_isBarActive(c))
|
||||||
|
return false;
|
||||||
const p = c.position ?? SettingsData.Position.Top;
|
const p = c.position ?? SettingsData.Position.Top;
|
||||||
return p === SettingsData.Position.Top || p === SettingsData.Position.Bottom;
|
return p === SettingsData.Position.Top || p === SettingsData.Position.Bottom;
|
||||||
});
|
});
|
||||||
@@ -72,7 +75,8 @@ Item {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const hasVertical = configs.some(c => {
|
const hasVertical = configs.some(c => {
|
||||||
if (!_isBarActive(c)) return false;
|
if (!_isBarActive(c))
|
||||||
|
return false;
|
||||||
const p = c.position ?? SettingsData.Position.Top;
|
const p = c.position ?? SettingsData.Position.Top;
|
||||||
return p === SettingsData.Position.Left || p === SettingsData.Position.Right;
|
return p === SettingsData.Position.Left || p === SettingsData.Position.Right;
|
||||||
});
|
});
|
||||||
@@ -136,7 +140,9 @@ Item {
|
|||||||
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
scrollYBehavior: defaultBar.scrollYBehavior ?? "workspace",
|
||||||
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
shadowIntensity: defaultBar.shadowIntensity ?? 0,
|
||||||
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
shadowOpacity: defaultBar.shadowOpacity ?? 60,
|
||||||
shadowColorMode: defaultBar.shadowColorMode ?? "text",
|
shadowDirectionMode: defaultBar.shadowDirectionMode ?? "inherit",
|
||||||
|
shadowDirection: defaultBar.shadowDirection ?? "top",
|
||||||
|
shadowColorMode: defaultBar.shadowColorMode ?? "default",
|
||||||
shadowCustomColor: defaultBar.shadowCustomColor ?? "#000000"
|
shadowCustomColor: defaultBar.shadowCustomColor ?? "#000000"
|
||||||
};
|
};
|
||||||
SettingsData.addBarConfig(newBar);
|
SettingsData.addBarConfig(newBar);
|
||||||
@@ -1040,6 +1046,237 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsCard {
|
||||||
|
id: shadowCard
|
||||||
|
iconName: "layers"
|
||||||
|
title: I18n.tr("Shadow Override", "bar shadow settings card")
|
||||||
|
settingKey: "barShadow"
|
||||||
|
collapsible: true
|
||||||
|
expanded: true
|
||||||
|
visible: selectedBarConfig?.enabled
|
||||||
|
|
||||||
|
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
|
||||||
|
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "default") === "custom"
|
||||||
|
readonly property string directionSource: selectedBarConfig?.shadowDirectionMode ?? "inherit"
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
width: parent.width
|
||||||
|
text: I18n.tr("Enable a custom override below to set per-bar shadow intensity, opacity, and color.")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceVariantText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
text: I18n.tr("Custom Shadow Override")
|
||||||
|
description: I18n.tr("Override the global shadow with per-bar settings")
|
||||||
|
checked: shadowCard.shadowActive
|
||||||
|
onToggled: checked => {
|
||||||
|
if (checked) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowIntensity: 12,
|
||||||
|
shadowOpacity: 60
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowIntensity: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
text: I18n.tr("Intensity", "shadow intensity slider")
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
unit: "px"
|
||||||
|
defaultValue: 12
|
||||||
|
value: selectedBarConfig?.shadowIntensity ?? 0
|
||||||
|
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowIntensity: newValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
text: I18n.tr("Opacity")
|
||||||
|
minimum: 10
|
||||||
|
maximum: 100
|
||||||
|
unit: "%"
|
||||||
|
defaultValue: 60
|
||||||
|
value: selectedBarConfig?.shadowOpacity ?? 60
|
||||||
|
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowOpacity: newValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
text: I18n.tr("Direction Source", "bar shadow direction source")
|
||||||
|
description: I18n.tr("Choose how this bar resolves shadow direction")
|
||||||
|
settingKey: "barShadowDirectionSource"
|
||||||
|
options: [I18n.tr("Inherit Global (Default)", "bar shadow direction source option"), I18n.tr("Auto (Bar-aware)", "bar shadow direction source option"), I18n.tr("Manual", "bar shadow direction source option")]
|
||||||
|
currentValue: {
|
||||||
|
switch (shadowCard.directionSource) {
|
||||||
|
case "autoBar":
|
||||||
|
return I18n.tr("Auto (Bar-aware)", "bar shadow direction source option");
|
||||||
|
case "manual":
|
||||||
|
return I18n.tr("Manual", "bar shadow direction source option");
|
||||||
|
default:
|
||||||
|
return I18n.tr("Inherit Global (Default)", "bar shadow direction source option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onValueChanged: value => {
|
||||||
|
if (value === I18n.tr("Auto (Bar-aware)", "bar shadow direction source option")) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirectionMode: "autoBar"
|
||||||
|
});
|
||||||
|
} else if (value === I18n.tr("Manual", "bar shadow direction source option")) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirectionMode: "manual"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirectionMode: "inherit"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
visible: shadowCard.shadowActive && shadowCard.directionSource === "manual"
|
||||||
|
text: I18n.tr("Manual Direction", "bar manual shadow direction")
|
||||||
|
description: I18n.tr("Use a fixed shadow direction for this bar")
|
||||||
|
settingKey: "barShadowDirectionManual"
|
||||||
|
options: [I18n.tr("Top", "shadow direction option"), I18n.tr("Top Left", "shadow direction option"), I18n.tr("Top Right", "shadow direction option"), I18n.tr("Bottom", "shadow direction option")]
|
||||||
|
currentValue: {
|
||||||
|
switch (selectedBarConfig?.shadowDirection) {
|
||||||
|
case "topLeft":
|
||||||
|
return I18n.tr("Top Left", "shadow direction option");
|
||||||
|
case "topRight":
|
||||||
|
return I18n.tr("Top Right", "shadow direction option");
|
||||||
|
case "bottom":
|
||||||
|
return I18n.tr("Bottom", "shadow direction option");
|
||||||
|
default:
|
||||||
|
return I18n.tr("Top", "shadow direction option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onValueChanged: value => {
|
||||||
|
if (value === I18n.tr("Top Left", "shadow direction option")) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirection: "topLeft"
|
||||||
|
});
|
||||||
|
} else if (value === I18n.tr("Top Right", "shadow direction option")) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirection: "topRight"
|
||||||
|
});
|
||||||
|
} else if (value === I18n.tr("Bottom", "shadow direction option")) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirection: "bottom"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowDirection: "top"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
visible: shadowCard.shadowActive
|
||||||
|
width: parent.width
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Color")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
color: Theme.surfaceText
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.spacingM
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: parent.width
|
||||||
|
height: shadowColorGroup.implicitHeight
|
||||||
|
|
||||||
|
DankButtonGroup {
|
||||||
|
id: shadowColorGroup
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
buttonPadding: parent.width < 420 ? Theme.spacingXS : Theme.spacingS
|
||||||
|
minButtonWidth: parent.width < 420 ? 36 : 56
|
||||||
|
textSize: parent.width < 420 ? Theme.fontSizeSmall : Theme.fontSizeMedium
|
||||||
|
model: [I18n.tr("Default (Black)"), I18n.tr("Surface", "shadow color option"), I18n.tr("Primary"), I18n.tr("Secondary"), I18n.tr("Custom")]
|
||||||
|
selectionMode: "single"
|
||||||
|
currentIndex: {
|
||||||
|
switch (selectedBarConfig?.shadowColorMode || "default") {
|
||||||
|
case "surface":
|
||||||
|
return 1;
|
||||||
|
case "primary":
|
||||||
|
return 2;
|
||||||
|
case "secondary":
|
||||||
|
return 3;
|
||||||
|
case "custom":
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSelectionChanged: (index, selected) => {
|
||||||
|
if (!selected)
|
||||||
|
return;
|
||||||
|
let mode = "default";
|
||||||
|
switch (index) {
|
||||||
|
case 1:
|
||||||
|
mode = "surface";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mode = "primary";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mode = "secondary";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
mode = "custom";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowColorMode: mode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: selectedBarConfig?.shadowColorMode === "custom"
|
||||||
|
width: 32
|
||||||
|
height: 32
|
||||||
|
radius: 16
|
||||||
|
color: selectedBarConfig?.shadowCustomColor ?? "#000000"
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
PopoutService.colorPickerModal.selectedColor = selectedBarConfig?.shadowCustomColor ?? "#000000";
|
||||||
|
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Color");
|
||||||
|
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
||||||
|
SettingsData.updateBarConfig(selectedBarId, {
|
||||||
|
shadowCustomColor: color.toString()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
PopoutService.colorPickerModal.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
iconName: "rounded_corner"
|
iconName: "rounded_corner"
|
||||||
title: I18n.tr("Corners & Background")
|
title: I18n.tr("Corners & Background")
|
||||||
@@ -1142,134 +1379,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
|
||||||
id: shadowCard
|
|
||||||
iconName: "layers"
|
|
||||||
title: I18n.tr("Shadow", "bar shadow settings card")
|
|
||||||
settingKey: "barShadow"
|
|
||||||
collapsible: true
|
|
||||||
expanded: false
|
|
||||||
visible: selectedBarConfig?.enabled
|
|
||||||
|
|
||||||
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
|
|
||||||
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "text") === "custom"
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
text: I18n.tr("Intensity", "shadow intensity slider")
|
|
||||||
minimum: 0
|
|
||||||
maximum: 100
|
|
||||||
unit: "%"
|
|
||||||
value: selectedBarConfig?.shadowIntensity ?? 0
|
|
||||||
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowIntensity: newValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsSliderRow {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
text: I18n.tr("Opacity")
|
|
||||||
minimum: 10
|
|
||||||
maximum: 100
|
|
||||||
unit: "%"
|
|
||||||
value: selectedBarConfig?.shadowOpacity ?? 60
|
|
||||||
onSliderValueChanged: newValue => SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowOpacity: newValue
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
visible: shadowCard.shadowActive
|
|
||||||
width: parent.width
|
|
||||||
spacing: Theme.spacingS
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
text: I18n.tr("Color")
|
|
||||||
font.pixelSize: Theme.fontSizeMedium
|
|
||||||
color: Theme.surfaceText
|
|
||||||
horizontalAlignment: Text.AlignLeft
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: Theme.spacingM
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: parent.width
|
|
||||||
height: shadowColorGroup.implicitHeight
|
|
||||||
|
|
||||||
DankButtonGroup {
|
|
||||||
id: shadowColorGroup
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
buttonPadding: parent.width < 420 ? Theme.spacingXS : Theme.spacingS
|
|
||||||
minButtonWidth: parent.width < 420 ? 36 : 56
|
|
||||||
textSize: parent.width < 420 ? Theme.fontSizeSmall : Theme.fontSizeMedium
|
|
||||||
model: [I18n.tr("Text", "shadow color option"), I18n.tr("Surface", "shadow color option"), I18n.tr("Primary"), I18n.tr("Secondary"), I18n.tr("Custom")]
|
|
||||||
selectionMode: "single"
|
|
||||||
currentIndex: {
|
|
||||||
switch (selectedBarConfig?.shadowColorMode || "text") {
|
|
||||||
case "surface":
|
|
||||||
return 1;
|
|
||||||
case "primary":
|
|
||||||
return 2;
|
|
||||||
case "secondary":
|
|
||||||
return 3;
|
|
||||||
case "custom":
|
|
||||||
return 4;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onSelectionChanged: (index, selected) => {
|
|
||||||
if (!selected)
|
|
||||||
return;
|
|
||||||
let mode = "text";
|
|
||||||
switch (index) {
|
|
||||||
case 1:
|
|
||||||
mode = "surface";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mode = "primary";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mode = "secondary";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
mode = "custom";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowColorMode: mode
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: selectedBarConfig?.shadowColorMode === "custom"
|
|
||||||
width: 32
|
|
||||||
height: 32
|
|
||||||
radius: 16
|
|
||||||
color: selectedBarConfig?.shadowCustomColor ?? "#000000"
|
|
||||||
border.color: Theme.outline
|
|
||||||
border.width: 1
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: {
|
|
||||||
PopoutService.colorPickerModal.selectedColor = selectedBarConfig?.shadowCustomColor ?? "#000000";
|
|
||||||
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Color");
|
|
||||||
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
|
||||||
SettingsData.updateBarConfig(selectedBarId, {
|
|
||||||
shadowCustomColor: color.toString()
|
|
||||||
});
|
|
||||||
};
|
|
||||||
PopoutService.colorPickerModal.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsToggleCard {
|
SettingsToggleCard {
|
||||||
iconName: "border_style"
|
iconName: "border_style"
|
||||||
title: I18n.tr("Border")
|
title: I18n.tr("Border")
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ Item {
|
|||||||
settingKey: "notificationPopupShadowEnabled"
|
settingKey: "notificationPopupShadowEnabled"
|
||||||
tags: ["notification", "popup", "shadow", "radius", "rounded"]
|
tags: ["notification", "popup", "shadow", "radius", "rounded"]
|
||||||
text: I18n.tr("Popup Shadow")
|
text: I18n.tr("Popup Shadow")
|
||||||
description: I18n.tr("Show drop shadow on notification popups")
|
description: I18n.tr("Show drop shadow on notification popups. Requires M3 Elevation to be enabled in Theme & Colors.")
|
||||||
checked: SettingsData.notificationPopupShadowEnabled
|
checked: SettingsData.notificationPopupShadowEnabled
|
||||||
onToggled: checked => SettingsData.set("notificationPopupShadowEnabled", checked)
|
onToggled: checked => SettingsData.set("notificationPopupShadowEnabled", checked)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,15 @@ Item {
|
|||||||
return Theme.warning;
|
return Theme.warning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openM3ShadowColorPicker() {
|
||||||
|
PopoutService.colorPickerModal.selectedColor = SettingsData.m3ElevationCustomColor ?? "#000000";
|
||||||
|
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Shadow Color");
|
||||||
|
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
||||||
|
SettingsData.set("m3ElevationCustomColor", color.toString());
|
||||||
|
};
|
||||||
|
PopoutService.colorPickerModal.show();
|
||||||
|
}
|
||||||
|
|
||||||
function formatThemeAutoTime(isoString) {
|
function formatThemeAutoTime(isoString) {
|
||||||
if (!isoString)
|
if (!isoString)
|
||||||
return "";
|
return "";
|
||||||
@@ -1592,6 +1601,189 @@ Item {
|
|||||||
defaultValue: 12
|
defaultValue: 12
|
||||||
onSliderValueChanged: newValue => SettingsData.setCornerRadius(newValue)
|
onSliderValueChanged: newValue => SettingsData.setCornerRadius(newValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "lift", "m3", "material"]
|
||||||
|
settingKey: "m3ElevationEnabled"
|
||||||
|
text: I18n.tr("Shadows")
|
||||||
|
description: I18n.tr("Material inspired shadows and elevation on modals, popouts, and dialogs")
|
||||||
|
checked: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onToggled: checked => SettingsData.set("m3ElevationEnabled", checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "intensity", "blur", "m3"]
|
||||||
|
settingKey: "m3ElevationIntensity"
|
||||||
|
text: I18n.tr("Shadow Intensity")
|
||||||
|
description: I18n.tr("Controls the base blur radius and offset of shadows")
|
||||||
|
value: SettingsData.m3ElevationIntensity ?? 12
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
unit: "px"
|
||||||
|
defaultValue: 12
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onSliderValueChanged: newValue => SettingsData.set("m3ElevationIntensity", newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsSliderRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "opacity", "transparency", "m3"]
|
||||||
|
settingKey: "m3ElevationOpacity"
|
||||||
|
text: I18n.tr("Shadow Opacity")
|
||||||
|
description: I18n.tr("Controls the transparency of the shadow")
|
||||||
|
value: SettingsData.m3ElevationOpacity ?? 30
|
||||||
|
minimum: 0
|
||||||
|
maximum: 100
|
||||||
|
unit: "%"
|
||||||
|
defaultValue: 30
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onSliderValueChanged: newValue => SettingsData.set("m3ElevationOpacity", newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "color", "m3"]
|
||||||
|
settingKey: "m3ElevationColorMode"
|
||||||
|
text: I18n.tr("Shadow Color")
|
||||||
|
description: I18n.tr("Base color for shadows (opacity is applied automatically)")
|
||||||
|
options: [I18n.tr("Default (Black)", "shadow color option"), I18n.tr("Text Color", "shadow color option"), I18n.tr("Primary", "shadow color option"), I18n.tr("Surface Variant", "shadow color option"), I18n.tr("Custom", "shadow color option")]
|
||||||
|
currentValue: {
|
||||||
|
switch (SettingsData.m3ElevationColorMode) {
|
||||||
|
case "text":
|
||||||
|
return I18n.tr("Text Color", "shadow color option");
|
||||||
|
case "primary":
|
||||||
|
return I18n.tr("Primary", "shadow color option");
|
||||||
|
case "surfaceVariant":
|
||||||
|
return I18n.tr("Surface Variant", "shadow color option");
|
||||||
|
case "custom":
|
||||||
|
return I18n.tr("Custom", "shadow color option");
|
||||||
|
default:
|
||||||
|
return I18n.tr("Default (Black)", "shadow color option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onValueChanged: value => {
|
||||||
|
if (value === I18n.tr("Primary", "shadow color option")) {
|
||||||
|
SettingsData.set("m3ElevationColorMode", "primary");
|
||||||
|
} else if (value === I18n.tr("Surface Variant", "shadow color option")) {
|
||||||
|
SettingsData.set("m3ElevationColorMode", "surfaceVariant");
|
||||||
|
} else if (value === I18n.tr("Custom", "shadow color option")) {
|
||||||
|
SettingsData.set("m3ElevationColorMode", "custom");
|
||||||
|
openM3ShadowColorPicker();
|
||||||
|
} else if (value === I18n.tr("Text Color", "shadow color option")) {
|
||||||
|
SettingsData.set("m3ElevationColorMode", "text");
|
||||||
|
} else {
|
||||||
|
SettingsData.set("m3ElevationColorMode", "default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "direction", "light", "advanced", "m3"]
|
||||||
|
settingKey: "m3ElevationLightDirection"
|
||||||
|
text: I18n.tr("Light Direction")
|
||||||
|
description: I18n.tr("Controls shadow cast direction for elevation layers")
|
||||||
|
options: [I18n.tr("Auto (Bar-aware)", "shadow direction option"), I18n.tr("Top (Default)", "shadow direction option"), I18n.tr("Top Left", "shadow direction option"), I18n.tr("Top Right", "shadow direction option"), I18n.tr("Bottom", "shadow direction option")]
|
||||||
|
currentValue: {
|
||||||
|
switch (SettingsData.m3ElevationLightDirection) {
|
||||||
|
case "autoBar":
|
||||||
|
return I18n.tr("Auto (Bar-aware)", "shadow direction option");
|
||||||
|
case "topLeft":
|
||||||
|
return I18n.tr("Top Left", "shadow direction option");
|
||||||
|
case "topRight":
|
||||||
|
return I18n.tr("Top Right", "shadow direction option");
|
||||||
|
case "bottom":
|
||||||
|
return I18n.tr("Bottom", "shadow direction option");
|
||||||
|
default:
|
||||||
|
return I18n.tr("Top (Default)", "shadow direction option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onValueChanged: value => {
|
||||||
|
if (value === I18n.tr("Auto (Bar-aware)", "shadow direction option")) {
|
||||||
|
SettingsData.set("m3ElevationLightDirection", "autoBar");
|
||||||
|
} else if (value === I18n.tr("Top Left", "shadow direction option")) {
|
||||||
|
SettingsData.set("m3ElevationLightDirection", "topLeft");
|
||||||
|
} else if (value === I18n.tr("Top Right", "shadow direction option")) {
|
||||||
|
SettingsData.set("m3ElevationLightDirection", "topRight");
|
||||||
|
} else if (value === I18n.tr("Bottom", "shadow direction option")) {
|
||||||
|
SettingsData.set("m3ElevationLightDirection", "bottom");
|
||||||
|
} else {
|
||||||
|
SettingsData.set("m3ElevationLightDirection", "top");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
visible: (SettingsData.m3ElevationEnabled ?? true) && SettingsData.m3ElevationColorMode === "custom"
|
||||||
|
width: parent.width
|
||||||
|
implicitHeight: 36
|
||||||
|
height: implicitHeight
|
||||||
|
|
||||||
|
Row {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("Custom Shadow Color")
|
||||||
|
color: Theme.surfaceText
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 26
|
||||||
|
height: 26
|
||||||
|
radius: 13
|
||||||
|
color: SettingsData.m3ElevationCustomColor ?? "#000000"
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: openM3ShadowColorPicker()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "modal", "dialog", "m3"]
|
||||||
|
settingKey: "modalElevationEnabled"
|
||||||
|
text: I18n.tr("Modal Shadows")
|
||||||
|
description: I18n.tr("Shadow elevation on modals and dialogs")
|
||||||
|
checked: SettingsData.modalElevationEnabled ?? true
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onToggled: checked => SettingsData.set("modalElevationEnabled", checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "popout", "popup", "osd", "dropdown", "m3"]
|
||||||
|
settingKey: "popoutElevationEnabled"
|
||||||
|
text: I18n.tr("Popout Shadows")
|
||||||
|
description: I18n.tr("Shadow elevation on popouts, OSDs, and dropdowns")
|
||||||
|
checked: SettingsData.popoutElevationEnabled ?? true
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onToggled: checked => SettingsData.set("popoutElevationEnabled", checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsToggleRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["elevation", "shadow", "bar", "panel", "navigation", "m3"]
|
||||||
|
settingKey: "barElevationEnabled"
|
||||||
|
text: I18n.tr("Bar Shadows")
|
||||||
|
description: I18n.tr("Shadow elevation on bars and panels")
|
||||||
|
checked: SettingsData.barElevationEnabled ?? true
|
||||||
|
visible: SettingsData.m3ElevationEnabled ?? true
|
||||||
|
onToggled: checked => SettingsData.set("barElevationEnabled", checked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
@@ -2138,12 +2330,41 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsCard {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["icon", "theme", "system"]
|
||||||
|
title: I18n.tr("Icon Theme")
|
||||||
|
settingKey: "iconTheme"
|
||||||
|
iconName: "interests"
|
||||||
|
|
||||||
|
SettingsDropdownRow {
|
||||||
|
tab: "theme"
|
||||||
|
tags: ["icon", "theme", "system"]
|
||||||
|
settingKey: "iconTheme"
|
||||||
|
text: I18n.tr("Icon Theme")
|
||||||
|
description: I18n.tr("DankShell & System Icons (requires restart)")
|
||||||
|
currentValue: SettingsData.iconTheme
|
||||||
|
enableFuzzySearch: true
|
||||||
|
popupWidthOffset: 100
|
||||||
|
maxPopupHeight: 236
|
||||||
|
options: cachedIconThemes
|
||||||
|
onValueChanged: value => {
|
||||||
|
SettingsData.setIconTheme(value);
|
||||||
|
if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") {
|
||||||
|
ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["matugen", "templates", "theming"]
|
tags: ["matugen", "templates", "theming"]
|
||||||
title: I18n.tr("Matugen Templates")
|
title: I18n.tr("Matugen Templates")
|
||||||
settingKey: "matugenTemplates"
|
settingKey: "matugenTemplates"
|
||||||
iconName: "auto_awesome"
|
iconName: "auto_awesome"
|
||||||
|
collapsible: true
|
||||||
|
expanded: false
|
||||||
visible: Theme.matugenAvailable
|
visible: Theme.matugenAvailable
|
||||||
|
|
||||||
SettingsToggleRow {
|
SettingsToggleRow {
|
||||||
@@ -2448,33 +2669,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsCard {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["icon", "theme", "system"]
|
|
||||||
title: I18n.tr("Icon Theme")
|
|
||||||
settingKey: "iconTheme"
|
|
||||||
iconName: "interests"
|
|
||||||
|
|
||||||
SettingsDropdownRow {
|
|
||||||
tab: "theme"
|
|
||||||
tags: ["icon", "theme", "system"]
|
|
||||||
settingKey: "iconTheme"
|
|
||||||
text: I18n.tr("Icon Theme")
|
|
||||||
description: I18n.tr("DankShell & System Icons (requires restart)")
|
|
||||||
currentValue: SettingsData.iconTheme
|
|
||||||
enableFuzzySearch: true
|
|
||||||
popupWidthOffset: 100
|
|
||||||
maxPopupHeight: 236
|
|
||||||
options: cachedIconThemes
|
|
||||||
onValueChanged: value => {
|
|
||||||
SettingsData.setIconTheme(value);
|
|
||||||
if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") {
|
|
||||||
ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsCard {
|
SettingsCard {
|
||||||
tab: "theme"
|
tab: "theme"
|
||||||
tags: ["system", "app", "theming", "gtk", "qt"]
|
tags: ["system", "app", "theming", "gtk", "qt"]
|
||||||
|
|||||||
@@ -706,14 +706,15 @@ Item {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
layer.enabled: true
|
layer.enabled: Theme.elevationEnabled
|
||||||
layer.effect: MultiEffect {
|
layer.effect: MultiEffect {
|
||||||
shadowEnabled: true
|
shadowEnabled: Theme.elevationEnabled
|
||||||
shadowHorizontalOffset: 0
|
shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel1)
|
||||||
shadowVerticalOffset: 4
|
shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel1, 1)
|
||||||
shadowBlur: 0.8
|
shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined ? Theme.elevationLevel1.blurPx : 4) / Theme.elevationBlurMax)) : 0
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.2)
|
blurMax: Theme.elevationBlurMax
|
||||||
shadowOpacity: 0.2
|
shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1)
|
||||||
|
shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -96,7 +95,6 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
layer.enabled: true
|
|
||||||
opacity: shouldBeVisible ? 1 : 0
|
opacity: shouldBeVisible ? 1 : 0
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -406,13 +404,15 @@ PanelWindow {
|
|||||||
onClicked: ToastService.hideToast()
|
onClicked: ToastService.hideToast()
|
||||||
}
|
}
|
||||||
|
|
||||||
layer.effect: MultiEffect {
|
ElevationShadow {
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowHorizontalOffset: 0
|
z: -1
|
||||||
shadowVerticalOffset: 4
|
level: Theme.elevationLevel3
|
||||||
shadowBlur: 0.8
|
fallbackOffset: 6
|
||||||
shadowColor: Qt.rgba(0, 0, 0, 0.3)
|
targetRadius: toast.radius
|
||||||
shadowOpacity: 0.3
|
targetColor: toast.color
|
||||||
|
shadowOpacity: Theme.elevationLevel3 && Theme.elevationLevel3.alpha !== undefined ? Theme.elevationLevel3.alpha : 0.3
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on opacity {
|
Behavior on opacity {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
@@ -17,59 +16,61 @@ Item {
|
|||||||
|
|
||||||
readonly property var allWorkspaces: Hyprland.workspaces?.values || []
|
readonly property var allWorkspaces: Hyprland.workspaces?.values || []
|
||||||
readonly property var allWorkspaceIds: {
|
readonly property var allWorkspaceIds: {
|
||||||
const workspaces = allWorkspaces
|
const workspaces = allWorkspaces;
|
||||||
if (!workspaces || workspaces.length === 0) return []
|
if (!workspaces || workspaces.length === 0)
|
||||||
|
return [];
|
||||||
try {
|
try {
|
||||||
const ids = workspaces.map(ws => ws?.id).filter(id => id !== null && id !== undefined)
|
const ids = workspaces.map(ws => ws?.id).filter(id => id !== null && id !== undefined);
|
||||||
return ids.sort((a, b) => a - b)
|
return ids.sort((a, b) => a - b);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var thisMonitorWorkspaceIds: {
|
readonly property var thisMonitorWorkspaceIds: {
|
||||||
const workspaces = allWorkspaces
|
const workspaces = allWorkspaces;
|
||||||
const mon = monitor
|
const mon = monitor;
|
||||||
if (!workspaces || workspaces.length === 0 || !mon) return []
|
if (!workspaces || workspaces.length === 0 || !mon)
|
||||||
|
return [];
|
||||||
try {
|
try {
|
||||||
const filtered = workspaces.filter(ws => ws?.monitor?.name === mon.name)
|
const filtered = workspaces.filter(ws => ws?.monitor?.name === mon.name);
|
||||||
return filtered.map(ws => ws?.id).filter(id => id !== null && id !== undefined).sort((a, b) => a - b)
|
return filtered.map(ws => ws?.id).filter(id => id !== null && id !== undefined).sort((a, b) => a - b);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property var displayedWorkspaceIds: {
|
readonly property var displayedWorkspaceIds: {
|
||||||
if (!allWorkspaceIds || allWorkspaceIds.length === 0) {
|
if (!allWorkspaceIds || allWorkspaceIds.length === 0) {
|
||||||
const result = []
|
const result = [];
|
||||||
for (let i = 1; i <= workspacesShown; i++) {
|
for (let i = 1; i <= workspacesShown; i++) {
|
||||||
result.push(i)
|
result.push(i);
|
||||||
}
|
}
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const maxExisting = Math.max(...allWorkspaceIds)
|
const maxExisting = Math.max(...allWorkspaceIds);
|
||||||
const totalNeeded = Math.max(workspacesShown, allWorkspaceIds.length)
|
const totalNeeded = Math.max(workspacesShown, allWorkspaceIds.length);
|
||||||
const result = []
|
const result = [];
|
||||||
|
|
||||||
for (let i = 1; i <= maxExisting; i++) {
|
for (let i = 1; i <= maxExisting; i++) {
|
||||||
result.push(i)
|
result.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nextId = maxExisting + 1
|
let nextId = maxExisting + 1;
|
||||||
while (result.length < totalNeeded) {
|
while (result.length < totalNeeded) {
|
||||||
result.push(nextId)
|
result.push(nextId);
|
||||||
nextId++
|
nextId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const result = []
|
const result = [];
|
||||||
for (let i = 1; i <= workspacesShown; i++) {
|
for (let i = 1; i <= workspacesShown; i++) {
|
||||||
result.push(i)
|
result.push(i);
|
||||||
}
|
}
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,24 +82,27 @@ Item {
|
|||||||
readonly property int effectiveRows: Math.max(SettingsData.overviewRows, Math.ceil(displayWorkspaceCount / effectiveColumns))
|
readonly property int effectiveRows: Math.max(SettingsData.overviewRows, Math.ceil(displayWorkspaceCount / effectiveColumns))
|
||||||
|
|
||||||
function getWorkspaceMonitorName(workspaceId) {
|
function getWorkspaceMonitorName(workspaceId) {
|
||||||
if (!allWorkspaces || !workspaceId) return ""
|
if (!allWorkspaces || !workspaceId)
|
||||||
|
return "";
|
||||||
try {
|
try {
|
||||||
const ws = allWorkspaces.find(w => w?.id === workspaceId)
|
const ws = allWorkspaces.find(w => w?.id === workspaceId);
|
||||||
return ws?.monitor?.name ?? ""
|
return ws?.monitor?.name ?? "";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function workspaceHasWindows(workspaceId) {
|
function workspaceHasWindows(workspaceId) {
|
||||||
if (!workspaceId) return false
|
if (!workspaceId)
|
||||||
|
return false;
|
||||||
try {
|
try {
|
||||||
const workspace = allWorkspaces.find(ws => ws?.id === workspaceId)
|
const workspace = allWorkspaces.find(ws => ws?.id === workspaceId);
|
||||||
if (!workspace) return false
|
if (!workspace)
|
||||||
const toplevels = workspace?.toplevels?.values || []
|
return false;
|
||||||
return toplevels.length > 0
|
const toplevels = workspace?.toplevels?.values || [];
|
||||||
|
return toplevels.length > 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,16 +128,16 @@ Item {
|
|||||||
implicitHeight: overviewBackground.implicitHeight + Theme.spacingL * 2
|
implicitHeight: overviewBackground.implicitHeight + Theme.spacingL * 2
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
Hyprland.refreshToplevels()
|
Hyprland.refreshToplevels();
|
||||||
Hyprland.refreshWorkspaces()
|
Hyprland.refreshWorkspaces();
|
||||||
Hyprland.refreshMonitors()
|
Hyprland.refreshMonitors();
|
||||||
}
|
}
|
||||||
|
|
||||||
onOverviewOpenChanged: {
|
onOverviewOpenChanged: {
|
||||||
if (overviewOpen) {
|
if (overviewOpen) {
|
||||||
Hyprland.refreshToplevels()
|
Hyprland.refreshToplevels();
|
||||||
Hyprland.refreshWorkspaces()
|
Hyprland.refreshWorkspaces();
|
||||||
Hyprland.refreshMonitors()
|
Hyprland.refreshMonitors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,15 +152,15 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceContainer
|
color: Theme.surfaceContainer
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
anchors.fill: parent
|
||||||
shadowEnabled: true
|
z: -1
|
||||||
shadowBlur: 0.5
|
level: Theme.elevationLevel2
|
||||||
shadowHorizontalOffset: 0
|
fallbackOffset: 4
|
||||||
shadowVerticalOffset: 4
|
targetRadius: Theme.cornerRadius
|
||||||
shadowColor: Theme.shadowStrong
|
targetColor: Theme.surfaceContainer
|
||||||
shadowOpacity: 1
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
blurMax: 32
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@@ -217,8 +221,8 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.draggingTargetWorkspace === -1) {
|
if (root.draggingTargetWorkspace === -1) {
|
||||||
root.overviewOpen = false
|
root.overviewOpen = false;
|
||||||
Hyprland.dispatch(`workspace ${workspaceValue}`)
|
Hyprland.dispatch(`workspace ${workspaceValue}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,13 +230,15 @@ Item {
|
|||||||
DropArea {
|
DropArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onEntered: {
|
onEntered: {
|
||||||
root.draggingTargetWorkspace = workspaceValue
|
root.draggingTargetWorkspace = workspaceValue;
|
||||||
if (root.draggingFromWorkspace == root.draggingTargetWorkspace) return
|
if (root.draggingFromWorkspace == root.draggingTargetWorkspace)
|
||||||
hoveredWhileDragging = true
|
return;
|
||||||
|
hoveredWhileDragging = true;
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
hoveredWhileDragging = false
|
hoveredWhileDragging = false;
|
||||||
if (root.draggingTargetWorkspace == workspaceValue) root.draggingTargetWorkspace = -1
|
if (root.draggingTargetWorkspace == workspaceValue)
|
||||||
|
root.draggingTargetWorkspace = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,27 +256,28 @@ Item {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: {
|
values: {
|
||||||
const workspaces = root.allWorkspaces
|
const workspaces = root.allWorkspaces;
|
||||||
const minId = root.minWorkspaceId
|
const minId = root.minWorkspaceId;
|
||||||
const maxId = root.maxWorkspaceId
|
const maxId = root.maxWorkspaceId;
|
||||||
|
|
||||||
if (!workspaces || workspaces.length === 0) return []
|
if (!workspaces || workspaces.length === 0)
|
||||||
|
return [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = []
|
const result = [];
|
||||||
for (const workspace of workspaces) {
|
for (const workspace of workspaces) {
|
||||||
const wsId = workspace?.id ?? -1
|
const wsId = workspace?.id ?? -1;
|
||||||
if (wsId >= minId && wsId <= maxId) {
|
if (wsId >= minId && wsId <= maxId) {
|
||||||
const toplevels = workspace?.toplevels?.values || []
|
const toplevels = workspace?.toplevels?.values || [];
|
||||||
for (const toplevel of toplevels) {
|
for (const toplevel of toplevels) {
|
||||||
result.push(toplevel)
|
result.push(toplevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("OverviewWidget filter error:", e)
|
console.error("OverviewWidget filter error:", e);
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,17 +289,19 @@ Item {
|
|||||||
readonly property int windowWorkspaceId: modelData?.workspace?.id ?? -1
|
readonly property int windowWorkspaceId: modelData?.workspace?.id ?? -1
|
||||||
|
|
||||||
function getWorkspaceIndex() {
|
function getWorkspaceIndex() {
|
||||||
if (!root.displayedWorkspaceIds || root.displayedWorkspaceIds.length === 0) return 0
|
if (!root.displayedWorkspaceIds || root.displayedWorkspaceIds.length === 0)
|
||||||
if (!windowWorkspaceId || windowWorkspaceId < 0) return 0
|
return 0;
|
||||||
|
if (!windowWorkspaceId || windowWorkspaceId < 0)
|
||||||
|
return 0;
|
||||||
try {
|
try {
|
||||||
for (let i = 0; i < root.displayedWorkspaceIds.length; i++) {
|
for (let i = 0; i < root.displayedWorkspaceIds.length; i++) {
|
||||||
if (root.displayedWorkspaceIds[i] === windowWorkspaceId) {
|
if (root.displayedWorkspaceIds[i] === windowWorkspaceId) {
|
||||||
return i
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return 0
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,48 +334,48 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
||||||
drag.target: parent
|
drag.target: parent
|
||||||
|
|
||||||
onPressed: (mouse) => {
|
onPressed: mouse => {
|
||||||
root.draggingFromWorkspace = windowData?.workspace.id
|
root.draggingFromWorkspace = windowData?.workspace.id;
|
||||||
window.pressed = true
|
window.pressed = true;
|
||||||
window.Drag.active = true
|
window.Drag.active = true;
|
||||||
window.Drag.source = window
|
window.Drag.source = window;
|
||||||
window.Drag.hotSpot.x = mouse.x
|
window.Drag.hotSpot.x = mouse.x;
|
||||||
window.Drag.hotSpot.y = mouse.y
|
window.Drag.hotSpot.y = mouse.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
onReleased: {
|
onReleased: {
|
||||||
const targetWorkspace = root.draggingTargetWorkspace
|
const targetWorkspace = root.draggingTargetWorkspace;
|
||||||
window.pressed = false
|
window.pressed = false;
|
||||||
window.Drag.active = false
|
window.Drag.active = false;
|
||||||
root.draggingFromWorkspace = -1
|
root.draggingFromWorkspace = -1;
|
||||||
root.draggingTargetWorkspace = -1
|
root.draggingTargetWorkspace = -1;
|
||||||
|
|
||||||
if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
|
if (targetWorkspace !== -1 && targetWorkspace !== windowData?.workspace.id) {
|
||||||
Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace},address:${windowData?.address}`)
|
Hyprland.dispatch(`movetoworkspacesilent ${targetWorkspace},address:${windowData?.address}`);
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
Hyprland.refreshToplevels()
|
Hyprland.refreshToplevels();
|
||||||
Hyprland.refreshWorkspaces()
|
Hyprland.refreshWorkspaces();
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
window.x = window.initX
|
window.x = window.initX;
|
||||||
window.y = window.initY
|
window.y = window.initY;
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
window.x = window.initX
|
window.x = window.initX;
|
||||||
window.y = window.initY
|
window.y = window.initY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: (event) => {
|
onClicked: event => {
|
||||||
if (!windowData || !windowData.address) return
|
if (!windowData || !windowData.address)
|
||||||
|
return;
|
||||||
if (event.button === Qt.LeftButton) {
|
if (event.button === Qt.LeftButton) {
|
||||||
root.overviewOpen = false
|
root.overviewOpen = false;
|
||||||
Hyprland.dispatch(`focuswindow address:${windowData.address}`)
|
Hyprland.dispatch(`focuswindow address:${windowData.address}`);
|
||||||
event.accepted = true
|
event.accepted = true;
|
||||||
} else if (event.button === Qt.MiddleButton) {
|
} else if (event.button === Qt.MiddleButton) {
|
||||||
Hyprland.dispatch(`closewindow address:${windowData.address}`)
|
Hyprland.dispatch(`closewindow address:${windowData.address}`);
|
||||||
event.accepted = true
|
event.accepted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ Item {
|
|||||||
sourceComponent: IconImage {
|
sourceComponent: IconImage {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: root.iconPath
|
source: root.iconPath
|
||||||
backer.sourceSize: Qt.size(root.iconSize, root.iconSize)
|
backer.sourceSize: Qt.size(root.iconSize * 2, root.iconSize * 2)
|
||||||
mipmap: true
|
mipmap: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
visible: status === Image.Ready
|
visible: status === Image.Ready
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ Rectangle {
|
|||||||
mipmap: true
|
mipmap: true
|
||||||
cache: true
|
cache: true
|
||||||
visible: false
|
visible: false
|
||||||
|
sourceSize.width: Math.max(width * 2, 128)
|
||||||
|
sourceSize.height: Math.max(height * 2, 128)
|
||||||
source: !root.shouldProbe ? root.imageSource : ""
|
source: !root.shouldProbe ? root.imageSource : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import "../Common/fzf.js" as Fzf
|
import "../Common/fzf.js" as Fzf
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -254,6 +253,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Rectangle {
|
contentItem: Rectangle {
|
||||||
|
id: contentSurface
|
||||||
|
|
||||||
LayoutMirroring.enabled: I18n.isRtl
|
LayoutMirroring.enabled: I18n.isRtl
|
||||||
LayoutMirroring.childrenInherit: true
|
LayoutMirroring.childrenInherit: true
|
||||||
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
|
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
|
||||||
@@ -261,12 +262,17 @@ Item {
|
|||||||
border.width: 2
|
border.width: 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
id: shadowLayer
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowBlur: 0.4
|
z: -1
|
||||||
shadowColor: Theme.shadowStrong
|
level: Theme.elevationLevel2
|
||||||
shadowVerticalOffset: 4
|
fallbackOffset: 4
|
||||||
|
targetRadius: contentSurface.radius
|
||||||
|
targetColor: contentSurface.color
|
||||||
|
borderColor: contentSurface.border.color
|
||||||
|
borderWidth: contentSurface.border.width
|
||||||
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Effects
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -132,16 +131,20 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Rectangle {
|
contentItem: Rectangle {
|
||||||
|
id: contentSurface
|
||||||
color: Theme.surface
|
color: Theme.surface
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|
||||||
layer.enabled: true
|
ElevationShadow {
|
||||||
layer.effect: MultiEffect {
|
id: shadowLayer
|
||||||
shadowEnabled: true
|
anchors.fill: parent
|
||||||
shadowColor: Theme.shadowStrong
|
z: -1
|
||||||
shadowBlur: 0.8
|
level: Theme.elevationLevel2
|
||||||
shadowHorizontalOffset: 0
|
fallbackOffset: 4
|
||||||
shadowVerticalOffset: 4
|
targetRadius: contentSurface.radius
|
||||||
|
targetColor: contentSurface.color
|
||||||
|
shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
|
||||||
|
shadowEnabled: Theme.elevationEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -257,11 +256,7 @@ PanelWindow {
|
|||||||
scale: shouldBeVisible ? 1 : 0.9
|
scale: shouldBeVisible ? 1 : 0.9
|
||||||
|
|
||||||
property bool childHovered: false
|
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 popupSurfaceAlpha: SettingsData.popupTransparency
|
||||||
readonly property real effectiveShadowAlpha: shouldBeVisible ? Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha)) : 0
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: background
|
id: background
|
||||||
@@ -273,38 +268,20 @@ PanelWindow {
|
|||||||
z: -1
|
z: -1
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
ElevationShadow {
|
||||||
id: bgShadowLayer
|
id: bgShadowLayer
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: osdContainer.popupSurfaceAlpha >= 0.95
|
visible: osdContainer.popupSurfaceAlpha >= 0.95
|
||||||
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
z: -1
|
||||||
layer.smooth: false
|
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.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
|
||||||
layer.textureMirroring: ShaderEffectSource.MirrorVertically
|
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 {
|
MouseArea {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import qs.Common
|
import qs.Common
|
||||||
@@ -31,6 +30,7 @@ Item {
|
|||||||
property bool backgroundInteractive: true
|
property bool backgroundInteractive: true
|
||||||
property bool contentHandlesKeys: false
|
property bool contentHandlesKeys: false
|
||||||
property bool fullHeightSurface: false
|
property bool fullHeightSurface: false
|
||||||
|
property bool _primeContent: false
|
||||||
property bool _resizeActive: false
|
property bool _resizeActive: false
|
||||||
property real _surfaceMarginLeft: 0
|
property real _surfaceMarginLeft: 0
|
||||||
property real _surfaceW: 0
|
property real _surfaceW: 0
|
||||||
@@ -77,6 +77,38 @@ Item {
|
|||||||
|
|
||||||
property int effectiveBarPosition: 0
|
property int effectiveBarPosition: 0
|
||||||
property real effectiveBarBottomGap: 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
|
// Snapshot mask geometry to prevent background damage on bar updates
|
||||||
property real _frozenMaskX: 0
|
property real _frozenMaskX: 0
|
||||||
@@ -89,6 +121,14 @@ Item {
|
|||||||
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
|
effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function primeContent() {
|
||||||
|
_primeContent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearPrimedContent() {
|
||||||
|
_primeContent = false;
|
||||||
|
}
|
||||||
|
|
||||||
function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
|
function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) {
|
||||||
triggerX = x;
|
triggerX = x;
|
||||||
triggerY = y;
|
triggerY = y;
|
||||||
@@ -152,6 +192,7 @@ Item {
|
|||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
shouldBeVisible = false;
|
shouldBeVisible = false;
|
||||||
|
_primeContent = false;
|
||||||
PopoutManager.popoutChanged();
|
PopoutManager.popoutChanged();
|
||||||
closeTimer.restart();
|
closeTimer.restart();
|
||||||
}
|
}
|
||||||
@@ -197,7 +238,11 @@ Item {
|
|||||||
readonly property real screenHeight: screen ? screen.height : 0
|
readonly property real screenHeight: screen ? screen.height : 0
|
||||||
readonly property real dpr: screen ? screen.devicePixelRatio : 1
|
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 alignedWidth: Theme.px(popupWidth, dpr)
|
||||||
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
readonly property real alignedHeight: Theme.px(popupHeight, dpr)
|
||||||
|
|
||||||
@@ -257,29 +302,30 @@ Item {
|
|||||||
}
|
}
|
||||||
})(), dpr)
|
})(), 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: {
|
readonly property real maskX: {
|
||||||
const triggeringBarX = (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? barWidth : 0;
|
|
||||||
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
|
const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0;
|
||||||
return Math.max(triggeringBarX, adjacentLeftBar);
|
return Math.max(triggeringBarLeftExclusion, adjacentLeftBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskY: {
|
readonly property real maskY: {
|
||||||
const triggeringBarY = (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? barHeight : 0;
|
|
||||||
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
|
const adjacentTopBar = adjacentBarInfo?.topBar ?? 0;
|
||||||
return Math.max(triggeringBarY, adjacentTopBar);
|
return Math.max(triggeringBarTopExclusion, adjacentTopBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskWidth: {
|
readonly property real maskWidth: {
|
||||||
const triggeringBarRight = (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? barWidth : 0;
|
|
||||||
const adjacentRightBar = adjacentBarInfo?.rightBar ?? 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);
|
return Math.max(100, screenWidth - maskX - rightExclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly property real maskHeight: {
|
readonly property real maskHeight: {
|
||||||
const triggeringBarBottom = (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? barHeight : 0;
|
|
||||||
const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 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);
|
return Math.max(100, screenHeight - maskY - bottomExclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +441,7 @@ Item {
|
|||||||
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
implicitWidth: useBackgroundWindow ? root._surfaceW : 0
|
||||||
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0
|
||||||
|
|
||||||
mask: (useBackgroundWindow && _fullHeight) ? contentInputMask : null
|
mask: useBackgroundWindow ? contentInputMask : null
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
id: contentInputMask
|
id: contentInputMask
|
||||||
@@ -405,10 +451,10 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
id: contentMaskRect
|
id: contentMaskRect
|
||||||
visible: false
|
visible: false
|
||||||
x: contentContainer.x - root.shadowBuffer
|
x: contentContainer.x
|
||||||
y: contentContainer.y - root.shadowBuffer
|
y: contentContainer.y
|
||||||
width: root.alignedWidth + root.shadowBuffer * 2
|
width: root.alignedWidth
|
||||||
height: root.alignedHeight + root.shadowBuffer * 2
|
height: root.alignedHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -480,42 +526,20 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
ElevationShadow {
|
||||||
id: shadowSource
|
id: shadowSource
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: "black"
|
|
||||||
visible: false
|
|
||||||
opacity: contentWrapper.opacity
|
opacity: contentWrapper.opacity
|
||||||
scale: contentWrapper.scale
|
scale: contentWrapper.scale
|
||||||
x: contentWrapper.x
|
x: contentWrapper.x
|
||||||
y: contentWrapper.y
|
y: contentWrapper.y
|
||||||
|
level: root.shadowLevel
|
||||||
property real shadowBlurPx: 10
|
direction: root.effectiveShadowDirection
|
||||||
property real shadowSpreadPx: 0
|
fallbackOffset: root.shadowFallbackOffset
|
||||||
property real shadowBaseAlpha: 0.60
|
targetRadius: Theme.cornerRadius
|
||||||
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
targetColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -546,13 +570,13 @@ Item {
|
|||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
border.color: Theme.outlineMedium
|
border.color: Theme.outlineMedium
|
||||||
border.width: 1
|
border.width: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
active: shouldBeVisible || contentWindow.visible
|
active: root._primeContent || shouldBeVisible || contentWindow.visible
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,11 @@
|
|||||||
--m3-radius: 12px;
|
--m3-radius: 12px;
|
||||||
--m3-radius-sm: 10px;
|
--m3-radius-sm: 10px;
|
||||||
--m3-elev-0: none;
|
--m3-elev-0: none;
|
||||||
--m3-elev-1: 0 1px 2px rgba(0,0,0,.08), 0 1px 3px rgba(0,0,0,.06);
|
--m3-elev-1: 0 1px 2px color-mix(in srgb, var(--md-sys-color-shadow) 8%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 6%, transparent);
|
||||||
--m3-elev-2: 0 2px 6px rgba(0,0,0,.10), 0 1px 3px rgba(0,0,0,.06);
|
--m3-elev-2: 0 2px 6px color-mix(in srgb, var(--md-sys-color-shadow) 10%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 6%, transparent);
|
||||||
|
--m3-elev-3: 0 11px 7px color-mix(in srgb, var(--md-sys-color-shadow) 19%, transparent), 0 13px 25px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
||||||
|
--m3-elev-4: 0 14px 12px color-mix(in srgb, var(--md-sys-color-shadow) 17%, transparent), 0 20px 40px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
||||||
|
--m3-elev-5: 0 17px 17px color-mix(in srgb, var(--md-sys-color-shadow) 15%, transparent), 0 27px 55px color-mix(in srgb, var(--md-sys-color-shadow) 30%, transparent);
|
||||||
|
|
||||||
--tab-height: 34px;
|
--tab-height: 34px;
|
||||||
--urlbar-height: 38px;
|
--urlbar-height: 38px;
|
||||||
@@ -118,8 +121,11 @@
|
|||||||
--md-sys-color-surface-container-high: {{colors.surface_container_high.dark.hex}};
|
--md-sys-color-surface-container-high: {{colors.surface_container_high.dark.hex}};
|
||||||
--md-sys-color-surface-container-highest: {{colors.surface_container_highest.dark.hex}};
|
--md-sys-color-surface-container-highest: {{colors.surface_container_highest.dark.hex}};
|
||||||
|
|
||||||
--m3-elev-1: 0 1px 2px rgba(0,0,0,.50), 0 1px 3px rgba(0,0,0,.35);
|
--m3-elev-1: 0 1px 2px color-mix(in srgb, var(--md-sys-color-shadow) 50%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 35%, transparent);
|
||||||
--m3-elev-2: 0 4px 10px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.35);
|
--m3-elev-2: 0 4px 10px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent), 0 1px 3px color-mix(in srgb, var(--md-sys-color-shadow) 35%, transparent);
|
||||||
|
--m3-elev-3: 0 11px 7px color-mix(in srgb, var(--md-sys-color-shadow) 45%, transparent), 0 13px 25px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
||||||
|
--m3-elev-4: 0 14px 12px color-mix(in srgb, var(--md-sys-color-shadow) 42%, transparent), 0 20px 40px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
||||||
|
--m3-elev-5: 0 17px 17px color-mix(in srgb, var(--md-sys-color-shadow) 40%, transparent), 0 27px 55px color-mix(in srgb, var(--md-sys-color-shadow) 55%, transparent);
|
||||||
|
|
||||||
--state-hover: color-mix(in srgb, var(--md-sys-color-on-surface) 6%, transparent);
|
--state-hover: color-mix(in srgb, var(--md-sys-color-on-surface) 6%, transparent);
|
||||||
--state-press: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent);
|
--state-press: color-mix(in srgb, var(--md-sys-color-on-surface) 10%, transparent);
|
||||||
|
|||||||
@@ -2416,6 +2416,74 @@
|
|||||||
],
|
],
|
||||||
"description": "0 = square corners"
|
"description": "0 = square corners"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"section": "m3ElevationEnabled",
|
||||||
|
"label": "M3 Elevation & Shadows",
|
||||||
|
"tabIndex": 10,
|
||||||
|
"category": "Theme & Colors",
|
||||||
|
"keywords": [
|
||||||
|
"appearance",
|
||||||
|
"elevation",
|
||||||
|
"lift",
|
||||||
|
"material",
|
||||||
|
"m3",
|
||||||
|
"shadow",
|
||||||
|
"shadows",
|
||||||
|
"theme"
|
||||||
|
],
|
||||||
|
"description": "Material Design 3 shadows and elevation on modals, popouts, and dialogs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "modalElevationEnabled",
|
||||||
|
"label": "Modal Shadows",
|
||||||
|
"tabIndex": 10,
|
||||||
|
"category": "Theme & Colors",
|
||||||
|
"keywords": [
|
||||||
|
"dialog",
|
||||||
|
"elevation",
|
||||||
|
"m3",
|
||||||
|
"material",
|
||||||
|
"modal",
|
||||||
|
"shadow",
|
||||||
|
"shadows"
|
||||||
|
],
|
||||||
|
"description": "Shadow elevation on modals and dialogs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "popoutElevationEnabled",
|
||||||
|
"label": "Popout Shadows",
|
||||||
|
"tabIndex": 10,
|
||||||
|
"category": "Theme & Colors",
|
||||||
|
"keywords": [
|
||||||
|
"dropdown",
|
||||||
|
"elevation",
|
||||||
|
"m3",
|
||||||
|
"material",
|
||||||
|
"osd",
|
||||||
|
"popout",
|
||||||
|
"popup",
|
||||||
|
"shadow",
|
||||||
|
"shadows"
|
||||||
|
],
|
||||||
|
"description": "Shadow elevation on popouts, OSDs, and dropdowns"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"section": "barElevationEnabled",
|
||||||
|
"label": "Bar Shadows",
|
||||||
|
"tabIndex": 10,
|
||||||
|
"category": "Theme & Colors",
|
||||||
|
"keywords": [
|
||||||
|
"bar",
|
||||||
|
"elevation",
|
||||||
|
"m3",
|
||||||
|
"material",
|
||||||
|
"navigation",
|
||||||
|
"panel",
|
||||||
|
"shadow",
|
||||||
|
"shadows"
|
||||||
|
],
|
||||||
|
"description": "Shadow elevation on bars and panels"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"section": "cursorSize",
|
"section": "cursorSize",
|
||||||
"label": "Cursor Size",
|
"label": "Cursor Size",
|
||||||
|
|||||||
Reference in New Issue
Block a user