From 0d2d0f1931f5b9afb0b1e4722b0b16fcd7a1d9cd Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Sun, 28 Sep 2025 12:49:52 -0400 Subject: [PATCH 01/62] Nicer SpinBox with better mTertiary hover --- Widgets/NSpinBox.qml | 160 ++++++++++++++++++++++++++++++------------- 1 file changed, 114 insertions(+), 46 deletions(-) diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 0f5feb0f..3d5c0e5e 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -5,6 +5,7 @@ import qs.Commons import qs.Services import qs.Widgets + RowLayout { id: root @@ -38,12 +39,11 @@ RowLayout { // Value Rectangle { id: spinBoxContainer - implicitWidth: 100 * scaling // Wider for better proportions implicitHeight: (root.baseSize - 4) * scaling // Slightly shorter than toggle - radius: height * 0.5 // Fully rounded like toggle + radius: height / 2 // Fully rounded like toggle color: Color.mSurfaceVariant - border.color: root.hovering ? Color.mPrimary : Color.mOutline + border.color: (root.hovering || decreaseArea.containsMouse || increaseArea.containsMouse) ? Color.mTertiary : Color.mOutline border.width: 1 Behavior on border.color { @@ -75,56 +75,124 @@ RowLayout { } // Decrease button (left) - Rectangle { + Item { id: decreaseButton - width: parent.height * 0.8 // Make it circular - height: parent.height * 0.8 - anchors.verticalCenter: parent.verticalCenter + height:parent.height + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom anchors.left: parent.left - anchors.leftMargin: parent.height * 0.1 - radius: width * 0.5 // Perfect circle - color: decreaseArea.containsMouse ? Color.mPrimary : "transparent" opacity: root.enabled && spinBox.value > spinBox.from ? 1.0 : 0.3 - Behavior on color { - ColorAnimation { - duration: Style.animationFast - easing.type: Easing.InOutCubic + Item { + id: leftSemicircle + width: Math.round(parent.height / 2) + height: parent.height + clip: true + anchors.left: parent.left + Rectangle { + width: Math.round(parent.height) + height: parent.height + radius: width / 2 + anchors.left: parent.left + color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + } + } + + Rectangle { + height: parent.height + width: parent.width - leftSemicircle.width + anchors.left: leftSemicircle.right + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { + position: 0.0 + color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + } + GradientStop { + position: 1.0 + color: "transparent" + } + } + } + + NIcon { + anchors.centerIn: parent + icon: "chevron-left" + font.pointSize: Style.fontSizeS * scaling + color: decreaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary + } + + MouseArea { + id: decreaseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: root.enabled && spinBox.value > spinBox.from + onClicked: spinBox.decrease() + } + } + + + // Increase button (right) + Item { + id: increaseButton + height: parent.height + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + opacity: root.enabled && spinBox.value < spinBox.to ? 1.0 : 0.3 + + Item { + id: rightSemicircle + width: Math.round(parent.height / 2) + height: parent.height + clip: true + anchors.right: parent.right + Rectangle { + width: Math.round(parent.height) + height: parent.height + radius: width / 2 + anchors.right: parent.right + color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } } } - NIcon { - anchors.centerIn: parent - icon: "chevron-left" - font.pointSize: Style.fontSizeS * scaling - color: decreaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary - } - - MouseArea { - id: decreaseArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - enabled: root.enabled && spinBox.value > spinBox.from - onClicked: spinBox.decrease() - } - } - - // Increase button (right) - Rectangle { - id: increaseButton - width: parent.height * 0.8 // Make it circular - height: parent.height * 0.8 - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: parent.height * 0.1 - radius: width * 0.5 // Perfect circle - color: increaseArea.containsMouse ? Color.mPrimary : "transparent" - opacity: root.enabled && spinBox.value < spinBox.to ? 1.0 : 0.3 - - Behavior on color { - ColorAnimation { - duration: Style.animationFast + Rectangle { + height: parent.height + width: parent.width - rightSemicircle.width + anchors.right: rightSemicircle.left + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { + position: 1.0 + color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + } + GradientStop { + position: 0.0 + color: "transparent" + } } } From 5f3c088f2201700870c963e21b18dea7fec41689 Mon Sep 17 00:00:00 2001 From: MrDowntempo Date: Sun, 28 Sep 2025 13:16:07 -0400 Subject: [PATCH 02/62] Update NSpinBox.qml I missed a line --- Widgets/NSpinBox.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 686e9c82..8562da1b 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -158,7 +158,6 @@ RowLayout { anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.right - opacity: root.enabled && spinBox.value < spinBox.to ? 1.0 : 0.3 opacity: root.enabled && root.value < root.to ? 1.0 : 0.3 From 072d80e2f3c91a49946c0e4f9ab480673ef2c5ee Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 16:39:23 -0400 Subject: [PATCH 03/62] Bar vs Dock: Dock are loaded only once the bar is fully loaded. This ensure the vertical bar use the full screen height if the dock is exclusive. --- Modules/Bar/Bar.qml | 6 ++++++ Modules/Dock/Dock.qml | 15 +++++++++++++-- Services/BarService.qml | 25 +++++++++++++++++++++---- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index 08c1c202..d6d4e356 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -55,6 +55,12 @@ Variants { right: Settings.data.bar.floating && Settings.data.bar.position !== "left" ? Settings.data.bar.marginHorizontal * Style.marginXL * scaling : 0 } + Component.onCompleted: { + if (modelData && modelData.name) { + BarService.registerBar(modelData.name) + } + } + Item { anchors.fill: parent clip: true diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index f02f8040..f6fab110 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -14,8 +14,19 @@ Variants { delegate: Item { id: root + required property ShellScreen modelData property real scaling: ScalingService.getScreenScale(modelData) + property bool barIsReady: BarService.isBarReady(modelData.name) + + Connections { + target: BarService + function onBarReadyChanged(screenName) { + if (screenName === modelData.name) { + barIsReady = true + } + } + } Connections { target: ScalingService @@ -187,7 +198,7 @@ Variants { // PEEK WINDOW - Always visible when auto-hide is enabled Loader { - active: Settings.isLoaded && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide + active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide sourceComponent: PanelWindow { id: peekWindow @@ -233,7 +244,7 @@ Variants { // DOCK WINDOW Loader { - active: Settings.isLoaded && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) + active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) sourceComponent: PanelWindow { id: dockWindow diff --git a/Services/BarService.qml b/Services/BarService.qml index 63e607cc..ca8ee961 100644 --- a/Services/BarService.qml +++ b/Services/BarService.qml @@ -9,6 +9,13 @@ Singleton { property bool hasAudioVisualizer: false property bool isVisible: true + property var readyBars: ({}) + + // Registry to store actual widget instances + // Key format: "screenName|section|widgetId|index" + property var widgetInstances: ({}) + + signal barReadyChanged(string screenName) // Simple timer that run once when the widget structure has changed // and determine if any MediaMini widget has the visualizer on @@ -28,14 +35,24 @@ Singleton { } } - // Registry to store actual widget instances - // Key format: "screenName|section|widgetId|index" - property var widgetInstances: ({}) - Component.onCompleted: { Logger.log("BarService", "Service started") } + // Function for the Bar to call when it's ready + function registerBar(screenName) { + if (!readyBars[screenName]) { + readyBars[screenName] = true + console.log("ShellStateService: Bar on screen '" + screenName + "' is ready.") + barReadyChanged(screenName) + } + } + + // Function for the Dock to check if the bar is ready + function isBarReady(screenName) { + return readyBars[screenName] || false + } + // Register a widget instance function registerWidget(screenName, section, widgetId, index, instance) { const key = [screenName, section, widgetId, index].join("|") From a41be0b5d99227bc3d6a13336e58632747a932b3 Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Sun, 28 Sep 2025 19:08:33 -0400 Subject: [PATCH 04/62] Removed gradient and redesigned buttons --- Widgets/NSpinBox.qml | 151 +++++++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 40 deletions(-) diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 8562da1b..d1ee2ed1 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -80,12 +80,12 @@ RowLayout { Item { id: decreaseButton height:parent.height - width: height + width: leftSemicircle.width + (leftDiamondContainer.width / 2) anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left opacity: root.enabled && root.value > root.from ? 1.0 : 0.3 - + clip: true Item { id: leftSemicircle @@ -107,31 +107,59 @@ RowLayout { } } - Rectangle { - height: parent.height - width: parent.width - leftSemicircle.width - anchors.left: leftSemicircle.right - gradient: Gradient { - orientation: Gradient.Horizontal - GradientStop { - position: 0.0 - color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" - Behavior on color { - ColorAnimation { - duration: Style.animationFast - } + // 1. A wrapper Item to define the final, pixel-perfect size. + Item { + id: leftDiamondContainer + + // Make the container's height a guaranteed even number + height: Math.round(parent.height / 2) * 2 + width: height * Math.sqrt(2) // Keep the final bounding box square + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: leftSemicircle.right + + // 2. The Rectangle to be rotated and scaled. + // We give it a fixed base size (e.g., 100x100) to make calculations stable. + Rectangle { + id: leftDiamondVisual + width: 100 + height: 100 + + // The radius is now based on the fixed size + radius: width / 4 + + color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast } } - GradientStop { - position: 1.0 - color: "transparent" - } + + // Center the base shape in the container + anchors.centerIn: parent + + // 3. Apply transforms: first rotate, then scale to fit. + transform: [ + Rotation { angle: 45; origin.x: 50; origin.y: 50 }, + Scale { + id: leftScaler + origin.x: 50 + origin.y: 50 + + // This is the full formula for the height of the rotated, rounded square + readonly property real trueHeight: (leftDiamondVisual.width - 2 * leftDiamondVisual.radius) * Math.sqrt(2) + (2 * leftDiamondVisual.radius) + + // The corrected scale factor + xScale: leftDiamondContainer.height / leftScaler.trueHeight + yScale: leftDiamondContainer.height / leftScaler.trueHeight + } + ] } } + NIcon { anchors.centerIn: parent - icon: "chevron-left" + icon: "minus" font.pointSize: Style.fontSizeS * scaling color: decreaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary } @@ -154,12 +182,12 @@ RowLayout { Item { id: increaseButton height: parent.height - width: height + width: rightSemicircle.width + (rightDiamondContainer.width / 2) anchors.top: parent.top anchors.bottom: parent.bottom anchors.right: parent.right opacity: root.enabled && root.value < root.to ? 1.0 : 0.3 - + clip: true Item { id: rightSemicircle @@ -181,31 +209,74 @@ RowLayout { } } - Rectangle { - height: parent.height - width: parent.width - rightSemicircle.width - anchors.right: rightSemicircle.left - gradient: Gradient { - orientation: Gradient.Horizontal - GradientStop { - position: 1.0 - color: increaseArea.containsMouse ? Color.mTertiary : "transparent" - Behavior on color { - ColorAnimation { - duration: Style.animationFast - } + Item { + id: rightDiamondContainer + + // Make the container's height a guaranteed even number + height: Math.round(parent.height / 2) * 2 + width: height * Math.sqrt(2) // Keep the final bounding box square + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: rightSemicircle.left + + // 2. The Rectangle to be rotated and scaled. + // We give it a fixed base size (e.g., 100x100) to make calculations stable. + Rectangle { + id: rightDiamondVisual + width: 100 + height: 100 + + // The radius is now based on the fixed size + radius: width / 4 + + color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + Behavior on color { + ColorAnimation { + duration: Style.animationFast } } - GradientStop { - position: 0.0 - color: "transparent" - } + + // Center the base shape in the container + anchors.centerIn: parent + + // 3. Apply transforms: first rotate, then scale to fit. + transform: [ + Rotation { angle: 45; origin.x: 50; origin.y: 50 }, + Scale { + id: rightScaler + origin.x: 50 + origin.y: 50 + + // This is the full formula for the height of the rotated, rounded square + readonly property real trueHeight: (rightDiamondVisual.width - 2 * rightDiamondVisual.radius) * Math.sqrt(2) + (2 * rightDiamondVisual.radius) + + // The corrected scale factor + xScale: rightDiamondContainer.height / rightScaler.trueHeight + yScale: rightDiamondContainer.height / rightScaler.trueHeight + } + ] } } + // + // Rectangle { + // height: (parent.height / Math.sqrt(2)) + (radius * (2 - Math.sqrt(2))) + // width: height + // radius: width / 4 + // anchors.verticalCenter: parent.verticalCenter + // anchors.horizontalCenter: rightSemicircle.left + // rotation: 45 + // color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + // Behavior on color { + // ColorAnimation { + // duration: Style.animationFast + // } + // } + // } + + NIcon { anchors.centerIn: parent - icon: "chevron-right" + icon: "plus" font.pointSize: Style.fontSizeS * scaling color: increaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary } From 0ed8ed7fe5385be9d53a21fde311ceaeafa55770 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 19:45:37 -0400 Subject: [PATCH 05/62] Tooltips: fix clipping for tooltips with long sentences. --- Modules/Tooltip/Tooltip.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Tooltip/Tooltip.qml b/Modules/Tooltip/Tooltip.qml index 6acb7e61..68648084 100644 --- a/Modules/Tooltip/Tooltip.qml +++ b/Modules/Tooltip/Tooltip.qml @@ -375,8 +375,8 @@ PopupWindow { anchors.fill: parent color: Color.mSurface border.color: Color.mOutline - border.width: Math.max(1, Style.borderS * scaling) - radius: Style.radiusS * scaling + border.width: Math.max(1, Style.borderS * root.scaling) + radius: Style.radiusS * root.scaling // Only show content when we have text visible: root.text !== "" @@ -386,12 +386,12 @@ PopupWindow { anchors.centerIn: parent anchors.margins: root.padding * root.scaling text: root.text - font.pointSize: Style.fontSizeS * scaling + font.pointSize: Style.fontSizeS * root.scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap - width: root.maxWidth + width: root.maxWidth * root.scaling - (root.padding * 2 * root.scaling) } } } From 97fa2fb1b55fbefb5515ecde398e80401987eab9 Mon Sep 17 00:00:00 2001 From: Corey Woodworth Date: Sun, 28 Sep 2025 20:20:02 -0400 Subject: [PATCH 06/62] Back to Chevrons. +/- were inconsistent sizes. Better alignment --- Widgets/NSpinBox.qml | 54 ++++++++------------------------------------ 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index d1ee2ed1..05546980 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -107,24 +107,18 @@ RowLayout { } } - // 1. A wrapper Item to define the final, pixel-perfect size. Item { id: leftDiamondContainer - // Make the container's height a guaranteed even number height: Math.round(parent.height / 2) * 2 - width: height * Math.sqrt(2) // Keep the final bounding box square + width: height * Math.sqrt(2) anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: leftSemicircle.right - // 2. The Rectangle to be rotated and scaled. - // We give it a fixed base size (e.g., 100x100) to make calculations stable. Rectangle { id: leftDiamondVisual width: 100 height: 100 - - // The radius is now based on the fixed size radius: width / 4 color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" @@ -134,10 +128,8 @@ RowLayout { } } - // Center the base shape in the container anchors.centerIn: parent - // 3. Apply transforms: first rotate, then scale to fit. transform: [ Rotation { angle: 45; origin.x: 50; origin.y: 50 }, Scale { @@ -147,8 +139,6 @@ RowLayout { // This is the full formula for the height of the rotated, rounded square readonly property real trueHeight: (leftDiamondVisual.width - 2 * leftDiamondVisual.radius) * Math.sqrt(2) + (2 * leftDiamondVisual.radius) - - // The corrected scale factor xScale: leftDiamondContainer.height / leftScaler.trueHeight yScale: leftDiamondContainer.height / leftScaler.trueHeight } @@ -156,10 +146,11 @@ RowLayout { } } - NIcon { - anchors.centerIn: parent - icon: "minus" + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.25 + anchors.verticalCenter: parent.verticalCenter + icon: "chevron-left" font.pointSize: Style.fontSizeS * scaling color: decreaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary } @@ -177,7 +168,6 @@ RowLayout { } } - // Increase button (right) Item { id: increaseButton @@ -212,20 +202,15 @@ RowLayout { Item { id: rightDiamondContainer - // Make the container's height a guaranteed even number height: Math.round(parent.height / 2) * 2 - width: height * Math.sqrt(2) // Keep the final bounding box square + width: height * Math.sqrt(2) anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: rightSemicircle.left - // 2. The Rectangle to be rotated and scaled. - // We give it a fixed base size (e.g., 100x100) to make calculations stable. Rectangle { id: rightDiamondVisual width: 100 height: 100 - - // The radius is now based on the fixed size radius: width / 4 color: increaseArea.containsMouse ? Color.mTertiary : "transparent" @@ -235,10 +220,8 @@ RowLayout { } } - // Center the base shape in the container anchors.centerIn: parent - // 3. Apply transforms: first rotate, then scale to fit. transform: [ Rotation { angle: 45; origin.x: 50; origin.y: 50 }, Scale { @@ -248,8 +231,6 @@ RowLayout { // This is the full formula for the height of the rotated, rounded square readonly property real trueHeight: (rightDiamondVisual.width - 2 * rightDiamondVisual.radius) * Math.sqrt(2) + (2 * rightDiamondVisual.radius) - - // The corrected scale factor xScale: rightDiamondContainer.height / rightScaler.trueHeight yScale: rightDiamondContainer.height / rightScaler.trueHeight } @@ -257,26 +238,11 @@ RowLayout { } } - // - // Rectangle { - // height: (parent.height / Math.sqrt(2)) + (radius * (2 - Math.sqrt(2))) - // width: height - // radius: width / 4 - // anchors.verticalCenter: parent.verticalCenter - // anchors.horizontalCenter: rightSemicircle.left - // rotation: 45 - // color: increaseArea.containsMouse ? Color.mTertiary : "transparent" - // Behavior on color { - // ColorAnimation { - // duration: Style.animationFast - // } - // } - // } - - NIcon { - anchors.centerIn: parent - icon: "plus" + anchors.right: parent.right + anchors.rightMargin: parent.width * 0.25 + anchors.verticalCenter: parent.verticalCenter + icon: "chevron-right" font.pointSize: Style.fontSizeS * scaling color: increaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary } From 68b2c83be16edbd890c78dcf766afb7c63e59ba9 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 20:35:25 -0400 Subject: [PATCH 07/62] DockMenu: use RowLayout and ColumnLayout --- Modules/Dock/DockMenu.qml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Modules/Dock/DockMenu.qml b/Modules/Dock/DockMenu.qml index a30ff193..ffd30a24 100644 --- a/Modules/Dock/DockMenu.qml +++ b/Modules/Dock/DockMenu.qml @@ -168,7 +168,7 @@ PopupWindow { } } - Column { + ColumnLayout { id: contextMenuColumn anchors.fill: parent anchors.margins: Style.marginM * scaling @@ -176,12 +176,12 @@ PopupWindow { // Focus item Rectangle { - width: parent.width + Layout.fillWidth: true height: 32 * scaling color: root.hoveredItem === 0 ? Color.mTertiary : Color.transparent radius: Style.radiusXS * scaling - Row { + RowLayout { anchors.left: parent.left anchors.leftMargin: Style.marginS * scaling anchors.verticalCenter: parent.verticalCenter @@ -191,26 +191,26 @@ PopupWindow { icon: "eye" font.pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } NText { text: I18n.tr("dock.menu.focus") font.pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } } } // Pin/Unpin item Rectangle { - width: parent.width + Layout.fillWidth: true height: 32 * scaling color: root.hoveredItem === 1 ? Color.mTertiary : Color.transparent radius: Style.radiusXS * scaling - Row { + RowLayout { anchors.left: parent.left anchors.leftMargin: Style.marginS * scaling anchors.verticalCenter: parent.verticalCenter @@ -224,7 +224,7 @@ PopupWindow { } font.pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } NText { @@ -235,19 +235,19 @@ PopupWindow { } font.pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } } } // Close item Rectangle { - width: parent.width + Layout.fillWidth: true height: 32 * scaling color: root.hoveredItem === 2 ? Color.mTertiary : Color.transparent radius: Style.radiusXS * scaling - Row { + RowLayout { anchors.left: parent.left anchors.leftMargin: Style.marginS * scaling anchors.verticalCenter: parent.verticalCenter @@ -257,14 +257,14 @@ PopupWindow { icon: "close" font.pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } NText { text: I18n.tr("dock.menu.close") font.pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } } } From 7f3842ddbf884cd14957e3854ca4d6c8b0e66024 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 20:39:28 -0400 Subject: [PATCH 08/62] Log cleanup (avoid super long string with path) --- Commons/I18n.qml | 2 +- Commons/Icons.qml | 2 +- Services/BarService.qml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Commons/I18n.qml b/Commons/I18n.qml index f55b3310..564f67f2 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -215,7 +215,7 @@ Singleton { const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json` fileView.path = filePath isLoaded = false - Logger.log("I18n", `Loading translations from: ${filePath}`) + Logger.log("I18n", `Loading translations: ${langCode}`) // Only load fallback translations if we are not using english and english is available if (langCode !== "en" && availableLanguages.includes("en")) { diff --git a/Commons/Icons.qml b/Commons/Icons.qml index 3fca6f5f..88b9b35b 100644 --- a/Commons/Icons.qml +++ b/Commons/Icons.qml @@ -50,7 +50,7 @@ Singleton { } function loadFontWithCacheBusting() { - Logger.log("Icons", "Loading font with cache busting:", cacheBustingPath) + Logger.log("Icons", "Loading font with cache busting") // Destroy old loader first if (currentFontLoader) { diff --git a/Services/BarService.qml b/Services/BarService.qml index ca8ee961..9a28b550 100644 --- a/Services/BarService.qml +++ b/Services/BarService.qml @@ -43,7 +43,7 @@ Singleton { function registerBar(screenName) { if (!readyBars[screenName]) { readyBars[screenName] = true - console.log("ShellStateService: Bar on screen '" + screenName + "' is ready.") + Logger.log("BarService", "Bar is ready on screen:", screenName) barReadyChanged(screenName) } } From b2688e9100fc250bef46c7d80b22d18d993eb7d5 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 20:49:57 -0400 Subject: [PATCH 09/62] More conversion of Row/Column to Layout --- Modules/Bar/Widgets/ActiveWindow.qml | 4 ++-- Modules/Bar/Widgets/MediaMini.qml | 4 ++-- Modules/OSD/OSD.qml | 14 +++++++------- .../Bar/WidgetSettings/ActiveWindowSettings.qml | 1 - 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 6f20c335..8caf90f9 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -239,7 +239,7 @@ Item { property real scrollX: 0 x: scrollX - Row { + RowLayout { spacing: 50 * scaling // Gap between text copies NText { @@ -358,4 +358,4 @@ Item { } } } -} +} \ No newline at end of file diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index b9e23efd..081748af 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -269,7 +269,7 @@ Item { property real scrollX: 0 x: scrollX - Row { + RowLayout { spacing: 50 * scaling // Gap between text copies NText { @@ -385,4 +385,4 @@ Item { } } } -} +} \ No newline at end of file diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index 059dcb5d..df6f574f 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -243,7 +243,7 @@ Variants { Item { anchors.fill: parent - Row { + RowLayout { anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter @@ -254,7 +254,7 @@ Variants { icon: root.getIcon() color: root.getIconColor() font.pointSize: Style.fontSizeXL * root.scaling - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter Behavior on color { ColorAnimation { @@ -266,11 +266,11 @@ Variants { // Progress bar with calculated width Rectangle { - width: Math.round(220 * root.scaling) + Layout.preferredWidth: Math.round(220 * root.scaling) height: panel.barThickness radius: Math.round(panel.barThickness / 2) color: Color.mSurfaceVariant - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter Rectangle { anchors.left: parent.left @@ -301,10 +301,10 @@ Variants { color: Color.mOnSurface font.pointSize: Style.fontSizeS * root.scaling font.family: Settings.data.ui.fontFixed - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter - width: Math.round(50 * root.scaling) + Layout.preferredWidth: Math.round(50 * root.scaling) } } } @@ -541,4 +541,4 @@ Variants { } } } -} +} \ No newline at end of file diff --git a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml index f28c4bac..cb4f2c5e 100644 --- a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml @@ -23,7 +23,6 @@ ColumnLayout { settings.autoHide = valueAutoHide settings.showIcon = valueShowIcon settings.scrollingMode = valueScrollingMode - console.log(JSON.stringify(settings)) return settings } From c35f37c7d785983d9acd1a1badb6d5778e0ff3f9 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 21:17:10 -0400 Subject: [PATCH 10/62] Use Color.transparent instead of "transparent" --- Modules/Bar/Widgets/ActiveWindow.qml | 2 +- Modules/Bar/Widgets/MediaMini.qml | 2 +- Modules/Bar/Widgets/Taskbar.qml | 2 +- Modules/Notification/Notification.qml | 2 +- Modules/OSD/OSD.qml | 2 +- Services/NotificationService.qml | 2 +- Widgets/NIconPicker.qml | 2 +- Widgets/NImageRounded.qml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 8caf90f9..2dbccdbc 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -358,4 +358,4 @@ Item { } } } -} \ No newline at end of file +} diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 081748af..2b5348da 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -385,4 +385,4 @@ Item { } } } -} \ No newline at end of file +} diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index e578622f..0201f95d 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -60,7 +60,7 @@ Rectangle { color: taskbarItem.isActive ? Color.mPrimary : root.color border.width: 0 radius: Math.round(Style.radiusXS * root.scaling) - border.color: "transparent" + border.color: Color.transparent z: -1 IconImage { diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index b7f48abe..3bb1383c 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -162,7 +162,7 @@ Variants { anchors.left: parent.left anchors.right: parent.right height: 2 * scaling - color: "transparent" + color: Color.transparent property real availableWidth: parent.width - (2 * parent.radius) diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index df6f574f..07b028e5 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -541,4 +541,4 @@ Variants { } } } -} \ No newline at end of file +} diff --git a/Services/NotificationService.qml b/Services/NotificationService.qml index 7eaf6f6b..aab8b7de 100644 --- a/Services/NotificationService.qml +++ b/Services/NotificationService.qml @@ -28,7 +28,7 @@ Singleton { PanelWindow { implicitHeight: 1 implicitWidth: 1 - color: "transparent" + color: Color.transparent mask: Region {} Image { diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml index 86ea50a4..d933dfd2 100644 --- a/Widgets/NIconPicker.qml +++ b/Widgets/NIconPicker.qml @@ -112,7 +112,7 @@ Popup { height: grid.cellHeight radius: Style.radiusS * scaling clip: true - color: (root.selectedIcon === modelData) ? Qt.alpha(Color.mPrimary, 0.15) : "transparent" + color: (root.selectedIcon === modelData) ? Qt.alpha(Color.mPrimary, 0.15) : Color.transparent border.color: (root.selectedIcon === modelData) ? Color.mPrimary : Qt.rgba(0, 0, 0, 0) border.width: (root.selectedIcon === modelData) ? Style.borderS * scaling : 0 diff --git a/Widgets/NImageRounded.qml b/Widgets/NImageRounded.qml index d03dcf1d..d7306958 100644 --- a/Widgets/NImageRounded.qml +++ b/Widgets/NImageRounded.qml @@ -66,7 +66,7 @@ Rectangle { Rectangle { id: background anchors.fill: parent - color: "transparent" + color: Color.transparent z: -1 } } From c1d2d82fa2a26ccee02b8b8477f352f0a7ee3440 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 21:19:10 -0400 Subject: [PATCH 11/62] NSpinBox: fixes - replaced row by rowlayount - using proper Color.mOnTertiary for hover text/icon - fixed binding break when entering value manually --- Widgets/NSpinBox.qml | 154 +++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 73 deletions(-) diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 05546980..278eb7b6 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -5,7 +5,6 @@ import qs.Commons import qs.Services import qs.Widgets - RowLayout { id: root @@ -79,7 +78,7 @@ RowLayout { // Decrease button (left) Item { id: decreaseButton - height:parent.height + height: parent.height width: leftSemicircle.width + (leftDiamondContainer.width / 2) anchors.top: parent.top anchors.bottom: parent.bottom @@ -94,66 +93,70 @@ RowLayout { clip: true anchors.left: parent.left Rectangle { - width: Math.round(parent.height) - height: parent.height - radius: width / 2 - anchors.left: parent.left - color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" - Behavior on color { - ColorAnimation { - duration: Style.animationFast - } - } - } - } - - Item { - id: leftDiamondContainer - - height: Math.round(parent.height / 2) * 2 - width: height * Math.sqrt(2) - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: leftSemicircle.right - - Rectangle { - id: leftDiamondVisual - width: 100 - height: 100 - radius: width / 4 - - color: decreaseArea.containsMouse ? Color.mTertiary : "transparent" - Behavior on color { - ColorAnimation { - duration: Style.animationFast - } - } - - anchors.centerIn: parent - - transform: [ - Rotation { angle: 45; origin.x: 50; origin.y: 50 }, - Scale { - id: leftScaler - origin.x: 50 - origin.y: 50 - - // This is the full formula for the height of the rotated, rounded square - readonly property real trueHeight: (leftDiamondVisual.width - 2 * leftDiamondVisual.radius) * Math.sqrt(2) + (2 * leftDiamondVisual.radius) - xScale: leftDiamondContainer.height / leftScaler.trueHeight - yScale: leftDiamondContainer.height / leftScaler.trueHeight - } - ] - } - } - - NIcon { + width: Math.round(parent.height) + height: parent.height + radius: width / 2 anchors.left: parent.left - anchors.leftMargin: parent.width * 0.25 - anchors.verticalCenter: parent.verticalCenter - icon: "chevron-left" - font.pointSize: Style.fontSizeS * scaling - color: decreaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary + color: decreaseArea.containsMouse ? Color.mTertiary : Color.transparent + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } } + } + + Item { + id: leftDiamondContainer + + height: Math.round(parent.height / 2) * 2 + width: height * Math.sqrt(2) + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: leftSemicircle.right + + Rectangle { + id: leftDiamondVisual + width: 100 + height: 100 + radius: width / 4 + + color: decreaseArea.containsMouse ? Color.mTertiary : Color.transparent + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + + anchors.centerIn: parent + + transform: [ + Rotation { + angle: 45 + origin.x: 50 + origin.y: 50 + }, + Scale { + id: leftScaler + origin.x: 50 + origin.y: 50 + + // This is the full formula for the height of the rotated, rounded square + readonly property real trueHeight: (leftDiamondVisual.width - 2 * leftDiamondVisual.radius) * Math.sqrt(2) + (2 * leftDiamondVisual.radius) + xScale: leftDiamondContainer.height / leftScaler.trueHeight + yScale: leftDiamondContainer.height / leftScaler.trueHeight + } + ] + } + } + + NIcon { + anchors.left: parent.left + anchors.leftMargin: parent.width * 0.25 + anchors.verticalCenter: parent.verticalCenter + icon: "chevron-left" + font.pointSize: Style.fontSizeS * scaling + color: decreaseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary + } MouseArea { id: decreaseArea @@ -190,7 +193,7 @@ RowLayout { height: parent.height radius: width / 2 anchors.right: parent.right - color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + color: increaseArea.containsMouse ? Color.mTertiary : Color.transparent Behavior on color { ColorAnimation { duration: Style.animationFast @@ -213,7 +216,7 @@ RowLayout { height: 100 radius: width / 4 - color: increaseArea.containsMouse ? Color.mTertiary : "transparent" + color: increaseArea.containsMouse ? Color.mTertiary : Color.transparent Behavior on color { ColorAnimation { duration: Style.animationFast @@ -223,7 +226,11 @@ RowLayout { anchors.centerIn: parent transform: [ - Rotation { angle: 45; origin.x: 50; origin.y: 50 }, + Rotation { + angle: 45 + origin.x: 50 + origin.y: 50 + }, Scale { id: rightScaler origin.x: 50 @@ -244,7 +251,7 @@ RowLayout { anchors.verticalCenter: parent.verticalCenter icon: "chevron-right" font.pointSize: Style.fontSizeS * scaling - color: increaseArea.containsMouse ? Color.mOnPrimary : Color.mPrimary + color: increaseArea.containsMouse ? Color.mOnTertiary: Color.mPrimary } MouseArea { @@ -268,32 +275,34 @@ RowLayout { anchors.verticalCenter: parent.verticalCenter anchors.margins: 4 * scaling height: parent.height - color: "transparent" + color: Color.transparent - Row { + RowLayout { anchors.centerIn: parent spacing: 0 // Prefix text (non-editable) - Text { + NText { text: root.prefix font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: root.prefix !== "" } // Editable number input TextInput { id: valueInput - text: root.value.toString() + text: valueInput.focus ? valueInput.text : root.value.toString() font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignVCenter selectByMouse: true enabled: root.enabled @@ -324,26 +333,25 @@ RowLayout { function applyValue() { let newValue = parseInt(text) if (!isNaN(newValue)) { + // Don't manually set text here - let the binding handle it newValue = Math.max(root.from, Math.min(root.to, newValue)) root.value = newValue - text = root.value.toString() - } else { - text = root.value.toString() } } } // Suffix text (non-editable) - Text { + NText { text: root.suffix font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignVCenter visible: root.suffix !== "" } } } } -} +} \ No newline at end of file From 49961882dd10381ce3bc273860a51197effa5f11 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Sun, 28 Sep 2025 23:39:34 -0400 Subject: [PATCH 12/62] Shell: changed init sequence so that i18n + Settings are fully loaded before any UI component spawn. --- Commons/I18n.qml | 3 +- Commons/Settings.qml | 20 +---- Widgets/NSpinBox.qml | 4 +- shell.qml | 180 ++++++++++++++++++++++++++----------------- 4 files changed, 113 insertions(+), 94 deletions(-) diff --git a/Commons/I18n.qml b/Commons/I18n.qml index 564f67f2..3a013c57 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -53,9 +53,10 @@ Singleton { try { var data = JSON.parse(text()) root.translations = data + Logger.log("I18n", `Loaded translations for "${root.langCode}"`) + root.isLoaded = true root.translationsLoaded() - Logger.log("I18n", `Loaded translations for "${root.langCode}"`) } catch (e) { Logger.error("I18n", `Failed to parse translation file: ${e}`) setLanguage("en") diff --git a/Commons/Settings.qml b/Commons/Settings.qml index bed06a98..986d4248 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -90,15 +90,10 @@ Singleton { } onLoaded: function () { if (!isLoaded) { - Logger.log("Settings", "----------------------------") - Logger.log("Settings", "Settings loaded successfully") + Logger.log("Settings", "Settings loaded") upgradeSettingsData() - validateMonitorConfigurations() - - kickOffServices() - isLoaded = true // Emit the signal @@ -515,17 +510,4 @@ Singleton { const widgetAfter = JSON.stringify(widget) return (widgetAfter !== widgetBefore) } - - // ----------------------------------------------------- - // Kickoff essential services - function kickOffServices() { - LocationService.init() - NightLightService.apply() - ColorSchemeService.init() - MatugenService.init() - WallpaperService.init() - FontService.init() - HooksService.init() - BluetoothService.init() - } } diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 278eb7b6..72be80d2 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -251,7 +251,7 @@ RowLayout { anchors.verticalCenter: parent.verticalCenter icon: "chevron-right" font.pointSize: Style.fontSizeS * scaling - color: increaseArea.containsMouse ? Color.mOnTertiary: Color.mPrimary + color: increaseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary } MouseArea { @@ -354,4 +354,4 @@ RowLayout { } } } -} \ No newline at end of file +} diff --git a/shell.qml b/shell.qml index 65cbf272..4a7afb58 100644 --- a/shell.qml +++ b/shell.qml @@ -29,7 +29,6 @@ import qs.Modules.Bar import qs.Modules.Bar.Extras import qs.Modules.Bar.Bluetooth import qs.Modules.Bar.Calendar - import qs.Modules.Bar.WiFi // Panels & UI Components @@ -45,79 +44,12 @@ import qs.Modules.Wallpaper ShellRoot { id: shellRoot - Background {} - Overview {} - ScreenCorners {} - Bar {} - Dock {} - - Notification { - id: notification - } - - LockScreen { - id: lockScreen - } - - ToastOverlay {} - OSD {} - - // IPCService is treated as a service - // but it's actually an Item that needs to exists in the shell. - IPCService {} - - // ------------------------------ - // All the NPanels - Launcher { - id: launcherPanel - objectName: "launcherPanel" - } - - ControlCenterPanel { - id: controlCenterPanel - objectName: "controlCenterPanel" - } - - CalendarPanel { - id: calendarPanel - objectName: "calendarPanel" - } - - SettingsPanel { - id: settingsPanel - objectName: "settingsPanel" - } - - NotificationHistoryPanel { - id: notificationHistoryPanel - objectName: "notificationHistoryPanel" - } - - SessionMenu { - id: sessionMenuPanel - objectName: "sessionMenuPanel" - } - - WiFiPanel { - id: wifiPanel - objectName: "wifiPanel" - } - - BluetoothPanel { - id: bluetoothPanel - objectName: "bluetoothPanel" - } - - WallpaperPanel { - id: wallpaperPanel - objectName: "wallpaperPanel" - } + property bool i18nLoaded: false + property bool settingsLoaded: false Component.onCompleted: { - // Save a ref. to our lockScreen so we can access it easily - PanelService.lockScreen = lockScreen - - BarWidgetRegistry.init() + Logger.log("Shell", "---------------------------") + Logger.log("Shell", "Noctalia Hello!") } Connections { @@ -126,4 +58,108 @@ ShellRoot { Quickshell.inhibitReloadPopup() } } + + Connections { + target: I18n + function onTranslationsLoaded() { + i18nLoaded = true + } + } + + Connections { + target: Settings + function onSettingsLoaded() { + settingsLoaded = true + } + } + + LazyLoader { + active: i18nLoaded && settingsLoaded + + Item { + Component.onCompleted: { + // Save a ref. to our lockScreen so we can access it easily + PanelService.lockScreen = lockScreen + + Logger.log("Shell", "---------------------------") + BarWidgetRegistry.init() + LocationService.init() + NightLightService.apply() + ColorSchemeService.init() + MatugenService.init() + WallpaperService.init() + FontService.init() + HooksService.init() + BluetoothService.init() + } + + Background {} + Overview {} + ScreenCorners {} + Bar {} + Dock {} + + Notification { + id: notification + } + + LockScreen { + id: lockScreen + } + + ToastOverlay {} + OSD {} + + // IPCService is treated as a service + // but it's actually an Item that needs to exists in the shell. + IPCService {} + + // ------------------------------ + // All the NPanels + Launcher { + id: launcherPanel + objectName: "launcherPanel" + } + + ControlCenterPanel { + id: controlCenterPanel + objectName: "controlCenterPanel" + } + + CalendarPanel { + id: calendarPanel + objectName: "calendarPanel" + } + + SettingsPanel { + id: settingsPanel + objectName: "settingsPanel" + } + + NotificationHistoryPanel { + id: notificationHistoryPanel + objectName: "notificationHistoryPanel" + } + + SessionMenu { + id: sessionMenuPanel + objectName: "sessionMenuPanel" + } + + WiFiPanel { + id: wifiPanel + objectName: "wifiPanel" + } + + BluetoothPanel { + id: bluetoothPanel + objectName: "bluetoothPanel" + } + + WallpaperPanel { + id: wallpaperPanel + objectName: "wallpaperPanel" + } + } + } } From e6b0be77e7bb39b1edf7eb72e118115a3bc23016 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Sun, 28 Sep 2025 15:34:49 +0200 Subject: [PATCH 13/62] Taskbar: Filter by same output and active workspaces. --- Modules/Bar/Widgets/Taskbar.qml | 15 +++++---- Services/CompositorService.qml | 59 ++++++++++++++++++++++++++++---- Services/HyprlandService.qml | 16 +++++++++ Services/NiriService.qml | 60 ++++++++++++++++++++++++++++++--- 4 files changed, 133 insertions(+), 17 deletions(-) diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index 0201f95d..253f2a88 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -41,12 +41,13 @@ Rectangle { columnSpacing: isVerticalBar ? 0 : Style.marginXXS * root.scaling Repeater { - model: ToplevelManager && ToplevelManager.toplevels ? ToplevelManager.toplevels : [] + model: CompositorService.windows delegate: Item { id: taskbarItem - required property Toplevel modelData - property Toplevel toplevel: modelData - property bool isActive: ToplevelManager.activeToplevel === modelData + required property var modelData + + // TODO: Make this configurable + visible: modelData.output == screen.name && CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId) Layout.preferredWidth: root.itemSize Layout.preferredHeight: root.itemSize @@ -57,7 +58,7 @@ Rectangle { anchors.centerIn: parent width: parent.width height: parent.height - color: taskbarItem.isActive ? Color.mPrimary : root.color + color: modelData.isFocused ? Color.mPrimary : root.color border.width: 0 radius: Math.round(Style.radiusXS * root.scaling) border.color: Color.transparent @@ -86,13 +87,13 @@ Rectangle { if (mouse.button === Qt.LeftButton) { try { - taskbarItem.modelData.activate() + CompositorService.focusWindow(taskbarItem.modelData.id) } catch (error) { Logger.error("Taskbar", "Failed to activate toplevel: " + error) } } else if (mouse.button === Qt.RightButton) { try { - taskbarItem.modelData.close() + CompositorService.closeWindow(taskbarItem.modelData.id) } catch (error) { Logger.error("Taskbar", "Failed to close toplevel: " + error) } diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index d2064350..f2106361 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -14,7 +14,7 @@ Singleton { // Generic workspace and window data property ListModel workspaces: ListModel {} - property var windows: [] + property ListModel windows: ListModel {} property int focusedWindowIndex: -1 // Generic events @@ -82,10 +82,17 @@ Singleton { workspaceChanged() }) - backend.activeWindowChanged.connect(activeWindowChanged) + backend.activeWindowChanged.connect(() => { + // Sync active window when it changes + // TODO: Avoid re-syncing all windows + syncWindows() + // Forward the signal + activeWindowChanged() + }) + backend.windowListChanged.connect(() => { // Sync windows when they change - windows = backend.windows + syncWindows() // Forward the signal windowListChanged() }) @@ -97,7 +104,7 @@ Singleton { // Initial sync syncWorkspaces() - windows = backend.windows + syncWindows() focusedWindowIndex = backend.focusedWindowIndex } @@ -110,10 +117,20 @@ Singleton { // Emit signal to notify listeners that workspace list has been updated workspacesChanged() } + + function syncWindows() { + windows.clear() + const ws = backend.windows + for (var i = 0; i < ws.length; i++) { + windows.append(ws[i]) + } + // Emit signal to notify listeners that workspace list has been updated + windowListChanged() + } // Get window title for focused window function getFocusedWindowTitle() { - if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length) { + if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { return windows[focusedWindowIndex].title || "" } return "" @@ -138,14 +155,44 @@ Singleton { } return null } + + // Get active workspaces + function getActiveWorkspaces() { + const activeWorkspaces = [] + for (var i = 0; i < workspaces.count; i++) { + const ws = workspaces.get(i) + if (ws.isActive) { + activeWorkspaces.push(ws) + } + } + return activeWorkspaces + } + + // Set focused window + function focusWindow(windowId) { + if (backend && backend.focusWindow) { + backend.focusWindow(windowId) + } else { + Logger.warn("Compositor", "No backend available for window focus") + } + } // Get focused window function getFocusedWindow() { - if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length) { + if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { return windows[focusedWindowIndex] } return null } + + // Close window + function closeWindow(windowId) { + if (backend && backend.closeWindow) { + backend.closeWindow(windowId) + } else { + Logger.warn("Compositor", "No backend available for window closing") + } + } // Session management function logout() { diff --git a/Services/HyprlandService.qml b/Services/HyprlandService.qml index 1b36cf4b..6c26dba6 100644 --- a/Services/HyprlandService.qml +++ b/Services/HyprlandService.qml @@ -277,6 +277,22 @@ Item { Logger.error("HyprlandService", "Failed to switch workspace:", e) } } + + function focusWindow(windowId) { + try { + Hyprland.dispatch(`focuswindow ${windowId}`) + } catch (e) { + Logger.error("HyprlandService", "Failed to switch window:", e) + } + } + + function closeWindow(windowId) { + try { + Hyprland.dispatch(`killwindow ${windowId}`) + } catch (e) { + Logger.error("HyprlandService", "Failed to close window:", e) + } + } function logout() { try { diff --git a/Services/NiriService.qml b/Services/NiriService.qml index b65d9d19..c298dbc2 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -94,12 +94,21 @@ Item { const windowsList = [] for (const win of windowsData) { + var output = null + for (var i = 0; i < workspaces.count; i++) { + if (workspaces.get(i).id === win.workspace_id) { + output = workspaces.get(i).output + break + } + } + windowsList.push({ "id": win.id, "title": win.title || "", "appId": win.app_id || "", "workspaceId": win.workspace_id || null, - "isFocused": win.is_focused === true + "isFocused": win.is_focused === true, + "output": output }) } @@ -161,13 +170,22 @@ Item { try { const windowData = eventData.window const existingIndex = windows.findIndex(w => w.id === windowData.id) + + var output = null + for (var i = 0; i < workspaces.count; i++) { + if (workspaces.get(i).id === windowData.workspace_id) { + output = workspaces.get(i).output + break + } + } const newWindow = { "id": windowData.id, "title": windowData.title || "", "appId": windowData.app_id || "", "workspaceId": windowData.workspace_id || null, - "isFocused": windowData.is_focused === true + "isFocused": windowData.is_focused === true, + "output": output } if (existingIndex >= 0) { @@ -226,15 +244,24 @@ Item { const windowsList = [] for (const win of windowsData) { + var output = "" + for (var i = 0; i < workspaces.count; i++) { + if (workspaces.get(i).id === win.workspace_id) { + output = workspaces.get(i).output + break + } + } + windowsList.push({ "id": win.id, "title": win.title || "", "appId": win.app_id || "", "workspaceId": win.workspace_id || null, - "isFocused": win.is_focused === true + "isFocused": win.is_focused === true, + "output": output, }) } - + windowsList.sort((a, b) => a.id - b.id) windows = windowsList windowListChanged() @@ -257,9 +284,18 @@ Item { function handleWindowFocusChanged(eventData) { try { const focusedId = eventData.id + + if (windows[focusedWindowIndex]) { + windows[focusedWindowIndex].isFocused = false + } if (focusedId) { const newIndex = windows.findIndex(w => w.id === focusedId) + + if (newIndex >= 0) { + windows[newIndex].isFocused = true + } + focusedWindowIndex = newIndex >= 0 ? newIndex : -1 } else { focusedWindowIndex = -1 @@ -279,6 +315,22 @@ Item { Logger.error("NiriService", "Failed to switch workspace:", e) } } + + function focusWindow(windowId) { + try { + Quickshell.execDetached(["niri", "msg", "action", "focus-window", "--id", windowId.toString()]) + } catch (e) { + Logger.error("NiriService", "Failed to switch window:", e) + } + } + + function closeWindow(windowId) { + try { + Quickshell.execDetached(["niri", "msg", "action", "close-window", "--id", windowId.toString()]) + } catch (e) { + Logger.error("NiriService", "Failed to close window:", e) + } + } function logout() { try { From b1f7ae5d9a81c5b5cd05b36296608628f2f17eb5 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Mon, 29 Sep 2025 00:59:02 +0200 Subject: [PATCH 14/62] Taskbar: Add settings. --- Assets/Translations/en.json | 10 +++++ Modules/Bar/Widgets/Taskbar.qml | 21 ++++++++- .../Settings/Bar/BarWidgetSettingsDialog.qml | 3 +- .../Bar/WidgetSettings/TaskbarSettings.qml | 43 +++++++++++++++++++ Services/BarWidgetRegistry.qml | 5 +++ 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 29ed9c5c..ac0bee75 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1000,6 +1000,16 @@ "description": "Use a space to separate each part onto a new line." }, "preview": "Preview" + }, + "taskbar": { + "only-active-workspaces": { + "label": "Only from active workspaces", + "description": "Show only apps from active workspaces." + }, + "only-same-output": { + "label": "Only from same output", + "description": "Show only apps from the output where the bar is located." + } } } }, diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index 253f2a88..8cfd8564 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -12,10 +12,27 @@ Rectangle { id: root property ShellScreen screen property real scaling: 1.0 + + // Widget properties passed from Bar.qml for per-instance settings + property string widgetId: "" + property string section: "" + property int sectionWidgetIndex: -1 + property int sectionWidgetsCount: 0 readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" readonly property bool compact: (Settings.data.bar.density === "compact") readonly property real itemSize: compact ? Style.capsuleHeight * 0.9 * scaling : Style.capsuleHeight * 0.8 * scaling + + property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] + property var widgetSettings: { + if (section && sectionWidgetIndex >= 0) { + var widgets = Settings.data.bar.widgets[section] + if (widgets && sectionWidgetIndex < widgets.length) { + return widgets[sectionWidgetIndex] + } + } + return {} + } // Always visible when there are toplevels implicitWidth: isVerticalBar ? Math.round(Style.capsuleHeight * scaling) : taskbarLayout.implicitWidth + Style.marginM * scaling * 2 @@ -46,8 +63,8 @@ Rectangle { id: taskbarItem required property var modelData - // TODO: Make this configurable - visible: modelData.output == screen.name && CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId) + visible: (!widgetSettings.onlySameOutput || modelData.output == screen.name) + && (!widgetSettings.onlyActiveWorkspaces || CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId)) Layout.preferredWidth: root.itemSize Layout.preferredHeight: root.itemSize diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index a198b1e3..4e52bc68 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -133,7 +133,8 @@ Popup { "Spacer": "WidgetSettings/SpacerSettings.qml", "SystemMonitor": "WidgetSettings/SystemMonitorSettings.qml", "Volume": "WidgetSettings/VolumeSettings.qml", - "Workspace": "WidgetSettings/WorkspaceSettings.qml" + "Workspace": "WidgetSettings/WorkspaceSettings.qml", + "Taskbar": "WidgetSettings/TaskbarSettings.qml" } const source = widgetSettingsMap[widgetId] diff --git a/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml new file mode 100644 index 00000000..98df4c3f --- /dev/null +++ b/Modules/Settings/Bar/WidgetSettings/TaskbarSettings.qml @@ -0,0 +1,43 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import qs.Commons +import qs.Widgets +import qs.Services + +ColumnLayout { + id: root + spacing: Style.marginM * scaling + + // Properties to receive data from parent + property var widgetData: null + property var widgetMetadata: null + + // Local state + property bool valueOnlyActiveWorkspaces: widgetData.onlyActiveWorkspaces !== undefined ? widgetData.onlyActiveWorkspaces : widgetMetadata.onlyActiveWorkspaces + property bool valueOnlySameOutput: widgetData.onlySameOutput !== undefined ? widgetData.onlySameOutput : widgetMetadata.onlySameOutput + + function saveSettings() { + var settings = Object.assign({}, widgetData || {}) + settings.onlySameOutput = valueOnlySameOutput + settings.onlyActiveWorkspaces = valueOnlyActiveWorkspaces + console.log(JSON.stringify(settings)) + return settings + } + + NToggle { + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.taskbar.only-same-output.label") + description: I18n.tr("bar.widget-settings.taskbar.only-same-output.description") + checked: root.valueOnlySameOutput + onToggled: checked => root.valueOnlySameOutput = checked + } + + NToggle { + Layout.fillWidth: true + label: I18n.tr("bar.widget-settings.taskbar.only-active-workspaces.label") + description: I18n.tr("bar.widget-settings.taskbar.only-active-workspaces.description") + checked: root.valueOnlyActiveWorkspaces + onToggled: checked => root.valueOnlyActiveWorkspaces = checked + } +} diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index bab1a4b4..6beda333 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -109,6 +109,11 @@ Singleton { "showNetworkStats": false, "showDiskUsage": false }, + "Taskbar": { + "allowUserSettings": true, + "onlySameOutput": true, + "onlyActiveWorkspaces": true + }, "Workspace": { "allowUserSettings": true, "labelMode": "index", From fa49d4aaa0bb82db8fee98a6d713ee44ee4b16ef Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Mon, 29 Sep 2025 11:08:48 +0200 Subject: [PATCH 15/62] Taskbar: Add German translation for Taskbar settings. --- Assets/Translations/de.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 03f22602..23dc2ec0 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1017,6 +1017,16 @@ "description": "Verwenden Sie ein Leerzeichen, um jeden Teil in eine neue Zeile zu trennen." }, "preview": "Vorschau" + }, + "taskbar": { + "only-active-workspaces": { + "label": "Nur von aktiven Arbeitsbereichen", + "description": "Zeige nur Apps von aktiven Arbeitsbereichen an." + }, + "only-same-output": { + "label": "Nur vom gleichen Bildschirm", + "description": "Zeige nur Apps vom dem Bildschirm an, wo sich die Taskbar befindet." + } } } }, From 0e6925627921287c9e70050a40e0d6a860948c83 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 13:13:21 +0200 Subject: [PATCH 16/62] Background: fix short flash of default wallpaper before actual wallpaper shows --- Modules/Background/Background.qml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 4dd653b2..eb92df41 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -44,14 +44,27 @@ Variants { property real fillMode: 1.0 property vector4d fillColor: Qt.vector4d(Settings.data.wallpaper.fillColor.r, Settings.data.wallpaper.fillColor.g, Settings.data.wallpaper.fillColor.b, 1.0) - // On startup assign wallpaper immediately - Component.onCompleted: { - fillMode = WallpaperService.getFillModeUniform() + // On startup, defer assigning wallpaper until the service cache is ready + function _startWallpaperOnceReady() { + if (!modelData) { + Qt.callLater(_startWallpaperOnceReady) + return + } - var path = modelData ? WallpaperService.getWallpaper(modelData.name) : "" + var cacheReady = WallpaperService && WallpaperService.currentWallpapers && Object.keys(WallpaperService.currentWallpapers).length > 0 + if (!cacheReady) { + // Try again on the next tick until WallpaperService.init() populates cache + Qt.callLater(_startWallpaperOnceReady) + return + } + + fillMode = WallpaperService.getFillModeUniform() + var path = WallpaperService.getWallpaper(modelData.name) setWallpaperImmediate(path) } + Component.onCompleted: _startWallpaperOnceReady() + Connections { target: Settings.data.wallpaper function onFillModeChanged() { From f11d27bcf1ae00d9b05ac9773cb6c17b9953ff72 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 13:18:45 +0200 Subject: [PATCH 17/62] Background: "explicitly set currentWallpaper.source to nothing as an attempt to fix the odd memory usage after a few hours" --- Modules/Background/Background.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index eb92df41..fefdcc6a 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -243,6 +243,9 @@ Variants { easing.type: Easing.InOutCubic onFinished: { // Swap images after transition completes + if (currentWallpaper.source !== "") { + currentWallpaper.source = "" + } currentWallpaper.source = nextWallpaper.source nextWallpaper.source = "" transitionProgress = 0.0 @@ -255,6 +258,9 @@ Variants { function setWallpaperImmediate(source) { transitionAnimation.stop() transitionProgress = 0.0 + if (currentWallpaper.source !== "") { + currentWallpaper.source = "" + } currentWallpaper.source = source nextWallpaper.source = "" } From ece9789f6bd24228535093939bbb70b5497b896c Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 13:43:37 +0200 Subject: [PATCH 18/62] Matugen: add custom-colors.toml --- Assets/Matugen/extra/custom-colors.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Assets/Matugen/extra/custom-colors.toml diff --git a/Assets/Matugen/extra/custom-colors.toml b/Assets/Matugen/extra/custom-colors.toml new file mode 100644 index 00000000..cb145f2f --- /dev/null +++ b/Assets/Matugen/extra/custom-colors.toml @@ -0,0 +1,10 @@ +[config.custom_colors] +red = { color = "#ff0000", blend = true } +green = { color = "#00ff00", blend = true } +blue = { color = "#0000ff", blend = true } +yellow = { color = "#ffff00", blend = true } +orange = { color = "#ff9900", blend = true } +purple = { color = "#a020f0", blend = true } +cyan = { color = "#00ffff", blend = true } +magenta = { color = "#ff00ff", blend = true } + From 250822e81933b1750b24fafdba7e840c615705e9 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 14:13:22 +0200 Subject: [PATCH 19/62] Revert "Matugen: add custom-colors.toml" This reverts commit ece9789f6bd24228535093939bbb70b5497b896c. --- Assets/Matugen/extra/custom-colors.toml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 Assets/Matugen/extra/custom-colors.toml diff --git a/Assets/Matugen/extra/custom-colors.toml b/Assets/Matugen/extra/custom-colors.toml deleted file mode 100644 index cb145f2f..00000000 --- a/Assets/Matugen/extra/custom-colors.toml +++ /dev/null @@ -1,10 +0,0 @@ -[config.custom_colors] -red = { color = "#ff0000", blend = true } -green = { color = "#00ff00", blend = true } -blue = { color = "#0000ff", blend = true } -yellow = { color = "#ffff00", blend = true } -orange = { color = "#ff9900", blend = true } -purple = { color = "#a020f0", blend = true } -cyan = { color = "#00ffff", blend = true } -magenta = { color = "#ff00ff", blend = true } - From b8b54825d55f65897cdc4e7c5f4d28e0f50ecde1 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 14:20:15 +0200 Subject: [PATCH 20/62] SessionMenu: move lockAndSuspend to CompositorService --- Modules/SessionMenu/SessionMenu.qml | 5 +---- Services/CompositorService.qml | 12 ++++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index 05b92b68..885b43ed 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -103,10 +103,7 @@ NPanel { } break case "lockAndSuspend": - if (!lockScreen.active) { - lockScreen.active = true - } - CompositorService.suspend() + CompositorService.lockAndSuspend() break case "suspend": CompositorService.suspend() diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index d2064350..1391ea3a 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -167,4 +167,16 @@ Singleton { function suspend() { Quickshell.execDetached(["systemctl", "suspend"]) } + + function lockAndSuspend() { + try { + if (PanelService && PanelService.lockScreen && !PanelService.lockScreen.active) { + PanelService.lockScreen.active = true + } + } catch (e) { + Logger.warn("Compositor", "Failed to activate lock screen before suspend: " + e) + } + // Queue suspend to the next event loop cycle to allow lock UI to render + Qt.callLater(suspend) + } } From 9ed92310709095daa4236d96420d5bfb1126dbd3 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:11:37 -0400 Subject: [PATCH 21/62] Init Sequence: removed a bunch of no longer necessary Settings.isLoaded --- Modules/Background/Background.qml | 37 ++++++++++---------------- Modules/Background/Overview.qml | 2 +- Modules/Bar/Bar.qml | 2 +- Modules/Bar/Extras/BarWidgetLoader.qml | 2 +- Modules/Dock/Dock.qml | 6 ++--- Modules/Notification/Notification.qml | 6 ++--- Modules/OSD/OSD.qml | 4 +-- Modules/Toast/ToastOverlay.qml | 2 +- Modules/Toast/ToastScreen.qml | 2 +- Services/ClipboardService.qml | 2 +- Services/MatugenService.qml | 7 +---- Services/WallpaperService.qml | 6 ++++- 12 files changed, 34 insertions(+), 44 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index fefdcc6a..a83aed58 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -13,7 +13,7 @@ Variants { required property ShellScreen modelData - active: Settings.isLoaded && modelData && Settings.data.wallpaper.enabled + active: modelData && Settings.data.wallpaper.enabled sourceComponent: PanelWindow { id: root @@ -41,29 +41,10 @@ Variants { property string futureWallpaper: "" // Fillmode default is "crop" - property real fillMode: 1.0 + property real fillMode: WallpaperService.getFillModeUniform() property vector4d fillColor: Qt.vector4d(Settings.data.wallpaper.fillColor.r, Settings.data.wallpaper.fillColor.g, Settings.data.wallpaper.fillColor.b, 1.0) - // On startup, defer assigning wallpaper until the service cache is ready - function _startWallpaperOnceReady() { - if (!modelData) { - Qt.callLater(_startWallpaperOnceReady) - return - } - - var cacheReady = WallpaperService && WallpaperService.currentWallpapers && Object.keys(WallpaperService.currentWallpapers).length > 0 - if (!cacheReady) { - // Try again on the next tick until WallpaperService.init() populates cache - Qt.callLater(_startWallpaperOnceReady) - return - } - - fillMode = WallpaperService.getFillModeUniform() - var path = WallpaperService.getWallpaper(modelData.name) - setWallpaperImmediate(path) - } - - Component.onCompleted: _startWallpaperOnceReady() + Component.onCompleted: setWallpaperInitial() Connections { target: Settings.data.wallpaper @@ -254,6 +235,16 @@ Variants { }) } } + + function setWallpaperInitial() { + // On startup, defer assigning wallpaper until the service cache is ready, retries every tick + if (!WallpaperService || !WallpaperService.isInitialized) { + Qt.callLater(setWallpaperInitial) + return + } + + setWallpaperImmediate(WallpaperService.getWallpaper(modelData.name)) + } function setWallpaperImmediate(source) { transitionAnimation.stop() @@ -324,4 +315,4 @@ Variants { } } } -} +} \ No newline at end of file diff --git a/Modules/Background/Overview.qml b/Modules/Background/Overview.qml index 0828be9a..7aa67240 100644 --- a/Modules/Background/Overview.qml +++ b/Modules/Background/Overview.qml @@ -12,7 +12,7 @@ Variants { delegate: Loader { required property ShellScreen modelData - active: Settings.isLoaded && CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled + active: CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled property string wallpaper: "" diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index d6d4e356..f1140d8e 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -28,7 +28,7 @@ Variants { } } - active: Settings.isLoaded && BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false + active: BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false sourceComponent: PanelWindow { screen: modelData || null diff --git a/Modules/Bar/Extras/BarWidgetLoader.qml b/Modules/Bar/Extras/BarWidgetLoader.qml index 3aa5911f..358a42ef 100644 --- a/Modules/Bar/Extras/BarWidgetLoader.qml +++ b/Modules/Bar/Extras/BarWidgetLoader.qml @@ -29,7 +29,7 @@ Item { id: loader anchors.fill: parent - active: Settings.isLoaded && widgetId !== "" + active: widgetId !== "" sourceComponent: { if (!active) { return null diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index f6fab110..ca3e6ae7 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -55,7 +55,7 @@ Variants { // Initial update when component is ready Component.onCompleted: { - if (Settings.isLoaded && ToplevelManager) { + if (ToplevelManager) { updateDockApps() } } @@ -198,7 +198,7 @@ Variants { // PEEK WINDOW - Always visible when auto-hide is enabled Loader { - active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide + active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide sourceComponent: PanelWindow { id: peekWindow @@ -244,7 +244,7 @@ Variants { // DOCK WINDOW Loader { - active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) + active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) sourceComponent: PanelWindow { id: dockWindow diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 3bb1383c..bb868bd6 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -22,7 +22,7 @@ Variants { property ListModel notificationModel: NotificationService.activeList // If no notification display activated in settings, then show them all - active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0)) + active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0)) Connections { target: ScalingService @@ -37,11 +37,11 @@ Variants { screen: modelData WlrLayershell.namespace: "noctalia-notifications" - WlrLayershell.layer: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top + WlrLayershell.layer: (Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top color: Color.transparent - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" + readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: location.indexOf("_left") >= 0 diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index 07b028e5..e518cf89 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -22,7 +22,7 @@ Variants { property ListModel notificationModel: NotificationService.activeList // If no notification display activated in settings, then show them all - property bool canShowOnThisScreen: Settings.isLoaded && modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0)) + property bool canShowOnThisScreen: modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0)) // Loader is only active when actually showing something active: false @@ -104,7 +104,7 @@ Variants { id: panel screen: modelData - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right" + readonly property string location: (Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: (location.indexOf("_left") >= 0) || (location === "left") diff --git a/Modules/Toast/ToastOverlay.qml b/Modules/Toast/ToastOverlay.qml index 78cb670a..11cb5037 100644 --- a/Modules/Toast/ToastOverlay.qml +++ b/Modules/Toast/ToastOverlay.qml @@ -16,6 +16,6 @@ Variants { scaling: ScalingService.getScreenScale(modelData) // Only activate on enabled screens - active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0) + active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0) } } diff --git a/Modules/Toast/ToastScreen.qml b/Modules/Toast/ToastScreen.qml index 6a635aea..ca35c68c 100644 --- a/Modules/Toast/ToastScreen.qml +++ b/Modules/Toast/ToastScreen.qml @@ -128,7 +128,7 @@ Item { screen: root.screen - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" + readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: location.indexOf("_left") >= 0 diff --git a/Services/ClipboardService.qml b/Services/ClipboardService.qml index 65287ea4..bb224a28 100644 --- a/Services/ClipboardService.qml +++ b/Services/ClipboardService.qml @@ -10,7 +10,7 @@ Singleton { id: root // Public API - property bool active: Settings.isLoaded && Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable + property bool active: Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable property bool loading: false property var items: [] // [{id, preview, mime, isImage}] diff --git a/Services/MatugenService.qml b/Services/MatugenService.qml index e3410d57..694bb1e7 100644 --- a/Services/MatugenService.qml +++ b/Services/MatugenService.qml @@ -10,7 +10,7 @@ import qs.Services Singleton { id: root - property string dynamicConfigPath: Settings.isLoaded ? Settings.cacheDir + "matugen.dynamic.toml" : "" + property string dynamicConfigPath: Settings.cacheDir + "matugen.dynamic.toml" // External state management Connections { @@ -47,11 +47,6 @@ Singleton { // Generate colors using current wallpaper and settings function generateFromWallpaper() { - if (!Settings.isLoaded) { - Logger.log("Matugen", "Settings not loaded yet, skipping wallpaper color generation") - return - } - Logger.log("Matugen", "Generating from wallpaper on screen:", Screen.name) var wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''") if (wp === "") { diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index 37181a64..8b01f76c 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -26,6 +26,8 @@ Singleton { // Cache for current wallpapers - can be updated directly since we use signals for notifications property var currentWallpapers: ({}) + property bool isInitialized: false + // Signals for reactive UI updates signal wallpaperChanged(string screenName, string path) // Emitted when a wallpaper changes @@ -75,6 +77,8 @@ Singleton { function init() { Logger.log("Wallpaper", "Service started") + translateModels() + // Rebuild cache from persisted settings var monitors = Settings.data.wallpaper.monitors || [] currentWallpapers = ({}) @@ -86,7 +90,7 @@ Singleton { } } - translateModels() + isInitialized = true } // ------------------------------------------------- From 0d0b9a21f2e76dbbef4611176d721251ac504f84 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:25:45 -0400 Subject: [PATCH 22/62] Wallpaper Selector: added a shortcut to the wallpaper settings in the top bar. --- Modules/Background/Background.qml | 8 ++------ Modules/Wallpaper/WallpaperPanel.qml | 12 ++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index a83aed58..3cd5661c 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -224,9 +224,7 @@ Variants { easing.type: Easing.InOutCubic onFinished: { // Swap images after transition completes - if (currentWallpaper.source !== "") { - currentWallpaper.source = "" - } + currentWallpaper.source = "" currentWallpaper.source = nextWallpaper.source nextWallpaper.source = "" transitionProgress = 0.0 @@ -249,9 +247,7 @@ Variants { function setWallpaperImmediate(source) { transitionAnimation.stop() transitionProgress = 0.0 - if (currentWallpaper.source !== "") { - currentWallpaper.source = "" - } + currentWallpaper.source = "" currentWallpaper.source = source nextWallpaper.source = "" } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 6266aa2b..4a8f8148 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -4,6 +4,7 @@ import QtQuick.Controls import Quickshell import Quickshell.Wayland import qs.Commons +import qs.Modules.Settings import qs.Services import qs.Widgets import "../../Helpers/FuzzySort.js" as FuzzySort @@ -63,6 +64,17 @@ NPanel { Layout.fillWidth: true } + NIconButton { + icon: "settings" + tooltipText: I18n.tr("settings.wallpaper.settings.section.label") + baseSize: Style.baseWidgetSize * 0.8 + onClicked: { + var settingsPanel = PanelService.getPanel("settingsPanel") + settingsPanel.requestedTab = SettingsPanel.Tab.Wallpaper + settingsPanel.open() + } + } + NIconButton { icon: "refresh" tooltipText: I18n.tr("tooltips.refresh-wallpaper-list") From 933ba5461214ef1bdd38d70f35b33d47bcdc671e Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:58:48 -0400 Subject: [PATCH 23/62] Init Sequence: minor reordering --- shell.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell.qml b/shell.qml index 4a7afb58..c15468e1 100644 --- a/shell.qml +++ b/shell.qml @@ -82,12 +82,12 @@ ShellRoot { PanelService.lockScreen = lockScreen Logger.log("Shell", "---------------------------") + WallpaperService.init() + MatugenService.init() + ColorSchemeService.init() BarWidgetRegistry.init() LocationService.init() NightLightService.apply() - ColorSchemeService.init() - MatugenService.init() - WallpaperService.init() FontService.init() HooksService.init() BluetoothService.init() From 22794ea922ec4bb97a18948de3c7370963b0e9e8 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 10:07:58 -0400 Subject: [PATCH 24/62] DateTime: proper locale usage. Fix #390 Replaced all Qt.formatDateTime() by Qt.locale().toString() --- Modules/Bar/Widgets/Clock.qml | 4 ++-- Modules/ControlCenter/Cards/WeatherCard.qml | 2 +- Modules/LockScreen/LockScreen.qml | 4 ++-- Modules/Settings/Bar/WidgetSettings/ClockSettings.qml | 4 ++-- Widgets/NDateTimeTokens.qml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index ae179ebe..14e1f4df 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -61,7 +61,7 @@ Rectangle { spacing: Settings.data.bar.showCapsule ? -4 * scaling : -2 * scaling Repeater { id: repeater - model: Qt.formatDateTime(now, formatHorizontal.trim()).split("\\n") + model: Qt.locale().toString(now, formatHorizontal.trim()).split("\\n") NText { visible: text !== "" text: modelData @@ -91,7 +91,7 @@ Rectangle { anchors.centerIn: parent spacing: -2 * scaling Repeater { - model: Qt.formatDateTime(now, formatVertical.trim()).split(" ") + model: Qt.locale().toString(now, formatVertical.trim()).split(" ") delegate: NText { visible: text !== "" text: modelData diff --git a/Modules/ControlCenter/Cards/WeatherCard.qml b/Modules/ControlCenter/Cards/WeatherCard.qml index 160c48cc..a5cf8f45 100644 --- a/Modules/ControlCenter/Cards/WeatherCard.qml +++ b/Modules/ControlCenter/Cards/WeatherCard.qml @@ -88,7 +88,7 @@ NBox { NText { text: { var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")) - return Qt.formatDateTime(weatherDate, "ddd") + return Qt.locale().toString(weatherDate, "ddd") } color: Color.mOnSurface Layout.alignment: Qt.AlignHCenter diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index be75508c..bdb5f4f4 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -27,12 +27,12 @@ Loader { } function formatTime() { - return Settings.data.location.use12hourFormat ? Qt.formatDateTime(new Date(), "h:mm A") : Qt.formatDateTime(new Date(), "HH:mm") + return Settings.data.location.use12hourFormat ? Qt.locale().toString(new Date(), "h:mm A") : Qt.locale().toString(new Date(), "HH:mm") } function formatDate() { // For full text date, day is always before month, so we use this format for everybody: Wednesday, September 17. - return Qt.formatDateTime(new Date(), "dddd, MMMM d") + return Qt.locale().toString(new Date(), "dddd, MMMM d") } function scheduleUnloadAfterUnlock() { diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index 6214590a..af48201a 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -182,7 +182,7 @@ ColumnLayout { // Horizontal Repeater { Layout.topMargin: Style.marginM * scaling - model: Qt.formatDateTime(now, valueFormatHorizontal.trim()).split("\\n") + model: Qt.locale().toString(now, valueFormatHorizontal.trim()).split("\\n") delegate: NText { visible: text !== "" text: modelData @@ -213,7 +213,7 @@ ColumnLayout { Repeater { Layout.topMargin: Style.marginM * scaling - model: Qt.formatDateTime(now, valueFormatVertical.trim()).split(" ") + model: Qt.locale().toString(now, valueFormatVertical.trim()).split(" ") delegate: NText { visible: text !== "" text: modelData diff --git a/Widgets/NDateTimeTokens.qml b/Widgets/NDateTimeTokens.qml index 523e74f0..eae75d7b 100644 --- a/Widgets/NDateTimeTokens.qml +++ b/Widgets/NDateTimeTokens.qml @@ -312,7 +312,7 @@ Rectangle { NText { anchors.centerIn: parent - text: Qt.formatDateTime(root.sampleDate, modelData.token) + text: Qt.locale().toString(root.sampleDate, modelData.token) color: tokenMouseArea.containsMouse ? Color.mOnPrimary : Color.mSurfaceVariant font.pointSize: Style.fontSizeS * scaling From 5cea61114bae4eb2c5c722b251cc1ea6d75a4345 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 10:20:19 -0400 Subject: [PATCH 25/62] Scaling: fix scaling not properly applied on startup. --- Modules/Background/Background.qml | 4 ++-- Modules/Dock/Dock.qml | 8 -------- Services/ScalingService.qml | 20 +++++++------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 3cd5661c..6a62ed9c 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -233,7 +233,7 @@ Variants { }) } } - + function setWallpaperInitial() { // On startup, defer assigning wallpaper until the service cache is ready, retries every tick if (!WallpaperService || !WallpaperService.isInitialized) { @@ -311,4 +311,4 @@ Variants { } } } -} \ No newline at end of file +} diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index ca3e6ae7..4d2158c0 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -60,14 +60,6 @@ Variants { } } - // Update when Settings are loaded - Connections { - target: Settings - function onSettingsLoaded() { - updateDockApps() - } - } - // Shared properties between peek and dock windows readonly property bool autoHide: Settings.data.dock.autoHide readonly property int hideDelay: 500 diff --git a/Services/ScalingService.qml b/Services/ScalingService.qml index 6b204f77..0b8ef479 100644 --- a/Services/ScalingService.qml +++ b/Services/ScalingService.qml @@ -15,19 +15,13 @@ Singleton { Component.onCompleted: { Logger.log("Scaling", "Service started") - } - - Connections { - target: Settings - function onSettingsLoaded() { - // Initialize cache from Settings once they are loaded on startup - var monitors = Settings.data.ui.monitorsScaling || [] - for (var i = 0; i < monitors.length; i++) { - if (monitors[i].name && monitors[i].scale !== undefined) { - currentScales[monitors[i].name] = monitors[i].scale - root.scaleChanged(monitors[i].name, monitors[i].scale) - Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale) - } + // Initialize cache from Settings once they are loaded on startup + var monitors = Settings.data.ui.monitorsScaling || [] + for (var i = 0; i < monitors.length; i++) { + if (monitors[i].name && monitors[i].scale !== undefined) { + currentScales[monitors[i].name] = monitors[i].scale + root.scaleChanged(monitors[i].name, monitors[i].scale) + Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale) } } } From 559609be64b9c88a6031b8cf0e1aaa74acc3f056 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Mon, 29 Sep 2025 16:31:53 +0200 Subject: [PATCH 26/62] Launcher: add pin to dock button if dock is enabled --- Assets/Translations/de.json | 4 + Assets/Translations/en.json | 4 + Assets/Translations/es.json | 4 + Assets/Translations/fr.json | 4 + Assets/Translations/pt.json | 4 + Assets/Translations/zh-CN.json | 4 + Commons/TablerIcons.qml | 2 + Modules/Launcher/Launcher.qml | 273 ++++++++++-------- .../Launcher/Plugins/ApplicationsPlugin.qml | 24 +- 9 files changed, 204 insertions(+), 119 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 03f22602..5a69f240 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1155,6 +1155,10 @@ "close": "Schließen" } }, + "launcher": { + "pin": "An das Dock anheften", + "unpin": "Vom Dock lösen" + }, "placeholders": { "search-icons": "z.B. noctalia, niri, battery, cloud", "profile-picture-path": "/home/benutzer/.face", diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 29ed9c5c..1915dcca 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1138,6 +1138,10 @@ "close": "Close" } }, + "launcher": { + "pin": "Pin to dock", + "unpin": "Unpin from dock" + }, "placeholders": { "search-icons": "e.g., noctalia, niri, battery, cloud", "profile-picture-path": "/home/user/.face", diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 29065f8a..398a5935 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1136,6 +1136,10 @@ "close": "Cerrar" } }, + "launcher": { + "pin": "Anclar al dock", + "unpin": "Desanclar del dock" + }, "placeholders": { "search-icons": "ej., noctalia, niri, battery, cloud", "profile-picture-path": "/home/usuario/.face", diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index fab353cc..15aecc4f 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1136,6 +1136,10 @@ "close": "Fermer" } }, + "launcher": { + "pin": "Épingler au dock", + "unpin": "Retirer du dock" + }, "placeholders": { "search-icons": "ex: noctalia, niri, batterie, nuage", "profile-picture-path": "/home/user/.face", diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 8b3002ae..b37bd547 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1136,6 +1136,10 @@ "close": "Fechar" } }, + "launcher": { + "pin": "Fixar no dock", + "unpin": "Desafixar do dock" + }, "placeholders": { "search-icons": "ex., noctalia, niri, battery, cloud", "profile-picture-path": "/home/usuario/.face", diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index d88f4eba..2fd17a68 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1136,6 +1136,10 @@ "close": "关闭" } }, + "launcher": { + "pin": "固定到 Dock", + "unpin": "从 Dock 取消固定" + }, "placeholders": { "search-icons": "例如:noctalia, niri, battery, cloud", "profile-picture-path": "/home/user/.face", diff --git a/Commons/TablerIcons.qml b/Commons/TablerIcons.qml index b10e66f8..39743adb 100644 --- a/Commons/TablerIcons.qml +++ b/Commons/TablerIcons.qml @@ -71,6 +71,8 @@ Singleton { "chevron-down": "chevron-down", "caret-up": "caret-up-filled", "caret-down": "caret-down-filled", + "star": "star", + "star-off": "star-off", "battery-exclamation": "battery-exclamation", "battery-charging": "battery-charging", "battery-4": "battery-4", diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index 0714530f..5b705bd4 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -302,11 +302,29 @@ NPanel { positionViewAtIndex(currentIndex, ListView.Contain) } } + onModelChanged: {} delegate: Rectangle { id: entry property bool isSelected: mouseArea.containsMouse || (index === selectedIndex) + // Accessor for app id + property string appId: (modelData && modelData.appId) ? String(modelData.appId) : "" + + // Pin helpers + function togglePin(appId) { + if (!appId) return + let arr = (Settings.data.dock.pinnedApps || []).slice() + const idx = arr.indexOf(appId) + if (idx >= 0) arr.splice(idx, 1) + else arr.push(appId) + Settings.data.dock.pinnedApps = arr + } + + function isPinned(appId) { + const arr = Settings.data.dock.pinnedApps || [] + return appId && arr.indexOf(appId) >= 0 + } // Property to reliably track the current item's ID. // This changes whenever the delegate is recycled for a new item. @@ -321,7 +339,7 @@ NPanel { } width: resultsList.width - Style.marginS * scaling - height: entryHeight + implicitHeight: entryHeight radius: Style.radiusM * scaling color: entry.isSelected ? Color.mTertiary : Color.mSurface @@ -332,136 +350,152 @@ NPanel { } } - RowLayout { + ColumnLayout { + id: contentLayout anchors.fill: parent anchors.margins: Style.marginM * scaling spacing: Style.marginM * scaling - // Icon badge or Image preview - Rectangle { - Layout.preferredWidth: badgeSize - Layout.preferredHeight: badgeSize - radius: Style.radiusM * scaling - color: Color.mSurfaceVariant - clip: true + // Top row - Main entry content with pin button + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM * scaling - // Image preview for clipboard images - NImageRounded { - id: imagePreview - anchors.fill: parent - visible: modelData.isImage - imageRadius: Style.radiusM * scaling - - // This property creates a dependency on the service's revision counter - readonly property int _rev: ClipboardService.revision - - // Fetches from the service's cache. - // The dependency on `_rev` ensures this binding is re-evaluated when the cache is updated. - imagePath: { - _rev - return ClipboardService.getImageData(modelData.clipboardId) || "" - } - - // Loading indicator - Rectangle { - anchors.fill: parent - visible: parent.status === Image.Loading - color: Color.mSurfaceVariant - - BusyIndicator { - anchors.centerIn: parent - running: true - width: Style.baseWidgetSize * 0.5 * scaling - height: width - } - } - - // Error fallback - onStatusChanged: status => { - if (status === Image.Error) { - iconLoader.visible = true - imagePreview.visible = false - } - } - } - - // Icon fallback - Loader { - id: iconLoader - anchors.fill: parent - anchors.margins: Style.marginXS * scaling - - visible: !modelData.isImage || imagePreview.status === Image.Error - active: visible - - sourceComponent: Component { - IconImage { - anchors.fill: parent - source: modelData.icon ? ThemeIcons.iconFromName(modelData.icon, "application-x-executable") : "" - visible: modelData.icon && source !== "" - asynchronous: true - } - } - } - - // Fallback text if no icon and no image - NText { - anchors.centerIn: parent - visible: !imagePreview.visible && !iconLoader.visible - text: modelData.name ? modelData.name.charAt(0).toUpperCase() : "?" - font.pointSize: Style.fontSizeXXL * scaling - font.weight: Style.fontWeightBold - color: Color.mOnPrimary - } - - // Image type indicator overlay + // Icon badge or Image preview Rectangle { - visible: modelData.isImage && imagePreview.visible - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.margins: 2 * scaling - width: formatLabel.width + 6 * scaling - height: formatLabel.height + 2 * scaling + Layout.preferredWidth: badgeSize + Layout.preferredHeight: badgeSize radius: Style.radiusM * scaling color: Color.mSurfaceVariant + clip: true + // Image preview for clipboard images + NImageRounded { + id: imagePreview + anchors.fill: parent + visible: modelData.isImage + imageRadius: Style.radiusM * scaling + + // This property creates a dependency on the service's revision counter + readonly property int _rev: ClipboardService.revision + + // Fetches from the service's cache. + // The dependency on `_rev` ensures this binding is re-evaluated when the cache is updated. + imagePath: { + _rev + return ClipboardService.getImageData(modelData.clipboardId) || "" + } + + // Loading indicator + Rectangle { + anchors.fill: parent + visible: parent.status === Image.Loading + color: Color.mSurfaceVariant + + BusyIndicator { + anchors.centerIn: parent + running: true + width: Style.baseWidgetSize * 0.5 * scaling + height: width + } + } + + // Error fallback + onStatusChanged: status => { + if (status === Image.Error) { + iconLoader.visible = true + imagePreview.visible = false + } + } + } + + // Icon fallback + Loader { + id: iconLoader + anchors.fill: parent + anchors.margins: Style.marginXS * scaling + + visible: !modelData.isImage || imagePreview.status === Image.Error + active: visible + + sourceComponent: Component { + IconImage { + anchors.fill: parent + source: modelData.icon ? ThemeIcons.iconFromName(modelData.icon, "application-x-executable") : "" + visible: modelData.icon && source !== "" + asynchronous: true + } + } + } + + // Fallback text if no icon and no image NText { - id: formatLabel anchors.centerIn: parent - text: { - if (!modelData.isImage) - return "" - const desc = modelData.description || "" - const parts = desc.split(" • ") - return parts[0] || "IMG" + visible: !imagePreview.visible && !iconLoader.visible + text: modelData.name ? modelData.name.charAt(0).toUpperCase() : "?" + font.pointSize: Style.fontSizeXXL * scaling + font.weight: Style.fontWeightBold + color: Color.mOnPrimary + } + + // Image type indicator overlay + Rectangle { + visible: modelData.isImage && imagePreview.visible + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.margins: 2 * scaling + width: formatLabel.width + 6 * scaling + height: formatLabel.height + 2 * scaling + radius: Style.radiusM * scaling + color: Color.mSurfaceVariant + + NText { + id: formatLabel + anchors.centerIn: parent + text: { + if (!modelData.isImage) + return "" + const desc = modelData.description || "" + const parts = desc.split(" • ") + return parts[0] || "IMG" + } + font.pointSize: Style.fontSizeXXS * scaling + color: Color.mPrimary } - font.pointSize: Style.fontSizeXXS * scaling - color: Color.mPrimary } } - } - // Text content - ColumnLayout { - Layout.fillWidth: true - spacing: 0 * scaling - - NText { - text: modelData.name || "Unknown" - font.pointSize: Style.fontSizeL * scaling - font.weight: Style.fontWeightBold - color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurface - elide: Text.ElideRight + // Text content + ColumnLayout { Layout.fillWidth: true + spacing: 0 * scaling + + NText { + text: modelData.name || "Unknown" + font.pointSize: Style.fontSizeL * scaling + font.weight: Style.fontWeightBold + color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurface + elide: Text.ElideRight + Layout.fillWidth: true + } + + NText { + text: modelData.description || "" + font.pointSize: Style.fontSizeS * scaling + color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant + elide: Text.ElideRight + Layout.fillWidth: true + visible: text !== "" + } } - NText { - text: modelData.description || "" - font.pointSize: Style.fontSizeS * scaling - color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant - elide: Text.ElideRight - Layout.fillWidth: true - visible: text !== "" + // Pin/Unpin action icon button + NIconButton { + visible: !!entry.appId && !modelData.isImage && entry.isSelected && (Settings.data.dock.monitors && Settings.data.dock.monitors.length > 0) + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + icon: entry.isPinned(entry.appId) ? "unpin" : "pin" + tooltipText: entry.isPinned(entry.appId) ? I18n.tr("launcher.unpin") : I18n.tr("launcher.pin") + onClicked: entry.togglePin(entry.appId) } } } @@ -469,12 +503,17 @@ NPanel { MouseArea { id: mouseArea anchors.fill: parent + z: -1 hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: { - selectedIndex = index - ui.activate() + onClicked: (mouse) => { + if (mouse.button === Qt.LeftButton) { + selectedIndex = index + ui.activate() + mouse.accepted = true + } } + acceptedButtons: Qt.LeftButton } } } @@ -498,4 +537,4 @@ NPanel { } } } -} +} \ No newline at end of file diff --git a/Modules/Launcher/Plugins/ApplicationsPlugin.qml b/Modules/Launcher/Plugins/ApplicationsPlugin.qml index 46d83094..4cbd7f1a 100644 --- a/Modules/Launcher/Plugins/ApplicationsPlugin.qml +++ b/Modules/Launcher/Plugins/ApplicationsPlugin.qml @@ -69,9 +69,14 @@ Item { if (!query || query.trim() === "") { // Return all apps, optionally sorted by usage + const favoriteApps = Settings.data.appLauncher.favoriteApps || [] let sorted if (Settings.data.appLauncher.sortByMostUsed) { sorted = entries.slice().sort((a, b) => { + // Favorites first + const aFav = favoriteApps.includes(getAppKey(a)) + const bFav = favoriteApps.includes(getAppKey(b)) + if (aFav !== bFav) return aFav ? -1 : 1 const ua = getUsageCount(a) const ub = getUsageCount(b) if (ub !== ua) @@ -79,7 +84,12 @@ Item { return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()) }) } else { - sorted = entries.slice().sort((a, b) => (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase())) + sorted = entries.slice().sort((a, b) => { + const aFav = favoriteApps.includes(getAppKey(a)) + const bFav = favoriteApps.includes(getAppKey(b)) + if (aFav !== bFav) return aFav ? -1 : 1 + return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()) + }) } return sorted.map(app => createResultEntry(app)) } @@ -92,7 +102,16 @@ Item { "limit": 20 }) - return fuzzyResults.map(result => createResultEntry(result.obj)) + // Sort favorites first within fuzzy results while preserving fuzzysort order otherwise + const favoriteApps = Settings.data.appLauncher.favoriteApps || [] + const fav = [] + const nonFav = [] + for (const r of fuzzyResults) { + const app = r.obj + if (favoriteApps.includes(getAppKey(app))) fav.push(r) + else nonFav.push(r) + } + return fav.concat(nonFav).map(result => createResultEntry(result.obj)) } else { // Fallback to simple search const searchTerm = query.toLowerCase() @@ -118,6 +137,7 @@ Item { function createResultEntry(app) { return { + "appId": getAppKey(app), "name": app.name || "Unknown", "description": app.genericName || app.comment || "", "icon": app.icon || "application-x-executable", From c53dd6fadea3db6e8fa43dc66d2c5cb0944514c6 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 15:04:13 -0400 Subject: [PATCH 27/62] Compositor: fix getFocusedWindowTitle. Since active workspace has been implemented. + autoformatting --- Modules/Bar/Widgets/Taskbar.qml | 9 +++--- Modules/Launcher/Launcher.qml | 29 +++++++++++-------- .../Launcher/Plugins/ApplicationsPlugin.qml | 12 +++++--- Services/CompositorService.qml | 12 ++++---- Services/HyprlandService.qml | 4 +-- Services/NiriService.qml | 20 ++++++------- 6 files changed, 47 insertions(+), 39 deletions(-) diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index 8cfd8564..d37100dd 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -12,7 +12,7 @@ Rectangle { id: root property ShellScreen screen property real scaling: 1.0 - + // Widget properties passed from Bar.qml for per-instance settings property string widgetId: "" property string section: "" @@ -22,7 +22,7 @@ Rectangle { readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" readonly property bool compact: (Settings.data.bar.density === "compact") readonly property real itemSize: compact ? Style.capsuleHeight * 0.9 * scaling : Style.capsuleHeight * 0.8 * scaling - + property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] property var widgetSettings: { if (section && sectionWidgetIndex >= 0) { @@ -62,9 +62,8 @@ Rectangle { delegate: Item { id: taskbarItem required property var modelData - - visible: (!widgetSettings.onlySameOutput || modelData.output == screen.name) - && (!widgetSettings.onlyActiveWorkspaces || CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId)) + + visible: (!widgetSettings.onlySameOutput || modelData.output == screen.name) && (!widgetSettings.onlyActiveWorkspaces || CompositorService.getActiveWorkspaces().map(ws => ws.id).includes(modelData.workspaceId)) Layout.preferredWidth: root.itemSize Layout.preferredHeight: root.itemSize diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index 5b705bd4..e79bee6b 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -302,7 +302,9 @@ NPanel { positionViewAtIndex(currentIndex, ListView.Contain) } } - onModelChanged: {} + onModelChanged: { + + } delegate: Rectangle { id: entry @@ -313,11 +315,14 @@ NPanel { // Pin helpers function togglePin(appId) { - if (!appId) return + if (!appId) + return let arr = (Settings.data.dock.pinnedApps || []).slice() const idx = arr.indexOf(appId) - if (idx >= 0) arr.splice(idx, 1) - else arr.push(appId) + if (idx >= 0) + arr.splice(idx, 1) + else + arr.push(appId) Settings.data.dock.pinnedApps = arr } @@ -506,13 +511,13 @@ NPanel { z: -1 hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: (mouse) => { - if (mouse.button === Qt.LeftButton) { - selectedIndex = index - ui.activate() - mouse.accepted = true - } - } + onClicked: mouse => { + if (mouse.button === Qt.LeftButton) { + selectedIndex = index + ui.activate() + mouse.accepted = true + } + } acceptedButtons: Qt.LeftButton } } @@ -537,4 +542,4 @@ NPanel { } } } -} \ No newline at end of file +} diff --git a/Modules/Launcher/Plugins/ApplicationsPlugin.qml b/Modules/Launcher/Plugins/ApplicationsPlugin.qml index 4cbd7f1a..84df4450 100644 --- a/Modules/Launcher/Plugins/ApplicationsPlugin.qml +++ b/Modules/Launcher/Plugins/ApplicationsPlugin.qml @@ -76,7 +76,8 @@ Item { // Favorites first const aFav = favoriteApps.includes(getAppKey(a)) const bFav = favoriteApps.includes(getAppKey(b)) - if (aFav !== bFav) return aFav ? -1 : 1 + if (aFav !== bFav) + return aFav ? -1 : 1 const ua = getUsageCount(a) const ub = getUsageCount(b) if (ub !== ua) @@ -87,7 +88,8 @@ Item { sorted = entries.slice().sort((a, b) => { const aFav = favoriteApps.includes(getAppKey(a)) const bFav = favoriteApps.includes(getAppKey(b)) - if (aFav !== bFav) return aFav ? -1 : 1 + if (aFav !== bFav) + return aFav ? -1 : 1 return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()) }) } @@ -108,8 +110,10 @@ Item { const nonFav = [] for (const r of fuzzyResults) { const app = r.obj - if (favoriteApps.includes(getAppKey(app))) fav.push(r) - else nonFav.push(r) + if (favoriteApps.includes(getAppKey(app))) + fav.push(r) + else + nonFav.push(r) } return fav.concat(nonFav).map(result => createResultEntry(result.obj)) } else { diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index c2380fda..b5cd62d2 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -117,12 +117,12 @@ Singleton { // Emit signal to notify listeners that workspace list has been updated workspacesChanged() } - + function syncWindows() { windows.clear() const ws = backend.windows for (var i = 0; i < ws.length; i++) { - windows.append(ws[i]) + windows.append(ws[i]) } // Emit signal to notify listeners that workspace list has been updated windowListChanged() @@ -131,7 +131,7 @@ Singleton { // Get window title for focused window function getFocusedWindowTitle() { if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { - return windows[focusedWindowIndex].title || "" + return windows.get(focusedWindowIndex).title || "" } return "" } @@ -155,7 +155,7 @@ Singleton { } return null } - + // Get active workspaces function getActiveWorkspaces() { const activeWorkspaces = [] @@ -167,7 +167,7 @@ Singleton { } return activeWorkspaces } - + // Set focused window function focusWindow(windowId) { if (backend && backend.focusWindow) { @@ -184,7 +184,7 @@ Singleton { } return null } - + // Close window function closeWindow(windowId) { if (backend && backend.closeWindow) { diff --git a/Services/HyprlandService.qml b/Services/HyprlandService.qml index 6c26dba6..1cd43f1e 100644 --- a/Services/HyprlandService.qml +++ b/Services/HyprlandService.qml @@ -277,7 +277,7 @@ Item { Logger.error("HyprlandService", "Failed to switch workspace:", e) } } - + function focusWindow(windowId) { try { Hyprland.dispatch(`focuswindow ${windowId}`) @@ -285,7 +285,7 @@ Item { Logger.error("HyprlandService", "Failed to switch window:", e) } } - + function closeWindow(windowId) { try { Hyprland.dispatch(`killwindow ${windowId}`) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index c298dbc2..3fe4af7a 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -101,7 +101,7 @@ Item { break } } - + windowsList.push({ "id": win.id, "title": win.title || "", @@ -170,7 +170,7 @@ Item { try { const windowData = eventData.window const existingIndex = windows.findIndex(w => w.id === windowData.id) - + var output = null for (var i = 0; i < workspaces.count; i++) { if (workspaces.get(i).id === windowData.workspace_id) { @@ -251,17 +251,17 @@ Item { break } } - + windowsList.push({ "id": win.id, "title": win.title || "", "appId": win.app_id || "", "workspaceId": win.workspace_id || null, "isFocused": win.is_focused === true, - "output": output, + "output": output }) } - + windowsList.sort((a, b) => a.id - b.id) windows = windowsList windowListChanged() @@ -284,18 +284,18 @@ Item { function handleWindowFocusChanged(eventData) { try { const focusedId = eventData.id - + if (windows[focusedWindowIndex]) { windows[focusedWindowIndex].isFocused = false } if (focusedId) { const newIndex = windows.findIndex(w => w.id === focusedId) - + if (newIndex >= 0) { windows[newIndex].isFocused = true } - + focusedWindowIndex = newIndex >= 0 ? newIndex : -1 } else { focusedWindowIndex = -1 @@ -315,7 +315,7 @@ Item { Logger.error("NiriService", "Failed to switch workspace:", e) } } - + function focusWindow(windowId) { try { Quickshell.execDetached(["niri", "msg", "action", "focus-window", "--id", windowId.toString()]) @@ -323,7 +323,7 @@ Item { Logger.error("NiriService", "Failed to switch window:", e) } } - + function closeWindow(windowId) { try { Quickshell.execDetached(["niri", "msg", "action", "close-window", "--id", windowId.toString()]) From 51ed6ea2b064a672be11f2e63fe64b342c9a384d Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 15:10:44 -0400 Subject: [PATCH 28/62] Compositor: fix getFocusedWindow() --- Services/CompositorService.qml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Services/CompositorService.qml b/Services/CompositorService.qml index b5cd62d2..4d30421c 100644 --- a/Services/CompositorService.qml +++ b/Services/CompositorService.qml @@ -128,7 +128,15 @@ Singleton { windowListChanged() } - // Get window title for focused window + // Get focused window + function getFocusedWindow() { + if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { + return windows.get(focusedWindowIndex) + } + return null + } + + // Get focused window title function getFocusedWindowTitle() { if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { return windows.get(focusedWindowIndex).title || "" @@ -177,14 +185,6 @@ Singleton { } } - // Get focused window - function getFocusedWindow() { - if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.count) { - return windows[focusedWindowIndex] - } - return null - } - // Close window function closeWindow(windowId) { if (backend && backend.closeWindow) { From 26ee5046f6972de1e2f3358d065cd77aefa8bc34 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Sun, 28 Sep 2025 15:34:49 +0200 Subject: [PATCH 29/62] NiriService: Sort windows by their scrolling position. --- Services/NiriService.qml | 222 ++++++++++++++++++++------------------- 1 file changed, 114 insertions(+), 108 deletions(-) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index 3fe4af7a..e697c567 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -6,6 +6,9 @@ import qs.Commons Item { id: root + // Sorts floating windows after scrolling ones + property int floatingWindowPosition: Number.MAX_SAFE_INTEGER + // Properties that match the facade interface property ListModel workspaces: ListModel {} property var windows: [] @@ -91,41 +94,7 @@ Item { onRead: function (line) { try { const windowsData = JSON.parse(line) - const windowsList = [] - - for (const win of windowsData) { - var output = null - for (var i = 0; i < workspaces.count; i++) { - if (workspaces.get(i).id === win.workspace_id) { - output = workspaces.get(i).output - break - } - } - - windowsList.push({ - "id": win.id, - "title": win.title || "", - "appId": win.app_id || "", - "workspaceId": win.workspace_id || null, - "isFocused": win.is_focused === true, - "output": output - }) - } - - windowsList.sort((a, b) => a.id - b.id) - windows = windowsList - windowListChanged() - - // Update focused window index - focusedWindowIndex = -1 - for (var i = 0; i < windowsList.length; i++) { - if (windowsList[i].isFocused) { - focusedWindowIndex = i - break - } - } - - activeWindowChanged() + recollectWindows(windowsData) } catch (e) { Logger.error("NiriService", "Failed to parse windows:", e, line) } @@ -141,52 +110,106 @@ Item { stdout: SplitParser { onRead: data => { - try { - const event = JSON.parse(data.trim()) + try { + const event = JSON.parse(data.trim()) - if (event.WorkspacesChanged) { - updateWorkspaces() - } else if (event.WindowOpenedOrChanged) { - handleWindowOpenedOrChanged(event.WindowOpenedOrChanged) - } else if (event.WindowClosed) { - handleWindowClosed(event.WindowClosed) - } else if (event.WindowsChanged) { - handleWindowsChanged(event.WindowsChanged) - } else if (event.WorkspaceActivated) { - updateWorkspaces() - } else if (event.WindowFocusChanged) { - handleWindowFocusChanged(event.WindowFocusChanged) - } - // Removed OverviewOpenedOrClosed handling - } catch (e) { - Logger.error("NiriService", "Error parsing event stream:", e, data) - } - } + if (event.WorkspacesChanged) { + updateWorkspaces() + } else if (event.WindowOpenedOrChanged) { + handleWindowOpenedOrChanged(event.WindowOpenedOrChanged) + } else if (event.WindowClosed) { + handleWindowClosed(event.WindowClosed) + } else if (event.WindowsChanged) { + handleWindowsChanged(event.WindowsChanged) + } else if (event.WorkspaceActivated) { + updateWorkspaces() + } else if (event.WindowFocusChanged) { + handleWindowFocusChanged(event.WindowFocusChanged) + } else if (event.WindowLayoutsChanged) { + handleWindowLayoutsChanged(event.WindowLayoutsChanged) + } + } catch (e) { + Logger.error("NiriService", "Error parsing event stream:", e, data) + } + } } } + // Utility functions + function getWindowPosition(layout) { + if (layout.pos_in_scrolling_layout) { + return { + x: layout.pos_in_scrolling_layout[0], + y: layout.pos_in_scrolling_layout[1] + } + } else { + return { + x: floatingWindowPosition, + y: floatingWindowPosition + } + } + } + + function getWindowOutput(win) { + for (var i = 0; i < workspaces.count; i++) { + if (workspaces.get(i).id === win.workspace_id) { + return workspaces.get(i).output + } + } + return null + } + + function getWindowData(win) { + return { + "id": win.id, + "title": win.title || "", + "appId": win.app_id || "", + "workspaceId": win.workspace_id || null, + "isFocused": win.is_focused === true, + "output": getWindowOutput(win) || "", + "position": getWindowPosition(win.layout) + } + } + + // Sort windows + // 1. by workspace ID + // 2. by position X + // 3. by position Y + function compareWindows(a, b) { + if (a.workspaceId !== b.workspaceId) { + return a.workspaceId - b.workspaceId + } + if (a.position.x !== b.position.x) { + return a.position.x - b.position.x + } + return a.position.y - b.position.y + } + + function recollectWindows(windowsData) { + const windowsList = [] + for (const win of windowsData) { + windowsList.push(getWindowData(win)) + } + windowsList.sort(compareWindows) + windows = windowsList + windowListChanged() + + focusedWindowIndex = -1 + for (var i = 0; i < windowsList.length; i++) { + if (windowsList[i].isFocused) { + focusedWindowIndex = i + break + } + } + activeWindowChanged() + } + // Event handlers function handleWindowOpenedOrChanged(eventData) { try { const windowData = eventData.window const existingIndex = windows.findIndex(w => w.id === windowData.id) - - var output = null - for (var i = 0; i < workspaces.count; i++) { - if (workspaces.get(i).id === windowData.workspace_id) { - output = workspaces.get(i).output - break - } - } - - const newWindow = { - "id": windowData.id, - "title": windowData.title || "", - "appId": windowData.app_id || "", - "workspaceId": windowData.workspace_id || null, - "isFocused": windowData.is_focused === true, - "output": output - } + const newWindow = getWindowData(windowData) if (existingIndex >= 0) { // Update existing window @@ -194,7 +217,7 @@ Item { } else { // Add new window windows.push(newWindow) - windows.sort((a, b) => a.id - b.id) + windows.sort(compareWindows) } // Update focused window index if this window is focused @@ -241,41 +264,7 @@ Item { function handleWindowsChanged(eventData) { try { const windowsData = eventData.windows - const windowsList = [] - - for (const win of windowsData) { - var output = "" - for (var i = 0; i < workspaces.count; i++) { - if (workspaces.get(i).id === win.workspace_id) { - output = workspaces.get(i).output - break - } - } - - windowsList.push({ - "id": win.id, - "title": win.title || "", - "appId": win.app_id || "", - "workspaceId": win.workspace_id || null, - "isFocused": win.is_focused === true, - "output": output - }) - } - - windowsList.sort((a, b) => a.id - b.id) - windows = windowsList - windowListChanged() - - // Update focused window index - focusedWindowIndex = -1 - for (var i = 0; i < windowsList.length; i++) { - if (windowsList[i].isFocused) { - focusedWindowIndex = i - break - } - } - - activeWindowChanged() + recollectWindows(windowsData) } catch (e) { Logger.error("NiriService", "Error handling WindowsChanged:", e) } @@ -307,6 +296,23 @@ Item { } } + function handleWindowLayoutsChanged(eventData) { + try { + for (const [windowId, layout] of eventData.changes) { + const window = windows.find(w => w.id === windowId) + if (window) { + window.position = getWindowPosition(layout) + } + } + + windows.sort(compareWindows) + + windowListChanged() + } catch (e) { + Logger.error("NiriService", "Error handling WindowLayoutChanged:", e) + } + } + // Public functions function switchToWorkspace(workspaceId) { try { From 82bfa346a71ad8521353d7f66c9d870184c47005 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Mon, 29 Sep 2025 22:16:46 +0200 Subject: [PATCH 30/62] NiriService: Fix stale focus state when opening a new window. --- Services/NiriService.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index e697c567..69728a3d 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -227,6 +227,7 @@ Item { // Only emit activeWindowChanged if the focused window actually changed if (oldFocusedIndex !== focusedWindowIndex) { + windows[oldFocusedIndex].isFocused = false activeWindowChanged() } } From fc4418be0c8c68527b0e71aabf903b3b4eb928de Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 16:53:33 -0400 Subject: [PATCH 31/62] Shader: fix "disc" shader (no disc at 0 progress) --- Shaders/frag/wp_disc.frag | 5 ++++- Shaders/qsb/wp_disc.frag.qsb | Bin 5385 -> 5456 bytes 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Shaders/frag/wp_disc.frag b/Shaders/frag/wp_disc.frag index 0fc21229..ba0192c3 100644 --- a/Shaders/frag/wp_disc.frag +++ b/Shaders/frag/wp_disc.frag @@ -110,8 +110,11 @@ void main() { // Add extra range for smoothness to ensure complete coverage // Adjust smoothness for aspect ratio to maintain consistent visual appearance float adjustedSmoothness = mappedSmoothness * max(1.0, ubuf.aspectRatio); - float radius = ubuf.progress * (maxDist + adjustedSmoothness); + // Start the radius from -adjustedSmoothness, this ensures the disc is completely hidden when progress=0 + float totalDistance = maxDist + 2.0 * adjustedSmoothness; + float radius = -adjustedSmoothness + ubuf.progress * totalDistance; + // Use smoothstep for a smooth edge transition float factor = smoothstep(radius - adjustedSmoothness, radius + adjustedSmoothness, dist); diff --git a/Shaders/qsb/wp_disc.frag.qsb b/Shaders/qsb/wp_disc.frag.qsb index 8e1705e73a0dbca41b23da0cf4982d3efe75fc9b..5dddf017f8f0f023c13c6ced8873ee399405634d 100644 GIT binary patch literal 5456 zcmV-W6|d?50D9hdob6o+lv`JM{@={lV~-Ojj-7>sB+qdYH1=4QX!!IYe{`-9;f~=`i`! zpj}j^GF2&0DI)42BKkf)6!T#L7f^w!Y-{+v%0s#2LIsY*W8s0N1J zofwu=j(jRnNIq5R7|8d`jr=&sZ|+3CifS~ix+A11Dn(2>(240H@~B1?@+n6l9aJ6* zs0_Blots{ufQnS4eN?7A`CvHKSx-RIs?&WsN&)4Sk!i5q-ihrJ!M2Bd3TTq1C~Pv` zF+Y77u;u5g&oEAP)>osPiUaPkmPXB1?5t0+NsXGZ(uwhcW(U}V=w2DuaUUL}%c(|X zs#8^k7<)5;amQNQK2h?FAXg*)xqcSoH+Ks@mp|Owv!4}3RbP49%bM%TC9HG zbn~H`leI9P93J86hn7>XqT{;rs9*Vmf2O^l#P}D9=!C=m=~Z|?%b;Fbjh5`8KJ}eH zi&S}0v)m8AN^A{&8_WT=Q(!&7b_=W**dBrP0lQgXi+~*v*kWLZ1=bJjn820*yIo*Q zf!!gn0bqH7Edw?suycSF1$Hj5ioliw<2byD`qX#hFH^osl(|o?5aq9c-VtR<|1|1* zL|N8z{~CEKsYlVRre5W9{(celDj&K;bTRcQ-z`R+OMS|3{rKTB`^?a+rp3x%TxPnZ z_<0E}Rk5)+W&oM;Wzm zf`7h0D`5}&Q2UB#6y-I*E~GxX8alW=>rlQ1al!o8f_AZ}A4H6p@&@>h%S^{J2@&mB zMLo1p;71hv=nhk^tMa`&hG>!EKM9O~3=PK{k-L*^{ax5fsOR$Ui89kaYSsUR)wX{^ zEOXob8ErGZ`ghRw!&hAXA~3H157ezhJ@?^Pgg%!4RrISVe+~U>=%2RepTSr)W{}1TDCg}ecIMY9c@>W`+V&j`?Zq%{Qx>?>+ zp#3uHjh+7|?0gnwqxZYe`;5^0J>X3L9h40{2i_Wt5kv2AFgluEZFHQLojs1WlgAwE zW_e7*wBJI#k-ZqQd3+h!{XDh=&5{_JrH;lQphc=YztP<{l)W|(XrgoxUu7W*ui7p(5&G7kFetcNAs-^vR6Vj&xwX_m80d?D*+Y)T?+4#{N3VlJf-f1PZ-b+8qc7!X-VLJ7X|y>3ds1jK&u3{Ne`AdQ zhaHU@nvocqO^(Km?VDlyCSk)CVFSzD3>$b3-6CXdbM!oG%A-79ME_ssXd1@Pp~Z@3 z46<)PJL2ZfBoj$XS=`BvCv`u~WdX>JuXM=hRX;4wOnJDTR0pt;S_Yp|I| z$I%~Y=wP1PU?Z=c6Z8T%$)u1^c{(-b0yK=9^*e`W_XPAzz(=>C zt~ozjelJ*lp9D=o&~OgzHW4cU=%%0}56txSYcL<0HWp)iH4WU*lw$l)25xMtfUhj# z?k?!72>n&)H*r$~T^07;3Cz%km@7>AZp`0CM+5nqyTzD41-^#hdoB2kpY8$1W9mL& zuLJKrB8Fdw7(R|TJ1zY3BQY`jdf+C8?*n!(V)%X$!(8_U)fO%L4MO$(ub&5<#x?c} zz|DO84q!&cFIwx{FU8pV%fJoIuf*8<9^l5__k!;|BG!Ku`rZp$-VMyy@@v?ynDYCv zpE2!w7&Pw}dOv{vFnT`->;q!l{yKO+2)*wEX7v09_C-eKZ(4EjAuBFE44MxK9Up<5 z4~y~m5sXJOX70Df=W%Pz*(7ZGE$l77M?LDh+0*jgm-93HS%tkT=SVLU``e4ep7vt# z{SxT8RO|;oYV8j{X6-jWZj~Pq`$zu$+t9~t{us)}Z=ZmEuKPI3rtXulhwC0ec`NlR znZJX5JIiCfM?m*c)S2AO@56qX_xS_hW={JqFI{26p#3i`){U4M>xw(ALD7vql;DU9VkF6{bC z*d_B*e+At5;IDx_3cHM)Cxl&p1Kpnj{o}%}zePRU^=V-j<4+PPjO9Hk?E1SHyZ#=y z@z*~9GyXDiJ}vC}N9cY6^iRT$&k8%3<}*YJWB$*;4*pxkzhJK7zhRhX$iKbcrr2md9>vy#@`n}^Lfbl0>&q&D)IMK^QU$E$?N>RYfk#rT2L;z=~QZ< zQuT9zDoq8GQx&&REPLT-8yu9v(Sd^?8728~gL zDG3bjuXwp2JSEXewLDq%Yc+}G{8H#wkF`U`B~+U(m&2)&#p~57el9%dg+W=ug`im6 zSI+wq3#PqE|7eg8r_yck9zU3z3e)lAnGWO;yq2r_eo4`{!C;i;8vTs+pSgwu^ zoE{w*sF#95xjM~$b?X!Lf`GL5YuZzbK$r>}< z9f$qKu5!7WPjMY%Ij@+j7roHG^+-Yi^^-%*W=^WMh_Y_PAUa-n<9gKx?pTw_-O!?M zcSe((TbdMpb2muH@>#|Wt6r(bP4@G*9%1&Ax-uxZ3B_kR-M!9DB}WETr8c%HLyJBT zH2k8H;I378!Zu~7-IBr4s3_I+{e?o!=e8u~EXG~0Rkl3b^6j9zmQ9b-WNel#STBue zG1-n1{2My!*8Hc{zkadiTkebVa@u$~N-8_tEBfx3JMA^ve4~S;lbd7+3D1j;^oo9d zFSqPa@LJZU;!a0QI+@~#(1r{Sy6fBo zj8c&xnyz~$(mU;LkL#t3?4@=VtGBXg?ysP6{7>E z)#@>fCFf`mPTh!LOW12s=r@Mk`K~OAzT#EAX)(!T_rR!fnUT_7o6)tiE+2C7Q=CIa zy!n!WlP1dLqMJ=`-RO=*r6e0_sYyw)ObSIFimRE+UWk|^M$&dSZ6tM^gu%*EC8g24 zMQYBZQZbshv}ryi+c1-6W^FYuqB%Vh)x4!$b9y93^W563SX<3I-BiU@wkE`Ea}vZZ zt39awMp&=|pC~yRDgas*xC5Gq$annQYA%+cugn!{&=w`n1AnuTt^z zhnkN7YK>|nQpr>*ozkD-&BI$a509ibrbaey**csW&TQSZW%I}o&+TSvZt<_R5$PN+ ze`mcGVxG`*{mEp*@Q6o_A-8@qc`A-|mwJF{vNInZbK=Fc2#!Y@o)2ogKjB|qDd#6z zrVUxTEPpk22et5++gbiNv7PjG3p}xRWBdZ*@DFS z7)lnS)SD+>cWqQ-L{`Deg=G#G9gwxquOuLUeT*GLM)|tfN{$wYpDbo?ta_8Xz0ey^ zoxrfs19J$IiCUqD6WWBqc)qn5>GGle^uU0XWZ=IW;B)@6R+1r;>Lw0e_{6~sDT8jZ zpqnh1{rRDrENFhZ$pZ1|CJVaBf`v#HbkhXgG(k5_&`lF`(*)f#K{rkCLzE_Xr$`el zZ>0%Fx@m$Jf0`gD#T_Ro*F)&7dXv!GJz~&3V$eNe&^=<%%^Gx%7__nk-K;_PaKR7F z;ezhbg6`3R?$Lto(Sje$qXo@py}73gS}e0?3VK>EqSE(^aufAJ!LO=^*lljrpA2fD zUrkJ;%<-&h`R?qrcW1e(TRz+vRywlH>j~~Qx8mhqqfb{Ra;b=)3@Oa9XouTro8Gr5 zn+JjftvP#RlfJeS>G3wwyW2^{d8R1!NIR`K1!EJ(8QeTSY}3YAEDp4_k;hmqPqta~ zn`RQ8v5DjCmg$o=`WV~g0cV>$&g1gPbCiCwq(ovl|_a|QrDQeliW;1Zn}fqOsrg{9;k(0802&t?Ie(_i)Mmw zYv|B{y$6qEcU8-^T6S-#QV-=-lBhIyn|t`>$9C=Ce{gq7yDCP;{(5K$5o+CS?x7>u z!(MgL4ApNqc>j)_O=ybVlKbv8ZD&lD0{>pabO(c ztP3#n5aq5nif6b4Q;1i%Q1@VFFkp^1VWij7O|M63t@9G%sAP7gs}M-F2u~EgU|FzOgfn=BpZzxF2oeh^hS*AtxTl1+IeQW60;!v*17MLt~vBx z+_jiUAL@%G^Ba_%uErE*us-H?%o$B8mf-o^kby&z4ctGS$Mu+5XMr<3^MchV=G063 z(yZLh@v~1*JO*6z}uhz^lob6|k&X;QfF5F1_XT5Thozs<@ z$a7A63ue1?V{i1I!!?|uU#-mL9!^1B#3`6Xz`ltikf_%pcX7CwZoZkexl#nv;!2qtPjOCbCs(a&3P$*4G!?p1a*z=uP_BfWMn5IP&y8CMl9J zGjeMN*FcPFEupLmnn)r^=>U-{5bH`*z-gHq?88fu%>O4ayrxq1CZ|0&SM*AgZa(lP zOXV78BZA3Nx$5WLtJWW#4r;ZaG`YS~Er;dsRK>4dH88LyDCLTEekz#uL$8>vh52GI zv0dP`U^>5n|4B}59~h{!2)E=-`?ZRf^IgRi_hOW03bOlhlzALpGFhDH@g+EyJ3qw% z(JAFKKCVVjA~ks8L=0z8njzsdK3=c+)kLwJD@k^h(h5q&pya#RtQUsWV4@!S*=!== z74P;=)v~&Ba4;^t6i!urFYo5crCJEB*Q$+td&RY4Ti>BpJBp`>5>Hhs+OAbI!C84J z%N&zav%HpNPPwVMzh+_9+|(T25HWjh>cyU#I-{4g6uervZQFvrs^x6ur=G7@wm`*; z^QA55zlDBv%L|>STF_Ux%rQ+h|JS&jL7EEs&iGX>&sVN${)=2}V#~ZxBd-%%$ZMIu zB!zzC&~&B9S%I^$CcbErVLH0HFP8a%KKqr_QJ)Y&-<}HNZR@mO65Cq+EnzmRZcuW^ z$IXM-i4$=_?v9V^QxR&Rl%mI4e)$>)>>JmXjF%qI&d9nvua7#Z&K$^)M9t9Ry;2bBFaLk_UL z6))TidFGY|Og@J+;MsaHkG0=^9$(KBtLY40(zCz`!IoLwm-Q(3m94zkbj+zbJ-n@R zby3E+vvp#DD(iF_=hGIc*%*iItOIxWKU?wNKU@EUCez|SZnKkdbLPW;2-n81KK~Ey G0-l{*JrqCy literal 5385 zcmV+k753@?0C?lCzm!xe@lXKdn2}#q^ zCJ>sX=fC&6(*LfWW-$YHTj?Cz`oH^c_rL#L_3kqfEh3^`B65i6BD$AC%F+SysX^PQ zOl7K4o>D|KkBI08_)yG;6)dF!Rmr1qC0tbETK%-53+NctsX#;vsownlnBY2B8PFc? zCXYg@Qa}wNS`3bB1^0R8%W{b9p$d7Fqkuv>0i)L%@9fWcRG})BX`HI$Q;lj6*xpIt z9LkYTB?`%>Djf#o6w*Ewv4F}D zJJ7l61q!H0McPee%99U)!=3E}G^rZhr$ZD_UOAbD*qxokE)rrp$ftnDX@bJ0;N7#c zmw{M*w)TwRL}z<7%Beiy7He75V#Ut(q?oj*1uLBdmo^)~?nDpDypH>DCq0L1RHiyr zRf=&m6XQQ`Lb}sd)c<`S|FDNnoWgfuMjl1$z_868u%SSOaA9kK2OlH zoZHvvTSoH~-wNtcG3W0WP>+hCOGFn^uZrCQl)2Qa;?{>hOmoZ(&k99%cEyABy z(IS-_3t~Eup)a8xT7n#6y-R^Ffgj5t&v~$d`e?cGpL=@L)#;hYR`H z{#gcpIEFe_L?fVA0z032=}Oq(`m6?h74m}RuLkb|Q9ghiG4xu*j%nuOk%Wl0E~k04 zPT&U>{KQs6*A@NX)WeS_2L6Ssrc)Q9PVmi(QLuK#+PujI_M z#XK+2Jmm|^a-IKK#ExV2RY7z4Hw4Ww`KCobXUTutl7G?S|E@*jeR<|**5EY4!mDQx$*PAg`Y2iHg>-U zyDtd4-v`e8-vw>>Inh?44;X%jlh4uoY9Zsa{G8`#KeMW8{G?_oBNN^ z-N$`L@GOksS>$N^5t^^)er`iY<7d%Ag)K%ONus}Iz{h@Y4lafb&VjQX9WNfYjE!>~ zjT=ACgCE?t4bKu@-v~dJI$Cat(7g=0dCW6%%N>pH#Ta|Oqh*)FKkgIf3)>gLHjg7l z$EzHT8=i|}{JX@_xbg4R+%}HJjof9ByHvxB;+g%7NA1AO2ybED9;+0o;wp+~sCi1xq6(L9WwMGF+qD0E+sa@NaZ@2JqTmFF!{ zk85LMd7Yzi71WBWFt|3>J)LFm89(YT>^@K`12ovh0tdI&ad zb~MjUVfPkC>$w?rc@DWn=-BP(dBxDTLZ@k)J&xwNRq*V!WNx$k*vIjAG;VnIJ9<7e zW84A6Dh(SfvmZY4ymkPxJT4z{^xSRe!;W4H7~Mx4Js0k!K2?5)qcQo1?Q+?e7+YB{ z>$(GWd95-g+Ti{4<-TP^x#OWz$fE3F);L{h{KzZW0!%4agOsPz)ah{25W_@gpLGo!?OxJ1A=EYaARi> za;stIa$sh@NTS`iYz=6mKL!13h5j_~Ptbg|ml*=abNutvL+g>NXk z?m(H*8q8xZx?q#Gwq__*Q{j zS>)ZluvZcGtFUkKrUt$${JjU5;SVuZ82Ubp-^NA*XC?QEK7Rso4Iy_w6%0LFdl zAz-hA>;oc)Uxyq%f;>AZ;_^c=IsC)GO%6W<>_O!4!y<>d?DeWHTKDUP?nh$UFeCM#nE&^V=`Q`1{Mi4bQK{`1>y4#@}~C?p-3+e--xL4PV{~%=q$aSg#oR zy;#qf`n?Z4?-h36kM=NjKLG6gqTl{HWIq7A?*V4){07!VM(1x@dGSFjFFpjG4+w)*E0YtC6OeEKb{Ex%9m)OWL{<+U%Lo$zNl)~vAeq5{{`QMMh9@qJ!piSI90sCC`anPphlkkVj9tXXN z`jpP!#=4#LvE1X}`v}U+xykRre|aYJ`@qeZ_6NZDeEEIUtFTW2=P~ZnVvJ+_Ng{=D zoSqc6J`-c>4}pIYw*ClM9qnrL@W0=pKE?CLuzfN3pA>%m3Ch{8r-fgPKSiW4*7ua~ z>(AhqJUjYx;3fut0qhC*W%N8P{Q67S{xtZX5`O&^%Gs~a3cnbChDc$o?-}9OU&r|M zH^5E2{uY>tm(lZC;n&~6_S4{h27Y{A_`y7%BT^X4e-3`|?*#vdv5J2`Fnh@_0O!8- z1;~6J<^224KcPRF9RDKfatQtJOW^q;bbJZ@laCSc+ot(h8$UOlM=Ou})ml(4x#?7@ zzf$#cfubgY@rjCCD3-l&qzw*A;YfdfEv(jap?j=e=zpN!bzOJT3y0i$!|ZM^tOkt{ zg((dT?x}dWAUq+_O0_&*^=mbW<@{3UR}Z&CMI8!iAt% z++EK55(_51asN<|4=2)X@D4v1p9s_O?3oVi5xkbG`hH3Ax5JuWIDJm=-0f-O3|-ow!5`*y_)mWBhxTsM*91Yd({&`X`C%) zxH%5^jcw&}HJ{=##&TXUS1)>@fBV6N0_w*Ho7EgwbrH0#!~hyzMB_Tu2JUE6$X(mw zZx2S3ookvDadX#7$ckCU4Xa+M##Q$7w;yEj;zhV+Vl zeka##e{etB=vXm#mFAAoQf@Y%tq+YflLj4d*V^txP1)^{PzBVt~ zI-TWov%e`@r#fatl(u@L_CIRGqyxK#4vSF4=Ly{4#E&+t&-DN z-Y6|+QmGir8`~_Okad{KGK;pV7qOfkj#}Q>ZaF<1V|iwER-&!yoot%oBHI#jwmAr5 zmDQfqej}_`{mk}+O45jD13JmeLEhyhbRv?O_2cfSwVIl7)+(<$tV3Jb+v18WOI4@K zadlW#Oz*?e5b4`7om-w}*LCo9sNL60JJ)cGuNm9d%v8Q+jBo4Amm%}TOnutmq*tl< z`Tfl;fSRKkiBvL`N~iQ^Xv5H^4MW4}b*bTX8#fK5hBBMhZ`?3E$YZ-1np^U#Y(xgf z%imM4g%~IFSbsd(FfwAxG3eHhCr`wQZc`hWrZ~%Cn-j05#c(82@qAF@^$Gvum2!Tf z<=UWS%ZgWHdr%7x%eB{3_IVxRu90pW9*AL#vvH)|#*sm{P2Z6?S$EVe`la!3LeJpF z>%pe(fryl;a5N9>)L5n5Nhec-Q~O`_@C)j3(MTfI*)3h zUr9jini$zZV>3?iplW2OA1`Kata{_yz0ey=9Ywb5{xpa&KuxSe3GKo_yxb~OPVU7| z_V-(71AN?%&$*v!oegAC-TnS6zu%u?r{CS2TCpNlWBR17H#Ic z{Fcb{8~k~#Hzlc;T74{ctX?SiRkior>{k8ppceYo#IcllhN)Vg9A zjcoH7es{B5@p7-#k02&;sYsj*E8MYohuV3YtzmICpPCW8<^dI(_5Mz*N7`8LYiAV? z{Y1Hk+j+&KA~tiJ!_9|mZQdA<#ZzBx>@i-;$G;bPj?uSqTJM!sRK(GAekZk+q zkVtX~@#(LJWTV$Z3ifIfYGQ7P=n}1@?RoErL*l7wsIzW~%tDpB#u%RBrbr>);9Ol6 znZkh?UKf#3PdB3;<+Ywp5YH24r@DWTo#Fk1X2aSyMy9A;{GAbKn(EfbEE@P!?~SCB zsY0^RnBvw*;Z(1U$kxh4TB}`Vs(T}I(r%sGPT874>&4w2iL{}cSKcq+0Ll4)0|Nyb^0cviQDPo39r$zk=rND6py`s zGQ)JX_adEdphUJHkyZPQ?x5Jq@9A!(NdKq3my(^)y_Cp4r@aQ#-Au6;`Y++GO3|-Y zW^!4jpl+)a%p_o6R}n}wYLN>oW@c$!S;=;~vSNuhFRjSQDSBjP9;v&)g#~mH76Vm$sa2G#ZUgM_%HL zNezkZJ6e4+uWh&N) zsDhL7M6Va``@v`FvnwlAZ+y~ob49N-?&bq;yi~678A32#Dp&oyd&QbVlR>Q(l*ZRo zs^zd8o~Zb>EBgCa2BloF&TIKeKlF;(T9_{e$F>N(7EI>X@?Xh`E&cs9SVgLRo~0IxpJu% z!s^v(`Q2V{wOEXIDAj@DA)>@HhRU|9)ktt!-ZwJCBc*BHI5MLXrJ27$VA>O<8NB>p z`V*xy{XprI-ak_CYT@S1bNUvN({-x!a=ncNCeF zO!+_kpjA?5eL^IC`vDd&TPOXJSk~%q3A0#rgOWQoW;S9+kH#grJ2s}DWl(G0LAR|F znqPs(#>@j?Q!-`*V_Gqq4h%)AKJ1o;p)Jakv6)zt>5i@1@}E)nfs-R`2X{d!`I64= zPWkOIvpKty0qJ;d7wPV^I=wsPx5~`s^iHwRq*;H8ZoryW~qaygOa*oUzv1 zFXNkMVlAD*`)B6(7_a5l|L*tDl&#~e$(Tpjbg#4?Vv7pKJ;)~Jm9jns<72S-Y7oVf nZPwFm_#Zs+p8;F{pCa?(zxlGy&}J-$|30iuUVZ)t7G58p^r}B! From b12cf345dc0461f9c808db2897f3a68cb35b7525 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 16:53:59 -0400 Subject: [PATCH 32/62] Background Wallpaper: attempt to free up memory earlier. --- Modules/Background/Background.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 6a62ed9c..5bb903ac 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -261,8 +261,12 @@ Variants { // We are interrupting a transition transitionAnimation.stop() transitionProgress = 0 - currentWallpaper.source = nextWallpaper.source + + const newCurrentSource = nextWallpaper.source + currentWallpaper.source = "" nextWallpaper.source = "" + + currentWallpaper.source = newCurrentSource } nextWallpaper.source = source From c92478d27dfef8d589e02df1028a411a751db44f Mon Sep 17 00:00:00 2001 From: Matan Bendix Shenhav Date: Tue, 30 Sep 2025 00:10:32 +0200 Subject: [PATCH 33/62] feat(flake): restart systemd service on package update --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index 9b869208..437af0d7 100644 --- a/flake.nix +++ b/flake.nix @@ -264,6 +264,7 @@ after = [ cfg.target ]; partOf = [ cfg.target ]; wantedBy = [ cfg.target ]; + restartTriggers = [ cfg.package ]; unitConfig = { StartLimitIntervalSec = 60; From df35589328d97e5aa0f824a8f199e7426fc71a28 Mon Sep 17 00:00:00 2001 From: Matan Bendix Shenhav Date: Tue, 30 Sep 2025 00:11:03 +0200 Subject: [PATCH 34/62] feat(flake): write settings to a fallback path --- Commons/Settings.qml | 24 ++++++++++++++++++++++-- flake.nix | 5 ++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 986d4248..0a38ca72 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -71,7 +71,13 @@ Singleton { id: saveTimer running: false interval: 1000 - onTriggered: settingsFileView.writeAdapter() + onTriggered: { + settingsFileView.writeAdapter() + // Write to fallback location if set + if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) { + settingsFallbackFileView.writeAdapter() + } + } } FileView { @@ -101,11 +107,25 @@ Singleton { } } onLoadFailed: function (error) { - if (error.toString().includes("No such file") || error === 2) + if (error.toString().includes("No such file") || error === 2) { // File doesn't exist, create it with default values writeAdapter() + // Also write to fallback if set + if (Quickshell.env("NOCTALIA_SETTINGS_FALLBACK")) { + settingsFallbackFileView.writeAdapter() + } + } } } + + // Fallback FileView for writing settings to alternate location + FileView { + id: settingsFallbackFileView + path: Quickshell.env("NOCTALIA_SETTINGS_FALLBACK") || "" + adapter: Quickshell.env("NOCTALIA_SETTINGS_FALLBACK") ? adapter : null + printErrors: false + watchChanges: false + } JsonAdapter { id: adapter diff --git a/flake.nix b/flake.nix index 437af0d7..179164ac 100644 --- a/flake.nix +++ b/flake.nix @@ -277,7 +277,10 @@ RestartSec = 3; TimeoutStartSec = 10; TimeoutStopSec = 5; - Environment = [ "PATH=${config.system.path}/bin" ]; + Environment = [ + "PATH=${config.system.path}/bin" + "NOCTALIA_SETTINGS_FALLBACK=%h/.config/noctalia/gui-settings.json" + ]; }; }; From 1f257ce84711b40ac34dbe415d50dacf77cd0ed8 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Tue, 30 Sep 2025 01:33:09 +0200 Subject: [PATCH 35/62] ControlCenter: fix custom image --- Modules/Bar/Widgets/ControlCenter.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Bar/Widgets/ControlCenter.qml b/Modules/Bar/Widgets/ControlCenter.qml index 69c1b39b..65eb3b8c 100644 --- a/Modules/Bar/Widgets/ControlCenter.qml +++ b/Modules/Bar/Widgets/ControlCenter.qml @@ -54,7 +54,7 @@ NIconButton { height: width source: { if (customIconPath !== "") - return customIconPath + return customIconPath.startsWith("file://") ? customIconPath : "file://" + customIconPath if (useDistroLogo) return DistroLogoService.osLogo return "" From 1e8b122911732f502d041f29ec7f817c85b09512 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 21:19:08 -0400 Subject: [PATCH 36/62] NiriService: syntax fix --- Services/NiriService.qml | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index 69728a3d..944e3d4a 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -110,28 +110,28 @@ Item { stdout: SplitParser { onRead: data => { - try { - const event = JSON.parse(data.trim()) + try { + const event = JSON.parse(data.trim()) - if (event.WorkspacesChanged) { - updateWorkspaces() - } else if (event.WindowOpenedOrChanged) { - handleWindowOpenedOrChanged(event.WindowOpenedOrChanged) - } else if (event.WindowClosed) { - handleWindowClosed(event.WindowClosed) - } else if (event.WindowsChanged) { - handleWindowsChanged(event.WindowsChanged) - } else if (event.WorkspaceActivated) { - updateWorkspaces() - } else if (event.WindowFocusChanged) { - handleWindowFocusChanged(event.WindowFocusChanged) - } else if (event.WindowLayoutsChanged) { - handleWindowLayoutsChanged(event.WindowLayoutsChanged) - } - } catch (e) { - Logger.error("NiriService", "Error parsing event stream:", e, data) - } - } + if (event.WorkspacesChanged) { + updateWorkspaces() + } else if (event.WindowOpenedOrChanged) { + handleWindowOpenedOrChanged(event.WindowOpenedOrChanged) + } else if (event.WindowClosed) { + handleWindowClosed(event.WindowClosed) + } else if (event.WindowsChanged) { + handleWindowsChanged(event.WindowsChanged) + } else if (event.WorkspaceActivated) { + updateWorkspaces() + } else if (event.WindowFocusChanged) { + handleWindowFocusChanged(event.WindowFocusChanged) + } else if (event.WindowLayoutsChanged) { + handleWindowLayoutsChanged(event.WindowLayoutsChanged) + } + } catch (e) { + Logger.error("NiriService", "Error parsing event stream:", e, data) + } + } } } @@ -139,13 +139,13 @@ Item { function getWindowPosition(layout) { if (layout.pos_in_scrolling_layout) { return { - x: layout.pos_in_scrolling_layout[0], - y: layout.pos_in_scrolling_layout[1] + "x": layout.pos_in_scrolling_layout[0], + "y": layout.pos_in_scrolling_layout[1] } } else { return { - x: floatingWindowPosition, - y: floatingWindowPosition + "x": floatingWindowPosition, + "y": floatingWindowPosition } } } @@ -182,7 +182,7 @@ Item { if (a.position.x !== b.position.x) { return a.position.x - b.position.x } - return a.position.y - b.position.y + return a.position.y - b.position.y } function recollectWindows(windowsData) { @@ -299,7 +299,9 @@ Item { function handleWindowLayoutsChanged(eventData) { try { - for (const [windowId, layout] of eventData.changes) { + for (const change of eventData.changes) { + const windowId = change[0] + const layout = change[1] const window = windows.find(w => w.id === windowId) if (window) { window.position = getWindowPosition(layout) From 4b13e89a64b7467dda3746820dbfb192a7372b71 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 21:31:45 -0400 Subject: [PATCH 37/62] Font: added per font family scaling. removed billboard font --- Assets/Translations/de.json | 6 -- Assets/Translations/en.json | 18 +++--- Assets/Translations/es.json | 6 -- Assets/Translations/fr.json | 6 -- Assets/Translations/pt.json | 6 -- Assets/Translations/zh-CN.json | 6 -- Assets/settings-default.json | 3 +- Commons/Settings.qml | 3 +- .../Bar/Bluetooth/BluetoothDevicesList.qml | 12 ++-- Modules/Bar/Bluetooth/BluetoothPanel.qml | 10 ++-- Modules/Bar/Calendar/CalendarPanel.qml | 10 ++-- Modules/Bar/Extras/BarPillHorizontal.qml | 4 +- Modules/Bar/Extras/BarPillVertical.qml | 4 +- Modules/Bar/Extras/TrayMenu.qml | 4 +- Modules/Bar/WiFi/WiFiPanel.qml | 34 +++++------ Modules/Bar/Widgets/ActiveWindow.qml | 4 +- Modules/Bar/Widgets/Clock.qml | 8 +-- Modules/Bar/Widgets/MediaMini.qml | 2 +- Modules/Bar/Widgets/SystemMonitor.qml | 24 ++++---- Modules/Bar/Widgets/Workspace.qml | 13 ++-- Modules/ControlCenter/Cards/MediaCard.qml | 8 +-- Modules/ControlCenter/Cards/ProfileCard.qml | 2 +- Modules/ControlCenter/Cards/WeatherCard.qml | 8 +-- Modules/Dock/DockMenu.qml | 6 +- Modules/Launcher/Launcher.qml | 10 ++-- Modules/LockScreen/LockScreen.qml | 59 +++++++++---------- Modules/Notification/Notification.qml | 6 +- .../Notification/NotificationHistoryPanel.qml | 14 ++--- Modules/OSD/OSD.qml | 8 +-- Modules/SessionMenu/SessionMenu.qml | 8 +-- Modules/Settings/Bar/BarSectionEditor.qml | 8 +-- .../Settings/Bar/BarWidgetSettingsDialog.qml | 2 +- .../Bar/WidgetSettings/ClockSettings.qml | 8 +-- .../WidgetSettings/ControlCenterSettings.qml | 2 +- .../WidgetSettings/CustomButtonSettings.qml | 2 +- Modules/Settings/SettingsPanel.qml | 4 +- Modules/Settings/Tabs/AboutTab.qml | 4 +- Modules/Settings/Tabs/AudioTab.qml | 2 +- Modules/Settings/Tabs/BarTab.qml | 4 +- Modules/Settings/Tabs/ColorSchemeTab.qml | 2 +- Modules/Settings/Tabs/DisplayTab.qml | 36 +++++------ Modules/Settings/Tabs/GeneralTab.qml | 43 ++++++++++---- Modules/Settings/Tabs/LauncherTab.qml | 4 +- Modules/Settings/Tabs/LocationTab.qml | 2 +- Modules/Settings/Tabs/WallpaperTab.qml | 4 +- Modules/Toast/SimpleToast.qml | 4 +- Modules/Tooltip/Tooltip.qml | 2 +- Modules/Wallpaper/WallpaperPanel.qml | 12 ++-- Widgets/NButton.qml | 3 +- Widgets/NCircleStat.qml | 2 +- Widgets/NCollapsible.qml | 4 +- Widgets/NColorPicker.qml | 2 +- Widgets/NColorPickerDialog.qml | 12 ++-- Widgets/NComboBox.qml | 4 +- Widgets/NContextMenu.qml | 2 +- Widgets/NDateTimeTokens.qml | 8 +-- Widgets/NFilePicker.qml | 10 ++-- Widgets/NHeader.qml | 4 +- Widgets/NIconPicker.qml | 6 +- Widgets/NLabel.qml | 4 +- Widgets/NRadioButton.qml | 2 +- Widgets/NSearchableComboBox.qml | 4 +- Widgets/NSpinBox.qml | 8 +-- Widgets/NText.qml | 11 +++- Widgets/NValueSlider.qml | 4 +- 65 files changed, 271 insertions(+), 276 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index f624ab06..76511329 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -71,12 +71,6 @@ "description": "Monospace-Schriftart für Zahlen und Statistik-Anzeigen.", "placeholder": "Monospace-Schriftart auswählen...", "search-placeholder": "Monospace-Schriftarten suchen..." - }, - "accent": { - "label": "Akzent-Schriftart", - "description": "Große Schriftart für hervorgehobene Anzeigen.", - "placeholder": "Display-Schriftart auswählen...", - "search-placeholder": "Display-Schriftarten suchen..." } } }, diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 25b42c3b..1ded8fcf 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -64,19 +64,21 @@ "label": "Default font", "description": "Main font used throughout the interface.", "placeholder": "Select default font...", - "search-placeholder": "Search fonts..." + "search-placeholder": "Search font...", + "scale": { + "label": "Default font size", + "description": "Increase or decrease the size of the standard text." + } }, "monospace": { "label": "Monospaced font", "description": "Monospaced font used for numbers and stats display.", "placeholder": "Select monospace font...", - "search-placeholder": "Search monospace fonts..." - }, - "accent": { - "label": "Accent font", - "description": "Large font used for prominent displays.", - "placeholder": "Select display font...", - "search-placeholder": "Search display fonts..." + "search-placeholder": "Search monospace font...", + "scale": { + "label": "Monospaced font size", + "description": "Increase or decrease the size of the monospaced text." + } } } }, diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 398a5935..2effb703 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -69,12 +69,6 @@ "description": "Fuente monoespaciada utilizada para la visualización de números y estadísticas.", "placeholder": "Seleccionar fuente monoespaciada...", "search-placeholder": "Buscar fuentes monoespaciadas..." - }, - "accent": { - "label": "Fuente de acento", - "description": "Fuente grande utilizada para visualizaciones destacadas.", - "placeholder": "Seleccionar fuente de visualización...", - "search-placeholder": "Buscar fuentes de visualización..." } } }, diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 15aecc4f..86ab1b48 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -69,12 +69,6 @@ "description": "Police à chasse fixe utilisée pour l'affichage des chiffres et des statistiques.", "placeholder": "Sélectionner la police à chasse fixe...", "search-placeholder": "Rechercher des polices à chasse fixe..." - }, - "accent": { - "label": "Police d'accentuation", - "description": "Grande police utilisée pour les affichages proéminents.", - "placeholder": "Sélectionner la police d'affichage...", - "search-placeholder": "Rechercher des polices d'affichage..." } } }, diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index b37bd547..365d6be9 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -69,12 +69,6 @@ "description": "Fonte monoespaçada usada para exibição de números e estatísticas.", "placeholder": "Selecione a fonte monoespaçada...", "search-placeholder": "Pesquisar fontes monoespaçadas..." - }, - "accent": { - "label": "Fonte de destaque", - "description": "Fonte grande usada para exibições proeminentes.", - "placeholder": "Selecione a fonte de exibição...", - "search-placeholder": "Pesquisar fontes de exibição..." } } }, diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 2fd17a68..baeffea4 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -69,12 +69,6 @@ "description": "用于数字和统计信息显示的等宽字体。", "placeholder": "选择等宽字体...", "search-placeholder": "搜索等宽字体..." - }, - "accent": { - "label": "强调字体", - "description": "用于突出显示内容的大字体。", - "placeholder": "选择标题字体...", - "search-placeholder": "搜索标题字体..." } } }, diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 3fddf7cd..d0a35397 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -148,7 +148,8 @@ "ui": { "fontDefault": "Roboto", "fontFixed": "DejaVu Sans Mono", - "fontBillboard": "Inter", + "fontDefaultScale": 1, + "fontFixedScale": 1, "monitorsScaling": [], "idleInhibitorEnabled": false }, diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 986d4248..8fd245c7 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -272,7 +272,8 @@ Singleton { property JsonObject ui: JsonObject { property string fontDefault: "Roboto" property string fontFixed: "DejaVu Sans Mono" - property string fontBillboard: "Inter" + property real fontDefaultScale: 1.0 + property real fontFixedScale: 1.0 property list monitorsScaling: [] property bool idleInhibitorEnabled: false } diff --git a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml index a7895e47..5e6a7109 100644 --- a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml +++ b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml @@ -22,7 +22,7 @@ ColumnLayout { NText { text: root.label - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mSecondary font.weight: Style.fontWeightMedium Layout.fillWidth: true @@ -79,7 +79,7 @@ ColumnLayout { // Device name NText { text: modelData.name || modelData.deviceName - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium elide: Text.ElideRight color: getContentColor(Color.mOnSurface) @@ -90,7 +90,7 @@ ColumnLayout { NText { text: BluetoothService.getStatusString(modelData) visible: text !== "" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: getContentColor(Color.mOnSurfaceVariant) } @@ -103,7 +103,7 @@ ColumnLayout { // Device signal strength - "Unknown" when not connected NText { text: BluetoothService.getSignalStrength(modelData) - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: getContentColor(Color.mOnSurfaceVariant) } @@ -117,7 +117,7 @@ ColumnLayout { NText { visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked text: (modelData.signalStrength !== undefined && modelData.signalStrength > 0) ? modelData.signalStrength + "%" : "" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: getContentColor(Color.mOnSurface) } } @@ -126,7 +126,7 @@ ColumnLayout { NText { visible: modelData.batteryAvailable text: BluetoothService.getBattery(modelData) - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: getContentColor(Color.mOnSurfaceVariant) } } diff --git a/Modules/Bar/Bluetooth/BluetoothPanel.qml b/Modules/Bar/Bluetooth/BluetoothPanel.qml index c625f1f1..46ad2046 100644 --- a/Modules/Bar/Bluetooth/BluetoothPanel.qml +++ b/Modules/Bar/Bluetooth/BluetoothPanel.qml @@ -36,7 +36,7 @@ NPanel { NText { text: I18n.tr("bluetooth.panel.title") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface Layout.fillWidth: true @@ -95,14 +95,14 @@ NPanel { NText { text: I18n.tr("bluetooth.panel.disabled") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { text: I18n.tr("bluetooth.panel.enable-message") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } @@ -200,14 +200,14 @@ NPanel { NText { text: I18n.tr("bluetooth.panel.scanning") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurface } } NText { text: I18n.tr("bluetooth.panel.pairing-mode") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } diff --git a/Modules/Bar/Calendar/CalendarPanel.qml b/Modules/Bar/Calendar/CalendarPanel.qml index ac70310c..8fedb3b9 100644 --- a/Modules/Bar/Calendar/CalendarPanel.qml +++ b/Modules/Bar/Calendar/CalendarPanel.qml @@ -43,7 +43,7 @@ NPanel { text: grid.title Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: Color.mPrimary } @@ -83,7 +83,7 @@ NPanel { anchors.centerIn: parent text: I18n.tr("calendar.panel.week") color: Color.mOutline - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling font.weight: Style.fontWeightRegular horizontalAlignment: Text.AlignHCenter } @@ -113,7 +113,7 @@ NPanel { return Qt.locale().dayName(dayIndex, Locale.ShortFormat) } color: Color.mSecondary - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold horizontalAlignment: Text.AlignHCenter } @@ -148,7 +148,7 @@ NPanel { NText { anchors.centerIn: parent color: Color.mOutline - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling font.weight: Style.fontWeightBold text: { // Calculate the date shown in the first column of this row @@ -229,7 +229,7 @@ NPanel { text: model.day color: model.today ? Color.mOnPrimary : Color.mOnSurface opacity: model.month === grid.month ? Style.opacityHeavy : Style.opacityLight - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: model.today ? Style.fontWeightBold : Style.fontWeightRegular } diff --git a/Modules/Bar/Extras/BarPillHorizontal.qml b/Modules/Bar/Extras/BarPillHorizontal.qml index f3dac570..2bdd1f1d 100644 --- a/Modules/Bar/Extras/BarPillHorizontal.qml +++ b/Modules/Bar/Extras/BarPillHorizontal.qml @@ -84,8 +84,8 @@ Item { return centerX + offset } text: root.text + root.suffix - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightBold color: forceOpen ? Color.mOnSurface : Color.mPrimary visible: revealed diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml index aeb89f49..5bdf75c3 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Modules/Bar/Extras/BarPillVertical.qml @@ -98,8 +98,8 @@ Item { return offset } text: root.text + root.suffix - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/Modules/Bar/Extras/TrayMenu.qml b/Modules/Bar/Extras/TrayMenu.qml index 8753deb8..415333fd 100644 --- a/Modules/Bar/Extras/TrayMenu.qml +++ b/Modules/Bar/Extras/TrayMenu.qml @@ -160,7 +160,7 @@ PopupWindow { Layout.fillWidth: true color: (modelData?.enabled ?? true) ? (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) : Color.mOnSurfaceVariant text: modelData?.text !== "" ? modelData?.text.replace(/[\n\r]+/g, ' ') : "..." - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap } @@ -175,7 +175,7 @@ PopupWindow { NIcon { icon: modelData?.hasChildren ? "menu" : "" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling verticalAlignment: Text.AlignVCenter visible: modelData?.hasChildren ?? false color: (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) diff --git a/Modules/Bar/WiFi/WiFiPanel.qml b/Modules/Bar/WiFi/WiFiPanel.qml index ebb8a0b7..e205e8be 100644 --- a/Modules/Bar/WiFi/WiFiPanel.qml +++ b/Modules/Bar/WiFi/WiFiPanel.qml @@ -41,7 +41,7 @@ NPanel { NText { text: I18n.tr("wifi.panel.title") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface Layout.fillWidth: true @@ -99,7 +99,7 @@ NPanel { NText { text: NetworkService.lastError color: Color.mError - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling wrapMode: Text.Wrap Layout.fillWidth: true } @@ -137,14 +137,14 @@ NPanel { NText { text: I18n.tr("wifi.panel.disabled") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { text: I18n.tr("wifi.panel.enable-message") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } @@ -173,7 +173,7 @@ NPanel { NText { text: I18n.tr("wifi.panel.searching") - font.pointSize: Style.fontSizeNormal * scaling + pointSize: Style.fontSizeNormal * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } @@ -252,7 +252,7 @@ NPanel { NText { text: modelData.ssid - font.pointSize: Style.fontSizeNormal * scaling + pointSize: Style.fontSizeNormal * scaling font.weight: modelData.connected ? Style.fontWeightBold : Style.fontWeightMedium color: Color.mOnSurface elide: Text.ElideRight @@ -266,19 +266,19 @@ NPanel { text: I18n.tr("system.signal-strength", { "signal": modelData.signal }) - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } NText { text: "•" - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } NText { text: NetworkService.isSecured(modelData.security) ? modelData.security : "Open" - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } @@ -298,7 +298,7 @@ NPanel { id: connectedText anchors.centerIn: parent text: I18n.tr("wifi.panel.connected") - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } } @@ -314,7 +314,7 @@ NPanel { id: disconnectingText anchors.centerIn: parent text: I18n.tr("wifi.panel.disconnecting") - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } } @@ -330,7 +330,7 @@ NPanel { id: forgettingText anchors.centerIn: parent text: I18n.tr("wifi.panel.forgetting") - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } } @@ -348,7 +348,7 @@ NPanel { id: savedText anchors.centerIn: parent text: I18n.tr("wifi.panel.saved") - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } } @@ -456,12 +456,12 @@ NPanel { } } - Text { + NText { visible: parent.text.length === 0 anchors.verticalCenter: parent.verticalCenter text: I18n.tr("wifi.panel.enter-password") color: Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling } } } @@ -514,7 +514,7 @@ NPanel { NText { text: I18n.tr("wifi.panel.forget-network") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mError Layout.fillWidth: true } @@ -564,7 +564,7 @@ NPanel { NText { text: I18n.tr("wifi.panel.no-networks") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index 2dbccdbc..711ab18c 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -108,7 +108,7 @@ Item { id: fullTitleMetrics visible: false text: windowTitle - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightMedium } @@ -245,7 +245,7 @@ Item { NText { id: titleText text: windowTitle - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightMedium verticalAlignment: Text.AlignVCenter color: Color.mOnSurface diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index 14e1f4df..810d2b9f 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -65,8 +65,8 @@ Rectangle { NText { visible: text !== "" text: modelData - font.family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault - font.pointSize: { + family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault + pointSize: { if (repeater.model.length == 1) { return Style.fontSizeS * scaling } else { @@ -95,8 +95,8 @@ Rectangle { delegate: NText { visible: text !== "" text: modelData - font.family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault - font.pointSize: Style.fontSizeS * scaling + family: useMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightBold color: usePrimaryColor ? Color.mPrimary : Color.mOnSurface wrapMode: Text.WordWrap diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 2b5348da..98aadcdd 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -275,7 +275,7 @@ Item { NText { id: titleText text: getTitle() - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightMedium verticalAlignment: Text.AlignVCenter color: Color.mOnSurface diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index 2376af86..2d9f47e9 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -114,8 +114,8 @@ Rectangle { NText { text: `${Math.round(SystemStatService.cpuUsage)}%` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : percentTextWidth @@ -155,8 +155,8 @@ Rectangle { NText { text: `${Math.round(SystemStatService.cpuTemp)}°` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : tempTextWidth @@ -196,8 +196,8 @@ Rectangle { NText { text: showMemoryAsPercent ? `${Math.round(SystemStatService.memPercent)}%` : `${SystemStatService.memGb.toFixed(1)}G` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : (showMemoryAsPercent ? percentTextWidth : memTextWidth) @@ -237,8 +237,8 @@ Rectangle { NText { text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.rxSpeed) : SystemStatService.formatSpeed(SystemStatService.rxSpeed) - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : memTextWidth @@ -278,8 +278,8 @@ Rectangle { NText { text: isVertical ? SystemStatService.formatCompactSpeed(SystemStatService.txSpeed) : SystemStatService.formatSpeed(SystemStatService.txSpeed) - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : memTextWidth @@ -319,8 +319,8 @@ Rectangle { NText { text: `${SystemStatService.diskPercent}%` - font.family: Settings.data.ui.fontFixed - font.pointSize: textSize + family: Settings.data.ui.fontFixed + pointSize: textSize font.weight: Style.fontWeightMedium Layout.alignment: Qt.AlignCenter Layout.preferredWidth: isVertical ? -1 : percentTextWidth diff --git a/Modules/Bar/Widgets/Workspace.qml b/Modules/Bar/Widgets/Workspace.qml index 33c1f580..689b962f 100644 --- a/Modules/Bar/Widgets/Workspace.qml +++ b/Modules/Bar/Widgets/Workspace.qml @@ -7,6 +7,7 @@ import Quickshell import Quickshell.Io import qs.Commons import qs.Services +import qs.Widgets Item { id: root @@ -274,7 +275,7 @@ Item { Loader { active: (labelMode !== "none") sourceComponent: Component { - Text { + NText { x: (pill.width - width) / 2 y: (pill.height - height) / 2 + (height - contentHeight) / 2 text: { @@ -284,9 +285,9 @@ Item { return model.idx.toString() } } - font.pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42 + family: Settings.data.ui.fontFixed + pointSize: model.isFocused ? workspacePillContainer.height * 0.45 : workspacePillContainer.height * 0.42 font.capitalization: Font.AllUppercase - font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightBold wrapMode: Text.Wrap color: { @@ -418,7 +419,7 @@ Item { Loader { active: (labelMode !== "none") sourceComponent: Component { - Text { + NText { x: (pillVertical.width - width) / 2 y: (pillVertical.height - height) / 2 + (height - contentHeight) / 2 text: { @@ -428,9 +429,9 @@ Item { return model.idx.toString() } } - font.pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42 + family: Settings.data.ui.fontFixed + pointSize: model.isFocused ? workspacePillContainerVertical.width * 0.45 : workspacePillContainerVertical.width * 0.42 font.capitalization: Font.AllUppercase - font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightBold wrapMode: Text.Wrap color: { diff --git a/Modules/ControlCenter/Cards/MediaCard.qml b/Modules/ControlCenter/Cards/MediaCard.qml index 032eb106..da223e5b 100644 --- a/Modules/ControlCenter/Cards/MediaCard.qml +++ b/Modules/ControlCenter/Cards/MediaCard.qml @@ -74,7 +74,7 @@ NBox { NText { text: playerSelectorButton.currentPlayer ? playerSelectorButton.currentPlayer.identity : "" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant Layout.fillWidth: true } @@ -162,7 +162,7 @@ NBox { NText { visible: MediaService.trackTitle !== "" text: MediaService.trackTitle - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold elide: Text.ElideRight wrapMode: Text.Wrap @@ -174,7 +174,7 @@ NBox { visible: MediaService.trackArtist !== "" text: MediaService.trackArtist color: Color.mPrimary - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling elide: Text.ElideRight Layout.fillWidth: true } @@ -183,7 +183,7 @@ NBox { visible: MediaService.trackAlbum !== "" text: MediaService.trackAlbum color: Color.mOnSurface - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling elide: Text.ElideRight Layout.fillWidth: true } diff --git a/Modules/ControlCenter/Cards/ProfileCard.qml b/Modules/ControlCenter/Cards/ProfileCard.qml index 9b619edf..6728ef7f 100644 --- a/Modules/ControlCenter/Cards/ProfileCard.qml +++ b/Modules/ControlCenter/Cards/ProfileCard.qml @@ -45,7 +45,7 @@ NBox { text: I18n.tr("system.uptime", { "uptime": uptimeText }) - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant } } diff --git a/Modules/ControlCenter/Cards/WeatherCard.qml b/Modules/ControlCenter/Cards/WeatherCard.qml index a5cf8f45..1bda1b82 100644 --- a/Modules/ControlCenter/Cards/WeatherCard.qml +++ b/Modules/ControlCenter/Cards/WeatherCard.qml @@ -36,7 +36,7 @@ NBox { const chunks = Settings.data.location.name.split(",") return chunks[0] } - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold } @@ -56,13 +56,13 @@ NBox { temp = Math.round(temp) return `${temp}°${suffix}` } - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold } NText { text: weatherReady ? `(${LocationService.data.weather.timezone_abbreviation})` : "" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant visible: LocationService.data.weather } @@ -112,7 +112,7 @@ NBox { min = Math.round(min) return `${max}°/${min}°` } - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } } diff --git a/Modules/Dock/DockMenu.qml b/Modules/Dock/DockMenu.qml index ffd30a24..90388e3a 100644 --- a/Modules/Dock/DockMenu.qml +++ b/Modules/Dock/DockMenu.qml @@ -196,7 +196,7 @@ PopupWindow { NText { text: I18n.tr("dock.menu.focus") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -233,7 +233,7 @@ PopupWindow { return I18n.tr("dock.menu.pin") return root.isAppPinned(root.toplevel.appId) ? I18n.tr("dock.menu.unpin") : I18n.tr("dock.menu.pin") } - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -262,7 +262,7 @@ PopupWindow { NText { text: I18n.tr("dock.menu.close") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index e79bee6b..195512fd 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -438,7 +438,7 @@ NPanel { anchors.centerIn: parent visible: !imagePreview.visible && !iconLoader.visible text: modelData.name ? modelData.name.charAt(0).toUpperCase() : "?" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling font.weight: Style.fontWeightBold color: Color.mOnPrimary } @@ -464,7 +464,7 @@ NPanel { const parts = desc.split(" • ") return parts[0] || "IMG" } - font.pointSize: Style.fontSizeXXS * scaling + pointSize: Style.fontSizeXXS * scaling color: Color.mPrimary } } @@ -477,7 +477,7 @@ NPanel { NText { text: modelData.name || "Unknown" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurface elide: Text.ElideRight @@ -486,7 +486,7 @@ NPanel { NText { text: modelData.description || "" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant elide: Text.ElideRight Layout.fillWidth: true @@ -536,7 +536,7 @@ NPanel { const prefix = activePlugin?.name ? `${activePlugin.name}: ` : "" return prefix + `${results.length} result${results.length !== 1 ? 's' : ''}` } - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignCenter } diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index bdb5f4f4..de7bdc21 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -147,9 +147,8 @@ Loader { NText { id: timeText text: formatTime() - font.family: Settings.data.ui.fontBillboard // Smaller time display when using longer 12 hour format - font.pointSize: Settings.data.location.use12hourFormat ? Style.fontSizeXXXL * 4 * scaling : Style.fontSizeXXXL * 5 * scaling + pointSize: Settings.data.location.use12hourFormat ? Style.fontSizeXXXL * 4 * scaling : Style.fontSizeXXXL * 5 * scaling font.weight: Style.fontWeightBold font.letterSpacing: -2 * scaling color: Color.mOnSurface @@ -174,8 +173,7 @@ Loader { NText { id: dateText text: formatDate() - font.family: Settings.data.ui.fontBillboard - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling font.weight: Font.Light color: Color.mOnSurface horizontalAlignment: Text.AlignHCenter @@ -385,8 +383,8 @@ Loader { NText { text: I18n.tr("lock-screen.secure-terminal") color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold Layout.fillWidth: true } @@ -396,8 +394,8 @@ Loader { NText { text: keyboardLayout.currentLayout color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold } NIcon { @@ -419,8 +417,8 @@ Loader { NText { text: Math.round(batteryIndicator.percent) + "%" color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold } } @@ -443,8 +441,8 @@ Loader { NText { text: Quickshell.env("USER") + "@noctalia:~$" color: Color.mPrimary - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold } @@ -452,8 +450,8 @@ Loader { id: welcomeText text: "" color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling property int currentIndex: 0 property string fullText: I18n.tr("system.welcome-back", { "user": Quickshell.env("USER") @@ -482,16 +480,16 @@ Loader { NText { text: Quickshell.env("USER") + "@noctalia:~$" color: Color.mPrimary - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold } NText { text: I18n.tr("lock-screen.unlock-command") color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling } } @@ -502,8 +500,8 @@ Loader { NText { text: I18n.tr("lock-screen.password") color: Color.mPrimary - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold } @@ -545,8 +543,8 @@ Loader { id: asterisksText text: "*".repeat(passwordInput.text.length) color: Color.mOnSurface - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling visible: passwordInput.activeFocus && !lockContext.unlockInProgress anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter @@ -612,8 +610,7 @@ Loader { return Color.mError return Color.transparent } - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling Layout.fillWidth: true SequentialAnimation on opacity { @@ -647,8 +644,8 @@ Loader { anchors.centerIn: parent text: lockContext.unlockInProgress ? "EXECUTING" : "EXECUTE" color: executeButtonArea.containsMouse ? Color.mOnPrimary : Color.mPrimary - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold } @@ -767,8 +764,8 @@ Loader { text: messages[index % messages.length] color: Color.mError - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeXXL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeXXL * scaling font.weight: Style.fontWeightBold x: baseX @@ -905,7 +902,7 @@ Loader { anchors.margins: Style.marginM * scaling anchors.fill: parent text: I18n.tr("lock-screen.shut-down") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -957,7 +954,7 @@ Loader { anchors.margins: Style.marginM * scaling anchors.fill: parent text: I18n.tr("lock-screen.restart") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -1010,7 +1007,7 @@ Loader { anchors.margins: Style.marginM * scaling anchors.fill: parent text: I18n.tr("lock-screen.suspend") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index bb868bd6..3ffe05e2 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -307,7 +307,7 @@ Variants { NText { text: `${model.appName || I18n.tr("system.unknown-app")} · ${Time.formatRelativeTime(model.timestamp)}` color: Color.mSecondary - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling } Item { @@ -317,7 +317,7 @@ Variants { NText { text: model.summary || I18n.tr("general.no-summary") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface textFormat: Text.PlainText @@ -330,7 +330,7 @@ Variants { NText { text: model.body || "" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurface textFormat: Text.PlainText wrapMode: Text.WrapAtWordBoundaryOrAnywhere diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index f5bd43d7..5b0f5627 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -38,7 +38,7 @@ NPanel { NText { text: I18n.tr("notifications.panel.title") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface Layout.fillWidth: true @@ -95,14 +95,14 @@ NPanel { NText { text: I18n.tr("notifications.panel.no-notifications") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { text: I18n.tr("notifications.panel.description") - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true @@ -199,13 +199,13 @@ NPanel { NText { text: model.appName || "Unknown App" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mSecondary } NText { text: Time.formatRelativeTime(model.timestamp) - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mSecondary } @@ -217,7 +217,7 @@ NPanel { // Summary NText { text: model.summary || I18n.tr("general.no-summary") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Font.Medium color: Color.mOnSurface textFormat: Text.PlainText @@ -230,7 +230,7 @@ NPanel { // Body NText { text: model.body || "" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant textFormat: Text.PlainText wrapMode: Text.Wrap diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index e518cf89..8b33101b 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -299,8 +299,8 @@ Variants { NText { text: root.getDisplayPercentage() color: Color.mOnSurface - font.pointSize: Style.fontSizeS * root.scaling - font.family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeS * root.scaling + family: Settings.data.ui.fontFixed Layout.alignment: Qt.AlignVCenter horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter @@ -340,8 +340,8 @@ Variants { id: percentText text: root.getDisplayPercentage() color: Color.mOnSurface - font.pointSize: Style.fontSizeS * root.scaling - font.family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeS * root.scaling + family: Settings.data.ui.fontFixed anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter horizontalAlignment: Text.AlignHCenter diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index 885b43ed..e48ab0d5 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -276,7 +276,7 @@ NPanel { "seconds": Math.ceil(timeRemaining / 1000) }) : I18n.tr("session-menu.title") font.weight: Style.fontWeightBold - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: timerActive ? Color.mPrimary : Color.mOnSurface Layout.alignment: Qt.AlignVCenter verticalAlignment: Text.AlignVCenter @@ -409,7 +409,7 @@ NPanel { NText { text: buttonRoot.title font.weight: Style.fontWeightMedium - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: { if (buttonRoot.pending) return Color.mPrimary @@ -434,7 +434,7 @@ NPanel { } return buttonRoot.subtitle } - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: { if (buttonRoot.pending) return Color.mPrimary @@ -464,7 +464,7 @@ NPanel { NText { anchors.centerIn: parent text: Math.ceil(timeRemaining / 1000) - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightBold color: Color.mOnPrimary } diff --git a/Modules/Settings/Bar/BarSectionEditor.qml b/Modules/Settings/Bar/BarSectionEditor.qml index b1b9e10d..ba587246 100644 --- a/Modules/Settings/Bar/BarSectionEditor.qml +++ b/Modules/Settings/Bar/BarSectionEditor.qml @@ -70,7 +70,7 @@ NBox { NText { text: sectionName + " Section" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface Layout.alignment: Qt.AlignVCenter @@ -225,7 +225,7 @@ NBox { NText { text: modelData.id - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: root.getWidgetColor(modelData)[1] horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight @@ -312,10 +312,10 @@ NBox { z: 2000 clip: false // Ensure ghost isn't clipped - Text { + NText { id: ghostText anchors.centerIn: parent - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnPrimary } } diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index 4e52bc68..1c2a1aaf 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -61,7 +61,7 @@ Popup { text: I18n.tr("system.widget-settings-title", { "widget": widgetSettings.widgetId }) - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary Layout.fillWidth: true diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index af48201a..fe3f1e73 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -186,8 +186,8 @@ ColumnLayout { delegate: NText { visible: text !== "" text: modelData - font.family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault - font.pointSize: Style.fontSizeM * scaling + family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: valueUsePrimaryColor ? Color.mPrimary : Color.mOnSurface wrapMode: Text.WordWrap @@ -217,8 +217,8 @@ ColumnLayout { delegate: NText { visible: text !== "" text: modelData - font.family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault - font.pointSize: Style.fontSizeM * scaling + family: valueUseMonospacedFont ? Settings.data.ui.fontFixed : Settings.data.ui.fontDefault + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: valueUsePrimaryColor ? Color.mPrimary : Color.mOnSurface wrapMode: Text.WordWrap diff --git a/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml b/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml index cd44b941..ac4ae04c 100644 --- a/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml @@ -59,7 +59,7 @@ ColumnLayout { NIcon { Layout.alignment: Qt.AlignVCenter icon: valueIcon - font.pointSize: Style.fontSizeXXL * 1.5 * scaling + pointSize: Style.fontSizeXXL * 1.5 * scaling visible: valueIcon !== "" && valueCustomIconPath === "" } } diff --git a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index 9c7aaed0..0520740f 100644 --- a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -37,7 +37,7 @@ ColumnLayout { NIcon { Layout.alignment: Qt.AlignVCenter icon: valueIcon - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling visible: valueIcon !== "" } diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 266f8667..4a5706b8 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -403,7 +403,7 @@ NPanel { NText { text: I18n.tr(modelData.label) color: tabTextColor - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter @@ -462,7 +462,7 @@ NPanel { // Main title NText { text: I18n.tr(root.tabsModel[currentTabIndex]?.label) || "" - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary Layout.fillWidth: true diff --git a/Modules/Settings/Tabs/AboutTab.qml b/Modules/Settings/Tabs/AboutTab.qml index 1a4610d7..22566118 100644 --- a/Modules/Settings/Tabs/AboutTab.qml +++ b/Modules/Settings/Tabs/AboutTab.qml @@ -98,7 +98,7 @@ ColumnLayout { NText { id: updateText text: I18n.tr("settings.about.noctalia.download-latest") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: updateArea.containsMouse ? Color.mSurface : Color.mPrimary } } @@ -200,7 +200,7 @@ ColumnLayout { NText { text: (modelData.contributions || 0) + " " + ((modelData.contributions || 0) === 1 ? "commit" : "commits") - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: contributorArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface } } diff --git a/Modules/Settings/Tabs/AudioTab.qml b/Modules/Settings/Tabs/AudioTab.qml index d15060a9..e4f70407 100644 --- a/Modules/Settings/Tabs/AudioTab.qml +++ b/Modules/Settings/Tabs/AudioTab.qml @@ -309,7 +309,7 @@ ColumnLayout { NText { text: modelData color: Color.mOnSurface - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling Layout.alignment: Qt.AlignVCenter Layout.leftMargin: Style.marginS * scaling } diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 454db34f..31405f5c 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -140,7 +140,7 @@ ColumnLayout { NText { text: I18n.tr("settings.bar.appearance.margins.vertical") - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } @@ -160,7 +160,7 @@ ColumnLayout { NText { text: I18n.tr("settings.bar.appearance.margins.horizontal") - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index 57f3d399..b57f0041 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -261,7 +261,7 @@ ColumnLayout { var chunks = schemePath.replace(".json", "").split("/") return chunks[chunks.length - 1] } - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: getSchemeColor(modelData, "mOnSurface") Layout.fillWidth: true diff --git a/Modules/Settings/Tabs/DisplayTab.qml b/Modules/Settings/Tabs/DisplayTab.qml index e4431285..d2f50dd2 100644 --- a/Modules/Settings/Tabs/DisplayTab.qml +++ b/Modules/Settings/Tabs/DisplayTab.qml @@ -174,7 +174,7 @@ ColumnLayout { // Method text positioned in the button area NText { text: brightnessMonitor ? brightnessMonitor.method : "" - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter @@ -186,22 +186,18 @@ ColumnLayout { } } } - // Brightness Step Section - ColumnLayout { - spacing: Style.marginS * scaling - Layout.fillWidth: true - NSpinBox { - Layout.fillWidth: true - label: I18n.tr("settings.display.monitors.brightness-step.label") - description: I18n.tr("settings.display.monitors.brightness-step.description") - minimum: 1 - maximum: 50 - value: Settings.data.brightness.brightnessStep - stepSize: 1 - suffix: "%" - onValueChanged: Settings.data.brightness.brightnessStep = value - } + // Brightness Step + NSpinBox { + Layout.fillWidth: true + label: I18n.tr("settings.display.monitors.brightness-step.label") + description: I18n.tr("settings.display.monitors.brightness-step.description") + minimum: 1 + maximum: 50 + value: Settings.data.brightness.brightnessStep + stepSize: 1 + suffix: "%" + onValueChanged: Settings.data.brightness.brightnessStep = value } } @@ -258,7 +254,7 @@ ColumnLayout { NText { text: I18n.tr("settings.display.night-light.temperature.night") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -280,7 +276,7 @@ ColumnLayout { NText { text: I18n.tr("settings.display.night-light.temperature.day") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -327,7 +323,7 @@ ColumnLayout { NText { text: I18n.tr("settings.display.night-light.manual-schedule.sunrise") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant } @@ -345,7 +341,7 @@ ColumnLayout { NText { text: I18n.tr("settings.display.night-light.manual-schedule.sunset") - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant } diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index c5f20cc2..45be5b9c 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -187,6 +187,7 @@ ColumnLayout { } } } + NDivider { Layout.fillWidth: true Layout.topMargin: Style.marginXL * scaling @@ -236,17 +237,37 @@ ColumnLayout { } } - NSearchableComboBox { - label: I18n.tr("settings.general.fonts.accent.label") - description: I18n.tr("settings.general.fonts.accent.description") - model: FontService.displayFonts - currentKey: Settings.data.ui.fontBillboard - placeholder: I18n.tr("settings.general.fonts.accent.placeholder") - searchPlaceholder: I18n.tr("settings.general.fonts.accent.search-placeholder") - popupHeight: 320 * scaling - minimumWidth: 300 * scaling - onSelected: function (key) { - Settings.data.ui.fontBillboard = key + ColumnLayout { + NLabel { + label: I18n.tr("settings.general.fonts.default.scale.label") + description: I18n.tr("settings.general.fonts.default.scale.description") + } + + NValueSlider { + Layout.fillWidth: true + from: 0.75 + to: 1.25 + stepSize: 0.01 + value: Settings.data.ui.fontDefaultScale + onMoved: value => Settings.data.ui.fontDefaultScale = value + text: Math.floor(Settings.data.ui.fontDefaultScale * 100) + "%" + } + } + + ColumnLayout { + NLabel { + label: I18n.tr("settings.general.fonts.monospace.scale.label") + description: I18n.tr("settings.general.fonts.monospace.scale.description") + } + + NValueSlider { + Layout.fillWidth: true + from: 0.75 + to: 1.25 + stepSize: 0.01 + value: Settings.data.ui.fontFixedScale + onMoved: value => Settings.data.ui.fontFixedScale = value + text: Math.floor(Settings.data.ui.fontFixedScale * 100) + "%" } } } diff --git a/Modules/Settings/Tabs/LauncherTab.qml b/Modules/Settings/Tabs/LauncherTab.qml index 1a77f880..ea9df35b 100644 --- a/Modules/Settings/Tabs/LauncherTab.qml +++ b/Modules/Settings/Tabs/LauncherTab.qml @@ -53,14 +53,14 @@ ColumnLayout { NText { text: I18n.tr("settings.launcher.settings.background-opacity.label") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface } NText { text: I18n.tr("settings.launcher.settings.background-opacity.description") - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant wrapMode: Text.WordWrap Layout.fillWidth: true diff --git a/Modules/Settings/Tabs/LocationTab.qml b/Modules/Settings/Tabs/LocationTab.qml index eafa3902..769735d2 100644 --- a/Modules/Settings/Tabs/LocationTab.qml +++ b/Modules/Settings/Tabs/LocationTab.qml @@ -46,7 +46,7 @@ ColumnLayout { "name": LocationService.stableName, "coordinates": LocationService.displayCoordinates }) - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignRight diff --git a/Modules/Settings/Tabs/WallpaperTab.qml b/Modules/Settings/Tabs/WallpaperTab.qml index 742849b9..ad1ee6b1 100644 --- a/Modules/Settings/Tabs/WallpaperTab.qml +++ b/Modules/Settings/Tabs/WallpaperTab.qml @@ -77,7 +77,7 @@ ColumnLayout { text: (modelData.name || "Unknown") color: Color.mPrimary font.weight: Style.fontWeightBold - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling } NTextInputButton { @@ -327,7 +327,7 @@ ColumnLayout { id: chipLabel anchors.centerIn: parent text: parent.label - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: parent.selected ? Color.mOnPrimary : Color.mOnSurface } } diff --git a/Modules/Toast/SimpleToast.qml b/Modules/Toast/SimpleToast.qml index 2d8bdf70..cde497ce 100644 --- a/Modules/Toast/SimpleToast.qml +++ b/Modules/Toast/SimpleToast.qml @@ -114,7 +114,7 @@ Rectangle { Layout.fillWidth: true text: root.message color: Color.mOnSurface - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold wrapMode: Text.WordWrap visible: text.length > 0 @@ -124,7 +124,7 @@ Rectangle { Layout.fillWidth: true text: root.description color: Color.mOnSurface - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling wrapMode: Text.WordWrap visible: text.length > 0 } diff --git a/Modules/Tooltip/Tooltip.qml b/Modules/Tooltip/Tooltip.qml index 68648084..ded2b479 100644 --- a/Modules/Tooltip/Tooltip.qml +++ b/Modules/Tooltip/Tooltip.qml @@ -386,7 +386,7 @@ PopupWindow { anchors.centerIn: parent anchors.margins: root.padding * root.scaling text: root.text - font.pointSize: Style.fontSizeS * root.scaling + pointSize: Style.fontSizeS * root.scaling color: Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 4a8f8148..1d7095b9 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -58,7 +58,7 @@ NPanel { NText { text: I18n.tr("wallpaper.panel.title") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface Layout.fillWidth: true @@ -134,11 +134,11 @@ NPanel { } } - contentItem: Text { + contentItem: NText { text: parent.text - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: screenTabBar.currentIndex === index ? Style.fontWeightBold : Style.fontWeightRegular - font.family: Settings.data.ui.fontDefault + family: Settings.data.ui.fontDefault color: screenTabBar.currentIndex === index ? Color.mOnSecondary : Color.mOnSurfaceVariant horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -189,7 +189,7 @@ NPanel { NText { text: I18n.tr("wallpaper.panel.search") color: Color.mOnSurface - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling Layout.preferredWidth: implicitWidth } @@ -405,7 +405,7 @@ NPanel { text: filename color: Color.mOnSurfaceVariant opacity: 0.5 - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling Layout.fillWidth: true Layout.leftMargin: Style.marginS * scaling Layout.rightMargin: Style.marginS * scaling diff --git a/Widgets/NButton.qml b/Widgets/NButton.qml index df48655e..d6f6335e 100644 --- a/Widgets/NButton.qml +++ b/Widgets/NButton.qml @@ -78,7 +78,6 @@ Rectangle { NIcon { Layout.alignment: Qt.AlignVCenter visible: root.icon !== "" - icon: root.icon font.pointSize: root.iconSize color: { @@ -105,7 +104,7 @@ Rectangle { Layout.alignment: Qt.AlignVCenter visible: root.text !== "" text: root.text - font.pointSize: root.fontSize + pointSize: root.fontSize font.weight: root.fontWeight color: { if (!root.enabled) diff --git a/Widgets/NCircleStat.qml b/Widgets/NCircleStat.qml index 16e6e0a9..074ea51d 100644 --- a/Widgets/NCircleStat.qml +++ b/Widgets/NCircleStat.qml @@ -79,7 +79,7 @@ Rectangle { id: valueLabel anchors.centerIn: parent text: `${root.value}${root.suffix}` - font.pointSize: Style.fontSizeM * scaling * contentScale + pointSize: Style.fontSizeM * scaling * contentScale font.weight: Style.fontWeightBold color: Color.mOnSurface horizontalAlignment: Text.AlignHCenter diff --git a/Widgets/NCollapsible.qml b/Widgets/NCollapsible.qml index 1403cf39..6cc4b34b 100644 --- a/Widgets/NCollapsible.qml +++ b/Widgets/NCollapsible.qml @@ -109,7 +109,7 @@ ColumnLayout { NText { text: root.label - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightSemiBold color: root.expanded ? Color.mOnSecondary : Color.mOnSurface Layout.fillWidth: true @@ -124,7 +124,7 @@ ColumnLayout { NText { text: root.description - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightRegular color: root.expanded ? Color.mOnSecondary : Color.mOnSurfaceVariant Layout.fillWidth: true diff --git a/Widgets/NColorPicker.qml b/Widgets/NColorPicker.qml index 8eee16ba..642d74a9 100644 --- a/Widgets/NColorPicker.qml +++ b/Widgets/NColorPicker.qml @@ -58,7 +58,7 @@ Rectangle { NText { text: root.selectedColor.toString().toUpperCase() - font.family: Settings.data.ui.fontFixed + family: Settings.data.ui.fontFixed Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter } diff --git a/Widgets/NColorPickerDialog.qml b/Widgets/NColorPickerDialog.qml index 7c823444..3165922e 100644 --- a/Widgets/NColorPickerDialog.qml +++ b/Widgets/NColorPickerDialog.qml @@ -138,13 +138,13 @@ Popup { NIcon { icon: "color-picker" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mPrimary } NText { text: I18n.tr("widgets.color-picker.title") - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary } @@ -179,8 +179,8 @@ Popup { NText { text: root.selectedColor.toString().toUpperCase() - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeL * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeL * scaling font.weight: Font.Bold color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? "#000000" : "#FFFFFF" Layout.alignment: Qt.AlignHCenter @@ -188,8 +188,8 @@ Popup { NText { text: "RGB(" + Math.round(root.selectedColor.r * 255) + ", " + Math.round(root.selectedColor.g * 255) + ", " + Math.round(root.selectedColor.b * 255) + ")" - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling color: root.selectedColor.r + root.selectedColor.g + root.selectedColor.b > 1.5 ? "#000000" : "#FFFFFF" Layout.alignment: Qt.AlignHCenter } diff --git a/Widgets/NComboBox.qml b/Widgets/NComboBox.qml index 6035b620..c8d746cd 100644 --- a/Widgets/NComboBox.qml +++ b/Widgets/NComboBox.qml @@ -89,7 +89,7 @@ RowLayout { contentItem: NText { leftPadding: Style.marginL * scaling rightPadding: combo.indicator.width + Style.marginL * scaling - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling verticalAlignment: Text.AlignVCenter elide: Text.ElideRight color: (combo.currentIndex >= 0 && combo.currentIndex < itemCount()) ? Color.mOnSurface : Color.mOnSurfaceVariant @@ -159,7 +159,7 @@ RowLayout { var item = root.getItem(index) return item && item.name ? item.name : "" } - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: highlighted ? Color.mOnTertiary : Color.mOnSurface verticalAlignment: Text.AlignVCenter elide: Text.ElideRight diff --git a/Widgets/NContextMenu.qml b/Widgets/NContextMenu.qml index a1b7562c..e5bebeee 100644 --- a/Widgets/NContextMenu.qml +++ b/Widgets/NContextMenu.qml @@ -75,7 +75,7 @@ Popup { NText { text: modelData.label || modelData.text || "" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: menuItem.hovered && menuItem.enabled ? Color.mOnTertiary : Color.mOnSurface verticalAlignment: Text.AlignVCenter Layout.fillWidth: true diff --git a/Widgets/NDateTimeTokens.qml b/Widgets/NDateTimeTokens.qml index eae75d7b..1ad1ec94 100644 --- a/Widgets/NDateTimeTokens.qml +++ b/Widgets/NDateTimeTokens.qml @@ -238,7 +238,7 @@ Rectangle { anchors.centerIn: parent text: modelData.category color: getCategoryColor(modelData.category)[1] - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling } } @@ -261,7 +261,7 @@ Rectangle { anchors.centerIn: parent text: modelData.token color: tokenMouseArea.containsMouse ? Color.mOnPrimary : Color.mSurface - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightBold Behavior on color { @@ -278,7 +278,7 @@ Rectangle { Layout.alignment: Qt.AlignVCenter // Added this line text: modelData.description color: tokenMouseArea.containsMouse ? Color.mOnSurface : Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling wrapMode: Text.WordWrap Behavior on color { @@ -314,7 +314,7 @@ Rectangle { anchors.centerIn: parent text: Qt.locale().toString(root.sampleDate, modelData.token) color: tokenMouseArea.containsMouse ? Color.mOnPrimary : Color.mSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling Behavior on color { ColorAnimation { diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index d2e2f766..3a9e026c 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -195,7 +195,7 @@ Popup { } NText { text: root.title - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary Layout.fillWidth: true @@ -641,7 +641,7 @@ Popup { else return Color.mOnSurface } - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: isSelected ? Style.fontWeightBold : Style.fontWeightRegular Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter @@ -735,7 +735,7 @@ Popup { NText { text: model.fileName color: filePickerPanel.currentSelection.includes(model.filePath) ? Color.mOnSecondary : Color.mOnSurface - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: filePickerPanel.currentSelection.includes(model.filePath) ? Style.fontWeightBold : Style.fontWeightRegular Layout.fillWidth: true elide: Text.ElideRight @@ -744,7 +744,7 @@ Popup { NText { text: model.fileIsDir ? "" : root.formatFileSize(model.fileSize) color: filePickerPanel.currentSelection.includes(model.filePath) ? Color.mOnSecondary : Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling visible: !model.fileIsDir Layout.preferredWidth: implicitWidth } @@ -810,7 +810,7 @@ Popup { } } color: filePickerPanel.searchText.length > 0 ? Color.mPrimary : Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling Layout.fillWidth: true } diff --git a/Widgets/NHeader.qml b/Widgets/NHeader.qml index f8bd2beb..dfbcfd54 100644 --- a/Widgets/NHeader.qml +++ b/Widgets/NHeader.qml @@ -14,7 +14,7 @@ ColumnLayout { NText { text: root.label - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mSecondary visible: root.label !== "" @@ -22,7 +22,7 @@ ColumnLayout { NText { text: root.description - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant wrapMode: Text.WordWrap Layout.fillWidth: true diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml index d933dfd2..813aa468 100644 --- a/Widgets/NIconPicker.qml +++ b/Widgets/NIconPicker.qml @@ -64,7 +64,7 @@ Popup { Layout.fillWidth: true NText { text: I18n.tr("widgets.icon-picker.title") - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary Layout.fillWidth: true @@ -137,7 +137,7 @@ Popup { NIcon { Layout.alignment: Qt.AlignHCenter icon: modelData - font.pointSize: 42 * scaling + pointSize: 42 * scaling } NText { Layout.alignment: Qt.AlignHCenter @@ -148,7 +148,7 @@ Popup { maximumLineCount: 1 horizontalAlignment: Text.AlignHCenter color: Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling text: modelData } Item { diff --git a/Widgets/NLabel.qml b/Widgets/NLabel.qml index c322e164..8348fd0c 100644 --- a/Widgets/NLabel.qml +++ b/Widgets/NLabel.qml @@ -15,7 +15,7 @@ ColumnLayout { NText { text: label - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: labelColor visible: label !== "" @@ -24,7 +24,7 @@ ColumnLayout { NText { text: description - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: descriptionColor wrapMode: Text.WordWrap visible: description !== "" diff --git a/Widgets/NRadioButton.qml b/Widgets/NRadioButton.qml index 6b71dc37..d04ea777 100644 --- a/Widgets/NRadioButton.qml +++ b/Widgets/NRadioButton.qml @@ -41,7 +41,7 @@ RadioButton { contentItem: NText { text: root.text - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling anchors.verticalCenter: parent.verticalCenter anchors.left: outerCircle.right anchors.right: parent.right diff --git a/Widgets/NSearchableComboBox.qml b/Widgets/NSearchableComboBox.qml index e949405d..736511a3 100644 --- a/Widgets/NSearchableComboBox.qml +++ b/Widgets/NSearchableComboBox.qml @@ -138,7 +138,7 @@ RowLayout { contentItem: NText { leftPadding: Style.marginL * scaling rightPadding: combo.indicator.width + Style.marginL * scaling - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling verticalAlignment: Text.AlignVCenter elide: Text.ElideRight color: (combo.currentIndex >= 0 && combo.currentIndex < filteredModel.count) ? Color.mOnSurface : Color.mOnSurfaceVariant @@ -206,7 +206,7 @@ RowLayout { contentItem: NText { text: name - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: highlighted ? Color.mSurface : Color.mOnSurface verticalAlignment: Text.AlignVCenter elide: Text.ElideRight diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index 72be80d2..b84f3ec7 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -284,8 +284,8 @@ RowLayout { // Prefix text (non-editable) NText { text: root.prefix - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface verticalAlignment: Text.AlignVCenter @@ -343,8 +343,8 @@ RowLayout { // Suffix text (non-editable) NText { text: root.suffix - font.family: Settings.data.ui.fontFixed - font.pointSize: Style.fontSizeM * scaling + family: Settings.data.ui.fontFixed + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface verticalAlignment: Text.AlignVCenter diff --git a/Widgets/NText.qml b/Widgets/NText.qml index a0434821..9efd199e 100644 --- a/Widgets/NText.qml +++ b/Widgets/NText.qml @@ -6,9 +6,16 @@ import qs.Widgets Text { id: root - font.family: Settings.data.ui.fontDefault - font.pointSize: Style.fontSizeM * scaling + + property string family: Settings.data.ui.fontDefault + property real pointSize: Style.fontSizeM * scaling + property real fontScale: { + return (root.family === Settings.data.ui.fontDefault ? Settings.data.ui.fontDefaultScale : Settings.data.ui.fontFixedScale) + } + + font.family: root.family font.weight: Style.fontWeightMedium + font.pointSize: root.pointSize * fontScale color: Color.mOnSurface elide: Text.ElideRight wrapMode: Text.NoWrap diff --git a/Widgets/NValueSlider.qml b/Widgets/NValueSlider.qml index 981b7905..67f6089f 100644 --- a/Widgets/NValueSlider.qml +++ b/Widgets/NValueSlider.qml @@ -40,9 +40,9 @@ RowLayout { NText { visible: root.text !== "" text: root.text - font.family: Settings.data.ui.fontFixed + family: Settings.data.ui.fontFixed Layout.alignment: Qt.AlignVCenter - Layout.preferredWidth: 40 * scaling + Layout.preferredWidth: 50 * scaling horizontalAlignment: Text.AlignRight } } From 602d79c98e8353f2e4a05974236a402fdea2118f Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 21:38:51 -0400 Subject: [PATCH 38/62] TrayMenu: fix icon size --- Modules/Bar/Extras/TrayMenu.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Bar/Extras/TrayMenu.qml b/Modules/Bar/Extras/TrayMenu.qml index 415333fd..b78e3123 100644 --- a/Modules/Bar/Extras/TrayMenu.qml +++ b/Modules/Bar/Extras/TrayMenu.qml @@ -175,7 +175,7 @@ PopupWindow { NIcon { icon: modelData?.hasChildren ? "menu" : "" - pointSize: Style.fontSizeS * scaling + font.pointSize: Style.fontSizeS * scaling verticalAlignment: Text.AlignVCenter visible: modelData?.hasChildren ?? false color: (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) From d2e5d0664a5ac1d32f788f853c415788ebfe5524 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 21:42:47 -0400 Subject: [PATCH 39/62] Font: added reset button for scaling --- Assets/Translations/en.json | 1 + Modules/Settings/Tabs/DisplayTab.qml | 4 +- Modules/Settings/Tabs/GeneralTab.qml | 68 ++++++++++++++++++++++------ Widgets/NValueSlider.qml | 2 +- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 1ded8fcf..a9d7b1c7 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -56,6 +56,7 @@ } }, "fonts": { + "reset-scaling": "Reset scaling", "section": { "label": "Fonts", "description": "Choose the fonts used throughout the interface." diff --git a/Modules/Settings/Tabs/DisplayTab.qml b/Modules/Settings/Tabs/DisplayTab.qml index d2f50dd2..6eb9dca2 100644 --- a/Modules/Settings/Tabs/DisplayTab.qml +++ b/Modules/Settings/Tabs/DisplayTab.qml @@ -126,7 +126,7 @@ ColumnLayout { // Reset button container Item { - Layout.preferredWidth: 40 * scaling + Layout.preferredWidth: 30 * scaling Layout.preferredHeight: 30 * scaling NIconButton { @@ -168,7 +168,7 @@ ColumnLayout { // Empty container to match scale row layout Item { - Layout.preferredWidth: 40 * scaling + Layout.preferredWidth: 30 * scaling Layout.preferredHeight: 30 * scaling // Method text positioned in the button area diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index 45be5b9c..405a5cd9 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -243,14 +243,34 @@ ColumnLayout { description: I18n.tr("settings.general.fonts.default.scale.description") } - NValueSlider { + RowLayout { + spacing: Style.marginL * scaling Layout.fillWidth: true - from: 0.75 - to: 1.25 - stepSize: 0.01 - value: Settings.data.ui.fontDefaultScale - onMoved: value => Settings.data.ui.fontDefaultScale = value - text: Math.floor(Settings.data.ui.fontDefaultScale * 100) + "%" + + NValueSlider { + Layout.fillWidth: true + from: 0.75 + to: 1.25 + stepSize: 0.01 + value: Settings.data.ui.fontDefaultScale + onMoved: value => Settings.data.ui.fontDefaultScale = value + text: Math.floor(Settings.data.ui.fontDefaultScale * 100) + "%" + } + + // Reset button container + Item { + Layout.preferredWidth: 30 * scaling + Layout.preferredHeight: 30 * scaling + + NIconButton { + icon: "refresh" + baseSize: Style.baseWidgetSize * 0.9 + tooltipText: I18n.tr("settings.general.fonts.reset-scaling") + onClicked: Settings.data.ui.fontDefaultScale = 1.0 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + } + } } } @@ -260,14 +280,34 @@ ColumnLayout { description: I18n.tr("settings.general.fonts.monospace.scale.description") } - NValueSlider { + RowLayout { + spacing: Style.marginL * scaling Layout.fillWidth: true - from: 0.75 - to: 1.25 - stepSize: 0.01 - value: Settings.data.ui.fontFixedScale - onMoved: value => Settings.data.ui.fontFixedScale = value - text: Math.floor(Settings.data.ui.fontFixedScale * 100) + "%" + + NValueSlider { + Layout.fillWidth: true + from: 0.75 + to: 1.25 + stepSize: 0.01 + value: Settings.data.ui.fontFixedScale + onMoved: value => Settings.data.ui.fontFixedScale = value + text: Math.floor(Settings.data.ui.fontFixedScale * 100) + "%" + } + + // Reset button container + Item { + Layout.preferredWidth: 30 * scaling + Layout.preferredHeight: 30 * scaling + + NIconButton { + icon: "refresh" + baseSize: Style.baseWidgetSize * 0.9 + tooltipText: I18n.tr("settings.general.fonts.reset-scaling") + onClicked: Settings.data.ui.fontFixedScale = 1.0 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + } + } } } } diff --git a/Widgets/NValueSlider.qml b/Widgets/NValueSlider.qml index 67f6089f..32d8ed76 100644 --- a/Widgets/NValueSlider.qml +++ b/Widgets/NValueSlider.qml @@ -42,7 +42,7 @@ RowLayout { text: root.text family: Settings.data.ui.fontFixed Layout.alignment: Qt.AlignVCenter - Layout.preferredWidth: 50 * scaling + Layout.preferredWidth: 45 * scaling horizontalAlignment: Text.AlignRight } } From 518e90d9107eb6f7781b593445ad6d2f95a78ea7 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 21:46:10 -0400 Subject: [PATCH 40/62] SystemMonitor: apply fontScale to TextMetrics for smarted calculation --- Modules/Bar/Widgets/SystemMonitor.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index 2d9f47e9..a1090936 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -53,7 +53,7 @@ Rectangle { id: percentMetrics font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightMedium - font.pointSize: textSize + font.pointSize: textSize * Settings.data.ui.fontFixedScale text: "99%" // Use the longest possible string for measurement } @@ -61,7 +61,7 @@ Rectangle { id: tempMetrics font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightMedium - font.pointSize: textSize + font.pointSize: textSize * Settings.data.ui.fontFixedScale text: "99°" // Use the longest possible string for measurement } @@ -69,7 +69,7 @@ Rectangle { id: memMetrics font.family: Settings.data.ui.fontFixed font.weight: Style.fontWeightMedium - font.pointSize: textSize + font.pointSize: textSize * Settings.data.ui.fontFixedScale text: "99.9K" // Longest value part of network speed } From f61f9a5809285fa908246918b168a2c03f0d8454 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Tue, 30 Sep 2025 09:01:58 +0200 Subject: [PATCH 41/62] NiriService: Keep windows sorted when moving them with the mouse. --- Services/NiriService.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index 944e3d4a..79d9a8b7 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -217,8 +217,8 @@ Item { } else { // Add new window windows.push(newWindow) - windows.sort(compareWindows) } + windows.sort(compareWindows) // Update focused window index if this window is focused if (newWindow.isFocused) { From 4c3eca80a4fb8560651e8a2be6003b7d004c29c8 Mon Sep 17 00:00:00 2001 From: "M.Silva" Date: Tue, 30 Sep 2025 08:32:01 +0100 Subject: [PATCH 42/62] chore: refresh ghostty configuration --- Assets/Matugen/Matugen.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Matugen/Matugen.qml b/Assets/Matugen/Matugen.qml index 009349e6..82a804cd 100644 --- a/Assets/Matugen/Matugen.qml +++ b/Assets/Matugen/Matugen.qml @@ -51,7 +51,7 @@ Singleton { lines.push("\n[templates.ghostty]") lines.push('input_path = "' + Quickshell.shellDir + '/Assets/Matugen/templates/ghostty.conf"') lines.push('output_path = "~/.config/ghostty/themes/noctalia"') - lines.push("post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config\"") + lines.push("post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config; and pkill -SIGUSR2 ghostty\"") } if (Settings.data.matugen.foot) { lines.push("\n[templates.foot]") From 78cf0bc8a2634b027e438c32d000a9d72c9be5fa Mon Sep 17 00:00:00 2001 From: pugaizai Date: Tue, 30 Sep 2025 18:42:59 +0800 Subject: [PATCH 43/62] i18n: update zh-CN translations --- Assets/Translations/zh-CN.json | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index baeffea4..07635f86 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -54,6 +54,7 @@ } }, "fonts": { + "reset-scaling": "恢复默认缩放", "section": { "label": "字体", "description": "选择整个界面中使用的字体。" @@ -62,13 +63,21 @@ "label": "默认字体", "description": "整个界面使用的主要字体。", "placeholder": "选择默认字体...", - "search-placeholder": "搜索字体..." + "search-placeholder": "搜索字体...", + "scale": { + "label": "默认字体大小", + "description": "增大或减小标准文本的尺寸" + } }, "monospace": { "label": "等宽字体", "description": "用于数字和统计信息显示的等宽字体。", "placeholder": "选择等宽字体...", - "search-placeholder": "搜索等宽字体..." + "search-placeholder": "搜索等宽字体...", + "scale": { + "label": "默认等宽字体大小", + "description": "增大或减小等宽文本的尺寸" + } } } }, @@ -992,6 +1001,16 @@ "description": "使用空格将每个部分分隔到新行。" }, "preview": "预览" + }, + "taskbar": { + "only-active-workspaces": { + "label": "仅显示活动工作区", + "description": "仅显示来自活动工作区的应用程序" + }, + "only-same-output": { + "label": "仅显示同屏幕", + "description": "仅显示任务栏所在屏幕上的应用程序" + } } } }, From 773318191d31bb4bbc871b10e4e250cedbae0e6d Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Tue, 30 Sep 2025 13:02:56 +0200 Subject: [PATCH 44/62] NIcon: use textSize for font.pointSize --- Widgets/NIcon.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Widgets/NIcon.qml b/Widgets/NIcon.qml index 9f66c7c1..7e501fcd 100644 --- a/Widgets/NIcon.qml +++ b/Widgets/NIcon.qml @@ -21,7 +21,7 @@ Text { return Icons.get(icon) } font.family: Icons.fontFamily - font.pointSize: Style.fontSizeL * scaling + font.pointSize: textSize color: Color.mOnSurface verticalAlignment: Text.AlignVCenter } From 2008ba85bcb8822d5e94af1d90109f24115e576a Mon Sep 17 00:00:00 2001 From: pugaizai Date: Tue, 30 Sep 2025 19:00:16 +0800 Subject: [PATCH 45/62] update sessionmenu translation --- Assets/Translations/de.json | 6 +++--- Assets/Translations/en.json | 9 ++++++--- Assets/Translations/es.json | 6 +++--- Assets/Translations/fr.json | 6 +++--- Assets/Translations/pt.json | 6 +++--- Assets/Translations/zh-CN.json | 11 +++++++---- Modules/SessionMenu/SessionMenu.qml | 8 ++++---- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 76511329..0205cfe8 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1268,14 +1268,14 @@ "title": "Sitzungsmenü", "click-again": "Erneut klicken für sofortige Ausführung", "action-in-seconds": "{action} in {seconds} Sekunden...", + "lock": "Sperren", "lock-subtitle": "Sitzung sperren", "lock-and-suspend": "Sperren und Ruhezustand", "lock-and-suspend-subtitle": "Sitzung sperren und System in den Ruhezustand versetzen", - "end-subtitle": "Sitzung beenden", - "lock": "Sperren", "suspend": "Ruhezustand", "reboot": "Neu starten", "logout": "Abmelden", + "logout-subtitle": "Sitzung beenden", "shutdown": "Herunterfahren" }, "plugins": { @@ -1399,4 +1399,4 @@ "description": "Das Control-Center-Widget wurde aus der Leiste entfernt. Um es erneut über die Leiste zu öffnen, fügen Sie das Widget wieder hinzu." } } -} \ No newline at end of file +} diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index a9d7b1c7..8d688282 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -1259,15 +1259,18 @@ "title": "Session Menu", "click-again": "Click again to execute immediately", "action-in-seconds": "{action} in {seconds} seconds...", + "lock": "Lock", "lock-subtitle": "Lock your session", "lock-and-suspend": "Lock and Suspend", "lock-and-suspend-subtitle": "Lock session and put system to sleep", - "end-subtitle": "End your session", - "lock": "Lock", "suspend": "Suspend", + "suspend-subtitle": "Put system to sleep", "reboot": "Reboot", + "reboot-subtitle": "Restart your computer", "logout": "Logout", - "shutdown": "Shutdown" + "logout-subtitle": "End your session", + "shutdown": "Shutdown", + "shutdown-subtitle": "Turn off your computer" }, "plugins": { "applications": "Applications", diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 2effb703..485879f3 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -1237,14 +1237,14 @@ "title": "Menú de sesión", "click-again": "Haz clic de nuevo para ejecutar inmediatamente", "action-in-seconds": "{action} en {seconds} segundos...", + "lock": "Bloquear", "lock-subtitle": "Bloquea tu sesión", "lock-and-suspend": "Bloquear y Suspender", "lock-and-suspend-subtitle": "Bloquear sesión y poner el sistema en suspensión", - "end-subtitle": "Finaliza tu sesión", - "lock": "Bloquear", "suspend": "Suspender", "reboot": "Reiniciar", "logout": "Cerrar sesión", + "logout-subtitle": "Finaliza tu sesión", "shutdown": "Apagar" }, "plugins": { @@ -1385,4 +1385,4 @@ "charging": "Cargando.", "discharging": "Descargando." } -} \ No newline at end of file +} diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 86ab1b48..32644792 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1237,14 +1237,14 @@ "title": "Menu de session", "click-again": "Cliquez à nouveau pour exécuter immédiatement", "action-in-seconds": "{action} dans {seconds} secondes...", + "lock": "Verrouiller", "lock-subtitle": "Verrouiller votre session", "lock-and-suspend": "Verrouiller et Mettre en veille", "lock-and-suspend-subtitle": "Verrouiller la session et mettre le système en veille", - "end-subtitle": "Terminer votre session", - "lock": "Verrouiller", "suspend": "Mettre en veille", "reboot": "Redémarrer", "logout": "Déconnexion", + "logout-subtitle": "Terminer votre session", "shutdown": "Éteindre" }, "plugins": { @@ -1385,4 +1385,4 @@ "charging": "En charge.", "discharging": "En décharge." } -} \ No newline at end of file +} diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 365d6be9..7f41cb46 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -1237,14 +1237,14 @@ "title": "Menu da Sessão", "click-again": "Clique novamente para executar imediatamente", "action-in-seconds": "{action} em {seconds} segundos...", + "lock": "Bloquear", "lock-subtitle": "Bloqueie sua sessão", "lock-and-suspend": "Bloquear e Suspender", "lock-and-suspend-subtitle": "Bloquear sessão e colocar o sistema em suspensão", - "end-subtitle": "Encerre sua sessão", - "lock": "Bloquear", "suspend": "Suspender", "reboot": "Reiniciar", "logout": "Sair", + "logout-subtitle": "Encerre sua sessão", "shutdown": "Desligar" }, "plugins": { @@ -1385,4 +1385,4 @@ "charging": "Carregando.", "discharging": "Descarregando." } -} \ No newline at end of file +} diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 07635f86..c2cd2f0b 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -1256,15 +1256,18 @@ "title": "会话菜单", "click-again": "再次点击立即执行", "action-in-seconds": "{seconds} 秒后{action}...", + "lock": "锁定", "lock-subtitle": "锁定您的会话", "lock-and-suspend": "锁定并挂起", - "lock-and-suspend-subtitle": "锁定会话并将系统挂起", - "end-subtitle": "结束您的会话", - "lock": "锁定", + "lock-and-suspend-subtitle": "锁定会话并使系统进入睡眠状态", "suspend": "挂起", + "suspend-subtitle": "使系统进入睡眠状态", "reboot": "重启", + "reboot-subtitle": "重新启动计算机", "logout": "注销", - "shutdown": "关机" + "logout-subtitle": "结束您的会话", + "shutdown": "关机", + "shutdown-subtitle": "关闭计算机" }, "plugins": { "applications": "应用程序", diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index e48ab0d5..7fda6a03 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -41,22 +41,22 @@ NPanel { "action": "suspend", "icon": "suspend", "title": I18n.tr("session-menu.suspend"), - "subtitle": "Put the system to sleep" + "subtitle": I18n.tr("session-menu.suspend-subtitle") }, { "action": "reboot", "icon": "reboot", "title": I18n.tr("session-menu.reboot"), - "subtitle": "Restart the system" + "subtitle": I18n.tr("session-menu.reboot-subtitle") }, { "action": "logout", "icon": "logout", "title": I18n.tr("session-menu.logout"), - "subtitle": I18n.tr("session-menu.end-subtitle") + "subtitle": I18n.tr("session-menu.logout-subtitle") }, { "action": "shutdown", "icon": "shutdown", "title": I18n.tr("session-menu.shutdown"), - "subtitle": "Turn off the system", + "subtitle": I18n.tr("session-menu.shutdown-subtitle"), "isShutdown": true }] From 23887574cf00188b720576376eaee649f14e07aa Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Tue, 30 Sep 2025 13:12:49 +0200 Subject: [PATCH 46/62] NIcon: fix fontSize --- Widgets/NIcon.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Widgets/NIcon.qml b/Widgets/NIcon.qml index 7e501fcd..adca75f6 100644 --- a/Widgets/NIcon.qml +++ b/Widgets/NIcon.qml @@ -7,6 +7,7 @@ Text { id: root property string icon: Icons.defaultIcon + property real pointSize: Style.fontSizeL * scaling visible: (icon !== undefined) && (icon !== "") text: { @@ -21,7 +22,7 @@ Text { return Icons.get(icon) } font.family: Icons.fontFamily - font.pointSize: textSize + font.pointSize: root.pointSize color: Color.mOnSurface verticalAlignment: Text.AlignVCenter } From 43dee793de19308927cfb3027ccadcff4b4754be Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 07:44:03 -0400 Subject: [PATCH 47/62] More pointSize cleanup --- Modules/Bar/Bluetooth/BluetoothDevicesList.qml | 4 ++-- Modules/Bar/Bluetooth/BluetoothPanel.qml | 6 +++--- Modules/Bar/Extras/BarPillHorizontal.qml | 2 +- Modules/Bar/Extras/BarPillVertical.qml | 2 +- Modules/Bar/Extras/TrayMenu.qml | 2 +- Modules/Bar/WiFi/WiFiPanel.qml | 13 +++++++------ Modules/Bar/Widgets/MediaMini.qml | 4 ++-- Modules/Bar/Widgets/SystemMonitor.qml | 12 ++++++------ Modules/ControlCenter/Cards/MediaCard.qml | 6 +++--- Modules/ControlCenter/Cards/WeatherCard.qml | 4 ++-- Modules/Dock/Dock.qml | 2 +- Modules/Dock/DockMenu.qml | 6 +++--- Modules/LockScreen/LockScreen.qml | 10 +++++----- Modules/Notification/NotificationHistoryPanel.qml | 4 ++-- Modules/OSD/OSD.qml | 4 ++-- Modules/SessionMenu/SessionMenu.qml | 2 +- Modules/Settings/SettingsPanel.qml | 4 ++-- Modules/Settings/Tabs/AboutTab.qml | 2 +- Modules/Settings/Tabs/ColorSchemeTab.qml | 2 +- Modules/Toast/SimpleToast.qml | 2 +- Modules/Wallpaper/WallpaperPanel.qml | 6 +++--- Widgets/NButton.qml | 2 +- Widgets/NCheckbox.qml | 2 +- Widgets/NCircleStat.qml | 2 +- Widgets/NCollapsible.qml | 2 +- Widgets/NComboBox.qml | 2 +- Widgets/NContextMenu.qml | 2 +- Widgets/NFilePicker.qml | 12 ++++++------ Widgets/NIconButton.qml | 2 +- Widgets/NImageCircled.qml | 2 +- Widgets/NImageRounded.qml | 2 +- Widgets/NSearchableComboBox.qml | 2 +- Widgets/NSpinBox.qml | 4 ++-- 33 files changed, 68 insertions(+), 67 deletions(-) diff --git a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml index 5e6a7109..f40b13e1 100644 --- a/Modules/Bar/Bluetooth/BluetoothDevicesList.qml +++ b/Modules/Bar/Bluetooth/BluetoothDevicesList.qml @@ -67,7 +67,7 @@ ColumnLayout { // One device BT icon NIcon { icon: BluetoothService.getDeviceIcon(modelData) - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: getContentColor(Color.mOnSurface) Layout.alignment: Qt.AlignVCenter } @@ -110,7 +110,7 @@ ColumnLayout { NIcon { visible: modelData.signalStrength > 0 && !modelData.pairing && !modelData.blocked text: BluetoothService.getSignalIcon(modelData) - font.pointSize: Style.fontSizeXS * scaling + pointSize: Style.fontSizeXS * scaling color: getContentColor(Color.mOnSurface) } diff --git a/Modules/Bar/Bluetooth/BluetoothPanel.qml b/Modules/Bar/Bluetooth/BluetoothPanel.qml index 46ad2046..c11d38eb 100644 --- a/Modules/Bar/Bluetooth/BluetoothPanel.qml +++ b/Modules/Bar/Bluetooth/BluetoothPanel.qml @@ -30,7 +30,7 @@ NPanel { NIcon { icon: "bluetooth" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mPrimary } @@ -88,7 +88,7 @@ NPanel { NIcon { icon: "bluetooth-off" - font.pointSize: 64 * scaling + pointSize: 64 * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } @@ -186,7 +186,7 @@ NPanel { NIcon { icon: "refresh" - font.pointSize: Style.fontSizeXXL * 1.5 * scaling + pointSize: Style.fontSizeXXL * 1.5 * scaling color: Color.mPrimary RotationAnimation on rotation { diff --git a/Modules/Bar/Extras/BarPillHorizontal.qml b/Modules/Bar/Extras/BarPillHorizontal.qml index 2bdd1f1d..95f95b15 100644 --- a/Modules/Bar/Extras/BarPillHorizontal.qml +++ b/Modules/Bar/Extras/BarPillHorizontal.qml @@ -126,7 +126,7 @@ Item { NIcon { icon: root.icon - font.pointSize: iconSize + pointSize: iconSize color: hovered ? Color.mOnTertiary : Color.mOnSurface // Center horizontally x: (iconCircle.width - width) / 2 diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml index 5bdf75c3..d37f454d 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Modules/Bar/Extras/BarPillVertical.qml @@ -151,7 +151,7 @@ Item { NIcon { icon: root.icon - font.pointSize: iconSize + pointSize: iconSize color: hovered ? Color.mOnTertiary : Color.mOnSurface // Center horizontally x: (iconCircle.width - width) / 2 diff --git a/Modules/Bar/Extras/TrayMenu.qml b/Modules/Bar/Extras/TrayMenu.qml index b78e3123..415333fd 100644 --- a/Modules/Bar/Extras/TrayMenu.qml +++ b/Modules/Bar/Extras/TrayMenu.qml @@ -175,7 +175,7 @@ PopupWindow { NIcon { icon: modelData?.hasChildren ? "menu" : "" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling verticalAlignment: Text.AlignVCenter visible: modelData?.hasChildren ?? false color: (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) diff --git a/Modules/Bar/WiFi/WiFiPanel.qml b/Modules/Bar/WiFi/WiFiPanel.qml index e205e8be..4bd32b47 100644 --- a/Modules/Bar/WiFi/WiFiPanel.qml +++ b/Modules/Bar/WiFi/WiFiPanel.qml @@ -35,7 +35,7 @@ NPanel { NIcon { icon: Settings.data.network.wifiEnabled ? "wifi" : "wifi-off" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Settings.data.network.wifiEnabled ? Color.mPrimary : Color.mOnSurfaceVariant } @@ -92,7 +92,7 @@ NPanel { NIcon { icon: "warning" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mError } @@ -130,7 +130,7 @@ NPanel { NIcon { icon: "wifi-off" - font.pointSize: 64 * scaling + pointSize: 64 * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } @@ -242,7 +242,7 @@ NPanel { NIcon { icon: NetworkService.signalIcon(modelData.signal) - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: modelData.connected ? Color.mPrimary : Color.mOnSurface } @@ -439,6 +439,7 @@ NPanel { anchors.verticalCenter: parent.verticalCenter anchors.margins: Style.marginS * scaling text: passwordInput + font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurface echoMode: TextInput.Password @@ -508,7 +509,7 @@ NPanel { RowLayout { NIcon { icon: "trash" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mError } @@ -557,7 +558,7 @@ NPanel { NIcon { icon: "search" - font.pointSize: 64 * scaling + pointSize: 64 * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 98aadcdd..f1a32669 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -157,7 +157,7 @@ Item { NIcon { id: windowIcon icon: MediaService.isPlaying ? "media-pause" : "media-play" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter Layout.alignment: Qt.AlignVCenter visible: !showAlbumArt && getTitle() !== "" && !trackArt.visible @@ -342,7 +342,7 @@ Item { id: mediaIconVertical anchors.fill: parent icon: MediaService.isPlaying ? "media-pause" : "media-play" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index a1090936..2d18b8b5 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -106,7 +106,7 @@ Rectangle { NIcon { icon: "cpu-usage" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 @@ -147,7 +147,7 @@ Rectangle { NIcon { icon: "cpu-temperature" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 @@ -188,7 +188,7 @@ Rectangle { NIcon { icon: "memory" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 @@ -229,7 +229,7 @@ Rectangle { NIcon { icon: "download-speed" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 @@ -270,7 +270,7 @@ Rectangle { NIcon { icon: "upload-speed" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 @@ -311,7 +311,7 @@ Rectangle { NIcon { icon: "storage" - font.pointSize: iconSize + pointSize: iconSize Layout.alignment: Qt.AlignCenter Layout.row: isVertical ? 1 : 0 Layout.column: 0 diff --git a/Modules/ControlCenter/Cards/MediaCard.qml b/Modules/ControlCenter/Cards/MediaCard.qml index da223e5b..be99ef13 100644 --- a/Modules/ControlCenter/Cards/MediaCard.qml +++ b/Modules/ControlCenter/Cards/MediaCard.qml @@ -28,7 +28,7 @@ NBox { NIcon { icon: "disc" - font.pointSize: Style.fontSizeXXXL * 3 * scaling + pointSize: Style.fontSizeXXXL * 3 * scaling color: Color.mPrimary Layout.alignment: Qt.AlignHCenter } @@ -68,7 +68,7 @@ NBox { NIcon { icon: "caret-down" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mOnSurfaceVariant } @@ -147,7 +147,7 @@ NBox { NIcon { icon: "disc" color: Color.mPrimary - font.pointSize: Style.fontSizeXXXL * 3 * scaling + pointSize: Style.fontSizeXXXL * 3 * scaling visible: !trackArt.visible anchors.centerIn: parent } diff --git a/Modules/ControlCenter/Cards/WeatherCard.qml b/Modules/ControlCenter/Cards/WeatherCard.qml index 1bda1b82..778d277b 100644 --- a/Modules/ControlCenter/Cards/WeatherCard.qml +++ b/Modules/ControlCenter/Cards/WeatherCard.qml @@ -24,7 +24,7 @@ NBox { NIcon { Layout.alignment: Qt.AlignVCenter icon: weatherReady ? LocationService.weatherSymbolFromCode(LocationService.data.weather.current_weather.weathercode) : "" - font.pointSize: Style.fontSizeXXXL * 1.75 * scaling + pointSize: Style.fontSizeXXXL * 1.75 * scaling color: Color.mPrimary } @@ -96,7 +96,7 @@ NBox { NIcon { Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter icon: LocationService.weatherSymbolFromCode(LocationService.data.weather.daily.weathercode[index]) - font.pointSize: Style.fontSizeXXL * 1.6 * scaling + pointSize: Style.fontSizeXXL * 1.6 * scaling color: Color.mPrimary } NText { diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index 4d2158c0..57df42ec 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -417,7 +417,7 @@ Variants { anchors.centerIn: parent visible: !appIcon.visible icon: "question-mark" - font.pointSize: iconSize * 0.7 + pointSize: iconSize * 0.7 color: appButton.isActive ? Color.mPrimary : Color.mOnSurfaceVariant opacity: appButton.isRunning ? 1.0 : 0.6 scale: appButton.hovered ? 1.15 : 1.0 diff --git a/Modules/Dock/DockMenu.qml b/Modules/Dock/DockMenu.qml index 90388e3a..30de31e4 100644 --- a/Modules/Dock/DockMenu.qml +++ b/Modules/Dock/DockMenu.qml @@ -189,7 +189,7 @@ PopupWindow { NIcon { icon: "eye" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 0 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -222,7 +222,7 @@ PopupWindow { return "pin" return root.isAppPinned(root.toplevel.appId) ? "unpin" : "pin" } - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 1 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } @@ -255,7 +255,7 @@ PopupWindow { NIcon { icon: "close" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: root.hoveredItem === 2 ? Color.mOnTertiary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter } diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index de7bdc21..70868d85 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -400,7 +400,7 @@ Loader { } NIcon { icon: "keyboard" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: Color.mOnSurface } } @@ -410,7 +410,7 @@ Loader { visible: batteryIndicator.batteryVisible NIcon { icon: BatteryService.getIcon(batteryIndicator.percent, batteryIndicator.charging, batteryIndicator.isReady) - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: batteryIndicator.charging ? Color.mPrimary : Color.mOnSurface rotation: -90 } @@ -882,7 +882,7 @@ Loader { id: iconPower anchors.centerIn: parent icon: "shutdown" - font.pointSize: Style.fontSizeXXXL * scaling + pointSize: Style.fontSizeXXXL * scaling color: powerButtonArea.containsMouse ? Color.mOnError : Color.mError } @@ -934,7 +934,7 @@ Loader { id: iconReboot anchors.centerIn: parent icon: "reboot" - font.pointSize: Style.fontSizeXXXL * scaling + pointSize: Style.fontSizeXXXL * scaling color: restartButtonArea.containsMouse ? Color.mOnPrimary : Color.mPrimary } @@ -987,7 +987,7 @@ Loader { id: iconSuspend anchors.centerIn: parent icon: "suspend" - font.pointSize: Style.fontSizeXXXL * scaling + pointSize: Style.fontSizeXXXL * scaling color: suspendButtonArea.containsMouse ? Color.mOnSecondary : Color.mSecondary } diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index 5b0f5627..3bdcdbd4 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -32,7 +32,7 @@ NPanel { NIcon { icon: "bell" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mPrimary } @@ -88,7 +88,7 @@ NPanel { NIcon { icon: "bell-off" - font.pointSize: 64 * scaling + pointSize: 64 * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index 8b33101b..605aea37 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -253,7 +253,7 @@ Variants { NIcon { icon: root.getIcon() color: root.getIconColor() - font.pointSize: Style.fontSizeXL * root.scaling + pointSize: Style.fontSizeXL * root.scaling Layout.alignment: Qt.AlignVCenter Behavior on color { @@ -389,7 +389,7 @@ Variants { NIcon { icon: root.getIcon() color: root.getIconColor() - font.pointSize: Style.fontSizeXL * root.scaling + pointSize: Style.fontSizeXL * root.scaling Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.bottomMargin: vMargin + Math.round(Style.marginM * root.scaling) + balanceDelta Behavior on color { diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index 7fda6a03..039c2c98 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -385,7 +385,7 @@ NPanel { return Color.mOnTertiary return Color.mOnSurface } - font.pointSize: Style.fontSizeXXXL * scaling + pointSize: Style.fontSizeXXXL * scaling width: Style.baseWidgetSize * 0.6 * scaling horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 4a5706b8..6b7a6619 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -396,7 +396,7 @@ NPanel { NIcon { icon: modelData.icon color: tabTextColor - font.pointSize: Style.fontSizeXL * scaling + pointSize: Style.fontSizeXL * scaling } // Tab label @@ -456,7 +456,7 @@ NPanel { NIcon { icon: root.tabsModel[currentTabIndex]?.icon color: Color.mPrimary - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling } // Main title diff --git a/Modules/Settings/Tabs/AboutTab.qml b/Modules/Settings/Tabs/AboutTab.qml index 22566118..fb2eaaff 100644 --- a/Modules/Settings/Tabs/AboutTab.qml +++ b/Modules/Settings/Tabs/AboutTab.qml @@ -91,7 +91,7 @@ ColumnLayout { NIcon { icon: "download" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: updateArea.containsMouse ? Color.mSurface : Color.mPrimary } diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index b57f0041..5855d755 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -326,7 +326,7 @@ ColumnLayout { NIcon { icon: "check" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent diff --git a/Modules/Toast/SimpleToast.qml b/Modules/Toast/SimpleToast.qml index cde497ce..339e09c6 100644 --- a/Modules/Toast/SimpleToast.qml +++ b/Modules/Toast/SimpleToast.qml @@ -100,7 +100,7 @@ Rectangle { return Color.mOnSurface } } - font.pointSize: Style.fontSizeXXL * 1.5 * scaling + pointSize: Style.fontSizeXXL * 1.5 * scaling Layout.alignment: Qt.AlignVCenter } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 1d7095b9..46c32417 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -52,7 +52,7 @@ NPanel { NIcon { icon: "settings-wallpaper-selector" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mPrimary } @@ -367,7 +367,7 @@ NPanel { NIcon { icon: "check" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent @@ -443,7 +443,7 @@ NPanel { } NIcon { icon: "folder-open" - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling color: Color.mOnSurface Layout.alignment: Qt.AlignHCenter } diff --git a/Widgets/NButton.qml b/Widgets/NButton.qml index d6f6335e..93390ce9 100644 --- a/Widgets/NButton.qml +++ b/Widgets/NButton.qml @@ -79,7 +79,7 @@ Rectangle { Layout.alignment: Qt.AlignVCenter visible: root.icon !== "" icon: root.icon - font.pointSize: root.iconSize + pointSize: root.iconSize color: { if (!root.enabled) return Color.mOnSurfaceVariant diff --git a/Widgets/NCheckbox.qml b/Widgets/NCheckbox.qml index b9c2ae64..4ea76318 100644 --- a/Widgets/NCheckbox.qml +++ b/Widgets/NCheckbox.qml @@ -60,7 +60,7 @@ RowLayout { anchors.horizontalCenterOffset: -1 * scaling icon: "check" color: root.activeOnColor - font.pointSize: Math.max(Style.fontSizeXS, root.baseSize * 0.5) * scaling + pointSize: Math.max(Style.fontSizeXS, root.baseSize * 0.5) * scaling font.weight: Style.fontWeightBold } diff --git a/Widgets/NCircleStat.qml b/Widgets/NCircleStat.qml index 074ea51d..67668184 100644 --- a/Widgets/NCircleStat.qml +++ b/Widgets/NCircleStat.qml @@ -102,7 +102,7 @@ Rectangle { anchors.centerIn: parent icon: root.icon color: Color.mOnPrimary - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } diff --git a/Widgets/NCollapsible.qml b/Widgets/NCollapsible.qml index 6cc4b34b..2efd3f01 100644 --- a/Widgets/NCollapsible.qml +++ b/Widgets/NCollapsible.qml @@ -82,7 +82,7 @@ ColumnLayout { NIcon { id: chevronIcon icon: "chevron-right" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: root.expanded ? Color.mOnSecondary : Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter diff --git a/Widgets/NComboBox.qml b/Widgets/NComboBox.qml index c8d746cd..a7a054b5 100644 --- a/Widgets/NComboBox.qml +++ b/Widgets/NComboBox.qml @@ -100,7 +100,7 @@ RowLayout { x: combo.width - width - Style.marginM * scaling y: combo.topPadding + (combo.availableHeight - height) / 2 icon: "caret-down" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling } popup: Popup { diff --git a/Widgets/NContextMenu.qml b/Widgets/NContextMenu.qml index e5bebeee..55d0f6ae 100644 --- a/Widgets/NContextMenu.qml +++ b/Widgets/NContextMenu.qml @@ -62,7 +62,7 @@ Popup { NIcon { visible: modelData.icon !== undefined icon: modelData.icon || "" - font.pointSize: Style.fontSizeM * scaling + pointSize: Style.fontSizeM * scaling color: menuItem.hovered && menuItem.enabled ? Color.mOnTertiary : Color.mOnSurface Layout.leftMargin: root.itemPadding diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index 3a9e026c..24922ec7 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -191,7 +191,7 @@ Popup { NIcon { icon: "filepicker-folder" color: Color.mPrimary - font.pointSize: Style.fontSizeXXL * scaling + pointSize: Style.fontSizeXXL * scaling } NText { text: root.title @@ -357,7 +357,7 @@ Popup { NIcon { icon: "filepicker-search" color: Color.mOnSurfaceVariant - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling } NTextInput { id: searchInput @@ -588,7 +588,7 @@ Popup { visible: thumbnail.status === Image.Loading NIcon { icon: "filepicker-photo" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant anchors.centerIn: parent } @@ -597,7 +597,7 @@ Popup { NIcon { icon: model.fileIsDir ? "filepicker-folder" : root.getFileIcon(model.fileName) - font.pointSize: Style.fontSizeXXL * 2 * scaling + pointSize: Style.fontSizeXXL * 2 * scaling color: { if (isSelected) return Color.mSecondary @@ -623,7 +623,7 @@ Popup { visible: isSelected NIcon { icon: "filepicker-check" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightBold color: Color.mOnSecondary anchors.centerIn: parent @@ -728,7 +728,7 @@ Popup { NIcon { icon: model.fileIsDir ? "filepicker-folder" : root.getFileIcon(model.fileName) - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling color: model.fileIsDir ? (filePickerPanel.currentSelection.includes(model.filePath) ? Color.mOnSecondary : Color.mPrimary) : Color.mOnSurfaceVariant } diff --git a/Widgets/NIconButton.qml b/Widgets/NIconButton.qml index 290fb00b..d533153c 100644 --- a/Widgets/NIconButton.qml +++ b/Widgets/NIconButton.qml @@ -48,7 +48,7 @@ Rectangle { NIcon { icon: root.icon - font.pointSize: Math.max(1, root.compact ? root.width * 0.65 : root.width * 0.48) + pointSize: Math.max(1, root.compact ? root.width * 0.65 : root.width * 0.48) color: root.enabled && root.hovering ? colorFgHover : colorFg // Center horizontally x: (root.width - width) / 2 diff --git a/Widgets/NImageCircled.qml b/Widgets/NImageCircled.qml index 57ff3db4..eb0ee9bd 100644 --- a/Widgets/NImageCircled.qml +++ b/Widgets/NImageCircled.qml @@ -58,7 +58,7 @@ Rectangle { sourceComponent: NIcon { anchors.centerIn: parent icon: fallbackIcon - font.pointSize: fallbackIconSize + pointSize: fallbackIconSize z: 0 } } diff --git a/Widgets/NImageRounded.qml b/Widgets/NImageRounded.qml index d7306958..ff55a571 100644 --- a/Widgets/NImageRounded.qml +++ b/Widgets/NImageRounded.qml @@ -78,7 +78,7 @@ Rectangle { sourceComponent: NIcon { anchors.centerIn: parent icon: fallbackIcon - font.pointSize: fallbackIconSize + pointSize: fallbackIconSize z: 0 } } diff --git a/Widgets/NSearchableComboBox.qml b/Widgets/NSearchableComboBox.qml index 736511a3..3175f126 100644 --- a/Widgets/NSearchableComboBox.qml +++ b/Widgets/NSearchableComboBox.qml @@ -149,7 +149,7 @@ RowLayout { x: combo.width - width - Style.marginM * scaling y: combo.topPadding + (combo.availableHeight - height) / 2 icon: "caret-down" - font.pointSize: Style.fontSizeL * scaling + pointSize: Style.fontSizeL * scaling } popup: Popup { diff --git a/Widgets/NSpinBox.qml b/Widgets/NSpinBox.qml index b84f3ec7..697cb056 100644 --- a/Widgets/NSpinBox.qml +++ b/Widgets/NSpinBox.qml @@ -154,7 +154,7 @@ RowLayout { anchors.leftMargin: parent.width * 0.25 anchors.verticalCenter: parent.verticalCenter icon: "chevron-left" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: decreaseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary } @@ -250,7 +250,7 @@ RowLayout { anchors.rightMargin: parent.width * 0.25 anchors.verticalCenter: parent.verticalCenter icon: "chevron-right" - font.pointSize: Style.fontSizeS * scaling + pointSize: Style.fontSizeS * scaling color: increaseArea.containsMouse ? Color.mOnTertiary : Color.mPrimary } From 970684e304a2fd21592f76fc45fd97ff589f5f39 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 08:07:18 -0400 Subject: [PATCH 48/62] Niri: temp warning fix --- Services/NiriService.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index 79d9a8b7..2e14747e 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -164,7 +164,7 @@ Item { "id": win.id, "title": win.title || "", "appId": win.app_id || "", - "workspaceId": win.workspace_id || null, + "workspaceId": win.workspace_id || -1, "isFocused": win.is_focused === true, "output": getWindowOutput(win) || "", "position": getWindowPosition(win.layout) From 650dcb881116d6655e34334fdd7195671b039bd2 Mon Sep 17 00:00:00 2001 From: Aiser <2912778691@qq.com> Date: Tue, 30 Sep 2025 21:32:03 +0800 Subject: [PATCH 49/62] i18n: Optimize Chinese translation --- Assets/Translations/zh-CN.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index c2cd2f0b..9c854954 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -164,7 +164,7 @@ "title": "显示", "monitors": { "section": { - "label": "每显示器设置", + "label": "显示器设置", "description": "调整每个显示器的缩放比例和亮度。" }, "scale": "缩放比例", @@ -228,8 +228,8 @@ "description": "调整状态栏的背景不透明度。" }, "show-capsule": { - "label": "显示胶囊", - "description": "显示小部件背景。" + "label": "显示组件背景", + "description": "为每个小部件添加背景。" }, "floating": { "label": "浮动状态栏", From a0f6d1433435d2050d52593f31e974c5217c6146 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Tue, 30 Sep 2025 18:37:45 +0200 Subject: [PATCH 50/62] MediaMini: add no active player placeholder --- Assets/Translations/de.json | 3 +- Assets/Translations/en.json | 3 +- Assets/Translations/es.json | 3 +- Assets/Translations/fr.json | 3 +- Assets/Translations/pt.json | 3 +- Assets/Translations/zh-CN.json | 3 +- Modules/Bar/Widgets/MediaMini.qml | 47 ++++++++++++++++++------------- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 0205cfe8..c81f4eb8 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -987,7 +987,8 @@ "scrolling-mode": { "label": "Scrollmodus", "description": "Steuern, wann Textscrolling für lange Track-Titel aktiviert ist." - } + }, + "no-active-player": "Kein aktiver Player" }, "clock": { "use-primary-color": { diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 8d688282..4d307af2 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -979,7 +979,8 @@ "scrolling-mode": { "label": "Scrolling mode", "description": "Control when text scrolling is enabled for long track titles." - } + }, + "no-active-player": "No active player" }, "clock": { "use-primary-color": { diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index 485879f3..22e39288 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -968,7 +968,8 @@ "scrolling-mode": { "label": "Modo de desplazamiento", "description": "Controlar cuándo está habilitado el desplazamiento de texto para títulos de pista largos." - } + }, + "no-active-player": "Sin reproductor activo" }, "clock": { "use-primary-color": { diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 32644792..3e7bbcfb 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -968,7 +968,8 @@ "auto-hide": { "label": "Masquer automatiquement", "description": "Masquer automatiquement le widget quand aucun média n'est en cours de lecture." - } + }, + "no-active-player": "Aucun lecteur actif" }, "clock": { "use-primary-color": { diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index 7f41cb46..068f5d04 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -968,7 +968,8 @@ "scrolling-mode": { "label": "Modo de rolagem", "description": "Controlar quando a rolagem de texto está habilitada para títulos de faixa longos." - } + }, + "no-active-player": "Nenhum player ativo" }, "clock": { "use-primary-color": { diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 9c854954..562e4cda 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -977,7 +977,8 @@ "scrolling-mode": { "label": "滚动模式", "description": "控制何时为长曲目标题启用文本滚动。" - } + }, + "no-active-player": "无活动播放器" }, "clock": { "use-primary-color": { diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index f1a32669..a65e99d1 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -42,6 +42,9 @@ Item { // Fixed width - no expansion readonly property real widgetWidth: Math.max(1, screen.width * 0.06) + readonly property bool hasActivePlayer: MediaService.currentPlayer !== null && getTitle() !== "" + readonly property string placeholderText: I18n.tr("bar.widget-settings.media-mini.no-active-player") + readonly property string tooltipText: { var title = getTitle() var controls = "" @@ -60,7 +63,7 @@ Item { implicitHeight: visible ? ((barPosition === "left" || barPosition === "right") ? calculatedVerticalHeight() : Math.round(Style.barHeight * scaling)) : 0 implicitWidth: visible ? ((barPosition === "left" || barPosition === "right") ? Math.round(Style.baseWidgetSize * 0.8 * scaling) : (widgetWidth * scaling)) : 0 - opacity: !autoHide || getTitle() !== "" ? 1.0 : 0 + opacity: !autoHide || hasActivePlayer || (!hasActivePlayer && !autoHide) ? 1.0 : 0 Behavior on opacity { NumberAnimation { duration: Style.animationNormal @@ -151,21 +154,21 @@ Item { anchors.verticalCenter: parent.verticalCenter spacing: Style.marginS * scaling - visible: (barPosition === "top" || barPosition === "bottom") && getTitle() !== "" + visible: (barPosition === "top" || barPosition === "bottom") z: 1 // Above the visualizer NIcon { id: windowIcon - icon: MediaService.isPlaying ? "media-pause" : "media-play" + icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "music-off" pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter Layout.alignment: Qt.AlignVCenter - visible: !showAlbumArt && getTitle() !== "" && !trackArt.visible + visible: !showAlbumArt && !trackArt.visible } ColumnLayout { Layout.alignment: Qt.AlignVCenter - visible: showAlbumArt + visible: showAlbumArt && hasActivePlayer spacing: 0 Item { @@ -187,6 +190,10 @@ Item { Item { id: titleContainer Layout.preferredWidth: { + if (!hasActivePlayer) { + // When no active player, take full width to center the placeholder + return mainContainer.width - Style.marginXXS * scaling * 2 + } // Calculate available width based on other elements in the row var iconWidth = (windowIcon.visible ? (Style.fontSizeL * scaling + Style.marginS * scaling) : 0) var albumArtWidth = (showAlbumArt ? (18 * scaling + Style.marginS * scaling) : 0) @@ -195,7 +202,7 @@ Item { return Math.max(20 * scaling, availableWidth) } Layout.maximumWidth: Layout.preferredWidth - Layout.alignment: Qt.AlignVCenter + Layout.alignment: hasActivePlayer ? Qt.AlignVCenter : Qt.AlignCenter Layout.preferredHeight: titleText.height clip: true @@ -264,29 +271,31 @@ Item { Item { id: scrollContainer height: parent.height - width: childrenRect.width + width: hasActivePlayer ? childrenRect.width : parent.width property real scrollX: 0 - x: scrollX + x: hasActivePlayer ? scrollX : 0 RowLayout { spacing: 50 * scaling // Gap between text copies NText { id: titleText - text: getTitle() + text: hasActivePlayer ? getTitle() : placeholderText pointSize: Style.fontSizeS * scaling font.weight: Style.fontWeightMedium verticalAlignment: Text.AlignVCenter - color: Color.mOnSurface + horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter + color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant } NText { - text: getTitle() + text: hasActivePlayer ? getTitle() : placeholderText font: titleText.font verticalAlignment: Text.AlignVCenter - color: Color.mOnSurface - visible: titleContainer.needsScrolling && titleContainer.isScrolling + horizontalAlignment: hasActivePlayer ? Text.AlignLeft : Text.AlignHCenter + color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant + visible: hasActivePlayer && titleContainer.needsScrolling && titleContainer.isScrolling } } @@ -336,12 +345,11 @@ Item { width: Style.baseWidgetSize * 0.5 * scaling height: Style.baseWidgetSize * 0.5 * scaling anchors.centerIn: parent - visible: getTitle() !== "" NIcon { id: mediaIconVertical anchors.fill: parent - icon: MediaService.isPlaying ? "media-pause" : "media-play" + icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "music-off" pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter @@ -354,10 +362,10 @@ Item { id: mouseArea anchors.fill: parent hoverEnabled: true - cursorShape: Qt.PointingHandCursor + cursorShape: hasActivePlayer ? Qt.PointingHandCursor : Qt.ArrowCursor acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton onClicked: mouse => { - if (!MediaService.currentPlayer || !MediaService.canPlay) { + if (!hasActivePlayer || !MediaService.currentPlayer || !MediaService.canPlay) { return } @@ -375,8 +383,9 @@ Item { } onEntered: { - if ((tooltipText !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) { - TooltipService.show(root, tooltipText, BarService.getTooltipDirection()) + var textToShow = hasActivePlayer ? tooltipText : placeholderText + if ((textToShow !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) { + TooltipService.show(root, textToShow, BarService.getTooltipDirection()) } } onExited: { From 32712c70527eb9ecc01a1b8f064280fceb3a2766 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Tue, 30 Sep 2025 19:23:18 +0200 Subject: [PATCH 51/62] MediaMini: replace placeholder icon --- Modules/Bar/Widgets/MediaMini.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index a65e99d1..c9c11b3d 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -159,7 +159,7 @@ Item { NIcon { id: windowIcon - icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "music-off" + icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc" pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter Layout.alignment: Qt.AlignVCenter @@ -349,7 +349,7 @@ Item { NIcon { id: mediaIconVertical anchors.fill: parent - icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "music-off" + icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc" pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter From fdc61acfe43bbabbdb59244dd9c073898d634469 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Tue, 30 Sep 2025 23:01:46 +0200 Subject: [PATCH 52/62] Dock: Add option to filter by output. --- Assets/Translations/en.json | 14 +++++++++----- Commons/Settings.qml | 1 + Modules/Dock/Dock.qml | 8 +++++++- Modules/Settings/Tabs/DockTab.qml | 7 +++++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 4d307af2..5e272038 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -2,7 +2,7 @@ "settings": { "general": { "title": "General", - + "profile": { "section": { "label": "Profile", @@ -285,6 +285,10 @@ "section": { "label": "Monitor display", "description": "Choose which monitor to display the dock on." + }, + "only-same-output": { + "label": "Only apps from same output", + "description": "Show only apps from the output where the dock is located." } } }, @@ -1162,7 +1166,7 @@ "enter-width-pixels": "Enter width in pixels", "enter-command": "Enter command to execute (app or custom script)", "command-example": "echo \"Hello World\"", - + "search-wallpapers": "Type to filter wallpapers...", "search-launcher": "Search entries... or use > for commands", "search": "Search...", @@ -1264,7 +1268,7 @@ "lock-subtitle": "Lock your session", "lock-and-suspend": "Lock and Suspend", "lock-and-suspend-subtitle": "Lock session and put system to sleep", - "suspend": "Suspend", + "suspend": "Suspend", "suspend-subtitle": "Put system to sleep", "reboot": "Reboot", "reboot-subtitle": "Restart your computer", @@ -1385,7 +1389,7 @@ }, "weather": { "clear-sky": "Clear sky", - "mainly-clear": "Mainly clear", + "mainly-clear": "Mainly clear", "partly-cloudy": "Partly cloudy", "overcast": "Overcast", "fog": "Fog", @@ -1395,7 +1399,7 @@ "thunderstorm": "Thunderstorm", "unknown": "Unknown" }, - + "authentication": { "failed": "Authentication failed", "error": "Authentication error" diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 8b581e8b..e52f663c 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -247,6 +247,7 @@ Singleton { property bool exclusive: false property real backgroundOpacity: 1.0 property real floatingRatio: 1.0 + property bool onlySameOutput: true property list monitors: [] // Desktop entry IDs pinned to the dock (e.g., "org.kde.konsole", "firefox.desktop") property list pinnedApps: [] diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index 57df42ec..8f31af3b 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -51,6 +51,9 @@ Variants { function onPinnedAppsChanged() { updateDockApps() } + function onOnlySameOutputChanged() { + updateDockApps() + } } // Initial update when component is ready @@ -108,7 +111,10 @@ Variants { // Strategy: Maintain app positions as much as possible // 1. First pass: Add all running apps (both pinned and non-pinned) in their current order runningApps.forEach(toplevel => { - if (toplevel && toplevel.appId) { + if ( + toplevel && toplevel.appId + && !(Settings.data.dock.onlySameOutput && toplevel.screens && !toplevel.screens.includes(modelData)) + ) { const isPinned = pinnedApps.includes(toplevel.appId) const appType = isPinned ? "pinned-running" : "running" diff --git a/Modules/Settings/Tabs/DockTab.qml b/Modules/Settings/Tabs/DockTab.qml index c3b1d559..55af3a6a 100644 --- a/Modules/Settings/Tabs/DockTab.qml +++ b/Modules/Settings/Tabs/DockTab.qml @@ -118,6 +118,13 @@ ColumnLayout { } } + NToggle { + label: I18n.tr("settings.dock.monitors.only-same-output.label") + description: I18n.tr("settings.dock.monitors.only-same-output.description") + checked: Settings.data.dock.onlySameOutput + onToggled: checked => Settings.data.dock.onlySameOutput = checked + } + NDivider { Layout.fillWidth: true Layout.topMargin: Style.marginXL * scaling From ec2fbb53dc2a234914ea2a356761a8f263f5768b Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Tue, 30 Sep 2025 23:02:13 +0200 Subject: [PATCH 53/62] Dock: Allow showing the dock on outputs without a bar. --- Modules/Dock/Dock.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index 8f31af3b..8260037f 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -196,7 +196,7 @@ Variants { // PEEK WINDOW - Always visible when auto-hide is enabled Loader { - active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide + active: (barIsReady || !hasBar) && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide sourceComponent: PanelWindow { id: peekWindow @@ -242,7 +242,7 @@ Variants { // DOCK WINDOW Loader { - active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) + active: (barIsReady || !hasBar) && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) sourceComponent: PanelWindow { id: dockWindow From 6d05a205561018aa37b1ab62d543fe12a8dd7195 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Tue, 30 Sep 2025 23:03:09 +0200 Subject: [PATCH 54/62] Dock: Reformat code. --- Modules/Dock/Dock.qml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index 8260037f..5652deae 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -111,10 +111,7 @@ Variants { // Strategy: Maintain app positions as much as possible // 1. First pass: Add all running apps (both pinned and non-pinned) in their current order runningApps.forEach(toplevel => { - if ( - toplevel && toplevel.appId - && !(Settings.data.dock.onlySameOutput && toplevel.screens && !toplevel.screens.includes(modelData)) - ) { + if (toplevel && toplevel.appId && !(Settings.data.dock.onlySameOutput && toplevel.screens && !toplevel.screens.includes(modelData))) { const isPinned = pinnedApps.includes(toplevel.appId) const appType = isPinned ? "pinned-running" : "running" From 4fb1e2de1efb24c50f1a9bd632f95f5131911ce1 Mon Sep 17 00:00:00 2001 From: Leopold Luley Date: Tue, 30 Sep 2025 23:07:24 +0200 Subject: [PATCH 55/62] i18n: Add German translation for new dock settings. --- Assets/Translations/de.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index c81f4eb8..009125f4 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -2,7 +2,7 @@ "settings": { "general": { "title": "Allgemein", - + "profile": { "section": { "label": "Profil", @@ -245,6 +245,10 @@ "section": { "label": "Monitor-Anzeige", "description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." + }, + "only-same-output": { + "label": "Nur Apps vom gleichen Bildschirm", + "description": "Zeige nur Apps vom dem Bildschirm an, wo sich das Dock befindet." } } }, @@ -1170,7 +1174,7 @@ "enter-width-pixels": "Breite in Pixeln eingeben", "enter-command": "Befehl eingeben (App oder benutzerdefiniertes Skript)", "command-example": "echo \"Hallo Welt\"", - + "search-wallpapers": "Zum Filtern von Hintergrundbildern eingeben...", "search-launcher": "Einträge suchen... oder > für Befehle verwenden", "search": "Suchen...", @@ -1242,7 +1246,7 @@ "frame-rates": { "fps": "{fps} FPS" }, - + "screen-recording": { "sources": { "portal": "Portal", From 6f4aa1a1a1f839d7ad6e3513ea0d395aa9a2b967 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 17:56:59 -0400 Subject: [PATCH 56/62] MediaMini: fix binding loop + edge case where no icon would appear. Also set Autohide to false by default for ActiveWindow and MediaMini --- Modules/Bar/Widgets/MediaMini.qml | 17 +++++++++++++---- Services/BarWidgetRegistry.qml | 4 ++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index c9c11b3d..0f96cb9a 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -160,10 +160,11 @@ Item { NIcon { id: windowIcon icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc" + color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter Layout.alignment: Qt.AlignVCenter - visible: !showAlbumArt && !trackArt.visible + visible: !hasActivePlayer || (!showAlbumArt && !trackArt.visible) } ColumnLayout { @@ -210,7 +211,7 @@ Item { property bool isScrolling: false property bool isResetting: false property real textWidth: fullTitleMetrics.contentWidth - property real containerWidth: width + property real containerWidth: 0 property bool needsScrolling: textWidth > containerWidth // Timer for "always" mode with delay @@ -257,8 +258,15 @@ Item { } } - onWidthChanged: updateScrollingState() - Component.onCompleted: updateScrollingState() + onWidthChanged: { + containerWidth = width + updateScrollingState() + } + + Component.onCompleted: { + containerWidth = width + updateScrollingState() + } Connections { target: mouseArea @@ -350,6 +358,7 @@ Item { id: mediaIconVertical anchors.fill: parent icon: hasActivePlayer ? (MediaService.isPlaying ? "media-pause" : "media-play") : "disc" + color: hasActivePlayer ? Color.mOnSurface : Color.mOnSurfaceVariant pointSize: Style.fontSizeL * scaling verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index 6beda333..b1d528ea 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -41,7 +41,7 @@ Singleton { "ActiveWindow": { "allowUserSettings": true, "showIcon": true, - "autoHide": true, + "autoHide": false, "scrollingMode": "hover" }, "Battery": { @@ -81,7 +81,7 @@ Singleton { }, "MediaMini": { "allowUserSettings": true, - "autoHide": true, + "autoHide": false, "scrollingMode": "hover", "showAlbumArt": false, "showVisualizer": false, From e324a33137a7eeef1f13419eaa217ef60ce3c53d Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 18:16:35 -0400 Subject: [PATCH 57/62] NiriService: added safe guards to avoid issue with wrong window indexes. --- Services/NiriService.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Services/NiriService.qml b/Services/NiriService.qml index 2e14747e..ef525bb8 100644 --- a/Services/NiriService.qml +++ b/Services/NiriService.qml @@ -227,7 +227,9 @@ Item { // Only emit activeWindowChanged if the focused window actually changed if (oldFocusedIndex !== focusedWindowIndex) { - windows[oldFocusedIndex].isFocused = false + if (oldFocusedIndex >= 0 && oldFocusedIndex < windows.length) { + windows[oldFocusedIndex].isFocused = false + } activeWindowChanged() } } @@ -282,7 +284,7 @@ Item { if (focusedId) { const newIndex = windows.findIndex(w => w.id === focusedId) - if (newIndex >= 0) { + if (newIndex >= 0 && newIndex < windows.length) { windows[newIndex].isFocused = true } From 52d2055699f3d1fcadda1d47c7bc8f8be99c2523 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 18:20:28 -0400 Subject: [PATCH 58/62] MediaMini: fix another binding loop. --- Modules/Bar/Widgets/MediaMini.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 0f96cb9a..ae960cd5 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -279,7 +279,7 @@ Item { Item { id: scrollContainer height: parent.height - width: hasActivePlayer ? childrenRect.width : parent.width + width: parent.width property real scrollX: 0 x: hasActivePlayer ? scrollX : 0 From c1abb3a7dc8f1222ea49f4384a258afe232d5db4 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 19:50:24 -0400 Subject: [PATCH 59/62] Default settings updated with Dock's: only same output. --- Assets/settings-default.json | 1 + 1 file changed, 1 insertion(+) diff --git a/Assets/settings-default.json b/Assets/settings-default.json index d0a35397..38767453 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -114,6 +114,7 @@ "exclusive": false, "backgroundOpacity": 1, "floatingRatio": 1, + "onlySameOutput": true, "monitors": [], "pinnedApps": [] }, From 056217bf432fdbb5b3ff628735e80d2eb77dc007 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 20:24:23 -0400 Subject: [PATCH 60/62] Wallpaper: fix double wallpaper init. --- Modules/Background/Background.qml | 1 - Services/WallpaperService.qml | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 5bb903ac..f40bcd8d 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -58,7 +58,6 @@ Variants { target: WallpaperService function onWallpaperChanged(screenName, path) { if (screenName === modelData.name) { - // Update wallpaper display // Set wallpaper immediately on startup futureWallpaper = path diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index 8b01f76c..46869ff2 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -79,14 +79,12 @@ Singleton { translateModels() - // Rebuild cache from persisted settings - var monitors = Settings.data.wallpaper.monitors || [] + // Rebuild cache from settings currentWallpapers = ({}) + var monitors = Settings.data.wallpaper.monitors || [] for (var i = 0; i < monitors.length; i++) { if (monitors[i].name && monitors[i].wallpaper) { currentWallpapers[monitors[i].name] = monitors[i].wallpaper - // Notify listeners so Background updates immediately after settings load - root.wallpaperChanged(monitors[i].name, monitors[i].wallpaper) } } From 368e80daf22716d22f7044f834f806ecbc617413 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 20:29:18 -0400 Subject: [PATCH 61/62] .gitignore cleanup --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index dfbea23a..e69de29b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +0,0 @@ -.qmlls.ini From b04366461799e9543d67b13f7f4989147ca61a9e Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 30 Sep 2025 21:33:06 -0400 Subject: [PATCH 62/62] Taskbar: Improved the look of the focused app. Made unfocused app icons semi transparent. --- Modules/Bar/Widgets/Taskbar.qml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Modules/Bar/Widgets/Taskbar.qml b/Modules/Bar/Widgets/Taskbar.qml index d37100dd..12ade07d 100644 --- a/Modules/Bar/Widgets/Taskbar.qml +++ b/Modules/Bar/Widgets/Taskbar.qml @@ -69,25 +69,25 @@ Rectangle { Layout.preferredHeight: root.itemSize Layout.alignment: Qt.AlignCenter - Rectangle { - id: iconBackground - anchors.centerIn: parent + IconImage { + + id: appIcon width: parent.width height: parent.height - color: modelData.isFocused ? Color.mPrimary : root.color - border.width: 0 - radius: Math.round(Style.radiusXS * root.scaling) - border.color: Color.transparent - z: -1 + source: ThemeIcons.iconForAppId(taskbarItem.modelData.appId) + smooth: true + asynchronous: true + opacity: modelData.isFocused ? 1.0 : 0.5 - IconImage { - id: appIcon - anchors.centerIn: parent - width: parent.width - height: parent.height - source: ThemeIcons.iconForAppId(taskbarItem.modelData.appId) - smooth: true - asynchronous: true + Rectangle { + anchors.bottomMargin: -2 * scaling + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + id: iconBackground + width: 4 * scaling + height: 4 * scaling + color: modelData.isFocused ? Color.mPrimary : Color.transparent + radius: width * 0.5 } }