1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-03 02:52:07 -04:00

re-organize settings

This commit is contained in:
bbedward
2026-04-30 15:19:06 -04:00
committed by purian23
parent 01da451f53
commit 7138c546e1
13 changed files with 240 additions and 298 deletions

View File

@@ -55,7 +55,7 @@ Singleton {
readonly property bool isDirectionalEffect: isConnectedEffect || _effect === 1 readonly property bool isDirectionalEffect: isConnectedEffect || _effect === 1
readonly property bool isDepthEffect: _effect === 2 readonly property bool isDepthEffect: _effect === 2
readonly property bool isConnectedEffect: (typeof SettingsData !== "undefined") && SettingsData.frameEnabled && _effect === 1 && SettingsData.directionalAnimationMode === 3 readonly property bool isConnectedEffect: (typeof SettingsData !== "undefined") && SettingsData.connectedFrameModeActive
readonly property real effectScaleCollapsed: _effectScaleCollapsed[_effect] !== undefined ? _effectScaleCollapsed[_effect] : 0.96 readonly property real effectScaleCollapsed: _effectScaleCollapsed[_effect] !== undefined ? _effectScaleCollapsed[_effect] : 0.96
readonly property real effectAnimOffset: _effectAnimOffsets[_effect] !== undefined ? _effectAnimOffsets[_effect] : 16 readonly property real effectAnimOffset: _effectAnimOffsets[_effect] !== undefined ? _effectAnimOffsets[_effect] : 16

View File

@@ -185,15 +185,6 @@ Singleton {
onAnimationVariantChanged: saveSettings() onAnimationVariantChanged: saveSettings()
property int motionEffect: SettingsData.AnimationEffect.Standard property int motionEffect: SettingsData.AnimationEffect.Standard
onMotionEffectChanged: saveSettings() onMotionEffectChanged: saveSettings()
property int directionalAnimationMode: 1
onDirectionalAnimationModeChanged: {
const normalized = directionalAnimationMode === 3 ? 3 : 1;
if (directionalAnimationMode !== normalized) {
directionalAnimationMode = normalized;
return;
}
saveSettings();
}
property bool m3ElevationEnabled: true property bool m3ElevationEnabled: true
onM3ElevationEnabledChanged: saveSettings() onM3ElevationEnabledChanged: saveSettings()
property int m3ElevationIntensity: 12 property int m3ElevationIntensity: 12
@@ -252,17 +243,11 @@ Singleton {
property string frameLauncherEmergeSide: "bottom" property string frameLauncherEmergeSide: "bottom"
onFrameLauncherEmergeSideChanged: saveSettings() onFrameLauncherEmergeSideChanged: saveSettings()
readonly property string frameModalEmergeSide: frameLauncherEmergeSide === "top" ? "bottom" : "top" readonly property string frameModalEmergeSide: frameLauncherEmergeSide === "top" ? "bottom" : "top"
property int previousDirectionalMode: 1 property string frameMode: "separate"
onPreviousDirectionalModeChanged: { onFrameModeChanged: saveSettings()
if (previousDirectionalMode !== 1) {
previousDirectionalMode = 1;
return;
}
saveSettings();
}
property var connectedFrameBarStyleBackups: ({}) property var connectedFrameBarStyleBackups: ({})
onConnectedFrameBarStyleBackupsChanged: saveSettings() onConnectedFrameBarStyleBackupsChanged: saveSettings()
readonly property bool connectedFrameModeActive: frameEnabled && motionEffect === SettingsData.AnimationEffect.Directional && directionalAnimationMode === 3 readonly property bool connectedFrameModeActive: frameEnabled && frameMode === "connected"
onConnectedFrameModeActiveChanged: { onConnectedFrameModeActiveChanged: {
if (_loading) if (_loading)
return; return;
@@ -1353,6 +1338,9 @@ Singleton {
Store.parse(root, obj); Store.parse(root, obj);
if (obj?.directionalAnimationMode === 3 && frameMode !== "connected")
frameMode = "connected";
if (obj?.weatherLocation !== undefined) if (obj?.weatherLocation !== undefined)
_legacyWeatherLocation = obj.weatherLocation; _legacyWeatherLocation = obj.weatherLocation;
if (obj?.weatherCoordinates !== undefined) if (obj?.weatherCoordinates !== undefined)

View File

@@ -51,8 +51,6 @@ var SPEC = {
enableRippleEffects: { def: true }, enableRippleEffects: { def: true },
animationVariant: { def: 0 }, animationVariant: { def: 0 },
motionEffect: { def: 0 }, motionEffect: { def: 0 },
directionalAnimationMode: { def: 1 },
previousDirectionalMode: { def: 1 },
m3ElevationEnabled: { def: true }, m3ElevationEnabled: { def: true },
m3ElevationIntensity: { def: 12 }, m3ElevationIntensity: { def: 12 },
m3ElevationOpacity: { def: 30 }, m3ElevationOpacity: { def: 30 },
@@ -566,7 +564,8 @@ var SPEC = {
frameShowOnOverview: { def: false }, frameShowOnOverview: { def: false },
frameBlurEnabled: { def: true }, frameBlurEnabled: { def: true },
frameCloseGaps: { def: false }, frameCloseGaps: { def: false },
frameLauncherEmergeSide: { def: "bottom" } frameLauncherEmergeSide: { def: "bottom" },
frameMode: { def: "separate" }
}; };
function getValidKeys() { function getValidKeys() {

View File

@@ -311,8 +311,8 @@ Item {
readonly property real shadowMotionPadding: { readonly property real shadowMotionPadding: {
if (Theme.isConnectedEffect) if (Theme.isConnectedEffect)
return 0; return 0;
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode > 0 && Theme.isDirectionalEffect) if (Theme.isDirectionalEffect)
return 0; // Wayland native overlap mask return 0;
if (animationType === "slide") if (animationType === "slide")
return 30; return 30;
if (Theme.isDirectionalEffect) if (Theme.isDirectionalEffect)

View File

@@ -746,7 +746,7 @@ Item {
Item { Item {
id: directionalClipMask id: directionalClipMask
readonly property bool shouldClip: Theme.isDirectionalEffect && typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode > 0 readonly property bool shouldClip: Theme.isDirectionalEffect
readonly property real clipOversize: 2000 readonly property real clipOversize: 2000
clip: shouldClip clip: shouldClip

View File

@@ -112,7 +112,9 @@ FocusScope {
focus: active focus: active
sourceComponent: Component { sourceComponent: Component {
DockTab {} DockTab {
parentModal: root.parentModal
}
} }
onActiveChanged: { onActiveChanged: {
@@ -218,7 +220,9 @@ FocusScope {
visible: active visible: active
focus: active focus: active
sourceComponent: ThemeColorsTab {} sourceComponent: ThemeColorsTab {
parentModal: root.parentModal
}
onActiveChanged: { onActiveChanged: {
if (active && item) if (active && item)

View File

@@ -708,42 +708,18 @@ Item {
} }
} }
Item { SettingsControlledByFrame {
visible: SettingsData.frameEnabled visible: SettingsData.frameEnabled
width: parent.width parentModal: dankBarTab.parentModal
implicitHeight: frameNote.implicitHeight + Theme.spacingS * 2 settingLabel: I18n.tr("Bar spacing and size")
reason: I18n.tr("Managed by Frame")
Row {
id: frameNote
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "frame_source"
size: Theme.fontSizeMedium
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Spacing and size are managed by Frame mode")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - Theme.fontSizeMedium - Theme.spacingS
}
}
} }
SettingsCard { SettingsCard {
iconName: "space_bar" iconName: "space_bar"
title: I18n.tr("Spacing") title: I18n.tr("Spacing")
settingKey: "barSpacing" settingKey: "barSpacing"
visible: selectedBarConfig?.enabled visible: (selectedBarConfig?.enabled ?? false) && !SettingsData.frameEnabled
enabled: !SettingsData.frameEnabled
opacity: SettingsData.frameEnabled ? 0.5 : 1.0
SettingsSliderRow { SettingsSliderRow {
id: edgeSpacingSlider id: edgeSpacingSlider
@@ -894,8 +870,7 @@ Item {
SettingsSliderRow { SettingsSliderRow {
id: barTransparencySlider id: barTransparencySlider
enabled: !SettingsData.frameEnabled visible: !SettingsData.frameEnabled
opacity: SettingsData.frameEnabled ? 0.5 : 1.0
text: I18n.tr("Bar Transparency") text: I18n.tr("Bar Transparency")
value: (selectedBarConfig?.transparency ?? 1.0) * 100 value: (selectedBarConfig?.transparency ?? 1.0) * 100
minimum: 0 minimum: 0
@@ -938,33 +913,11 @@ Item {
} }
} }
Item { SettingsControlledByFrame {
visible: SettingsData.frameEnabled visible: SettingsData.frameEnabled
width: parent.width parentModal: dankBarTab.parentModal
implicitHeight: transparencyFrameNote.implicitHeight + Theme.spacingS * 2 settingLabel: I18n.tr("Bar transparency")
reason: I18n.tr("Managed by Frame")
Row {
id: transparencyFrameNote
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "frame_source"
size: Theme.fontSizeMedium
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Opacity is controlled by Frame Border Opacity in Frame settings")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - Theme.fontSizeMedium - Theme.spacingS
}
}
} }
} }
@@ -1026,10 +979,16 @@ Item {
expanded: false expanded: false
visible: selectedBarConfig?.enabled visible: selectedBarConfig?.enabled
SettingsControlledByFrame {
visible: SettingsData.frameEnabled
parentModal: dankBarTab.parentModal
settingLabel: I18n.tr("Bar corners and background")
reason: I18n.tr("Managed by Frame")
}
SettingsToggleRow { SettingsToggleRow {
text: I18n.tr("Square Corners") text: I18n.tr("Square Corners")
enabled: !SettingsData.frameEnabled visible: !SettingsData.frameEnabled
opacity: SettingsData.frameEnabled ? 0.5 : 1.0
checked: selectedBarConfig?.squareCorners ?? false checked: selectedBarConfig?.squareCorners ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, { onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
squareCorners: checked squareCorners: checked
@@ -1038,8 +997,7 @@ Item {
SettingsToggleRow { SettingsToggleRow {
text: I18n.tr("No Background") text: I18n.tr("No Background")
enabled: !SettingsData.frameEnabled visible: !SettingsData.frameEnabled
opacity: SettingsData.frameEnabled ? 0.5 : 1.0
checked: selectedBarConfig?.noBackground ?? false checked: selectedBarConfig?.noBackground ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, { onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
noBackground: checked noBackground: checked
@@ -1079,8 +1037,7 @@ Item {
SettingsToggleRow { SettingsToggleRow {
text: I18n.tr("Goth Corners") text: I18n.tr("Goth Corners")
enabled: !SettingsData.frameEnabled visible: !SettingsData.frameEnabled
opacity: SettingsData.frameEnabled ? 0.5 : 1.0
checked: selectedBarConfig?.gothCornersEnabled ?? false checked: selectedBarConfig?.gothCornersEnabled ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, { onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
gothCornersEnabled: checked gothCornersEnabled: checked
@@ -1416,33 +1373,11 @@ Item {
} }
} }
Item { SettingsControlledByFrame {
visible: dankBarTab.connectedFrameModeActive visible: dankBarTab.connectedFrameModeActive
width: parent.width parentModal: dankBarTab.parentModal
implicitHeight: connectedFrameStyleNote.implicitHeight + Theme.spacingS * 2 settingLabel: I18n.tr("Bar shadow, border, and corners")
reason: I18n.tr("Managed by Frame in Connected Mode")
Row {
id: connectedFrameStyleNote
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "frame_source"
size: Theme.fontSizeMedium
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Connected Frame mode keeps bar shadow override, border, and corner overrides off while active")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - Theme.fontSizeMedium - Theme.spacingS
}
}
} }
SettingsCard { SettingsCard {
@@ -1452,9 +1387,7 @@ Item {
settingKey: "barShadow" settingKey: "barShadow"
collapsible: true collapsible: true
expanded: false expanded: false
visible: selectedBarConfig?.enabled visible: (selectedBarConfig?.enabled ?? false) && !dankBarTab.connectedFrameModeActive
enabled: !dankBarTab.connectedFrameModeActive
opacity: dankBarTab.connectedFrameModeActive ? 0.5 : 1.0
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0 readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "default") === "custom" readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "default") === "custom"

View File

@@ -7,9 +7,9 @@ import qs.Modules.Settings.Widgets
Item { Item {
id: root id: root
readonly property bool connectedFrameModeActive: SettingsData.frameEnabled
&& SettingsData.motionEffect === 1 property var parentModal: null
&& SettingsData.directionalAnimationMode === 3 readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
FileBrowserModal { FileBrowserModal {
id: dockLogoFileBrowser id: dockLogoFileBrowser
@@ -607,8 +607,7 @@ Item {
SettingsSliderRow { SettingsSliderRow {
text: I18n.tr("Exclusive Zone Offset") text: I18n.tr("Exclusive Zone Offset")
enabled: !root.connectedFrameModeActive visible: !root.connectedFrameModeActive
opacity: root.connectedFrameModeActive ? 0.5 : 1.0
value: SettingsData.dockBottomGap value: SettingsData.dockBottomGap
minimum: -100 minimum: -100
maximum: 100 maximum: 100
@@ -618,8 +617,7 @@ Item {
SettingsSliderRow { SettingsSliderRow {
text: I18n.tr("Margin") text: I18n.tr("Margin")
enabled: !root.connectedFrameModeActive visible: !root.connectedFrameModeActive
opacity: root.connectedFrameModeActive ? 0.5 : 1.0
value: SettingsData.dockMargin value: SettingsData.dockMargin
minimum: 0 minimum: 0
maximum: 100 maximum: 100
@@ -628,33 +626,11 @@ Item {
} }
} }
Item { SettingsControlledByFrame {
visible: root.connectedFrameModeActive visible: root.connectedFrameModeActive
width: parent.width parentModal: root.parentModal
implicitHeight: dockConnectedNote.implicitHeight + Theme.spacingS * 2 settingLabel: I18n.tr("Dock spacing, transparency, and border")
reason: I18n.tr("Managed by Frame in Connected Mode")
Row {
id: dockConnectedNote
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
DankIcon {
name: "frame_source"
size: Theme.fontSizeMedium
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
StyledText {
text: I18n.tr("Connected Frame mode manages dock edge offset, transparency, blur, and border styling")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width - Theme.fontSizeMedium - Theme.spacingS
}
}
} }
SettingsCard { SettingsCard {
@@ -662,8 +638,7 @@ Item {
iconName: "opacity" iconName: "opacity"
title: I18n.tr("Transparency") title: I18n.tr("Transparency")
settingKey: "dockTransparency" settingKey: "dockTransparency"
enabled: !root.connectedFrameModeActive visible: !root.connectedFrameModeActive
opacity: root.connectedFrameModeActive ? 0.5 : 1.0
SettingsSliderRow { SettingsSliderRow {
text: I18n.tr("Dock Transparency") text: I18n.tr("Dock Transparency")
@@ -683,8 +658,7 @@ Item {
settingKey: "dockBorder" settingKey: "dockBorder"
collapsible: true collapsible: true
expanded: false expanded: false
enabled: !root.connectedFrameModeActive visible: !root.connectedFrameModeActive
opacity: root.connectedFrameModeActive ? 0.5 : 1.0
SettingsToggleRow { SettingsToggleRow {
text: I18n.tr("Border") text: I18n.tr("Border")

View File

@@ -25,7 +25,6 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL spacing: Theme.spacingXL
// ── Enable Frame ──────────────────────────────────────────────────
SettingsCard { SettingsCard {
width: parent.width width: parent.width
iconName: "frame_source" iconName: "frame_source"
@@ -42,7 +41,35 @@ Item {
} }
} }
// ── Border ──────────────────────────────────────────────────────── SettingsCard {
width: parent.width
iconName: "tune"
title: I18n.tr("Mode")
settingKey: "frameMode"
visible: SettingsData.frameEnabled
SettingsButtonGroupRow {
settingKey: "frameModeSelector"
tags: ["frame", "mode", "connected", "separate", "popout"]
text: I18n.tr("Surface Behavior")
description: SettingsData.frameMode === "connected" ? I18n.tr("Surfaces emerge flush from the bar") : I18n.tr("Surfaces float independently of the frame")
model: [I18n.tr("Separate"), I18n.tr("Connected")]
currentIndex: SettingsData.frameMode === "connected" ? 1 : 0
onSelectionChanged: (index, selected) => {
if (!selected)
return;
switch (index) {
case 1:
SettingsData.set("frameMode", "connected");
break;
default:
SettingsData.set("frameMode", "separate");
break;
}
}
}
}
SettingsCard { SettingsCard {
width: parent.width width: parent.width
iconName: "border_outer" iconName: "border_outer"
@@ -56,9 +83,6 @@ Item {
settingKey: "frameRounding" settingKey: "frameRounding"
tags: ["frame", "border", "rounding", "radius", "corner"] tags: ["frame", "border", "rounding", "radius", "corner"]
text: I18n.tr("Border Radius") text: I18n.tr("Border Radius")
description: SettingsData.connectedFrameModeActive
? I18n.tr("Controls the radius of the frame and all connected popout, dock, and modal surfaces while Connected Mode is active")
: I18n.tr("Controls the frame border radius. This also becomes the connected surface radius whenever Connected Mode is active")
unit: "px" unit: "px"
minimum: 0 minimum: 0
maximum: 100 maximum: 100
@@ -99,7 +123,7 @@ Item {
settingKey: "frameBarSize" settingKey: "frameBarSize"
tags: ["frame", "bar", "thickness", "size", "height", "width"] tags: ["frame", "bar", "thickness", "size", "height", "width"]
text: I18n.tr("Size") text: I18n.tr("Size")
description: I18n.tr("Height of horizontal bars / width of vertical bars in frame mode") description: I18n.tr("Horizontal and vertical bar thickness")
unit: "px" unit: "px"
minimum: 24 minimum: 24
maximum: 100 maximum: 100
@@ -120,7 +144,6 @@ Item {
settingKey: "frameOpacity" settingKey: "frameOpacity"
tags: ["frame", "border", "surface", "popup", "opacity", "transparency"] tags: ["frame", "border", "surface", "popup", "opacity", "transparency"]
text: I18n.tr("Surface Opacity") text: I18n.tr("Surface Opacity")
description: I18n.tr("Frame border opacity. Controls all surface opacity globally when Connected Mode is active")
unit: "%" unit: "%"
minimum: 0 minimum: 0
maximum: 100 maximum: 100
@@ -140,9 +163,7 @@ Item {
settingKey: "frameBlurEnabled" settingKey: "frameBlurEnabled"
tags: ["frame", "blur", "background", "glass", "transparency", "frosted"] tags: ["frame", "blur", "background", "glass", "transparency", "frosted"]
text: I18n.tr("Frame Blur") text: I18n.tr("Frame Blur")
description: !BlurService.available description: !BlurService.available ? I18n.tr("Requires a newer version of Quickshell") : I18n.tr("Apply compositor blur behind the frame border")
? I18n.tr("Requires a newer version of Quickshell")
: I18n.tr("Apply compositor blur behind the frame border")
checked: SettingsData.frameBlurEnabled checked: SettingsData.frameBlurEnabled
onToggled: checked => SettingsData.set("frameBlurEnabled", checked) onToggled: checked => SettingsData.set("frameBlurEnabled", checked)
enabled: BlurService.available && SettingsData.blurEnabled enabled: BlurService.available && SettingsData.blurEnabled
@@ -170,7 +191,7 @@ Item {
} }
StyledText { StyledText {
text: I18n.tr("Frame Blur is controlled by Background Blur in Theme & Colors") text: I18n.tr("Frame Blur follows Background Blur in Theme & Colors")
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@@ -179,35 +200,47 @@ Item {
} }
} }
// Color mode buttons
SettingsButtonGroupRow { SettingsButtonGroupRow {
settingKey: "frameColor" settingKey: "frameColor"
tags: ["frame", "border", "color", "theme", "primary", "surface", "default"] tags: ["frame", "border", "color", "theme", "primary", "surface", "default"]
text: I18n.tr("Border color") text: I18n.tr("Border Color")
model: [I18n.tr("Default"), I18n.tr("Primary"), I18n.tr("Surface"), I18n.tr("Custom")] model: [I18n.tr("Default"), I18n.tr("Primary"), I18n.tr("Surface"), I18n.tr("Custom")]
currentIndex: { currentIndex: {
const fc = SettingsData.frameColor; const fc = SettingsData.frameColor;
if (!fc || fc === "default") return 0; if (!fc || fc === "default")
if (fc === "primary") return 1; return 0;
if (fc === "surface") return 2; switch (fc) {
return 3; case "primary":
return 1;
case "surface":
return 2;
default:
return 3;
}
} }
onSelectionChanged: (index, selected) => { onSelectionChanged: (index, selected) => {
if (!selected) return; if (!selected)
return;
switch (index) { switch (index) {
case 0: SettingsData.set("frameColor", ""); break; case 0:
case 1: SettingsData.set("frameColor", "primary"); break; SettingsData.set("frameColor", "");
case 2: SettingsData.set("frameColor", "surface"); break; break;
case 1:
SettingsData.set("frameColor", "primary");
break;
case 2:
SettingsData.set("frameColor", "surface");
break;
case 3: case 3:
const cur = SettingsData.frameColor; const cur = SettingsData.frameColor;
const isPreset = !cur || cur === "primary" || cur === "surface"; const isPreset = !cur || cur === "primary" || cur === "surface";
if (isPreset) SettingsData.set("frameColor", "#2a2a2a"); if (isPreset)
SettingsData.set("frameColor", "#2a2a2a");
break; break;
} }
} }
} }
// Custom color swatch — only visible when a hex color is stored (Custom mode)
Item { Item {
visible: { visible: {
const fc = SettingsData.frameColor; const fc = SettingsData.frameColor;
@@ -225,14 +258,13 @@ Item {
StyledText { StyledText {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Custom color") text: I18n.tr("Custom Color")
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium font.weight: Font.Medium
color: Theme.surfaceText color: Theme.surfaceText
} }
Rectangle { Rectangle {
id: colorSwatch
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: 32 width: 32
height: 32 height: 32
@@ -258,7 +290,39 @@ Item {
} }
} }
// ── Bar Integration ─────────────────────────────────────────────── SettingsCard {
width: parent.width
iconName: "blur_linear"
title: I18n.tr("Connected Options")
settingKey: "frameConnectedOptions"
collapsible: true
expanded: true
visible: SettingsData.frameEnabled && SettingsData.frameMode === "connected"
SettingsToggleRow {
settingKey: "frameCloseGaps"
tags: ["frame", "connected", "gap", "edge", "flush", "popout", "notification"]
text: I18n.tr("Close the Gaps")
description: I18n.tr("Connected popouts sit flush with the frame")
checked: SettingsData.frameCloseGaps
onToggled: checked => SettingsData.set("frameCloseGaps", checked)
}
SettingsButtonGroupRow {
settingKey: "frameLauncherEmergeSide"
tags: ["frame", "connected", "launcher", "modal", "emerge", "direction", "bottom", "top"]
text: I18n.tr("Launcher Emerge Side")
description: I18n.tr("Edge the launcher slides from")
model: [I18n.tr("Bottom"), I18n.tr("Top")]
currentIndex: SettingsData.frameLauncherEmergeSide === "top" ? 1 : 0
onSelectionChanged: (index, selected) => {
if (!selected)
return;
SettingsData.set("frameLauncherEmergeSide", index === 1 ? "top" : "bottom");
}
}
}
SettingsCard { SettingsCard {
width: parent.width width: parent.width
iconName: "toolbar" iconName: "toolbar"
@@ -266,73 +330,18 @@ Item {
settingKey: "frameBarIntegration" settingKey: "frameBarIntegration"
collapsible: true collapsible: true
expanded: true expanded: true
visible: SettingsData.frameEnabled visible: SettingsData.frameEnabled && CompositorService.isNiri
SettingsToggleRow { SettingsToggleRow {
visible: CompositorService.isNiri
settingKey: "frameShowOnOverview" settingKey: "frameShowOnOverview"
tags: ["frame", "overview", "show", "hide", "niri"] tags: ["frame", "overview", "show", "hide", "niri"]
text: I18n.tr("Show on Overview") text: I18n.tr("Show on Overview")
description: I18n.tr("Show the bar and frame during Niri overview mode") description: I18n.tr("Show during Niri overview")
checked: SettingsData.frameShowOnOverview checked: SettingsData.frameShowOnOverview
onToggled: checked => SettingsData.set("frameShowOnOverview", checked) onToggled: checked => SettingsData.set("frameShowOnOverview", checked)
} }
SettingsToggleRow {
visible: SettingsData.frameEnabled
settingKey: "directionalAnimationMode"
tags: ["frame", "connected", "popout", "corner", "animation"]
text: I18n.tr("Connected Mode")
description: I18n.tr("Popouts emerge flush from the bar edge as one continuous piece")
checked: SettingsData.connectedFrameModeActive
onToggled: checked => {
if (checked) {
if (SettingsData.directionalAnimationMode !== 3)
SettingsData.set("previousDirectionalMode", SettingsData.directionalAnimationMode);
SettingsData.set("motionEffect", 1);
SettingsData.set("directionalAnimationMode", 3);
} else {
SettingsData.set("directionalAnimationMode", SettingsData.previousDirectionalMode);
}
}
Connections {
target: SettingsData
function onDirectionalAnimationModeChanged() {}
function onMotionEffectChanged() {}
}
}
SettingsToggleRow {
visible: SettingsData.frameEnabled
settingKey: "frameCloseGaps"
tags: ["frame", "connected", "gap", "edge", "flush", "popout", "notification"]
text: I18n.tr("Close the Gaps")
description: I18n.tr("Connected popouts and notification corners sit flush against the frame edge")
checked: SettingsData.frameCloseGaps
enabled: SettingsData.connectedFrameModeActive
opacity: enabled ? 1.0 : 0.5
onToggled: checked => SettingsData.set("frameCloseGaps", checked)
}
SettingsButtonGroupRow {
visible: SettingsData.frameEnabled
settingKey: "frameLauncherEmergeSide"
tags: ["frame", "connected", "launcher", "modal", "emerge", "direction", "bottom", "top"]
text: I18n.tr("Launcher Emerge Side")
description: I18n.tr("Which frame edge the Launcher slides in from. Other modals emerge from the opposite side.")
model: [I18n.tr("Bottom"), I18n.tr("Top")]
currentIndex: SettingsData.frameLauncherEmergeSide === "top" ? 1 : 0
enabled: SettingsData.connectedFrameModeActive
opacity: enabled ? 1.0 : 0.5
onSelectionChanged: (index, selected) => {
if (!selected) return;
SettingsData.set("frameLauncherEmergeSide", index === 1 ? "top" : "bottom");
}
}
} }
// ── Display Assignment ────────────────────────────────────────────
SettingsCard { SettingsCard {
width: parent.width width: parent.width
iconName: "monitor" iconName: "monitor"

View File

@@ -11,6 +11,7 @@ import qs.Modules.Settings.Widgets
Item { Item {
id: themeColorsTab id: themeColorsTab
property var parentModal: null
readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive readonly property bool connectedFrameModeActive: SettingsData.connectedFrameModeActive
property var cachedIconThemes: SettingsData.availableIconThemes property var cachedIconThemes: SettingsData.availableIconThemes
property var cachedCursorThemes: SettingsData.availableCursorThemes property var cachedCursorThemes: SettingsData.availableCursorThemes
@@ -1614,16 +1615,20 @@ Item {
} }
} }
SettingsControlledByFrame {
visible: themeColorsTab.connectedFrameModeActive
parentModal: themeColorsTab.parentModal
settingLabel: I18n.tr("Surface Opacity")
reason: I18n.tr("Managed by Frame in Connected Mode")
}
SettingsSliderRow { SettingsSliderRow {
tab: "theme" tab: "theme"
tags: ["surface", "popup", "transparency", "opacity", "modal"] tags: ["surface", "popup", "transparency", "opacity", "modal"]
settingKey: "popupTransparency" settingKey: "popupTransparency"
text: I18n.tr("Surface Opacity") text: I18n.tr("Surface Opacity")
description: themeColorsTab.connectedFrameModeActive description: I18n.tr("Controls opacity of all popouts, modals, and their content layers")
? I18n.tr("Connected Frame mode follows Surface Opacity from the Frame tab for connected popouts, docks, and modal surfaces") visible: !themeColorsTab.connectedFrameModeActive
: I18n.tr("Controls opacity of all popouts, modals, and their content layers")
enabled: !themeColorsTab.connectedFrameModeActive
opacity: themeColorsTab.connectedFrameModeActive ? 0.5 : 1.0
value: Math.round(SettingsData.popupTransparency * 100) value: Math.round(SettingsData.popupTransparency * 100)
minimum: 0 minimum: 0
maximum: 100 maximum: 100
@@ -1637,9 +1642,7 @@ Item {
tags: ["corner", "radius", "rounded", "square"] tags: ["corner", "radius", "rounded", "square"]
settingKey: "cornerRadius" settingKey: "cornerRadius"
text: I18n.tr("Corner Radius") text: I18n.tr("Corner Radius")
description: themeColorsTab.connectedFrameModeActive description: I18n.tr("0 = square corners")
? I18n.tr("Controls general UI rounding. Connected frame popouts, docks, and modal surfaces follow Border Radius in the Frame tab while Connected Frame mode is active")
: I18n.tr("0 = square corners")
value: SettingsData.cornerRadius value: SettingsData.cornerRadius
minimum: 0 minimum: 0
maximum: 32 maximum: 32
@@ -1844,11 +1847,7 @@ Item {
tags: ["blur", "background", "transparency", "glass", "frosted"] tags: ["blur", "background", "transparency", "glass", "frosted"]
settingKey: "blurEnabled" settingKey: "blurEnabled"
text: I18n.tr("Background Blur") text: I18n.tr("Background Blur")
description: !BlurService.available description: !BlurService.available ? I18n.tr("Requires a newer version of Quickshell") : I18n.tr("Blur the background behind bars, popouts, modals, and notifications. Requires compositor support and configuration.")
? I18n.tr("Requires a newer version of Quickshell")
: (themeColorsTab.connectedFrameModeActive
? I18n.tr("Connected Frame mode follows Frame Blur for connected surfaces while this remains the master blur availability toggle")
: I18n.tr("Blur the background behind bars, popouts, modals, and notifications. Requires compositor support and configuration."))
checked: SettingsData.blurEnabled ?? false checked: SettingsData.blurEnabled ?? false
enabled: BlurService.available enabled: BlurService.available
onToggled: checked => SettingsData.set("blurEnabled", checked) onToggled: checked => SettingsData.set("blurEnabled", checked)

View File

@@ -191,46 +191,6 @@ Item {
} }
} }
} }
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.15
visible: SettingsData.motionEffect === 1
}
SettingsDropdownRow {
visible: SettingsData.motionEffect === 1
tab: "typography"
tags: ["animation", "directional", "behavior", "fluid", "connected"]
settingKey: "directionalAnimationMode"
text: I18n.tr("Directional Behavior")
description: {
if (SettingsData.connectedFrameModeActive)
return I18n.tr("Popouts emerge flush from the bar edge as a single continuous piece, with corner connectors bridging the junction");
return I18n.tr("How the popout emerges from the DankBar");
}
options: SettingsData.frameEnabled ? [I18n.tr("Fluid"), I18n.tr("Connected")] : [I18n.tr("Fluid")]
currentValue: {
switch (SettingsData.directionalAnimationMode) {
case 3:
return SettingsData.frameEnabled ? I18n.tr("Connected") : I18n.tr("Fluid");
default:
return I18n.tr("Fluid");
}
}
onValueChanged: value => {
if (value === I18n.tr("Fluid"))
SettingsData.set("directionalAnimationMode", 1);
else if (value === I18n.tr("Connected") && SettingsData.frameEnabled) {
if (SettingsData.directionalAnimationMode !== 3)
SettingsData.set("previousDirectionalMode", 1);
SettingsData.set("directionalAnimationMode", 3);
} else
SettingsData.set("directionalAnimationMode", 1);
}
}
} }
SettingsCard { SettingsCard {

View File

@@ -0,0 +1,79 @@
pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Widgets
StyledRect {
id: root
LayoutMirroring.enabled: I18n.isRtl
LayoutMirroring.childrenInherit: true
property string settingLabel: ""
property string reason: ""
property var parentModal: null
width: parent?.width ?? 0
height: contentRow.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.primary, 0.08)
border.color: Theme.withAlpha(Theme.primary, 0.18)
border.width: 1
Row {
id: contentRow
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
anchors.rightMargin: Theme.spacingM
spacing: Theme.spacingM
DankIcon {
name: "frame_source"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - Theme.iconSize - openButton.width - Theme.spacingM * 2
spacing: 2
StyledText {
text: root.settingLabel
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width
wrapMode: Text.WordWrap
}
StyledText {
text: root.reason
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: parent.width
wrapMode: Text.WordWrap
visible: root.reason !== ""
}
}
DankButton {
id: openButton
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr("Open Frame")
backgroundColor: Theme.primary
textColor: Theme.primaryText
buttonHeight: 32
horizontalPadding: Theme.spacingM
onClicked: {
if (!root.parentModal)
return;
root.parentModal.showWithTabName("frame");
}
}
}
}

View File

@@ -500,11 +500,8 @@ Item {
readonly property real shadowMotionPadding: { readonly property real shadowMotionPadding: {
if (Theme.isConnectedEffect) if (Theme.isConnectedEffect)
return Math.max(storedBarSpacing + Theme.connectedCornerRadius + 4, 40); return Math.max(storedBarSpacing + Theme.connectedCornerRadius + 4, 40);
if (Theme.isDirectionalEffect) { if (Theme.isDirectionalEffect)
if (typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode > 0) return 16;
return 16; // Fluid uses strict Wayland clipping instead of extra motion padding.
return Math.max(0, animationOffset) + 16;
}
if (Theme.isDepthEffect) if (Theme.isDepthEffect)
return Math.max(0, animationOffset) + 8; return Math.max(0, animationOffset) + 8;
return Math.max(0, animationOffset); return Math.max(0, animationOffset);
@@ -901,7 +898,7 @@ Item {
Item { Item {
id: directionalClipMask id: directionalClipMask
readonly property bool shouldClip: (Theme.isDirectionalEffect && typeof SettingsData !== "undefined" && SettingsData.directionalAnimationMode > 0) || Theme.isConnectedEffect readonly property bool shouldClip: Theme.isDirectionalEffect || Theme.isConnectedEffect
readonly property real clipOversize: 1000 readonly property real clipOversize: 1000
readonly property real connectedClipAllowance: { readonly property real connectedClipAllowance: {
if (!Theme.isConnectedEffect) if (!Theme.isConnectedEffect)