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

Compare commits

...

10 Commits

Author SHA1 Message Date
Archit Arora
bcf41ed5ca feat(system-tray): add icon tinting (#2266) 2026-04-25 15:32:14 -04:00
purian23
5033bdc630 (settings): Update monocrhrome & settings 2026-04-25 15:29:27 -04:00
purian23
b8bfaf9a26 (dbar): Settings reorg 2026-04-25 14:52:38 -04:00
Kangheng Liu
da45714c54 keybinds: add move workspace to monitor keybinds (#2268)
and distinguish with move columns
2026-04-25 14:45:23 -04:00
bbedward
0c2d00b79c fix transparency 2026-04-25 11:54:19 -04:00
purian23
c10b42f599 dms(blur): Dank all the things 2026-04-25 11:54:18 -04:00
bbedward
4c617cf022 fix popout transparency 2026-04-25 11:54:18 -04:00
bbedward
e75b95b854 blur: revise general blur styling and refine it
cherry-pick of 1abb2210 from master, translated to hotfix-1.4.5
(omits ElevationShadow gating since shadow overhaul isn't on this
branch; gates existing MultiEffect-based shadows by BlurService.enabled
instead). Drops DoNotDisturbDetail.qml hunk since the file does not
exist on this branch.
2026-04-25 11:54:18 -04:00
Lucas
6b15670918 nix: update quickshell version (#2263)
Updated the quickshell revision to 783c95, matching the "stable" package in other DMS distributions.
2026-04-24 17:17:36 -04:00
Walid Salah
c52b9e19a1 Fix focused app when switching to empty workspace (#2259)
* Fix multiple screens on niri, when switching to an empty wokspace the other screen focused app widget would get confused

* Blank workspace fix
2026-04-24 17:17:36 -04:00
70 changed files with 1668 additions and 786 deletions

10
flake.lock generated
View File

@@ -23,16 +23,16 @@
]
},
"locked": {
"lastModified": 1766725085,
"narHash": "sha256-O2aMFdDUYJazFrlwL7aSIHbUSEm3ADVZjmf41uBJfHs=",
"lastModified": 1776854048,
"narHash": "sha256-lLbV66V3RMNp1l8/UelmR4YzoJ5ONtgvEtiUMJATH/o=",
"ref": "refs/heads/master",
"rev": "41828c4180fb921df7992a5405f5ff05d2ac2fff",
"revCount": 715,
"rev": "783c953987dc56ff0601abe6845ed96f1d00495a",
"revCount": 806,
"type": "git",
"url": "https://git.outfoxxed.me/quickshell/quickshell"
},
"original": {
"rev": "41828c4180fb921df7992a5405f5ff05d2ac2fff",
"rev": "783c953987dc56ff0601abe6845ed96f1d00495a",
"type": "git",
"url": "https://git.outfoxxed.me/quickshell/quickshell"
}

View File

@@ -4,7 +4,7 @@
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
quickshell = {
url = "git+https://git.outfoxxed.me/quickshell/quickshell?rev=41828c4180fb921df7992a5405f5ff05d2ac2fff";
url = "git+https://git.outfoxxed.me/quickshell/quickshell?rev=783c953987dc56ff0601abe6845ed96f1d00495a";
inputs.nixpkgs.follows = "nixpkgs";
};
};

View File

@@ -158,10 +158,16 @@ const NIRI_ACTIONS = {
{ id: "focus-monitor-right", label: "Focus Monitor Right" },
{ id: "focus-monitor-down", label: "Focus Monitor Down" },
{ id: "focus-monitor-up", label: "Focus Monitor Up" },
{ id: "move-column-to-monitor-left", label: "Move to Monitor Left" },
{ id: "move-column-to-monitor-right", label: "Move to Monitor Right" },
{ id: "move-column-to-monitor-down", label: "Move to Monitor Down" },
{ id: "move-column-to-monitor-up", label: "Move to Monitor Up" }
{ id: "move-column-to-monitor-left", label: "Move Column to Monitor Left" },
{ id: "move-column-to-monitor-right", label: "Move Column to Monitor Right" },
{ id: "move-column-to-monitor-down", label: "Move Column to Monitor Down" },
{ id: "move-column-to-monitor-up", label: "Move Column to Monitor Up" },
{ id: "move-workspace-to-monitor-left", label: "Move Workspace to Monitor Left" },
{ id: "move-workspace-to-monitor-right", label: "Move Workspace to Monitor Right" },
{ id: "move-workspace-to-monitor-down", label: "Move Workspace to Monitor Down" },
{ id: "move-workspace-to-monitor-up", label: "Move Workspace to Monitor Up" },
{ id: "move-workspace-to-monitor-next", label: "Move Workspace to Next Monitor" },
{ id: "move-workspace-to-monitor-previous", label: "Move Workspace to Previous Monitor" }
],
"Screenshot": [
{ id: "screenshot", label: "Screenshot (Interactive)" },

View File

@@ -167,11 +167,15 @@ Singleton {
onEnableRippleEffectsChanged: saveSettings()
property bool blurEnabled: false
onBlurEnabledChanged: saveSettings()
property bool blurForegroundLayers: true
onBlurForegroundLayersChanged: saveSettings()
property real blurLayerOutlineOpacity: 0.12
onBlurLayerOutlineOpacityChanged: saveSettings()
property string blurBorderColor: "outline"
onBlurBorderColorChanged: saveSettings()
property string blurBorderCustomColor: "#ffffff"
onBlurBorderCustomColorChanged: saveSettings()
property real blurBorderOpacity: 1.0
property real blurBorderOpacity: 0.35
onBlurBorderOpacityChanged: saveSettings()
property string wallpaperFillMode: "Fill"
property bool blurredWallpaperLayer: false
@@ -190,6 +194,9 @@ Singleton {
property int selectedGpuIndex: 0
property var enabledGpuPciIds: []
property bool showSystemTray: true
property string systemTrayIconTintMode: "none"
property int systemTrayIconTintSaturation: 50
property int systemTrayIconTintStrength: 135
property bool showClock: true
property bool showNotificationButton: true
property bool showBattery: true
@@ -1292,9 +1299,7 @@ Singleton {
return true;
const msg = String(error || "").toLowerCase();
return msg.indexOf("file does not exist") !== -1
|| msg.indexOf("no such file") !== -1
|| msg.indexOf("enoent") !== -1;
return msg.indexOf("file does not exist") !== -1 || msg.indexOf("no such file") !== -1 || msg.indexOf("enoent") !== -1;
}
function loadPluginSettings() {

View File

@@ -561,8 +561,8 @@ Singleton {
property color success: currentThemeData.success || "#4CAF50"
property color primaryHover: Qt.rgba(primary.r, primary.g, primary.b, 0.12)
property color primaryHoverLight: Qt.rgba(primary.r, primary.g, primary.b, 0.08)
property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, 0.16)
property color primaryHoverLight: Qt.rgba(primary.r, primary.g, primary.b, transparentBlurLayers ? 0.12 : 0.08)
property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, transparentBlurLayers ? 0.24 : 0.16)
property color primarySelected: Qt.rgba(primary.r, primary.g, primary.b, 0.3)
property color primaryBackground: Qt.rgba(primary.r, primary.g, primary.b, 0.04)
@@ -571,17 +571,28 @@ Singleton {
property color surfaceHover: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.08)
property color surfacePressed: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.12)
property color surfaceSelected: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.15)
property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.1)
property color surfaceLight: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, transparentBlurLayers ? 0.3 : 0.1)
property color surfaceVariantAlpha: Qt.rgba(surfaceVariant.r, surfaceVariant.g, surfaceVariant.b, 0.2)
readonly property bool blurForegroundLayers: BlurService.enabled && (typeof SettingsData === "undefined" || (SettingsData.blurForegroundLayers ?? true))
readonly property bool transparentBlurLayers: BlurService.enabled && !blurForegroundLayers
readonly property color readableSurface: withAlpha(surfaceContainer, popupTransparency)
readonly property color readableSurfaceHigh: withAlpha(surfaceContainerHigh, popupTransparency)
readonly property color floatingSurface: transparentBlurLayers ? "transparent" : readableSurface
readonly property color floatingSurfaceHigh: transparentBlurLayers ? "transparent" : readableSurfaceHigh
readonly property color nestedSurface: floatingSurfaceHigh
readonly property real blurLayerOutlineOpacity: Math.max(0, Math.min(1, typeof SettingsData === "undefined" ? 0.12 : (SettingsData.blurLayerOutlineOpacity ?? 0.12)))
readonly property real layerOutlineOpacity: BlurService.enabled ? blurLayerOutlineOpacity : 0.08
readonly property int layerOutlineWidth: BlurService.enabled && layerOutlineOpacity > 0 ? 1 : 0
property color surfaceTextHover: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.08)
property color surfaceTextAlpha: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.3)
property color surfaceTextLight: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.06)
property color surfaceTextMedium: Qt.rgba(surfaceText.r, surfaceText.g, surfaceText.b, 0.7)
property color outlineButton: Qt.rgba(outline.r, outline.g, outline.b, 0.5)
property color outlineLight: Qt.rgba(outline.r, outline.g, outline.b, 0.05)
property color outlineMedium: Qt.rgba(outline.r, outline.g, outline.b, 0.08)
property color outlineStrong: Qt.rgba(outline.r, outline.g, outline.b, 0.12)
property color outlineLight: Qt.rgba(outline.r, outline.g, outline.b, BlurService.enabled ? Math.min(1, layerOutlineOpacity * 0.625) : 0.05)
property color outlineMedium: Qt.rgba(outline.r, outline.g, outline.b, layerOutlineOpacity)
property color outlineStrong: Qt.rgba(outline.r, outline.g, outline.b, BlurService.enabled ? Math.min(1, layerOutlineOpacity * 1.5) : 0.12)
property color errorHover: Qt.rgba(error.r, error.g, error.b, 0.12)
property color errorPressed: Qt.rgba(error.r, error.g, error.b, 0.16)
@@ -599,6 +610,12 @@ Singleton {
}
}
readonly property color ccTileInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.16) : (blurForegroundLayers ? withAlpha(surfaceContainerHigh, Math.min(popupTransparency, 0.24)) : withAlpha(surfaceContainer, popupTransparency))
readonly property color ccPillInactiveBg: transparentBlurLayers ? withAlpha(surfaceContainerHigh, 0.08) : nestedSurface
readonly property color ccPillInactiveHoverBg: transparentBlurLayers ? withAlpha(primary, 0.10) : primaryPressed
readonly property color ccSliderTrackColor: transparentBlurLayers ? surfaceText : surfaceContainerHigh
readonly property real ccSliderTrackOpacity: transparentBlurLayers ? 0.18 : popupTransparency
readonly property color ccTileActiveText: {
switch (SettingsData.controlCenterTileColorMode) {
case "primaryContainer":

View File

@@ -47,9 +47,11 @@ var SPEC = {
modalCustomAnimationDuration: { def: 150 },
enableRippleEffects: { def: true },
blurEnabled: { def: false },
blurForegroundLayers: { def: true },
blurLayerOutlineOpacity: { def: 0.12, coerce: percentToUnit },
blurBorderColor: { def: "outline" },
blurBorderCustomColor: { def: "#ffffff" },
blurBorderOpacity: { def: 1.0, coerce: percentToUnit },
blurBorderOpacity: { def: 0.35, coerce: percentToUnit },
wallpaperFillMode: { def: "Fill" },
blurredWallpaperLayer: { def: false },
blurWallpaperOnOverview: { def: false },
@@ -67,6 +69,9 @@ var SPEC = {
selectedGpuIndex: { def: 0 },
enabledGpuPciIds: { def: [] },
showSystemTray: { def: true },
systemTrayIconTintMode: { def: "none" },
systemTrayIconTintSaturation: { def: 50 },
systemTrayIconTintStrength: { def: 135 },
showClock: { def: true },
showNotificationButton: { def: true },
showBattery: { def: true },

View File

@@ -372,7 +372,7 @@ Popup {
anchors.fill: parent
implicitWidth: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
implicitHeight: menuColumn.implicitHeight + Theme.spacingS * 2
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
color: Theme.floatingSurface
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1

View File

@@ -58,9 +58,9 @@ Item {
item: items[i],
flatIndex: flatIdx,
sectionId: sectionId,
height: 52
height: 56
});
cumY += 52;
cumY += 56;
}
} else {
var cols = root.controller?.getGridColumns(sectionId) ?? root.gridColumns;
@@ -190,124 +190,135 @@ Item {
}
}
DankListView {
id: mainListView
Item {
id: listClip
anchors.fill: parent
anchors.topMargin: BlurService.enabled && stickyHeader.visible ? 32 : 0
clip: true
scrollBarTopMargin: (root.controller?.sections?.length > 0) ? 32 : 0
model: ScriptModel {
values: root._visualRows
objectProp: "_rowId"
}
DankListView {
id: mainListView
y: -listClip.anchors.topMargin
width: parent.width
height: parent.height + listClip.anchors.topMargin
clip: true
scrollBarTopMargin: (root.controller?.sections?.length > 0) ? 32 : 0
add: null
remove: null
displaced: null
move: null
delegate: Item {
id: delegateRoot
required property var modelData
required property int index
width: mainListView.width
height: modelData?.height ?? 52
SectionHeader {
anchors.fill: parent
visible: delegateRoot.modelData?.type === "header"
section: delegateRoot.modelData?.section ?? null
controller: root.controller
viewMode: {
var vt = root.controller?.viewModeVersion ?? 0;
void (vt);
return root.controller?.getSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? "list";
}
canChangeViewMode: {
var vt = root.controller?.viewModeVersion ?? 0;
void (vt);
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
}
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
model: ScriptModel {
values: root._visualRows
objectProp: "_rowId"
}
ResultItem {
anchors.fill: parent
visible: delegateRoot.modelData?.type === "list_item"
item: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.item ?? null) : null
isSelected: delegateRoot.modelData?.type === "list_item" && (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.flatIndex ?? -1) : -1
add: null
remove: null
displaced: null
move: null
onClicked: {
if (root.controller && delegateRoot.modelData?.item) {
root.controller.executeItem(delegateRoot.modelData.item);
delegate: Item {
id: delegateRoot
required property var modelData
required property int index
width: mainListView.width
height: modelData?.height ?? 52
SectionHeader {
anchors.fill: parent
visible: delegateRoot.modelData?.type === "header"
section: delegateRoot.modelData?.section ?? null
controller: root.controller
viewMode: {
var vt = root.controller?.viewModeVersion ?? 0;
void (vt);
return root.controller?.getSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? "list";
}
canChangeViewMode: {
var vt = root.controller?.viewModeVersion ?? 0;
void (vt);
return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
}
canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
}
ResultItem {
anchors.fill: parent
anchors.topMargin: 2
anchors.bottomMargin: 2
visible: delegateRoot.modelData?.type === "list_item"
item: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.item ?? null) : null
isSelected: delegateRoot.modelData?.type === "list_item" && (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.flatIndex ?? -1) : -1
onClicked: {
if (root.controller && delegateRoot.modelData?.item) {
root.controller.executeItem(delegateRoot.modelData.item);
}
}
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
}
}
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
}
}
Row {
id: gridRowContent
anchors.fill: parent
visible: delegateRoot.modelData?.type === "grid_row"
Row {
id: gridRowContent
anchors.fill: parent
visible: delegateRoot.modelData?.type === "grid_row"
Repeater {
model: delegateRoot.modelData?.type === "grid_row" ? (delegateRoot.modelData?.items ?? []) : []
Repeater {
model: delegateRoot.modelData?.type === "grid_row" ? (delegateRoot.modelData?.items ?? []) : []
Item {
id: gridCellDelegate
required property var modelData
required property int index
Item {
id: gridCellDelegate
required property var modelData
required property int index
readonly property real cellWidth: delegateRoot.modelData?.viewMode === "tile" ? Math.floor(delegateRoot.width / 3) : Math.floor(delegateRoot.width / (delegateRoot.modelData?.cols ?? root.gridColumns))
readonly property real cellWidth: delegateRoot.modelData?.viewMode === "tile" ? Math.floor(delegateRoot.width / 3) : Math.floor(delegateRoot.width / (delegateRoot.modelData?.cols ?? root.gridColumns))
width: cellWidth
height: delegateRoot.height
width: cellWidth
height: delegateRoot.height
GridItem {
width: parent.width - 4
height: parent.height - 4
anchors.centerIn: parent
visible: delegateRoot.modelData?.viewMode === "grid"
item: gridCellDelegate.modelData?.item ?? null
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
GridItem {
width: parent.width - 4
height: parent.height - 4
anchors.centerIn: parent
visible: delegateRoot.modelData?.viewMode === "grid"
item: gridCellDelegate.modelData?.item ?? null
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
onClicked: {
if (root.controller && gridCellDelegate.modelData?.item) {
root.controller.executeItem(gridCellDelegate.modelData.item);
}
}
onClicked: {
if (root.controller && gridCellDelegate.modelData?.item) {
root.controller.executeItem(gridCellDelegate.modelData.item);
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
}
}
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
}
}
TileItem {
width: parent.width - 4
height: parent.height - 4
anchors.centerIn: parent
visible: delegateRoot.modelData?.viewMode === "tile"
item: gridCellDelegate.modelData?.item ?? null
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
TileItem {
width: parent.width - 4
height: parent.height - 4
anchors.centerIn: parent
visible: delegateRoot.modelData?.viewMode === "tile"
item: gridCellDelegate.modelData?.item ?? null
isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
controller: root.controller
flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
onClicked: {
if (root.controller && gridCellDelegate.modelData?.item) {
root.controller.executeItem(gridCellDelegate.modelData.item);
onClicked: {
if (root.controller && gridCellDelegate.modelData?.item) {
root.controller.executeItem(gridCellDelegate.modelData.item);
}
}
}
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
onRightClicked: (mouseX, mouseY) => {
root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
}
}
}
}
@@ -365,7 +376,7 @@ Item {
anchors.top: parent.top
height: 32
z: 101
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
color: Theme.floatingSurface
visible: stickyHeaderSection !== null
readonly property int versionTrigger: root.controller?.viewModeVersion ?? 0

View File

@@ -50,7 +50,7 @@ Item {
id: listComponent
Column {
spacing: 2
spacing: 4
width: contentLoader.width
Repeater {

View File

@@ -34,7 +34,9 @@ PluginComponent {
id: detailRoot
implicitHeight: detailColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
DankActionButton {
anchors.top: parent.top

View File

@@ -27,12 +27,12 @@ Rectangle {
}
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing
color: isActive ? _tileBgActive : _tileBgInactive
border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: isActive ? 1 : 1
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6
function hoverTint(base) {

View File

@@ -507,7 +507,8 @@ Column {
anchors.centerIn: parent
width: parent.width
height: 14
property color sliderTrackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
sliderTrackColor: Theme.ccSliderTrackColor
sliderTrackOpacity: Theme.ccSliderTrackOpacity
}
}
}
@@ -529,7 +530,8 @@ Column {
instanceId: widgetData.instanceId || ""
screenName: root.screenName
parentScreen: root.parentScreen
property color sliderTrackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
sliderTrackColor: Theme.ccSliderTrackColor
sliderTrackOpacity: Theme.ccSliderTrackOpacity
onIconClicked: {
if (!root.editMode && DisplayService.devices && DisplayService.devices.length > 1) {
@@ -552,7 +554,8 @@ Column {
anchors.centerIn: parent
width: parent.width
height: 14
property color sliderTrackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
sliderTrackColor: Theme.ccSliderTrackColor
sliderTrackOpacity: Theme.ccSliderTrackOpacity
}
}
}

View File

@@ -1,5 +1,6 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Widgets
@@ -10,7 +11,11 @@ Row {
LayoutMirroring.childrenInherit: true
property var availableWidgets: []
property Item popoutContent: null
property var popupScreen: null
property real popoutX: 0
property real popoutY: 0
property real popoutWidth: 0
property real popoutHeight: 0
signal addWidget(string widgetId)
signal resetToDefault
@@ -19,121 +24,190 @@ Row {
height: 48
spacing: Theme.spacingS
onAddWidget: addWidgetPopup.close()
function openWidgetLibrary() {
if (popupScreen)
addWidgetWindow.screen = popupScreen;
addWidgetWindow.visible = true;
}
Popup {
id: addWidgetPopup
parent: popoutContent
x: parent ? Math.round((parent.width - width) / 2) : 0
y: parent ? Math.round((parent.height - height) / 2) : 0
width: 400
height: 300
modal: false
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
function closeWidgetLibrary() {
addWidgetWindow.visible = false;
}
background: Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
border.color: Theme.primarySelected
border.width: 0
radius: Theme.cornerRadius
onAddWidget: closeWidgetLibrary()
onVisibleChanged: {
if (!visible)
closeWidgetLibrary();
}
PanelWindow {
id: addWidgetWindow
screen: root.popupScreen
visible: false
color: "transparent"
WlrLayershell.namespace: "dms:control-center-widget-library"
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
anchors {
top: true
left: true
right: true
bottom: true
}
contentItem: Item {
readonly property bool blurActive: Theme.blurForegroundLayers || Theme.transparentBlurLayers
readonly property real surfaceAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.24 : 0.72) : Theme.popupTransparency
readonly property real rowAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.10 : 0.52) : Theme.popupTransparency
readonly property int panelWidth: 400
readonly property int panelHeight: 300
WindowBlur {
targetWindow: addWidgetWindow
blurX: widgetLibraryPanel.x
blurY: widgetLibraryPanel.y
blurWidth: addWidgetWindow.visible ? widgetLibraryPanel.width : 0
blurHeight: addWidgetWindow.visible ? widgetLibraryPanel.height : 0
blurRadius: Theme.cornerRadius
}
MouseArea {
anchors.fill: parent
anchors.margins: Theme.spacingL
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: root.closeWidgetLibrary()
}
Row {
id: headerRow
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: Theme.spacingM
FocusScope {
anchors.fill: parent
focus: addWidgetWindow.visible
DankIcon {
name: "add_circle"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Keys.onEscapePressed: event => {
root.closeWidgetLibrary();
event.accepted = true;
}
}
Typography {
text: I18n.tr("Add Widget")
style: Typography.Style.Subtitle
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: widgetLibraryPanel
width: addWidgetWindow.panelWidth
height: addWidgetWindow.panelHeight
x: Math.round((root.popoutWidth > 0 ? root.popoutX + (root.popoutWidth - width) / 2 : (addWidgetWindow.width - width) / 2))
y: Math.round((root.popoutHeight > 0 ? root.popoutY + (root.popoutHeight - height) / 2 : (addWidgetWindow.height - height) / 2))
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, addWidgetWindow.surfaceAlpha)
border.color: addWidgetWindow.blurActive ? Theme.outlineMedium : Theme.primarySelected
border.width: addWidgetWindow.blurActive ? Theme.layerOutlineWidth : 0
antialiasing: true
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: mouse => mouse.accepted = true
}
DankListView {
anchors.top: headerRow.bottom
anchors.topMargin: Theme.spacingM
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: Theme.spacingS
clip: true
model: root.availableWidgets
Item {
anchors.fill: parent
anchors.margins: Theme.spacingL
delegate: Rectangle {
width: 400 - Theme.spacingL * 2
height: 50
radius: Theme.cornerRadius
color: widgetMouseArea.containsMouse ? Theme.primaryHover : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: 0
Row {
id: headerRow
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: Theme.spacingM
Row {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
DankIcon {
name: modelData.icon
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
width: 400 - Theme.spacingL * 2 - Theme.iconSize - Theme.spacingM * 3 - Theme.iconSize
Typography {
text: modelData.text
style: Typography.Style.Body
color: Theme.surfaceText
elide: Text.ElideRight
width: parent.width
horizontalAlignment: Text.AlignLeft
}
Typography {
text: modelData.description
style: Typography.Style.Caption
color: Theme.outline
elide: Text.ElideRight
width: parent.width
horizontalAlignment: Text.AlignLeft
}
}
DankIcon {
name: "add"
size: Theme.iconSize - 4
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
DankIcon {
name: "add_circle"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: widgetMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.addWidget(modelData.id);
Typography {
text: I18n.tr("Add Widget")
style: Typography.Style.Subtitle
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
DankListView {
id: widgetList
anchors.top: headerRow.bottom
anchors.topMargin: Theme.spacingM
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: Theme.spacingS
clip: true
model: root.availableWidgets
delegate: Rectangle {
width: widgetList.width
height: 50
radius: Theme.cornerRadius
color: widgetMouseArea.containsMouse ? Theme.withAlpha(Theme.primary, addWidgetWindow.blurActive ? 0.12 : 0.08) : Theme.withAlpha(Theme.surfaceContainerHigh, addWidgetWindow.rowAlpha)
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
antialiasing: true
Row {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingM
DankIcon {
name: modelData.icon
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
width: parent.width - Theme.iconSize * 2 - Theme.spacingM * 3
Typography {
text: modelData.text
style: Typography.Style.Body
color: Theme.surfaceText
elide: Text.ElideRight
width: parent.width
horizontalAlignment: Text.AlignLeft
}
Typography {
text: modelData.description
style: Typography.Style.Caption
color: Theme.outline
elide: Text.ElideRight
width: parent.width
horizontalAlignment: Text.AlignLeft
}
}
DankIcon {
name: "add"
size: Theme.iconSize - 4
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
}
MouseArea {
id: widgetMouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.addWidget(modelData.id);
}
}
}
}
@@ -171,7 +245,7 @@ Row {
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: addWidgetPopup.open()
onClicked: root.openWidgetLibrary()
}
}

View File

@@ -21,9 +21,9 @@ Rectangle {
implicitHeight: 70
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Row {
anchors.left: parent.left

View File

@@ -41,7 +41,7 @@ DankPopout {
}
}
readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _containerBg: Theme.nestedSurface
function openWithSection(section) {
StateUtils.openWithSection(root, section);
@@ -210,7 +210,11 @@ DankPopout {
EditControls {
width: parent.width
visible: editMode
popoutContent: controlContent
popupScreen: root.screen
popoutX: root.alignedX
popoutY: root.alignedY
popoutWidth: root.alignedWidth
popoutHeight: root.alignedHeight
availableWidgets: {
if (!editMode)
return [];

View File

@@ -18,9 +18,9 @@ Rectangle {
implicitHeight: headerRow.height + (hasInputVolumeSliderInCC ? 0 : volumeSlider.height) + audioContent.height + Theme.spacingM
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Row {
id: headerRow
@@ -123,6 +123,8 @@ Rectangle {
unit: "%"
valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceVariant
trackColor: Theme.ccSliderTrackColor
trackOpacity: Theme.ccSliderTrackOpacity
onSliderValueChanged: function (newValue) {
if (AudioService.source && AudioService.source.audio) {

View File

@@ -18,9 +18,9 @@ Rectangle {
implicitHeight: headerRow.height + (!hasVolumeSliderInCC ? volumeSlider.height : 0) + audioContent.height + Theme.spacingM
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Row {
id: headerRow
@@ -132,6 +132,8 @@ Rectangle {
unit: "%"
valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceVariant
trackColor: Theme.ccSliderTrackColor
trackOpacity: Theme.ccSliderTrackOpacity
onSliderValueChanged: function (newValue) {
if (AudioService.sink && AudioService.sink.audio) {
@@ -448,6 +450,7 @@ Rectangle {
Item {
id: appVolumeRow
property color sliderTrackColor: "transparent"
property real sliderTrackOpacity: Theme.ccSliderTrackOpacity
anchors.centerIn: parent
height: 40
@@ -519,7 +522,8 @@ Rectangle {
unit: "%"
valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer
trackColor: appVolumeRow.sliderTrackColor.a > 0 ? appVolumeRow.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
trackColor: appVolumeRow.sliderTrackColor.a > 0 ? appVolumeRow.sliderTrackColor : Theme.ccSliderTrackColor
trackOpacity: appVolumeRow.sliderTrackOpacity
onSliderValueChanged: function (newValue) {
if (modelData) {

View File

@@ -12,9 +12,9 @@ Rectangle {
implicitHeight: contentColumn.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
function isActiveProfile(profile) {
if (typeof PowerProfiles === "undefined") {

View File

@@ -153,9 +153,9 @@ Item {
width: 320
height: contentColumn.implicitHeight + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.floatingSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
opacity: modalVisible ? 1 : 0
scale: modalVisible ? 1 : 0.9

View File

@@ -20,9 +20,9 @@ Rectangle {
return headerRow.height + bluetoothContent.height + Theme.spacingM;
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
property var bluetoothCodecModalRef: null
property var devicesBeingPaired: new Set()
@@ -115,7 +115,7 @@ Rectangle {
height: 36
radius: 18
color: scanMouseArea.containsMouse && adapterEnabled ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent"
border.color: adapterEnabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.color: adapterEnabled ? Theme.primary : Theme.outlineStrong
border.width: 0
visible: adapterEnabled
@@ -434,7 +434,7 @@ Rectangle {
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
color: Theme.outlineStrong
visible: pairedRepeater.count > 0 && availableRepeater.count > 0
}
@@ -609,7 +609,7 @@ Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
radius: Theme.cornerRadius
border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.color: Theme.outlineStrong
}
MenuItem {

View File

@@ -106,9 +106,9 @@ Rectangle {
return brightnessContent.height + Theme.spacingM;
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
DankFlickable {
id: brightnessContent

View File

@@ -16,9 +16,9 @@ Rectangle {
implicitHeight: diskContent.height + Theme.spacingM
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Component.onCompleted: {
DgopService.addRef(["diskmounts"]);

View File

@@ -22,9 +22,9 @@ Rectangle {
return headerRow.height + wifiOffContent.height + Theme.spacingM;
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Component.onCompleted: {
NetworkService.addRef();

View File

@@ -11,6 +11,7 @@ Row {
property var defaultSink: AudioService.sink
property color sliderTrackColor: "transparent"
property real sliderTrackOpacity: Theme.ccSliderTrackOpacity
height: 40
spacing: 0
@@ -80,7 +81,8 @@ Row {
unit: "%"
valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.ccSliderTrackColor
trackOpacity: root.sliderTrackOpacity
onSliderValueChanged: function (newValue) {
if (defaultSink?.audio) {

View File

@@ -13,6 +13,8 @@ Row {
property string instanceId: ""
property string screenName: ""
property var parentScreen: null
property color sliderTrackColor: "transparent"
property real sliderTrackOpacity: Theme.ccSliderTrackOpacity
signal iconClicked
@@ -184,7 +186,8 @@ Row {
}
}
thumbOutlineColor: Theme.surfaceContainer
trackColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.ccSliderTrackColor
trackOpacity: root.sliderTrackOpacity
Binding on value {
value: root.targetBrightness

View File

@@ -20,9 +20,9 @@ Rectangle {
width: parent ? parent.width : 200
height: 60
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6
Row {
@@ -64,6 +64,8 @@ Rectangle {
minimum: Math.round(root.minimumValue * 100)
maximum: Math.round(root.maximumValue * 100)
value: Math.round(root.value * 100)
trackColor: Theme.ccSliderTrackColor
trackOpacity: Theme.ccSliderTrackOpacity
onSliderValueChanged: root.sliderValueChanged(newValue / 100.0)
}
}

View File

@@ -29,23 +29,21 @@ Rectangle {
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _containerBg: Theme.ccPillInactiveBg
color: {
const baseColor = bodyMouse.containsMouse ? Theme.primaryPressed : _containerBg;
const baseColor = bodyMouse.containsMouse ? Theme.ccPillInactiveHoverBg : _containerBg;
return baseColor;
}
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.10)
border.width: 0
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
antialiasing: true
readonly property color _labelPrimary: Theme.surfaceText
readonly property color _labelSecondary: Theme.surfaceVariantText
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: {
const transparency = Theme.popupTransparency;
const surface = Theme.surfaceContainer || Qt.rgba(0.1, 0.1, 0.1, 1);
return Qt.rgba(surface.r, surface.g, surface.b, transparency);
return Theme.ccTileInactiveBg;
}
readonly property color _tileRingActive: Theme.ccTileRing
readonly property color _tileRingInactive: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.18)
@@ -92,8 +90,8 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
radius: _tileRadius
color: isActive ? _tileBgActive : _tileBgInactive
border.color: isActive ? _tileRingActive : "transparent"
border.width: isActive ? 1 : 0
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
antialiasing: true
Rectangle {

View File

@@ -11,6 +11,7 @@ Row {
property var defaultSource: AudioService.source
property color sliderTrackColor: "transparent"
property real sliderTrackOpacity: Theme.ccSliderTrackOpacity
height: 40
spacing: 0
@@ -73,7 +74,8 @@ Row {
unit: "%"
valueOverride: actualVolumePercent
thumbOutlineColor: Theme.surfaceContainer
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
trackColor: root.sliderTrackColor.a > 0 ? root.sliderTrackColor : Theme.ccSliderTrackColor
trackOpacity: root.sliderTrackOpacity
onSliderValueChanged: function (newValue) {
if (defaultSource?.audio) {
SessionData.suppressOSDTemporarily();

View File

@@ -28,7 +28,7 @@ Rectangle {
}
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing
readonly property color _tileIconActive: Theme.ccTileActiveText
readonly property color _tileIconInactive: Theme.ccTileInactiveIcon
@@ -36,11 +36,11 @@ Rectangle {
color: {
if (isActive)
return _tileBgActive;
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
const baseColor = mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBgInactive;
return baseColor;
}
border.color: isActive ? _tileRingActive : "transparent"
border.width: isActive ? 1 : 0
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
antialiasing: true
opacity: enabled ? 1.0 : 0.6

View File

@@ -38,11 +38,11 @@ Rectangle {
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _tileBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _tileBg: Theme.ccPillInactiveBg
color: mouseArea.containsMouse ? Theme.primaryPressed : _tileBg
border.color: "transparent"
border.width: 0
color: mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBg
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
antialiasing: true
opacity: enabled ? 1.0 : 0.6

View File

@@ -26,7 +26,7 @@ Rectangle {
}
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing
readonly property color _tileIconActive: Theme.ccTileActiveText
readonly property color _tileIconInactive: Theme.ccTileInactiveIcon
@@ -34,11 +34,11 @@ Rectangle {
color: {
if (isActive)
return _tileBgActive;
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
const baseColor = mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBgInactive;
return baseColor;
}
border.color: isActive ? _tileRingActive : "transparent"
border.width: isActive ? 1 : 0
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
antialiasing: true
opacity: enabled ? 1.0 : 0.6

View File

@@ -26,17 +26,17 @@ Rectangle {
}
readonly property color _tileBgActive: Theme.ccTileActiveBg
readonly property color _tileBgInactive: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _tileBgInactive: Theme.ccPillInactiveBg
readonly property color _tileRingActive: Theme.ccTileRing
color: {
if (isActive)
return _tileBgActive;
const baseColor = mouseArea.containsMouse ? Theme.primaryPressed : _tileBgInactive;
const baseColor = mouseArea.containsMouse ? Theme.ccPillInactiveHoverBg : _tileBgInactive;
return baseColor;
}
border.color: isActive ? _tileRingActive : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
border.color: isActive ? _tileRingActive : Theme.outlineMedium
border.width: isActive ? 1 : Theme.layerOutlineWidth
opacity: enabled ? 1.0 : 0.6
function hoverTint(base) {
@@ -44,7 +44,7 @@ Rectangle {
return Theme.isLightMode ? Qt.darker(base, factor) : Qt.lighter(base, factor);
}
readonly property color _containerBg: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
readonly property color _containerBg: Theme.ccPillInactiveBg
Rectangle {
anchors.fill: parent

View File

@@ -54,7 +54,7 @@ Item {
}
readonly property real shadowIntensity: barConfig?.shadowIntensity ?? 0
readonly property bool shadowEnabled: shadowIntensity > 0
readonly property bool shadowEnabled: !BlurService.enabled && shadowIntensity > 0
readonly property int blurMax: 64
readonly property real shadowBlurPx: shadowIntensity * 0.2
readonly property real shadowBlur: Math.max(0, Math.min(1, shadowBlurPx / blurMax))

View File

@@ -260,7 +260,7 @@ DankPopout {
width: (parent.width - Theme.spacingM) / 2
height: 64
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {
@@ -295,7 +295,7 @@ DankPopout {
width: (parent.width - Theme.spacingM) / 2
height: 64
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {
@@ -346,7 +346,7 @@ DankPopout {
width: parent.width
height: batteryColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {
@@ -416,7 +416,7 @@ DankPopout {
width: (parent.width - Theme.spacingS * 2) / 3
height: 48
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {
@@ -453,7 +453,7 @@ DankPopout {
width: (parent.width - Theme.spacingS * 2) / 3
height: 48
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {
@@ -482,7 +482,7 @@ DankPopout {
width: (parent.width - Theme.spacingS * 2) / 3
height: 48
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.width: 0
Column {

View File

@@ -110,7 +110,7 @@ PanelWindow {
width: Math.min(400, Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2))
height: Math.max(60, menuColumn.implicitHeight + Theme.spacingS * 2)
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
color: Theme.floatingSurface
radius: Theme.cornerRadius
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 1

View File

@@ -42,19 +42,26 @@ BasePill {
const active = ToplevelManager.activeToplevel;
if (!active) {
// Only clear if our tracked window is no longer alive
if (activeWindow) {
const alive = ToplevelManager.toplevels?.values;
if (alive && !Array.from(alive).some(t => t === activeWindow))
activeWindow = null;
if (CompositorService.isNiri) {
if (NiriService.currentOutput === (parentScreen?.name ?? ""))
activeWindow = null;
} else {
const alive = ToplevelManager.toplevels?.values;
if (alive && !Array.from(alive).some(t => t === activeWindow))
activeWindow = null;
}
}
return;
}
if (!parentScreen || CompositorService.filterCurrentDisplay([active], parentScreen?.name)?.length > 0) {
activeWindow = active;
} else if (activeWindow) {
const alive = ToplevelManager.toplevels?.values;
if (alive && !Array.from(alive).some(t => t === activeWindow))
activeWindow = null;
}
// else: active window is on a different screen so keep the previous value
}
Component.onCompleted: {
@@ -65,7 +72,8 @@ BasePill {
Connections {
target: ToplevelManager
function onActiveToplevelChanged() {
root.updateActiveWindow();
if (!CompositorService.isNiri)
root.updateActiveWindow();
}
}
@@ -76,6 +84,16 @@ BasePill {
}
}
Connections {
target: CompositorService.isNiri ? NiriService : null
function onWindowsChanged() {
root.updateActiveWindow();
}
function onCurrentOutputChanged() {
root.updateActiveWindow();
}
}
Connections {
target: DesktopEntries
function onApplicationsChanged() {
@@ -107,21 +125,17 @@ BasePill {
}
readonly property bool hasWindowsOnCurrentWorkspace: {
if (CompositorService.isNiri) {
let currentWorkspaceId = null;
for (var i = 0; i < NiriService.allWorkspaces.length; i++) {
const ws = NiriService.allWorkspaces[i];
if (ws.is_focused) {
currentWorkspaceId = ws.id;
break;
}
}
if (!currentWorkspaceId) {
if (!activeWindow || !(activeWindow.title || activeWindow.appId))
return false;
}
const workspaceWindows = NiriService.windows.filter(w => w.workspace_id === currentWorkspaceId);
return workspaceWindows.length > 0 && activeWindow && (activeWindow.title || activeWindow.appId);
if (NiriService.currentOutput !== (parentScreen?.name ?? ""))
return true;
const focusedWin = NiriService.windows.find(w => w.is_focused);
if (!focusedWin)
return false;
const screenWsIds = new Set(
NiriService.allWorkspaces.filter(ws => ws.output === parentScreen.name).map(ws => ws.id)
);
return screenWsIds.has(focusedWin.workspace_id);
}
if (CompositorService.isHyprland) {

View File

@@ -79,6 +79,66 @@ BasePill {
item: item
}))
readonly property var hiddenBarItems: allSortedTrayItems.filter(item => SessionData.isHiddenTrayId(root.getTrayItemKey(item)))
readonly property string trayIconTintMode: {
const configuredMode = SettingsData.systemTrayIconTintMode || "none";
switch (configuredMode) {
case "monochrome":
case "primary":
case "secondary":
return configuredMode;
default:
return "none";
}
}
readonly property bool trayIconTintEnabled: trayIconTintMode !== "none"
readonly property real trayIconTintSaturationAmount: {
const raw = SettingsData.systemTrayIconTintSaturation;
const value = (raw === undefined || raw === null) ? 50 : raw;
return Math.max(0, Math.min(100, value)) / 100;
}
readonly property real trayIconTintStrengthAmount: {
const raw = SettingsData.systemTrayIconTintStrength;
const value = (raw === undefined || raw === null) ? 135 : raw;
return Math.max(0, Math.min(200, value)) / 100;
}
readonly property real trayIconSaturation: {
switch (trayIconTintMode) {
case "monochrome":
return -1;
case "primary":
case "secondary":
return -root.trayIconTintSaturationAmount;
default:
return 0;
}
}
readonly property real trayIconColorization: {
switch (trayIconTintMode) {
case "primary":
case "secondary":
return root.trayIconTintStrengthAmount;
default:
return 0;
}
}
readonly property color trayIconTintColor: {
switch (trayIconTintMode) {
case "primary":
return Theme.primary;
case "secondary":
return Theme.secondary;
default:
return Theme.surfaceText;
}
}
readonly property bool reverseInlineHorizontal: !useOverflowPopup && !isVerticalOrientation && section === "right"
readonly property bool reverseInlineVertical: !useOverflowPopup && isVerticalOrientation && section === "right"
readonly property var displayedMainBarItems: reverseInlineHorizontal ? [...mainBarItems].reverse() : mainBarItems
readonly property var displayedInlineExpandedItems: (reverseInlineHorizontal ? [...hiddenBarItems].reverse() : hiddenBarItems).map(item => ({
key: getTrayItemKey(item),
item: item
}))
function moveTrayItemInFullOrder(visibleFromIndex, visibleToIndex) {
if (visibleFromIndex === visibleToIndex || visibleFromIndex < 0 || visibleToIndex < 0)
@@ -290,6 +350,12 @@ BasePill {
smooth: true
mipmap: true
visible: status === Image.Ready
layer.enabled: root.trayIconTintEnabled
layer.effect: MultiEffect {
saturation: root.trayIconSaturation
colorization: root.trayIconColorization
colorizationColor: root.trayIconTintColor
}
}
Text {
@@ -435,6 +501,313 @@ BasePill {
}
}
}
Repeater {
model: ScriptModel {
values: root.displayedInlineExpandedItems
objectProp: "key"
}
delegate: inlineExpandedTrayItemDelegate
}
}
}
Component {
id: inlineExpandedTrayItemDelegate
Item {
property var trayItem: modelData.item
property string itemKey: modelData.key
property string iconSource: root.trayIconSourceFor(trayItem)
width: root.isVerticalOrientation ? root.barThickness : (root.inlineExpanded ? root.trayItemSize : 0)
height: root.isVerticalOrientation ? (root.inlineExpanded ? root.trayItemSize : 0) : root.barThickness
visible: width > 0 || height > 0
Behavior on width {
enabled: !root.isVerticalOrientation
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on height {
enabled: root.isVerticalOrientation
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Rectangle {
id: inlineVisualContent
width: root.trayItemSize
height: root.trayItemSize
x: root.isVerticalOrientation ? Math.round((parent.width - width) / 2) : (root.reverseInlineHorizontal ? parent.width - width : 0)
y: root.isVerticalOrientation ? (root.reverseInlineVertical ? parent.height - height : 0) : Math.round((parent.height - height) / 2)
radius: Theme.cornerRadius
color: inlineTrayItemArea.containsMouse ? BlurService.hoverColor(Theme.widgetBaseHoverColor) : "transparent"
opacity: root.inlineExpanded ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
IconImage {
id: inlineIconImg
anchors.centerIn: parent
width: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
height: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
source: iconSource
asynchronous: true
smooth: true
mipmap: true
visible: status === Image.Ready
layer.enabled: root.trayIconTintEnabled
layer.effect: MultiEffect {
saturation: root.trayIconSaturation
colorization: root.trayIconColorization
colorizationColor: root.trayIconTintColor
}
}
Text {
anchors.centerIn: parent
visible: !inlineIconImg.visible
text: {
const itemId = trayItem?.id || "";
if (!itemId)
return "?";
return itemId.charAt(0).toUpperCase();
}
font.pixelSize: 10
color: Theme.widgetTextColor
}
DankRipple {
id: inlineItemRipple
cornerRadius: Theme.cornerRadius
}
}
MouseArea {
id: inlineTrayItemArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
enabled: root.inlineExpanded
onPressed: mouse => {
const pos = mapToItem(inlineVisualContent, mouse.x, mouse.y);
inlineItemRipple.trigger(pos.x, pos.y);
}
onClicked: mouse => {
if (mouse.button === Qt.LeftButton) {
root.activateInlineTrayItem(trayItem, inlineVisualContent);
return;
}
if (mouse.button !== Qt.RightButton)
return;
root.openInlineTrayContextMenu(trayItem, inlineTrayItemArea, mouse, inlineVisualContent);
}
}
}
}
Component {
id: verticalMainTrayItemDelegate
Item {
property var trayItem: modelData.item
property string itemKey: modelData.key
property string iconSource: root.trayIconSourceFor(trayItem)
width: root.barThickness
height: root.trayItemSize
z: dragHandler.dragging ? 100 : 0
property real shiftOffset: {
if (root.draggedIndex < 0)
return 0;
if (index === root.draggedIndex)
return 0;
const dragIdx = root.draggedIndex;
const dropIdx = root.dropTargetIndex;
const shiftAmount = root.trayItemSize;
if (dropIdx < 0)
return 0;
if (dragIdx < dropIdx && index > dragIdx && index <= dropIdx)
return -shiftAmount;
if (dragIdx > dropIdx && index >= dropIdx && index < dragIdx)
return shiftAmount;
return 0;
}
transform: Translate {
y: shiftOffset
Behavior on y {
enabled: !root.suppressShiftAnimation
NumberAnimation {
duration: 150
easing.type: Easing.OutCubic
}
}
}
Item {
id: dragHandler
anchors.fill: parent
property bool dragging: false
property point dragStartPos: Qt.point(0, 0)
property real dragAxisOffset: 0
property bool longPressing: false
Timer {
id: longPressTimer
interval: 400
repeat: false
onTriggered: dragHandler.longPressing = true
}
}
Rectangle {
id: visualContent
width: root.trayItemSize
height: root.trayItemSize
anchors.centerIn: parent
radius: Theme.cornerRadius
color: trayItemArea.containsMouse ? BlurService.hoverColor(Theme.widgetBaseHoverColor) : "transparent"
border.width: dragHandler.dragging ? 2 : 0
border.color: Theme.primary
opacity: dragHandler.dragging ? 0.8 : 1.0
transform: Translate {
y: dragHandler.dragging ? dragHandler.dragAxisOffset : 0
}
IconImage {
id: iconImg
anchors.centerIn: parent
width: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
height: Theme.barIconSize(root.barThickness, undefined, root.barConfig?.maximizeWidgetIcons, root.barConfig?.iconScale)
source: iconSource
asynchronous: true
smooth: true
mipmap: true
visible: status === Image.Ready
layer.enabled: root.trayIconTintEnabled
layer.effect: MultiEffect {
saturation: root.trayIconSaturation
colorization: root.trayIconColorization
colorizationColor: root.trayIconTintColor
}
}
Text {
anchors.centerIn: parent
visible: !iconImg.visible
text: {
const itemId = trayItem?.id || "";
if (!itemId)
return "?";
return itemId.charAt(0).toUpperCase();
}
font.pixelSize: 10
color: Theme.widgetTextColor
}
DankRipple {
id: itemRipple
cornerRadius: Theme.cornerRadius
}
}
MouseArea {
id: trayItemArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: dragHandler.longPressing ? Qt.DragMoveCursor : Qt.PointingHandCursor
onPressed: mouse => {
const pos = mapToItem(visualContent, mouse.x, mouse.y);
itemRipple.trigger(pos.x, pos.y);
if (mouse.button === Qt.LeftButton) {
dragHandler.dragStartPos = Qt.point(mouse.x, mouse.y);
longPressTimer.start();
}
}
onReleased: mouse => {
longPressTimer.stop();
const wasDragging = dragHandler.dragging;
const didReorder = wasDragging && root.dropTargetIndex >= 0 && root.dropTargetIndex !== root.draggedIndex;
if (didReorder) {
root.suppressShiftAnimation = true;
root.moveTrayItemInFullOrder(root.draggedIndex, root.dropTargetIndex);
Qt.callLater(() => root.suppressShiftAnimation = false);
}
dragHandler.longPressing = false;
dragHandler.dragging = false;
dragHandler.dragAxisOffset = 0;
root.draggedIndex = -1;
root.dropTargetIndex = -1;
if (wasDragging || mouse.button !== Qt.LeftButton)
return;
if (!trayItem)
return;
if (!trayItem.onlyMenu) {
trayItem.activate();
return;
}
if (!trayItem.hasMenu)
return;
if (root.useOverflowPopup)
root.menuOpen = false;
root.showForTrayItem(trayItem, visualContent, parentScreen, root.isAtBottom, root.isVerticalOrientation, root.axis);
}
onPositionChanged: mouse => {
if (dragHandler.longPressing && !dragHandler.dragging) {
const distance = Math.abs(mouse.y - dragHandler.dragStartPos.y);
if (distance > 5) {
dragHandler.dragging = true;
root.draggedIndex = index;
root.dropTargetIndex = root.draggedIndex;
}
}
if (!dragHandler.dragging)
return;
const axisOffset = mouse.y - dragHandler.dragStartPos.y;
dragHandler.dragAxisOffset = axisOffset;
const itemSize = root.trayItemSize;
const slotOffset = Math.round(axisOffset / itemSize);
const newTargetIndex = Math.max(0, Math.min(root.mainBarItems.length - 1, index + slotOffset));
if (newTargetIndex !== root.dropTargetIndex) {
root.dropTargetIndex = newTargetIndex;
}
}
onClicked: mouse => {
if (dragHandler.dragging)
return;
if (mouse.button !== Qt.RightButton)
return;
root.openInlineTrayContextMenu(trayItem, trayItemArea, mouse, visualContent);
}
}
}
}
@@ -550,6 +923,10 @@ BasePill {
smooth: true
mipmap: true
visible: status === Image.Ready
layer.enabled: root.trayIconsMonochrome && visible
layer.effect: MultiEffect {
saturation: -1
}
}
Text {
@@ -976,7 +1353,7 @@ BasePill {
Item {
id: bgShadowLayer
anchors.fill: parent
layer.enabled: true
layer.enabled: !BlurService.enabled
layer.smooth: true
layer.textureSize: Qt.size(Math.round(width * overflowMenu.dpr * 2), Math.round(height * overflowMenu.dpr * 2))
layer.textureMirroring: ShaderEffectSource.MirrorVertically
@@ -1067,6 +1444,12 @@ BasePill {
smooth: true
mipmap: true
visible: status === Image.Ready
layer.enabled: root.trayIconTintEnabled
layer.effect: MultiEffect {
saturation: root.trayIconSaturation
colorization: root.trayIconColorization
colorizationColor: root.trayIconTintColor
}
}
Text {
@@ -1466,7 +1849,7 @@ BasePill {
Item {
id: menuBgShadowLayer
anchors.fill: parent
layer.enabled: true
layer.enabled: !BlurService.enabled
layer.smooth: true
layer.textureSize: Qt.size(Math.round(width * menuWindow.dpr), Math.round(height * menuWindow.dpr))
layer.textureMirroring: ShaderEffectSource.MirrorVertically

View File

@@ -82,6 +82,7 @@ DankPopout {
isRightEdge: root.__dropdownRightEdge
activePlayer: root.__dropdownPlayer
allPlayers: root.__dropdownPlayers
targetWindow: root.backgroundWindow
onCloseRequested: root.__hideDropdowns()
onPanelEntered: root.__stopCloseTimer()
onPanelExited: root.__startCloseTimer()

View File

@@ -16,6 +16,7 @@ Item {
property var allPlayers: []
property point anchorPos: Qt.point(0, 0)
property bool isRightEdge: false
property var targetWindow: null
property bool __isChromeBrowser: {
if (!activePlayer?.identity)
@@ -57,6 +58,30 @@ Item {
});
}
readonly property Item __activePanel: {
switch (dropdownType) {
case 1:
return volumePanel;
case 2:
return audioDevicesPanel;
case 3:
return playersPanel;
default:
return null;
}
}
WindowBlur {
targetWindow: root.targetWindow
readonly property bool active: root.__activePanel !== null && root.__activePanel.visible && root.__activePanel.opacity > 0
readonly property real s: root.__activePanel ? Math.min(1, root.__activePanel.scale) : 1
blurX: root.__activePanel ? root.__activePanel.x + root.__activePanel.width * (1 - s) * 0.5 : 0
blurY: root.__activePanel ? root.__activePanel.y + root.__activePanel.height * (1 - s) * 0.5 : 0
blurWidth: active ? root.__activePanel.width * s : 0
blurHeight: active ? root.__activePanel.height * s : 0
blurRadius: Theme.cornerRadius * 2
}
Rectangle {
id: volumePanel
visible: dropdownType === 1 && volumeAvailable
@@ -65,8 +90,8 @@ Item {
x: isRightEdge ? anchorPos.x : anchorPos.x - width
y: anchorPos.y - height / 2
radius: Theme.cornerRadius * 2
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
color: Theme.floatingSurface
border.color: Theme.outlineStrong
border.width: 1
opacity: dropdownType === 1 ? 1 : 0
@@ -89,7 +114,7 @@ Item {
}
}
layer.enabled: true
layer.enabled: !BlurService.enabled
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
@@ -123,23 +148,26 @@ Item {
width: parent.width
height: parent.height
anchors.centerIn: parent
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.withAlpha(Theme.outline, Theme.popupTransparency)
radius: Theme.cornerRadius
}
Rectangle {
readonly property real ratio: volumeAvailable ? Math.min(1.0, currentVolume) : 0
readonly property real thumbHeight: 4
width: parent.width
height: volumeAvailable ? (Math.min(1.0, currentVolume) * parent.height) : 0
height: Math.max(0, ratio * (parent.height - thumbHeight) - 3)
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.primary
bottomLeftRadius: Theme.cornerRadius
bottomRightRadius: Theme.cornerRadius
radius: Theme.cornerRadius
topLeftRadius: 0
topRightRadius: 0
}
Rectangle {
width: parent.width + 8
height: 8
height: 4
radius: Theme.cornerRadius
y: {
const ratio = volumeAvailable ? Math.min(1.0, currentVolume) : 0;
@@ -148,8 +176,7 @@ Item {
}
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.primary
border.width: 3
border.color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1.0)
border.width: 0
}
MouseArea {
@@ -199,8 +226,8 @@ Item {
x: isRightEdge ? anchorPos.x : anchorPos.x - width
y: anchorPos.y - height / 2
radius: Theme.cornerRadius * 2
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
color: Theme.floatingSurface
border.color: Theme.outlineStrong
border.width: 2
opacity: dropdownType === 2 ? 1 : 0
@@ -223,7 +250,7 @@ Item {
}
}
layer.enabled: true
layer.enabled: !BlurService.enabled
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
@@ -267,7 +294,7 @@ Item {
width: parent.width
height: 48
radius: Theme.cornerRadius
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.nestedSurface
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === AudioService.sink ? 2 : 1
@@ -349,8 +376,8 @@ Item {
x: isRightEdge ? anchorPos.x : anchorPos.x - width
y: anchorPos.y - height / 2
radius: Theme.cornerRadius * 2
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
color: Theme.floatingSurface
border.color: Theme.outlineStrong
border.width: 2
opacity: dropdownType === 3 ? 1 : 0
@@ -373,7 +400,7 @@ Item {
}
}
layer.enabled: true
layer.enabled: !BlurService.enabled
layer.effect: MultiEffect {
shadowEnabled: true
shadowHorizontalOffset: 0
@@ -417,7 +444,7 @@ Item {
width: parent.width
height: 48
radius: Theme.cornerRadius
color: playerMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: playerMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.nestedSurface
border.color: modelData === activePlayer ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === activePlayer ? 2 : 1

View File

@@ -2,7 +2,6 @@ import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell.Services.Mpris
import Quickshell.Io
import qs.Common
import qs.Services
import qs.Widgets
@@ -638,7 +637,7 @@ Item {
x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
y: 185
color: playerSelectorArea.containsMouse || playersExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.color: Theme.outlineStrong
border.width: 1
z: 100
visible: (allPlayers?.length || 0) >= 1
@@ -681,7 +680,7 @@ Item {
x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
y: 130
color: volumeButtonArea.containsMouse && volumeAvailable || volumeExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, volumeAvailable ? 0.3 : 0.15)
border.color: volumeAvailable ? Theme.outlineStrong : Theme.outlineMedium
border.width: 1
z: 101
enabled: volumeAvailable
@@ -758,7 +757,7 @@ Item {
x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
y: 240
color: audioDevicesArea.containsMouse || devicesExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
border.color: Theme.outlineStrong
border.width: 1
z: 100

View File

@@ -83,8 +83,8 @@ Rectangle {
}
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: 1
Column {
@@ -351,7 +351,7 @@ Rectangle {
} else if (eventMouseArea.containsMouse) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06);
}
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
return Theme.nestedSurface;
}
border.color: {
if (modelData.url && eventMouseArea.containsMouse) {
@@ -359,9 +359,9 @@ Rectangle {
} else if (eventMouseArea.containsMouse) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15);
}
return "transparent";
return Theme.outlineMedium;
}
border.width: 1
border.width: eventMouseArea.containsMouse ? 1 : Theme.layerOutlineWidth
Rectangle {
width: 3

View File

@@ -10,8 +10,8 @@ Rectangle {
property int pad: Theme.spacingM
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: 1
default property alias content: contentItem.data

View File

@@ -103,7 +103,7 @@ Rectangle {
}
]
color: isCurrent ? Theme.withAlpha(Theme.primary, 0.1) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: isCurrent ? Theme.withAlpha(Theme.primary, 0.1) : Theme.nestedSurface
border.color: isCurrent ? Theme.withAlpha(Theme.primary, 0.3) : "transparent"
border.width: isCurrent ? 1 : 0

View File

@@ -213,8 +213,8 @@ Item {
width: parent.width
height: heroContent.height + Theme.spacingL * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Theme.withAlpha(Theme.outline, 0.08)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: 1
Column {

View File

@@ -35,14 +35,14 @@ Rectangle {
color: {
if (isSelected && keyboardNavigationActive)
return Theme.primaryPressed;
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
return Theme.floatingSurfaceHigh;
}
border.color: {
if (isSelected && keyboardNavigationActive)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.5);
if (historyItem.urgency === 2)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3);
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05);
return Theme.outlineMedium;
}
border.width: {
if (isSelected && keyboardNavigationActive)
@@ -122,12 +122,10 @@ Rectangle {
return "";
const appIcon = historyItem.appIcon;
if (!appIcon)
return iconFromImage ? Paths.resolveIconUrl(iconFromImage) : "";
return "";
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://") || appIcon.includes("/"))
return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return "";
return Paths.resolveIconPath(appIcon);
return "";
}
hasImage: hasNotificationImage

View File

@@ -71,7 +71,7 @@ Rectangle {
if (keyboardNavigationActive && expanded && selectedNotificationIndex >= 0) {
return Theme.primaryHoverLight;
}
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
return Theme.floatingSurfaceHigh;
}
border.color: {
if (isGroupSelected && keyboardNavigationActive) {
@@ -83,7 +83,7 @@ Rectangle {
if (notificationGroup?.latestNotification?.urgency === NotificationUrgency.Critical) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3);
}
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05);
return Theme.outlineMedium;
}
border.width: {
if (isGroupSelected && keyboardNavigationActive) {
@@ -169,12 +169,10 @@ Rectangle {
return "";
const appIcon = notificationGroup?.latestNotification?.appIcon;
if (!appIcon)
return iconFromImage ? Paths.resolveIconUrl(iconFromImage) : "";
return "";
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://") || appIcon.includes("/"))
return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return "";
return Paths.resolveIconPath(appIcon);
return "";
}
hasImage: hasNotificationImage
@@ -454,8 +452,8 @@ Rectangle {
return expandedBaseHeight;
}
radius: Theme.cornerRadius
color: isSelected ? Theme.primaryPressed : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
color: isSelected ? Theme.primaryPressed : Theme.nestedSurface
border.color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Theme.outlineMedium
border.width: 1
Behavior on border.color {
@@ -503,12 +501,10 @@ Rectangle {
return "";
const appIcon = modelData?.appIcon;
if (!appIcon)
return iconFromImage ? Paths.resolveIconUrl(iconFromImage) : "";
return "";
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://") || appIcon.includes("/"))
return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return "";
return Paths.resolveIconPath(appIcon);
return "";
}
fallbackIcon: {

View File

@@ -99,7 +99,9 @@ Item {
height: Theme.iconSize + Theme.spacingS
radius: Theme.cornerRadius
visible: root.currentTab === 0 ? NotificationService.notifications.length > 0 : NotificationService.historyList.length > 0
color: clearArea.containsMouse ? Theme.primaryHoverLight : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: clearArea.containsMouse ? Theme.primaryHoverLight : Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
Row {
id: clearButtonContent

View File

@@ -14,8 +14,8 @@ Rectangle {
visible: expanded
clip: true
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.3)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.1)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: 1
Behavior on height {

View File

@@ -325,8 +325,9 @@ PanelWindow {
property bool swipeDismissing: false
readonly property real radiusForShadow: Theme.cornerRadius
property real shadowBlurPx: SettingsData.notificationPopupShadowEnabled ? ((2 + radiusForShadow * 0.2) * (cardHoverHandler.hovered ? 1.2 : 1)) : 0
property real shadowSpreadPx: SettingsData.notificationPopupShadowEnabled ? (radiusForShadow * (cardHoverHandler.hovered ? 0.06 : 0)) : 0
readonly property bool shadowsAllowed: SettingsData.notificationPopupShadowEnabled && !BlurService.enabled
property real shadowBlurPx: shadowsAllowed ? ((2 + radiusForShadow * 0.2) * (cardHoverHandler.hovered ? 1.2 : 1)) : 0
property real shadowSpreadPx: shadowsAllowed ? (radiusForShadow * (cardHoverHandler.hovered ? 0.06 : 0)) : 0
property real shadowBaseAlpha: 0.35
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
@@ -349,7 +350,7 @@ PanelWindow {
id: bgShadowLayer
anchors.fill: parent
anchors.margins: Theme.snap(4, win.dpr)
layer.enabled: !win._isDestroying && win.screenValid
layer.enabled: !win._isDestroying && win.screenValid && content.shadowsAllowed
layer.smooth: false
layer.textureSize: Qt.size(Math.round(width * win.dpr), Math.round(height * win.dpr))
layer.textureMirroring: ShaderEffectSource.MirrorVertically
@@ -411,9 +412,10 @@ PanelWindow {
anchors.fill: parent
anchors.margins: content.cardInset
radius: Theme.cornerRadius
antialiasing: true
color: "transparent"
border.color: BlurService.borderColor
border.width: BlurService.borderWidth
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
border.width: BlurService.enabled ? BlurService.borderWidth : 1
z: 100
}
@@ -500,12 +502,10 @@ PanelWindow {
return "";
const appIcon = notificationData.appIcon;
if (!appIcon)
return iconFromImage ? Paths.resolveIconUrl(iconFromImage) : "";
return "";
if (appIcon.startsWith("file://") || appIcon.startsWith("http://") || appIcon.startsWith("https://") || appIcon.includes("/"))
return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return "";
return Paths.resolveIconPath(appIcon);
return "";
}
hasImage: hasNotificationImage

View File

@@ -33,7 +33,7 @@ Item {
Layout.fillWidth: true
Layout.preferredHeight: 80
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
RowLayout {
anchors.fill: parent
@@ -110,7 +110,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
ColumnLayout {
anchors.fill: parent

View File

@@ -163,7 +163,7 @@ Item {
property color extraInfoColor: Theme.surfaceVariantText
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.color: Theme.outlineLight
border.width: 1

View File

@@ -185,7 +185,7 @@ Popup {
}
contentItem: Rectangle {
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
color: Theme.floatingSurface
radius: Theme.cornerRadius
border.color: BlurService.enabled ? BlurService.borderColor : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: BlurService.enabled ? BlurService.borderWidth : 1

View File

@@ -357,7 +357,7 @@ DankPopout {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
clip: true
ProcessesView {

View File

@@ -23,7 +23,7 @@ Item {
Layout.fillWidth: true
Layout.preferredHeight: systemInfoColumn.implicitHeight + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
ColumnLayout {
id: systemInfoColumn
@@ -96,7 +96,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
ColumnLayout {
anchors.fill: parent

View File

@@ -52,9 +52,11 @@ Item {
}
function _isBarActive(c) {
if (!c.enabled) return false;
if (!c.enabled)
return false;
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;
}
@@ -64,7 +66,8 @@ Item {
return;
const hasHorizontal = configs.some(c => {
if (!_isBarActive(c)) return false;
if (!_isBarActive(c))
return false;
const p = c.position ?? SettingsData.Position.Top;
return p === SettingsData.Position.Top || p === SettingsData.Position.Bottom;
});
@@ -72,7 +75,8 @@ Item {
return;
const hasVertical = configs.some(c => {
if (!_isBarActive(c)) return false;
if (!_isBarActive(c))
return false;
const p = c.position ?? SettingsData.Position.Top;
return p === SettingsData.Position.Left || p === SettingsData.Position.Right;
});
@@ -305,7 +309,7 @@ Item {
const prefs = cfg?.screenPreferences || ["all"];
if (prefs.includes("all") || (typeof prefs[0] === "string" && prefs[0] === "all"))
return I18n.tr("All displays");
return I18n.tr("%1 display(s)").replace("%1", prefs.length);
return prefs.length === 1 ? I18n.tr("%1 display").arg(prefs.length) : I18n.tr("%1 displays").arg(prefs.length);
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
@@ -413,11 +417,71 @@ Item {
}
}
SettingsCard {
iconName: "vertical_align_center"
title: I18n.tr("Position")
settingKey: "barPosition"
visible: selectedBarConfig?.enabled ?? false
Item {
width: parent.width
height: positionButtonGroup.height
DankButtonGroup {
id: positionButtonGroup
anchors.horizontalCenter: parent.horizontalCenter
model: [I18n.tr("Top"), I18n.tr("Bottom"), I18n.tr("Left"), I18n.tr("Right")]
currentIndex: {
selectedBarId;
const config = SettingsData.getBarConfig(selectedBarId);
const pos = config?.position ?? 0;
switch (pos) {
case SettingsData.Position.Top:
return 0;
case SettingsData.Position.Bottom:
return 1;
case SettingsData.Position.Left:
return 2;
case SettingsData.Position.Right:
return 3;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newPos = 0;
switch (index) {
case 0:
newPos = SettingsData.Position.Top;
break;
case 1:
newPos = SettingsData.Position.Bottom;
break;
case 2:
newPos = SettingsData.Position.Left;
break;
case 3:
newPos = SettingsData.Position.Right;
break;
}
SettingsData.updateBarConfig(selectedBarId, {
position: newPos
});
notifyHorizontalBarChange();
}
}
}
}
SettingsCard {
iconName: "display_settings"
title: I18n.tr("Display Assignment")
settingKey: "barDisplay"
visible: selectedBarConfig?.enabled
collapsible: true
expanded: false
visible: selectedBarConfig?.enabled ?? false
StyledText {
width: parent.width
@@ -518,69 +582,13 @@ Item {
}
}
SettingsCard {
iconName: "vertical_align_center"
title: I18n.tr("Position")
settingKey: "barPosition"
visible: selectedBarConfig?.enabled
Item {
width: parent.width
height: positionButtonGroup.height
DankButtonGroup {
id: positionButtonGroup
anchors.horizontalCenter: parent.horizontalCenter
model: [I18n.tr("Top"), I18n.tr("Bottom"), I18n.tr("Left"), I18n.tr("Right")]
currentIndex: {
selectedBarId;
const config = SettingsData.getBarConfig(selectedBarId);
const pos = config?.position ?? 0;
switch (pos) {
case SettingsData.Position.Top:
return 0;
case SettingsData.Position.Bottom:
return 1;
case SettingsData.Position.Left:
return 2;
case SettingsData.Position.Right:
return 3;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newPos = 0;
switch (index) {
case 0:
newPos = SettingsData.Position.Top;
break;
case 1:
newPos = SettingsData.Position.Bottom;
break;
case 2:
newPos = SettingsData.Position.Left;
break;
case 3:
newPos = SettingsData.Position.Right;
break;
}
SettingsData.updateBarConfig(selectedBarId, {
position: newPos
});
notifyHorizontalBarChange();
}
}
}
}
SettingsCard {
iconName: "visibility_off"
title: I18n.tr("Visibility")
settingKey: "barVisibility"
visible: selectedBarConfig?.enabled
collapsible: true
expanded: false
visible: selectedBarConfig?.enabled ?? false
SettingsToggleRow {
text: I18n.tr("Auto-hide")
@@ -695,106 +703,11 @@ Item {
}
}
SettingsToggleCard {
iconName: "fit_screen"
title: I18n.tr("Maximize Detection")
description: I18n.tr("Remove gaps and border when windows are maximized")
visible: selectedBarConfig?.enabled && (CompositorService.isNiri || CompositorService.isHyprland)
checked: selectedBarConfig?.maximizeDetection ?? true
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
maximizeDetection: checked
})
}
SettingsToggleCard {
iconName: "mouse"
title: I18n.tr("Scroll Wheel")
description: I18n.tr("Control workspaces and columns by scrolling on the bar")
visible: selectedBarConfig?.enabled
checked: selectedBarConfig?.scrollEnabled ?? true
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
scrollEnabled: checked
})
SettingsButtonGroupRow {
text: I18n.tr("Y Axis")
model: CompositorService.isNiri ? [I18n.tr("None"), I18n.tr("Workspace"), I18n.tr("Column")] : [I18n.tr("None"), I18n.tr("Workspace")]
currentIndex: {
switch (selectedBarConfig?.scrollYBehavior || "workspace") {
case "none":
return 0;
case "workspace":
return 1;
case "column":
return 2;
default:
return 1;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let behavior = "workspace";
switch (index) {
case 0:
behavior = "none";
break;
case 1:
behavior = "workspace";
break;
case 2:
behavior = "column";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
scrollYBehavior: behavior
});
}
}
SettingsButtonGroupRow {
text: I18n.tr("X Axis")
visible: CompositorService.isNiri
model: [I18n.tr("None"), I18n.tr("Workspace"), I18n.tr("Column")]
currentIndex: {
switch (selectedBarConfig?.scrollXBehavior || "column") {
case "none":
return 0;
case "workspace":
return 1;
case "column":
return 2;
default:
return 2;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let behavior = "column";
switch (index) {
case 0:
behavior = "none";
break;
case 1:
behavior = "workspace";
break;
case 2:
behavior = "column";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
scrollXBehavior: behavior
});
}
}
}
SettingsCard {
iconName: "space_bar"
title: I18n.tr("Spacing")
settingKey: "barSpacing"
visible: selectedBarConfig?.enabled
visible: selectedBarConfig?.enabled ?? false
SettingsSliderRow {
id: edgeSpacingSlider
@@ -937,61 +850,11 @@ Item {
}
}
SettingsSliderCard {
id: fontScaleSliderCard
iconName: "text_fields"
title: I18n.tr("Font Scale")
description: I18n.tr("Scale DankBar font sizes independently")
visible: selectedBarConfig?.enabled
minimum: 50
maximum: 200
value: Math.round((selectedBarConfig?.fontScale ?? 1.0) * 100)
unit: "%"
defaultValue: 100
onSliderValueChanged: newValue => {
SettingsData.updateBarConfig(selectedBarId, {
fontScale: newValue / 100
});
}
Binding {
target: fontScaleSliderCard
property: "value"
value: Math.round((selectedBarConfig?.fontScale ?? 1.0) * 100)
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderCard {
id: iconScaleSliderCard
iconName: "interests"
title: I18n.tr("Icon Scale")
description: I18n.tr("Scale DankBar icon sizes independently")
visible: selectedBarConfig?.enabled
minimum: 50
maximum: 200
value: Math.round((selectedBarConfig?.iconScale ?? 1.0) * 100)
unit: "%"
defaultValue: 100
onSliderValueChanged: newValue => {
SettingsData.updateBarConfig(selectedBarId, {
iconScale: newValue / 100
});
}
Binding {
target: iconScaleSliderCard
property: "value"
value: Math.round((selectedBarConfig?.iconScale ?? 1.0) * 100)
restoreMode: Binding.RestoreBinding
}
}
SettingsCard {
iconName: "opacity"
title: I18n.tr("Transparency")
settingKey: "barTransparency"
visible: selectedBarConfig?.enabled
visible: selectedBarConfig?.enabled ?? false
SettingsSliderRow {
id: barTransparencySlider
@@ -1038,13 +901,63 @@ Item {
}
}
SettingsSliderCard {
id: fontScaleSliderCard
iconName: "text_fields"
title: I18n.tr("Font Scale")
description: I18n.tr("Scale DankBar font sizes independently")
visible: selectedBarConfig?.enabled ?? false
minimum: 50
maximum: 200
value: Math.round((selectedBarConfig?.fontScale ?? 1.0) * 100)
unit: "%"
defaultValue: 100
onSliderValueChanged: newValue => {
SettingsData.updateBarConfig(selectedBarId, {
fontScale: newValue / 100
});
}
Binding {
target: fontScaleSliderCard
property: "value"
value: Math.round((selectedBarConfig?.fontScale ?? 1.0) * 100)
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderCard {
id: iconScaleSliderCard
iconName: "interests"
title: I18n.tr("Icon Scale")
description: I18n.tr("Scale DankBar icon sizes independently")
visible: selectedBarConfig?.enabled ?? false
minimum: 50
maximum: 200
value: Math.round((selectedBarConfig?.iconScale ?? 1.0) * 100)
unit: "%"
defaultValue: 100
onSliderValueChanged: newValue => {
SettingsData.updateBarConfig(selectedBarId, {
iconScale: newValue / 100
});
}
Binding {
target: iconScaleSliderCard
property: "value"
value: Math.round((selectedBarConfig?.iconScale ?? 1.0) * 100)
restoreMode: Binding.RestoreBinding
}
}
SettingsCard {
iconName: "rounded_corner"
title: I18n.tr("Corners & Background")
settingKey: "barCorners"
collapsible: true
expanded: false
visible: selectedBarConfig?.enabled
visible: selectedBarConfig?.enabled ?? false
SettingsToggleRow {
text: I18n.tr("Square Corners")
@@ -1140,6 +1053,296 @@ Item {
}
}
SettingsToggleCard {
iconName: "fit_screen"
title: I18n.tr("Maximize Detection")
description: I18n.tr("Remove gaps and border when windows are maximized")
visible: (selectedBarConfig?.enabled ?? false) && (CompositorService.isNiri || CompositorService.isHyprland)
checked: selectedBarConfig?.maximizeDetection ?? true
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
maximizeDetection: checked
})
}
SettingsCard {
iconName: "filter_b_and_w"
title: I18n.tr("System Tray Icon Tint")
settingKey: "trayIconTint"
visible: selectedBarConfig?.enabled ?? false
StyledText {
text: I18n.tr("Choose monochrome or a theme color tint for system tray icons")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
horizontalAlignment: Text.AlignLeft
}
SettingsButtonGroupRow {
text: I18n.tr("Mode")
model: [I18n.tr("None"), I18n.tr("Monochrome"), I18n.tr("Primary"), I18n.tr("Secondary")]
currentIndex: {
let mode = SettingsData.systemTrayIconTintMode || "none";
switch (mode) {
case "monochrome":
return 1;
case "primary":
return 2;
case "secondary":
return 3;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let mode = "none";
switch (index) {
case 1:
mode = "monochrome";
break;
case 2:
mode = "primary";
break;
case 3:
mode = "secondary";
break;
}
SettingsData.set("systemTrayIconTintMode", mode);
}
}
SettingsSliderRow {
id: trayTintSaturationSlider
text: I18n.tr("Tint Saturation")
description: I18n.tr("Controls how much original icon color is removed before applying tint")
visible: {
const mode = SettingsData.systemTrayIconTintMode || "none";
return mode === "primary" || mode === "secondary";
}
value: SettingsData.systemTrayIconTintSaturation ?? 50
minimum: 0
maximum: 100
unit: "%"
defaultValue: 50
onSliderDragFinished: finalValue => SettingsData.set("systemTrayIconTintSaturation", finalValue)
Binding {
target: trayTintSaturationSlider
property: "value"
value: SettingsData.systemTrayIconTintSaturation ?? 50
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderRow {
id: trayTintStrengthSlider
text: I18n.tr("Tint Strength")
description: I18n.tr("Controls how strongly the selected tint color is applied")
visible: {
const mode = SettingsData.systemTrayIconTintMode || "none";
return mode === "primary" || mode === "secondary";
}
value: SettingsData.systemTrayIconTintStrength ?? 135
minimum: 0
maximum: 200
unit: "%"
defaultValue: 135
onSliderDragFinished: finalValue => SettingsData.set("systemTrayIconTintStrength", finalValue)
Binding {
target: trayTintStrengthSlider
property: "value"
value: SettingsData.systemTrayIconTintStrength ?? 135
restoreMode: Binding.RestoreBinding
}
}
}
SettingsToggleCard {
iconName: "border_style"
title: I18n.tr("Border")
visible: selectedBarConfig?.enabled ?? false
checked: selectedBarConfig?.borderEnabled ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
borderEnabled: checked
})
SettingsButtonGroupRow {
text: I18n.tr("Color")
model: ["Surface", "Secondary", "Primary"]
currentIndex: {
switch (selectedBarConfig?.borderColor || "surfaceText") {
case "surfaceText":
return 0;
case "secondary":
return 1;
case "primary":
return 2;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newColor = "surfaceText";
switch (index) {
case 0:
newColor = "surfaceText";
break;
case 1:
newColor = "secondary";
break;
case 2:
newColor = "primary";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
borderColor: newColor
});
}
}
SettingsSliderRow {
id: borderOpacitySlider
text: I18n.tr("Opacity")
value: (selectedBarConfig?.borderOpacity ?? 1.0) * 100
minimum: 0
maximum: 100
unit: "%"
defaultValue: 100
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
borderOpacity: finalValue / 100
});
}
Binding {
target: borderOpacitySlider
property: "value"
value: (selectedBarConfig?.borderOpacity ?? 1.0) * 100
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderRow {
id: borderThicknessSlider
text: I18n.tr("Thickness")
value: selectedBarConfig?.borderThickness ?? 1
minimum: 1
maximum: 10
unit: "px"
defaultValue: 1
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
borderThickness: finalValue
});
}
Binding {
target: borderThicknessSlider
property: "value"
value: selectedBarConfig?.borderThickness ?? 1
restoreMode: Binding.RestoreBinding
}
}
}
SettingsToggleCard {
iconName: "highlight"
title: I18n.tr("Widget Outline")
visible: selectedBarConfig?.enabled ?? false
checked: selectedBarConfig?.widgetOutlineEnabled ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineEnabled: checked
})
SettingsButtonGroupRow {
text: I18n.tr("Color")
model: ["Surface", "Secondary", "Primary"]
currentIndex: {
switch (selectedBarConfig?.widgetOutlineColor || "primary") {
case "surfaceText":
return 0;
case "secondary":
return 1;
case "primary":
return 2;
default:
return 2;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newColor = "primary";
switch (index) {
case 0:
newColor = "surfaceText";
break;
case 1:
newColor = "secondary";
break;
case 2:
newColor = "primary";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineColor: newColor
});
}
}
SettingsSliderRow {
id: widgetOutlineOpacitySlider
text: I18n.tr("Opacity")
value: (selectedBarConfig?.widgetOutlineOpacity ?? 1.0) * 100
minimum: 0
maximum: 100
unit: "%"
defaultValue: 100
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineOpacity: finalValue / 100
});
}
Binding {
target: widgetOutlineOpacitySlider
property: "value"
value: (selectedBarConfig?.widgetOutlineOpacity ?? 1.0) * 100
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderRow {
id: widgetOutlineThicknessSlider
text: I18n.tr("Thickness")
value: selectedBarConfig?.widgetOutlineThickness ?? 1
minimum: 1
maximum: 10
unit: "px"
defaultValue: 1
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineThickness: finalValue
});
}
Binding {
target: widgetOutlineThicknessSlider
property: "value"
value: selectedBarConfig?.widgetOutlineThickness ?? 1
restoreMode: Binding.RestoreBinding
}
}
}
SettingsCard {
id: shadowCard
iconName: "layers"
@@ -1147,7 +1350,7 @@ Item {
settingKey: "barShadow"
collapsible: true
expanded: false
visible: selectedBarConfig?.enabled
visible: selectedBarConfig?.enabled ?? false
readonly property bool shadowActive: (selectedBarConfig?.shadowIntensity ?? 0) > 0
readonly property bool isCustomColor: (selectedBarConfig?.shadowColorMode ?? "text") === "custom"
@@ -1269,114 +1472,62 @@ Item {
}
SettingsToggleCard {
iconName: "border_style"
title: I18n.tr("Border")
visible: selectedBarConfig?.enabled
checked: selectedBarConfig?.borderEnabled ?? false
iconName: "mouse"
title: I18n.tr("Scroll Wheel")
description: I18n.tr("Control workspaces and columns by scrolling on the bar")
visible: selectedBarConfig?.enabled ?? false
checked: selectedBarConfig?.scrollEnabled ?? true
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
borderEnabled: checked
scrollEnabled: checked
})
SettingsButtonGroupRow {
text: I18n.tr("Color")
model: ["Surface", "Secondary", "Primary"]
text: I18n.tr("Y Axis")
model: CompositorService.isNiri ? [I18n.tr("None"), I18n.tr("Workspace"), I18n.tr("Column")] : [I18n.tr("None"), I18n.tr("Workspace")]
currentIndex: {
switch (selectedBarConfig?.borderColor || "surfaceText") {
case "surfaceText":
switch (selectedBarConfig?.scrollYBehavior || "workspace") {
case "none":
return 0;
case "secondary":
case "workspace":
return 1;
case "primary":
case "column":
return 2;
default:
return 0;
return 1;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newColor = "surfaceText";
let behavior = "workspace";
switch (index) {
case 0:
newColor = "surfaceText";
behavior = "none";
break;
case 1:
newColor = "secondary";
behavior = "workspace";
break;
case 2:
newColor = "primary";
behavior = "column";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
borderColor: newColor
scrollYBehavior: behavior
});
}
}
SettingsSliderRow {
id: borderOpacitySlider
text: I18n.tr("Opacity")
value: (selectedBarConfig?.borderOpacity ?? 1.0) * 100
minimum: 0
maximum: 100
unit: "%"
defaultValue: 100
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
borderOpacity: finalValue / 100
});
}
Binding {
target: borderOpacitySlider
property: "value"
value: (selectedBarConfig?.borderOpacity ?? 1.0) * 100
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderRow {
id: borderThicknessSlider
text: I18n.tr("Thickness")
value: selectedBarConfig?.borderThickness ?? 1
minimum: 1
maximum: 10
unit: "px"
defaultValue: 1
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
borderThickness: finalValue
});
}
Binding {
target: borderThicknessSlider
property: "value"
value: selectedBarConfig?.borderThickness ?? 1
restoreMode: Binding.RestoreBinding
}
}
}
SettingsToggleCard {
iconName: "highlight"
title: I18n.tr("Widget Outline")
visible: selectedBarConfig?.enabled
checked: selectedBarConfig?.widgetOutlineEnabled ?? false
onToggled: checked => SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineEnabled: checked
})
SettingsButtonGroupRow {
text: I18n.tr("Color")
model: ["Surface", "Secondary", "Primary"]
text: I18n.tr("X Axis")
visible: CompositorService.isNiri
model: [I18n.tr("None"), I18n.tr("Workspace"), I18n.tr("Column")]
currentIndex: {
switch (selectedBarConfig?.widgetOutlineColor || "primary") {
case "surfaceText":
switch (selectedBarConfig?.scrollXBehavior || "column") {
case "none":
return 0;
case "secondary":
case "workspace":
return 1;
case "primary":
case "column":
return 2;
default:
return 2;
@@ -1385,67 +1536,23 @@ Item {
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newColor = "primary";
let behavior = "column";
switch (index) {
case 0:
newColor = "surfaceText";
behavior = "none";
break;
case 1:
newColor = "secondary";
behavior = "workspace";
break;
case 2:
newColor = "primary";
behavior = "column";
break;
}
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineColor: newColor
scrollXBehavior: behavior
});
}
}
SettingsSliderRow {
id: widgetOutlineOpacitySlider
text: I18n.tr("Opacity")
value: (selectedBarConfig?.widgetOutlineOpacity ?? 1.0) * 100
minimum: 0
maximum: 100
unit: "%"
defaultValue: 100
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineOpacity: finalValue / 100
});
}
Binding {
target: widgetOutlineOpacitySlider
property: "value"
value: (selectedBarConfig?.widgetOutlineOpacity ?? 1.0) * 100
restoreMode: Binding.RestoreBinding
}
}
SettingsSliderRow {
id: widgetOutlineThicknessSlider
text: I18n.tr("Thickness")
value: selectedBarConfig?.widgetOutlineThickness ?? 1
minimum: 1
maximum: 10
unit: "px"
defaultValue: 1
onSliderDragFinished: finalValue => {
SettingsData.updateBarConfig(selectedBarId, {
widgetOutlineThickness: finalValue
});
}
Binding {
target: widgetOutlineThicknessSlider
property: "value"
value: selectedBarConfig?.widgetOutlineThickness ?? 1
restoreMode: Binding.RestoreBinding
}
}
}
}
}

View File

@@ -1635,6 +1635,33 @@ Item {
onToggled: checked => SettingsData.set("blurEnabled", checked)
}
SettingsToggleRow {
tab: "theme"
tags: ["blur", "foreground", "layers", "contrast", "glass", "frosted"]
settingKey: "blurForegroundLayers"
text: I18n.tr("Foreground Layers")
description: I18n.tr("Show foreground surfaces on blurred panels for stronger contrast")
checked: SettingsData.blurForegroundLayers ?? true
visible: BlurService.available && (SettingsData.blurEnabled ?? false)
enabled: BlurService.available
onToggled: checked => SettingsData.set("blurForegroundLayers", checked)
}
SettingsSliderRow {
tab: "theme"
tags: ["blur", "foreground", "layers", "outline", "border", "cards", "widgets", "notifications", "control center"]
settingKey: "blurLayerOutlineOpacity"
text: I18n.tr("Layer Outline Opacity")
description: I18n.tr("Controls outlines around blurred foreground cards, pills, and notification cards")
visible: BlurService.available && (SettingsData.blurEnabled ?? false)
value: Math.round((SettingsData.blurLayerOutlineOpacity ?? 0.12) * 100)
minimum: 0
maximum: 40
unit: "%"
defaultValue: 12
onSliderValueChanged: newValue => SettingsData.set("blurLayerOutlineOpacity", newValue / 100)
}
SettingsDropdownRow {
tab: "theme"
tags: ["blur", "border", "outline", "edge"]
@@ -1678,12 +1705,13 @@ Item {
tags: ["blur", "border", "opacity"]
settingKey: "blurBorderOpacity"
text: I18n.tr("Blur Border Opacity")
description: I18n.tr("Controls the outer edge of protocol-blurred windows")
visible: SettingsData.blurEnabled
value: Math.round((SettingsData.blurBorderOpacity ?? 1.0) * 100)
value: Math.round((SettingsData.blurBorderOpacity ?? 0.35) * 100)
minimum: 0
maximum: 100
unit: "%"
defaultValue: 100
defaultValue: 35
onSliderValueChanged: newValue => SettingsData.set("blurBorderOpacity", newValue / 100)
}
}

View File

@@ -14,6 +14,10 @@ FloatingWindow {
property int selectedIndex: -1
property bool keyboardNavigationActive: false
property var parentModal: null
readonly property bool blurActive: Theme.blurForegroundLayers || Theme.transparentBlurLayers
readonly property real surfaceAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.36 : 0.78) : 1.0
readonly property real fieldAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.18 : 0.62) : 1.0
readonly property real rowAlpha: blurActive ? Math.min(Theme.popupTransparency, Theme.transparentBlurLayers ? 0.12 : 0.52) : 0.30
signal widgetSelected(string widgetId, string targetSection)
@@ -94,7 +98,7 @@ FloatingWindow {
minimumSize: Qt.size(400, 350)
implicitWidth: 500
implicitHeight: 550
color: Theme.surfaceContainer
color: blurActive ? "transparent" : Theme.surfaceContainer
visible: false
onVisibleChanged: {
@@ -119,6 +123,24 @@ FloatingWindow {
});
}
WindowBlur {
targetWindow: root
blurX: 0
blurY: 0
blurWidth: root.visible ? root.width : 0
blurHeight: root.visible ? root.height : 0
blurRadius: Theme.cornerRadius
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, root.surfaceAlpha)
border.color: root.blurActive ? Theme.outlineMedium : "transparent"
border.width: root.blurActive ? Theme.layerOutlineWidth : 0
antialiasing: true
}
FocusScope {
id: widgetKeyHandler
@@ -184,8 +206,7 @@ FloatingWindow {
Rectangle {
anchors.fill: parent
color: Theme.surfaceContainer
opacity: 0.5
color: Theme.withAlpha(Theme.surfaceContainerHigh, root.blurActive ? 0.20 : 0.50)
}
Row {
@@ -258,7 +279,7 @@ FloatingWindow {
width: parent.width
height: 48
cornerRadius: Theme.cornerRadius
backgroundColor: Theme.surfaceContainerHigh
backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, root.fieldAlpha)
normalBorderColor: Theme.outlineMedium
focusedBorderColor: Theme.primary
leftIconName: "search"
@@ -302,9 +323,10 @@ FloatingWindow {
height: 60
radius: Theme.cornerRadius
property bool isSelected: root.keyboardNavigationActive && index === root.selectedIndex
color: isSelected ? Theme.primarySelected : widgetArea.containsMouse ? Theme.primaryHover : Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
border.color: isSelected ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: isSelected ? 2 : 1
color: isSelected ? Theme.withAlpha(Theme.primary, root.blurActive ? 0.22 : 0.16) : widgetArea.containsMouse ? Theme.withAlpha(Theme.primary, root.blurActive ? 0.14 : 0.08) : Theme.withAlpha(Theme.surfaceVariant, root.rowAlpha)
border.color: isSelected ? Theme.primary : Theme.outlineMedium
border.width: isSelected ? 2 : Theme.layerOutlineWidth
antialiasing: true
Row {
anchors.fill: parent

View File

@@ -90,9 +90,9 @@ PanelWindow {
case ToastService.levelWarn:
return Theme.warning;
case ToastService.levelInfo:
return Theme.surfaceContainer;
return Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency);
default:
return Theme.surfaceContainer;
return Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency);
}
}
radius: Theme.cornerRadius

View File

@@ -5,6 +5,7 @@ import Quickshell.Wayland
import qs.Common
import qs.Modals.DankLauncherV2
import qs.Services
import qs.Widgets
Scope {
id: niriOverviewScope
@@ -124,6 +125,17 @@ Scope {
item: overlayVisible && spotlightContainer.visible ? spotlightContainer : null
}
WindowBlur {
targetWindow: overlayWindow
readonly property real s: Math.min(1, spotlightContainer.scale)
readonly property bool active: spotlightContainer.visible && spotlightContainer.opacity > 0
blurX: spotlightContainer.x + spotlightContainer.width * (1 - s) * 0.5
blurY: spotlightContainer.y + spotlightContainer.height * (1 - s) * 0.5
blurWidth: active ? spotlightContainer.width * s : 0
blurHeight: active ? spotlightContainer.height * s : 0
blurRadius: Theme.cornerRadius
}
onShouldShowSpotlightChanged: {
if (shouldShowSpotlight) {
if (launcherContent?.controller) {

View File

@@ -18,7 +18,7 @@ Singleton {
readonly property color borderColor: {
if (!enabled)
return "transparent";
const opacity = SettingsData.blurBorderOpacity ?? 0.5;
const opacity = SettingsData.blurBorderOpacity ?? 0.35;
switch (SettingsData.blurBorderColor ?? "outline") {
case "primary":
return Theme.withAlpha(Theme.primary, opacity);

View File

@@ -371,8 +371,21 @@ Singleton {
function filterCurrentDisplay(toplevels, screenName) {
if (!toplevels || toplevels.length === 0 || !screenName)
return toplevels;
if (useNiriSorting)
if (useNiriSorting) {
const active = ToplevelManager.activeToplevel;
if (active && toplevels.length === 1 && toplevels[0] === active) {
if (NiriService.currentOutput !== screenName)
return [];
const focusedWin = NiriService.windows.find(nw => nw.is_focused);
if (!focusedWin)
return [];
const screenWsIds = new Set(
NiriService.allWorkspaces.filter(ws => ws.output === screenName).map(ws => ws.id)
);
return screenWsIds.has(focusedWin.workspace_id) ? toplevels : [];
}
return NiriService.filterCurrentDisplay(toplevels, screenName);
}
if (isHyprland)
return filterHyprlandCurrentDisplaySafe(toplevels, screenName);
return toplevels;

View File

@@ -1,4 +1,5 @@
import QtQuick
import Quickshell.Io
import qs.Common
Item {
@@ -68,11 +69,11 @@ Item {
smooth: true
onStatusChanged: {
if (source == root.cachePath && status === Image.Error) {
if (source === root.cachePath && status === Image.Error) {
source = root.encodedImagePath;
return;
}
if (root.isRemoteUrl || source != root.encodedImagePath || status !== Image.Ready || !root.cachePath)
if (root.isRemoteUrl || source !== root.encodedImagePath || status !== Image.Ready || !root.cachePath)
return;
Paths.mkdir(Paths.imagecache);
const grabPath = root.cachePath;
@@ -82,6 +83,22 @@ Item {
}
}
Process {
id: cacheProbe
property string cachePath: ""
property string fallbackSource: ""
running: false
command: ["test", "-f", cachePath]
onExited: exitCode => {
if (cacheProbe.cachePath !== root.cachePath)
return;
staticImg.source = exitCode === 0 ? cacheProbe.cachePath : cacheProbe.fallbackSource;
}
}
onImagePathChanged: {
if (!imagePath) {
staticImg.source = "";
@@ -97,6 +114,13 @@ Item {
const hash = djb2Hash(normalizedPath);
const cPath = hash ? `${Paths.stringify(Paths.imagecache)}/${hash}@${maxCacheSize}x${maxCacheSize}.png` : "";
const encoded = "file://" + normalizedPath.split('/').map(s => encodeURIComponent(s)).join('/');
staticImg.source = cPath || encoded;
if (!cPath) {
staticImg.source = encoded;
return;
}
cacheProbe.running = false;
cacheProbe.cachePath = cPath;
cacheProbe.fallbackSource = encoded;
cacheProbe.running = true;
}
}

View File

@@ -277,7 +277,7 @@ PanelWindow {
id: background
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, osdContainer.popupSurfaceAlpha)
color: Theme.transparentBlurLayers ? "transparent" : Theme.withAlpha(Theme.surfaceContainer, osdContainer.popupSurfaceAlpha)
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
border.width: BlurService.enabled ? BlurService.borderWidth : 1
z: -1

View File

@@ -13,6 +13,7 @@ Item {
property alias contentLoader: contentLoader
property Component overlayContent: null
property alias overlayLoader: overlayLoader
readonly property alias backgroundWindow: backgroundWindow
property real popupWidth: 400
property real popupHeight: 300
property real triggerX: 0
@@ -511,7 +512,7 @@ Item {
readonly property real effectiveShadowAlpha: Math.max(0, Math.min(1, shadowBaseAlpha * popupSurfaceAlpha))
readonly property int blurMax: 64
layer.enabled: Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
layer.enabled: !BlurService.enabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" && !(root.suspendShadowWhileResizing && root._resizeActive)
layer.smooth: false
layer.effect: MultiEffect {
@@ -552,6 +553,12 @@ Item {
}
}
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
}
Loader {
id: contentLoader
anchors.fill: parent
@@ -569,9 +576,10 @@ Item {
scale: contentWrapper.scale
visible: contentWrapper.visible
radius: Theme.cornerRadius
antialiasing: true
color: "transparent"
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
border.width: BlurService.borderWidth
border.width: BlurService.enabled ? BlurService.borderWidth : 1
z: 100
}
}

View File

@@ -134,7 +134,7 @@ PanelWindow {
Rectangle {
anchors.fill: parent
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, contentRect.effectiveTransparency)
color: Theme.transparentBlurLayers ? "transparent" : Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, contentRect.effectiveTransparency)
radius: Theme.cornerRadius
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
border.width: BlurService.borderWidth

View File

@@ -22,6 +22,7 @@ Item {
property color thumbOutlineColor: Theme.surfaceContainer
property color trackColor: enabled ? Theme.outline : Theme.outline
property real trackOpacity: Theme.popupTransparency
signal sliderValueChanged(int newValue)
signal sliderDragFinished(int finalValue)
@@ -63,7 +64,7 @@ Item {
width: parent.width - (leftIconWidth + rightIconWidth + (slider.leftIcon.length > 0 ? Theme.spacingM : 0) + (slider.rightIcon.length > 0 ? Theme.spacingM : 0))
height: 12
radius: Theme.cornerRadius
color: slider.trackColor
color: Theme.withAlpha(slider.trackColor, slider.trackOpacity)
anchors.verticalCenter: parent.verticalCenter
clip: false
@@ -71,13 +72,16 @@ Item {
id: sliderFill
height: parent.height
radius: Theme.cornerRadius
topRightRadius: 0
bottomRightRadius: 0
width: {
const range = slider.maximum - slider.minimum;
const rawRatio = range === 0 ? 0 : (slider.value - slider.minimum) / range;
const ratio = slider.centerMinimum ? (0.5 + rawRatio * 0.5) : rawRatio;
const travel = sliderTrack.width - sliderHandle.width;
const center = (travel * ratio) + sliderHandle.width / 2;
return Math.max(0, Math.min(sliderTrack.width, center));
const handleLeft = travel * ratio;
const endPoint = handleLeft - 3;
return Math.max(0, Math.min(sliderTrack.width, endPoint));
}
color: slider.enabled ? Theme.primary : Theme.withAlpha(Theme.onSurface, 0.12)
}
@@ -87,8 +91,8 @@ Item {
property bool active: sliderMouseArea.containsMouse || sliderMouseArea.pressed || slider.isDragging
width: 8
height: 24
width: 4
height: 20
radius: Theme.cornerRadius
x: {
const range = slider.maximum - slider.minimum;
@@ -99,7 +103,7 @@ Item {
}
anchors.verticalCenter: parent.verticalCenter
color: slider.enabled ? Theme.primary : Theme.withAlpha(Theme.onSurface, 0.12)
border.width: 3
border.width: 0
border.color: slider.thumbOutlineColor
StyledRect {

View File

@@ -74,7 +74,7 @@ PanelWindow {
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
radius: Theme.cornerRadius
border.width: 1
border.color: Theme.outlineMedium
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
Text {
id: textContent

View File

@@ -114,7 +114,7 @@ Item {
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
radius: Theme.cornerRadius
border.width: 1
border.color: Theme.outlineMedium
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
}
contentItem: Text {

View File

@@ -19,7 +19,9 @@ Rectangle {
implicitHeight: 32 + 1 + listHeight + Theme.spacingS * 4 + Theme.spacingM * 2
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
color: Theme.nestedSurface
border.color: Theme.outlineMedium
border.width: Theme.layerOutlineWidth
FileBrowserSurfaceModal {
id: fileBrowser

View File

@@ -826,6 +826,31 @@
],
"icon": "visibility_off"
},
{
"section": "trayIconTint",
"label": "System Tray Icon Tint",
"tabIndex": 3,
"category": "Dank Bar",
"keywords": [
"bar",
"dank",
"icon",
"icons",
"monochrome",
"panel",
"primary",
"secondary",
"saturation",
"status",
"statusbar",
"strength",
"taskbar",
"tint",
"tray"
],
"icon": "filter_b_and_w",
"description": "Choose monochrome or a theme color tint for system tray icons"
},
{
"section": "workspaceDragReorder",
"label": "Drag to Reorder",
@@ -2501,6 +2526,60 @@
"theme"
]
},
{
"section": "blurForegroundLayers",
"label": "Foreground Layers",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"blur",
"blurred",
"colors",
"contrast",
"foreground",
"frosted",
"glass",
"layers",
"look",
"panels",
"scheme",
"show",
"stronger",
"style",
"surfaces",
"theme"
],
"description": "Show foreground surfaces on blurred panels for stronger contrast"
},
{
"section": "blurLayerOutlineOpacity",
"label": "Layer Outline Opacity",
"tabIndex": 10,
"category": "Theme & Colors",
"keywords": [
"appearance",
"blur",
"border",
"cards",
"colors",
"contrast",
"control",
"foreground",
"frosted",
"glass",
"intensity",
"layers",
"notifications",
"opacity",
"outline",
"pills",
"surfaces",
"theme",
"widgets"
],
"description": "Controls outlines around blurred foreground cards, pills, and notification cards"
},
{
"section": "matugenTemplateGtk",
"label": "GTK",
@@ -3916,6 +3995,27 @@
],
"description": "Automatically lock the screen when DMS starts"
},
{
"section": "lockBeforeSuspend",
"label": "Lock before suspend",
"tabIndex": 11,
"category": "Lock Screen",
"keywords": [
"automatic",
"automatically",
"before",
"lock",
"login",
"password",
"prepares",
"screen",
"security",
"sleep",
"suspend",
"system"
],
"description": "Automatically lock the screen when the system prepares to suspend"
},
{
"section": "lockScreenNotificationMode",
"label": "Notification Display",
@@ -5859,27 +5959,6 @@
"icon": "schedule",
"description": "Gradually fade the screen before locking with a configurable grace period"
},
{
"section": "lockBeforeSuspend",
"label": "Lock before suspend",
"tabIndex": 21,
"category": "Power & Sleep",
"keywords": [
"automatically",
"before",
"energy",
"lock",
"power",
"prepares",
"screen",
"security",
"shutdown",
"sleep",
"suspend",
"system"
],
"description": "Automatically lock the screen when the system prepares to suspend"
},
{
"section": "fadeToLockGracePeriod",
"label": "Lock fade grace period",
@@ -6050,6 +6129,29 @@
"turn"
]
},
{
"section": "postLockMonitorTimeout",
"label": "Turn off monitors after lock",
"tabIndex": 21,
"category": "Power & Sleep",
"keywords": [
"after",
"display",
"energy",
"lock",
"monitor",
"monitors",
"off",
"post",
"power",
"screen",
"shutdown",
"sleep",
"suspend",
"timeout",
"turn"
]
},
{
"section": "powerMenuGridLayout",
"label": "Use Grid Layout",