diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 1169c9f2..9fc0029c 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -14,7 +14,7 @@ import "settings/SettingsStore.js" as Store Singleton { id: root - readonly property int settingsConfigVersion: 5 + readonly property int settingsConfigVersion: 6 readonly property bool isGreeterMode: Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true" diff --git a/quickshell/Common/settings/SettingsSpec.js b/quickshell/Common/settings/SettingsSpec.js index 962d6e6e..898cf921 100644 --- a/quickshell/Common/settings/SettingsSpec.js +++ b/quickshell/Common/settings/SettingsSpec.js @@ -21,7 +21,7 @@ var SPEC = { widgetColorMode: { def: "default" }, controlCenterTileColorMode: { def: "primary" }, buttonColorMode: { def: "primary" }, - cornerRadius: { def: 12, onChange: "updateCompositorLayout" }, + cornerRadius: { def: 16, onChange: "updateCompositorLayout" }, niriLayoutGapsOverride: { def: -1, onChange: "updateCompositorLayout" }, niriLayoutRadiusOverride: { def: -1, onChange: "updateCompositorLayout" }, niriLayoutBorderSize: { def: -1, onChange: "updateCompositorLayout" }, diff --git a/quickshell/Common/settings/SettingsStore.js b/quickshell/Common/settings/SettingsStore.js index fb491033..bb91bbf4 100644 --- a/quickshell/Common/settings/SettingsStore.js +++ b/quickshell/Common/settings/SettingsStore.js @@ -226,6 +226,25 @@ function migrateToVersion(obj, targetVersion) { settings.configVersion = 5; } + if (currentVersion < 6) { + console.info("Migrating settings from version", currentVersion, "to version 6"); + + if (settings.barElevationEnabled === undefined) { + var legacyBars = Array.isArray(settings.barConfigs) ? settings.barConfigs : []; + var hadLegacyBarShadowEnabled = false; + for (var j = 0; j < legacyBars.length; j++) { + var legacyIntensity = Number(legacyBars[j] && legacyBars[j].shadowIntensity); + if (!isNaN(legacyIntensity) && legacyIntensity > 0) { + hadLegacyBarShadowEnabled = true; + break; + } + } + settings.barElevationEnabled = hadLegacyBarShadowEnabled; + } + + settings.configVersion = 6; + } + return settings; } diff --git a/quickshell/Modules/DankBar/BarCanvas.qml b/quickshell/Modules/DankBar/BarCanvas.qml index 30b3fca2..1dcfbd56 100644 --- a/quickshell/Modules/DankBar/BarCanvas.qml +++ b/quickshell/Modules/DankBar/BarCanvas.qml @@ -134,15 +134,15 @@ Item { Loader { id: shadowLoader anchors.fill: parent - active: root.shadowEnabled && mainPathCorrectShape && Theme.elevationEnabled + active: root.shadowEnabled && mainPathCorrectShape && (Theme.elevationEnabled || root.hasPerBarOverride) asynchronous: false sourceComponent: Item { anchors.fill: parent layer.enabled: true layer.smooth: true - layer.samples: 8 - layer.textureSize: Qt.size(Math.round(width * barWindow._dpr * 2), Math.round(height * barWindow._dpr * 2)) + layer.samples: barWindow._dpr > 1.5 ? 4 : 2 + layer.textureSize: Qt.size(Math.round(width * barWindow._dpr), Math.round(height * barWindow._dpr)) layer.effect: MultiEffect { shadowEnabled: true shadowBlur: root.shadowBlur diff --git a/quickshell/Modules/Notifications/Center/HistoryNotificationList.qml b/quickshell/Modules/Notifications/Center/HistoryNotificationList.qml index 7a4f6298..69fea418 100644 --- a/quickshell/Modules/Notifications/Center/HistoryNotificationList.qml +++ b/quickshell/Modules/Notifications/Center/HistoryNotificationList.qml @@ -232,6 +232,11 @@ Item { height: parent.height - filterChips.height - Theme.spacingS clip: true spacing: Theme.spacingS + readonly property real horizontalShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1) + readonly property real verticalShadowGutter: Theme.snap(Math.max(Theme.spacingS, 8), 1) + readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1) + topMargin: verticalShadowGutter + bottomMargin: verticalShadowGutter model: ScriptModel { id: historyModel @@ -263,13 +268,14 @@ Item { } width: ListView.view.width - height: historyCard.height + height: historyCard.height + historyListView.delegateShadowGutter clip: false HistoryNotificationCard { id: historyCard - width: parent.width - x: delegateRoot.swipeOffset + width: Math.max(0, parent.width - (historyListView.horizontalShadowGutter * 2)) + y: historyListView.delegateShadowGutter / 2 + x: historyListView.horizontalShadowGutter + delegateRoot.swipeOffset historyItem: modelData isSelected: root.keyboardActive && root.selectedIndex === index keyboardNavigationActive: root.keyboardActive diff --git a/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml b/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml index db39155d..855163dd 100644 --- a/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml +++ b/quickshell/Modules/Notifications/Center/KeyboardNavigatedNotificationList.qml @@ -18,6 +18,10 @@ DankListView { property real swipingCardOffset: 0 property real __pendingStableHeight: 0 property real __heightUpdateThreshold: 20 + readonly property real shadowBlurPx: Theme.elevationEnabled ? ((Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined) ? Theme.elevationLevel1.blurPx : 4) : 0 + readonly property real shadowHorizontalGutter: Theme.snap(Math.max(Theme.spacingS, Math.min(32, shadowBlurPx * 1.5 + 6)), 1) + readonly property real shadowVerticalGutter: Theme.snap(Math.max(Theme.spacingXS, 6), 1) + readonly property real delegateShadowGutter: Theme.snap(Math.max(Theme.spacingXS, 4), 1) Component.onCompleted: { Qt.callLater(() => { @@ -56,21 +60,26 @@ DankListView { let delta = 0; for (let i = 0; i < count; i++) { const item = itemAtIndex(i); - if (item && item.children[0] && item.children[0].isAnimating) - delta += item.children[0].targetHeight - item.height; + if (item && item.children[0] && item.children[0].isAnimating) { + const targetDelegateHeight = item.children[0].targetHeight + listView.delegateShadowGutter; + delta += targetDelegateHeight - item.height; + } } const targetHeight = contentHeight + delta; // During expansion, always update immediately without threshold check stableContentHeight = targetHeight; } else { __pendingStableHeight = contentHeight; - heightUpdateDebounce.restart(); + heightUpdateDebounce.stop(); + stableContentHeight = __pendingStableHeight; } } clip: true model: NotificationService.groupedNotifications spacing: Theme.spacingL + topMargin: shadowVerticalGutter + bottomMargin: shadowVerticalGutter onIsUserScrollingChanged: { if (isUserScrolling && keyboardController && keyboardController.keyboardNavigationActive) { @@ -134,8 +143,7 @@ DankListView { readonly property real dismissThreshold: width * 0.35 property bool __delegateInitialized: false - readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 && - (index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1) + readonly property bool isAdjacentToSwipe: listView.count >= 2 && listView.swipingCardIndex !== -1 && (index === listView.swipingCardIndex - 1 || index === listView.swipingCardIndex + 1) readonly property real adjacentSwipeInfluence: isAdjacentToSwipe ? listView.swipingCardOffset * 0.10 : 0 readonly property real adjacentScaleInfluence: isAdjacentToSwipe ? 1.0 - Math.abs(listView.swipingCardOffset) / width * 0.02 : 1.0 readonly property real swipeFadeStartOffset: width * 0.75 @@ -149,13 +157,14 @@ DankListView { } width: ListView.view.width - height: notificationCard.height - clip: notificationCard.isAnimating + height: notificationCard.height + listView.delegateShadowGutter + clip: false NotificationCard { id: notificationCard - width: parent.width - x: delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence + width: Math.max(0, parent.width - (listView.shadowHorizontalGutter * 2)) + y: listView.delegateShadowGutter / 2 + x: listView.shadowHorizontalGutter + delegateRoot.swipeOffset + delegateRoot.adjacentSwipeInfluence listLevelAdjacentScaleInfluence: delegateRoot.adjacentScaleInfluence listLevelScaleAnimationsEnabled: listView.swipingCardIndex === -1 || !delegateRoot.isAdjacentToSwipe notificationGroup: modelData diff --git a/quickshell/Modules/Notifications/Center/NotificationCard.qml b/quickshell/Modules/Notifications/Center/NotificationCard.qml index 20f235b5..e928a630 100644 --- a/quickshell/Modules/Notifications/Center/NotificationCard.qml +++ b/quickshell/Modules/Notifications/Center/NotificationCard.qml @@ -39,7 +39,13 @@ Rectangle { height: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight) readonly property real targetHeight: expanded ? (expandedContent.height + cardPadding * 2) : (baseCardHeight + collapsedContent.extraHeight) radius: Theme.cornerRadius - scale: (cardHoverHandler.hovered ? 1.01 : 1.0) * listLevelAdjacentScaleInfluence + scale: (cardHoverHandler.hovered ? 1.005 : 1.0) * listLevelAdjacentScaleInfluence + readonly property bool shadowsAllowed: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" + readonly property var shadowElevation: Theme.elevationLevel1 + readonly property real baseShadowBlurPx: (shadowElevation && shadowElevation.blurPx !== undefined) ? shadowElevation.blurPx : 4 + readonly property real hoverShadowBlurBoost: cardHoverHandler.hovered ? Math.min(2, baseShadowBlurPx * 0.25) : 0 + property real shadowBlurPx: shadowsAllowed ? (baseShadowBlurPx + hoverShadowBlurBoost) : 0 + property real shadowOffsetYPx: shadowsAllowed ? (1 + (cardHoverHandler.hovered ? 0.35 : 0)) : 0 property bool __initialized: false Component.onCompleted: { @@ -57,6 +63,20 @@ Rectangle { } } + Behavior on shadowBlurPx { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + + Behavior on shadowOffsetYPx { + NumberAnimation { + duration: Theme.shortDuration + easing.type: Theme.standardEasing + } + } + Behavior on border.color { enabled: root.__initialized ColorAnimation { @@ -100,24 +120,24 @@ Rectangle { } clip: false - layer.enabled: Theme.elevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1" - layer.effect: MultiEffect { - autoPaddingEnabled: true - shadowEnabled: Theme.elevationEnabled - blurEnabled: false - maskEnabled: false - shadowBlur: Math.max(0, Math.min(1, Theme.elevationLevel1.blurPx / Theme.elevationBlurMax)) - shadowScale: 1 - shadowVerticalOffset: Theme.elevationLevel1.offsetY - shadowHorizontalOffset: 0 - blurMax: Theme.elevationBlurMax - shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1) - } - HoverHandler { id: cardHoverHandler } + layer.enabled: root.shadowsAllowed + layer.effect: MultiEffect { + autoPaddingEnabled: true + shadowEnabled: root.shadowsAllowed + blurEnabled: false + maskEnabled: false + shadowBlur: Math.max(0, Math.min(1, root.shadowBlurPx / Theme.elevationBlurMax)) + shadowScale: 1 + shadowVerticalOffset: root.shadowOffsetYPx + shadowHorizontalOffset: 0 + blurMax: Theme.elevationBlurMax + shadowColor: root.shadowElevation ? Theme.elevationShadowColor(root.shadowElevation) : "transparent" + } + Rectangle { anchors.fill: parent radius: parent.radius diff --git a/quickshell/Modules/Notifications/Center/NotificationCenterPopout.qml b/quickshell/Modules/Notifications/Center/NotificationCenterPopout.qml index e7b34c07..2c58e62c 100644 --- a/quickshell/Modules/Notifications/Center/NotificationCenterPopout.qml +++ b/quickshell/Modules/Notifications/Center/NotificationCenterPopout.qml @@ -13,9 +13,16 @@ DankPopout { property var triggerScreen: null property real stablePopupHeight: 400 property real _lastAlignedContentHeight: -1 + property bool _pendingSizedOpen: false function updateStablePopupHeight() { const item = contentLoader.item; + if (item && !root.shouldBeVisible) { + const notificationList = findChild(item, "notificationList"); + if (notificationList && typeof notificationList.forceLayout === "function") { + notificationList.forceLayout(); + } + } const target = item ? Theme.px(item.implicitHeight, dpr) : 400; if (Math.abs(target - _lastAlignedContentHeight) < 0.5) return; @@ -26,7 +33,7 @@ DankPopout { NotificationKeyboardController { id: keyboardController listView: null - isOpen: notificationHistoryVisible + isOpen: root.shouldBeVisible onClose: () => { notificationHistoryVisible = false; } @@ -40,20 +47,42 @@ DankPopout { suspendShadowWhileResizing: false screen: triggerScreen - shouldBeVisible: notificationHistoryVisible function toggle() { notificationHistoryVisible = !notificationHistoryVisible; } + function openSized() { + if (!notificationHistoryVisible) + return; + + primeContent(); + if (contentLoader.item) { + updateStablePopupHeight(); + _pendingSizedOpen = false; + Qt.callLater(() => { + if (!notificationHistoryVisible) + return; + updateStablePopupHeight(); + open(); + clearPrimedContent(); + }); + return; + } + + _pendingSizedOpen = true; + } + onBackgroundClicked: { notificationHistoryVisible = false; } onNotificationHistoryVisibleChanged: { if (notificationHistoryVisible) { - open(); + openSized(); } else { + _pendingSizedOpen = false; + clearPrimedContent(); close(); } } @@ -82,6 +111,17 @@ DankPopout { target: contentLoader function onLoaded() { root.updateStablePopupHeight(); + if (root._pendingSizedOpen && root.notificationHistoryVisible) { + Qt.callLater(() => { + if (!root._pendingSizedOpen || !root.notificationHistoryVisible) + return; + root.updateStablePopupHeight(); + root._pendingSizedOpen = false; + root.open(); + root.clearPrimedContent(); + }); + return; + } if (root.shouldBeVisible) Qt.callLater(root.setupKeyboardNavigation); } @@ -139,7 +179,8 @@ DankPopout { baseHeight += Theme.spacingM * 2; const settingsHeight = notificationSettings.expanded ? notificationSettings.contentHeight : 0; - let listHeight = notificationHeader.currentTab === 0 ? notificationList.stableContentHeight : Math.max(200, NotificationService.historyList.length * 80); + const currentListHeight = root.shouldBeVisible ? notificationList.stableContentHeight : notificationList.listContentHeight; + let listHeight = notificationHeader.currentTab === 0 ? currentListHeight : Math.max(200, NotificationService.historyList.length * 80); if (notificationHeader.currentTab === 0 && NotificationService.groupedNotifications.length === 0) { listHeight = 200; } @@ -233,13 +274,21 @@ DankPopout { expanded: notificationHeader.showSettings } - KeyboardNavigatedNotificationList { - id: notificationList - objectName: "notificationList" + Item { visible: notificationHeader.currentTab === 0 width: parent.width height: parent.height - notificationContent.cachedHeaderHeight - notificationSettings.height - contentColumnInner.spacing * 2 - cardAnimateExpansion: true + + KeyboardNavigatedNotificationList { + id: notificationList + objectName: "notificationList" + anchors.fill: parent + anchors.leftMargin: -shadowHorizontalGutter + anchors.rightMargin: -shadowHorizontalGutter + anchors.topMargin: -(shadowVerticalGutter + delegateShadowGutter / 2) + anchors.bottomMargin: -(shadowVerticalGutter + delegateShadowGutter / 2) + cardAnimateExpansion: true + } } HistoryNotificationList { diff --git a/quickshell/Modules/Notifications/Popup/NotificationPopup.qml b/quickshell/Modules/Notifications/Popup/NotificationPopup.qml index 308219f3..e0b98bee 100644 --- a/quickshell/Modules/Notifications/Popup/NotificationPopup.qml +++ b/quickshell/Modules/Notifications/Popup/NotificationPopup.qml @@ -118,8 +118,8 @@ PanelWindow { WlrLayershell.exclusiveZone: -1 WlrLayershell.keyboardFocus: WlrKeyboardFocus.None color: "transparent" - implicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380 - implicitHeight: { + readonly property real contentImplicitWidth: screen ? Math.min(400, Math.max(320, screen.width * 0.23)) : 380 + readonly property real contentImplicitHeight: { if (SettingsData.notificationPopupPrivacyMode && !descriptionExpanded) return basePopupHeightPrivacy; if (!descriptionExpanded) @@ -130,6 +130,8 @@ PanelWindow { return basePopupHeight + bodyTextHeight - collapsedBodyHeight; return basePopupHeight; } + implicitWidth: contentImplicitWidth + (windowShadowPad * 2) + implicitHeight: contentImplicitHeight + (windowShadowPad * 2) Behavior on implicitHeight { enabled: !exiting && !_isDestroying @@ -182,11 +184,14 @@ PanelWindow { property bool isTopCenter: SettingsData.notificationPopupPosition === -1 property bool isBottomCenter: SettingsData.notificationPopupPosition === SettingsData.Position.BottomCenter property bool isCenterPosition: isTopCenter || isBottomCenter + readonly property real maxPopupShadowBlurPx: Math.max((Theme.elevationLevel3 && Theme.elevationLevel3.blurPx !== undefined) ? Theme.elevationLevel3.blurPx : 12, (Theme.elevationLevel4 && Theme.elevationLevel4.blurPx !== undefined) ? Theme.elevationLevel4.blurPx : 16) + readonly property real maxPopupShadowOffsetYPx: Math.max(Math.abs((Theme.elevationLevel3 && Theme.elevationLevel3.offsetY !== undefined) ? Theme.elevationLevel3.offsetY : 6), Math.abs((Theme.elevationLevel4 && Theme.elevationLevel4.offsetY !== undefined) ? Theme.elevationLevel4.offsetY : 8)) + readonly property real windowShadowPad: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled ? Theme.snap(Math.max(16, maxPopupShadowBlurPx + maxPopupShadowOffsetYPx + 8), dpr) : 0 anchors.top: true - anchors.bottom: true anchors.left: true - anchors.right: true + anchors.bottom: false + anchors.right: false mask: contentInputMask @@ -205,9 +210,9 @@ PanelWindow { } margins { - top: 0 + top: getWindowTopMargin() bottom: 0 - left: 0 + left: getWindowLeftMargin() right: 0 } @@ -250,7 +255,7 @@ PanelWindow { function getLeftMargin() { if (isCenterPosition) - return screen ? (screen.width - implicitWidth) / 2 : 0; + return screen ? (screen.width - alignedWidth) / 2 : 0; const popupPos = SettingsData.notificationPopupPosition; const isLeft = popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom; @@ -274,39 +279,56 @@ PanelWindow { return barInfo.rightBar > 0 ? barInfo.rightBar : Theme.popupDistance; } + function getContentX() { + if (!screen) + return 0; + + const popupPos = SettingsData.notificationPopupPosition; + const barLeft = getLeftMargin(); + const barRight = getRightMargin(); + + if (isCenterPosition) + return Theme.snap((screen.width - alignedWidth) / 2, dpr); + if (popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom) + return Theme.snap(barLeft, dpr); + return Theme.snap(screen.width - alignedWidth - barRight, dpr); + } + + function getContentY() { + if (!screen) + return 0; + + const popupPos = SettingsData.notificationPopupPosition; + const barTop = getTopMargin(); + const barBottom = getBottomMargin(); + const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left; + if (isTop) + return Theme.snap(barTop, dpr); + return Theme.snap(screen.height - alignedHeight - barBottom, dpr); + } + + function getWindowLeftMargin() { + if (!screen) + return 0; + return Theme.snap(getContentX() - windowShadowPad, dpr); + } + + function getWindowTopMargin() { + if (!screen) + return 0; + return Theme.snap(getContentY() - windowShadowPad, dpr); + } + readonly property bool screenValid: win.screen && !_isDestroying readonly property real dpr: screenValid ? CompositorService.getScreenScale(win.screen) : 1 - readonly property real alignedWidth: Theme.px(implicitWidth, dpr) - readonly property real alignedHeight: Theme.px(implicitHeight, dpr) + readonly property real alignedWidth: Theme.px(contentImplicitWidth, dpr) + readonly property real alignedHeight: Theme.px(contentImplicitHeight, dpr) Item { id: content - x: { - const popupPos = SettingsData.notificationPopupPosition; - const barLeft = getLeftMargin(); - const barRight = getRightMargin(); - - if (isCenterPosition) { - return Theme.snap((screen.width - alignedWidth) / 2, dpr); - } else if (popupPos === SettingsData.Position.Left || popupPos === SettingsData.Position.Bottom) { - return Theme.snap(barLeft, dpr); - } else { - return Theme.snap(screen.width - alignedWidth - barRight, dpr); - } - } - y: { - const popupPos = SettingsData.notificationPopupPosition; - const barTop = getTopMargin(); - const barBottom = getBottomMargin(); - - const isTop = isTopCenter || popupPos === SettingsData.Position.Top || popupPos === SettingsData.Position.Left; - if (isTop) { - return Theme.snap(barTop, dpr); - } else { - return Theme.snap(screen.height - alignedHeight - barBottom, dpr); - } - } + x: Theme.snap(windowShadowPad, dpr) + y: Theme.snap(windowShadowPad, dpr) width: alignedWidth height: alignedHeight visible: !win._finalized @@ -332,7 +354,7 @@ PanelWindow { readonly property bool shadowsAllowed: Theme.elevationEnabled && SettingsData.notificationPopupShadowEnabled readonly property var elevLevel: cardHoverHandler.hovered ? Theme.elevationLevel4 : Theme.elevationLevel3 readonly property real cardInset: Theme.snap(4, win.dpr) - readonly property real shadowRenderPadding: shadowsAllowed ? Theme.snap(Theme.elevationBlurMax * 1.5 + 24, win.dpr) : 0 + readonly property real shadowRenderPadding: shadowsAllowed ? Theme.snap(Math.max(16, shadowBlurPx + Math.abs(shadowOffsetY) + 8), win.dpr) : 0 property real shadowBlurPx: shadowsAllowed ? (elevLevel && elevLevel.blurPx !== undefined ? elevLevel.blurPx : 12) : 0 property real shadowOffsetY: shadowsAllowed ? (elevLevel && elevLevel.offsetY !== undefined ? elevLevel.offsetY : 6) : 0 diff --git a/quickshell/Modules/Settings/ThemeColorsTab.qml b/quickshell/Modules/Settings/ThemeColorsTab.qml index 5925d931..790ea4c3 100644 --- a/quickshell/Modules/Settings/ThemeColorsTab.qml +++ b/quickshell/Modules/Settings/ThemeColorsTab.qml @@ -2292,12 +2292,40 @@ Item { } } + SettingsCard { + tab: "theme" + tags: ["icon", "theme", "system"] + title: I18n.tr("Icon Theme") + settingKey: "iconTheme" + + SettingsDropdownRow { + tab: "theme" + tags: ["icon", "theme", "system"] + settingKey: "iconTheme" + text: I18n.tr("Icon Theme") + description: I18n.tr("DankShell & System Icons (requires restart)") + currentValue: SettingsData.iconTheme + enableFuzzySearch: true + popupWidthOffset: 100 + maxPopupHeight: 236 + options: cachedIconThemes + onValueChanged: value => { + SettingsData.setIconTheme(value); + if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") { + ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body")); + } + } + } + } + SettingsCard { tab: "theme" tags: ["matugen", "templates", "theming"] title: I18n.tr("Matugen Templates") settingKey: "matugenTemplates" iconName: "auto_awesome" + collapsible: true + expanded: false visible: Theme.matugenAvailable SettingsToggleRow { @@ -2602,32 +2630,6 @@ Item { } } - SettingsCard { - tab: "theme" - tags: ["icon", "theme", "system"] - title: I18n.tr("Icon Theme") - settingKey: "iconTheme" - - SettingsDropdownRow { - tab: "theme" - tags: ["icon", "theme", "system"] - settingKey: "iconTheme" - text: I18n.tr("Icon Theme") - description: I18n.tr("DankShell & System Icons (requires restart)") - currentValue: SettingsData.iconTheme - enableFuzzySearch: true - popupWidthOffset: 100 - maxPopupHeight: 236 - options: cachedIconThemes - onValueChanged: value => { - SettingsData.setIconTheme(value); - if (Quickshell.env("QT_QPA_PLATFORMTHEME") != "gtk3" && Quickshell.env("QT_QPA_PLATFORMTHEME") != "qt6ct" && Quickshell.env("QT_QPA_PLATFORMTHEME_QT6") != "qt6ct") { - ToastService.showError(I18n.tr("Missing Environment Variables", "qt theme env error title"), I18n.tr("You need to set either:\nQT_QPA_PLATFORMTHEME=gtk3 OR\nQT_QPA_PLATFORMTHEME=qt6ct\nas environment variables, and then restart the shell.\n\nqt6ct requires qt6ct-kde to be installed.", "qt theme env error body")); - } - } - } - } - SettingsCard { tab: "theme" tags: ["system", "app", "theming", "gtk", "qt"] diff --git a/quickshell/Widgets/DankOSD.qml b/quickshell/Widgets/DankOSD.qml index 1f6c0e23..499ed5f0 100644 --- a/quickshell/Widgets/DankOSD.qml +++ b/quickshell/Widgets/DankOSD.qml @@ -270,7 +270,7 @@ PanelWindow { radius: Theme.cornerRadius color: Theme.withAlpha(Theme.surfaceContainer, osdContainer.popupSurfaceAlpha) border.color: Theme.outlineMedium - border.width: 0 + border.width: 1 z: -1 } diff --git a/quickshell/Widgets/DankPopout.qml b/quickshell/Widgets/DankPopout.qml index 9445b689..538d7531 100644 --- a/quickshell/Widgets/DankPopout.qml +++ b/quickshell/Widgets/DankPopout.qml @@ -31,6 +31,7 @@ Item { property bool backgroundInteractive: true property bool contentHandlesKeys: false property bool fullHeightSurface: false + property bool _primeContent: false property bool _resizeActive: false property real _surfaceMarginLeft: 0 property real _surfaceW: 0 @@ -89,6 +90,14 @@ Item { effectiveBarBottomGap = bottomGap !== undefined ? bottomGap : 0; } + function primeContent() { + _primeContent = true; + } + + function clearPrimedContent() { + _primeContent = false; + } + function setTriggerPosition(x, y, width, section, targetScreen, barPosition, barThickness, barSpacing, barConfig) { triggerX = x; triggerY = y; @@ -152,6 +161,7 @@ Item { function close() { shouldBeVisible = false; + _primeContent = false; PopoutManager.popoutChanged(); closeTimer.restart(); } @@ -257,29 +267,30 @@ Item { } })(), dpr) + readonly property real triggeringBarLeftExclusion: (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? Math.max(0, barX + barWidth) : 0 + readonly property real triggeringBarTopExclusion: (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? Math.max(0, barY + barHeight) : 0 + readonly property real triggeringBarRightExclusion: (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? Math.max(0, screenWidth - barX) : 0 + readonly property real triggeringBarBottomExclusion: (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? Math.max(0, screenHeight - barY) : 0 + readonly property real maskX: { - const triggeringBarX = (effectiveBarPosition === SettingsData.Position.Left && barWidth > 0) ? barWidth : 0; const adjacentLeftBar = adjacentBarInfo?.leftBar ?? 0; - return Math.max(triggeringBarX, adjacentLeftBar); + return Math.max(triggeringBarLeftExclusion, adjacentLeftBar); } readonly property real maskY: { - const triggeringBarY = (effectiveBarPosition === SettingsData.Position.Top && barHeight > 0) ? barHeight : 0; const adjacentTopBar = adjacentBarInfo?.topBar ?? 0; - return Math.max(triggeringBarY, adjacentTopBar); + return Math.max(triggeringBarTopExclusion, adjacentTopBar); } readonly property real maskWidth: { - const triggeringBarRight = (effectiveBarPosition === SettingsData.Position.Right && barWidth > 0) ? barWidth : 0; const adjacentRightBar = adjacentBarInfo?.rightBar ?? 0; - const rightExclusion = Math.max(triggeringBarRight, adjacentRightBar); + const rightExclusion = Math.max(triggeringBarRightExclusion, adjacentRightBar); return Math.max(100, screenWidth - maskX - rightExclusion); } readonly property real maskHeight: { - const triggeringBarBottom = (effectiveBarPosition === SettingsData.Position.Bottom && barHeight > 0) ? barHeight : 0; const adjacentBottomBar = adjacentBarInfo?.bottomBar ?? 0; - const bottomExclusion = Math.max(triggeringBarBottom, adjacentBottomBar); + const bottomExclusion = Math.max(triggeringBarBottomExclusion, adjacentBottomBar); return Math.max(100, screenHeight - maskY - bottomExclusion); } @@ -395,7 +406,7 @@ Item { implicitWidth: useBackgroundWindow ? root._surfaceW : 0 implicitHeight: (useBackgroundWindow && !_fullHeight) ? (root.alignedHeight + shadowBuffer * 2) : 0 - mask: (useBackgroundWindow && _fullHeight) ? contentInputMask : null + mask: useBackgroundWindow ? contentInputMask : null Region { id: contentInputMask @@ -405,10 +416,10 @@ Item { Item { id: contentMaskRect visible: false - x: contentContainer.x - root.shadowBuffer - y: contentContainer.y - root.shadowBuffer - width: root.alignedWidth + root.shadowBuffer * 2 - height: root.alignedHeight + root.shadowBuffer * 2 + x: contentContainer.x + y: contentContainer.y + width: root.alignedWidth + height: root.alignedHeight } MouseArea { @@ -486,7 +497,7 @@ Item { width: parent.width height: parent.height radius: Theme.cornerRadius - color: "black" + color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency) opacity: contentWrapper.opacity scale: contentWrapper.scale x: contentWrapper.x @@ -550,7 +561,7 @@ Item { Loader { id: contentLoader anchors.fill: parent - active: shouldBeVisible || contentWindow.visible + active: root._primeContent || shouldBeVisible || contentWindow.visible asynchronous: false } }