From b18d33742abb131a65ea7187956d2664fcf97769 Mon Sep 17 00:00:00 2001 From: BUSTheid <91186864+BUSTheid@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:59:11 +0100 Subject: [PATCH] refactor(NScrollText.qml): MultiEffect fade mask Replace the leftGradient and rightGradient Rectangles in NScrollText with a MultiEffect mask approach. Old solution caused visual bugs. --- Modules/Bar/Widgets/ActiveWindow.qml | 9 ++- Modules/Bar/Widgets/MediaMini.qml | 7 +- Modules/Panels/Media/MediaPlayerPanel.qml | 8 +- Modules/Panels/Wallpaper/WallpaperPanel.qml | 3 +- Widgets/NScrollText.qml | 89 ++++++++------------- 5 files changed, 49 insertions(+), 67 deletions(-) diff --git a/Modules/Bar/Widgets/ActiveWindow.qml b/Modules/Bar/Widgets/ActiveWindow.qml index d615f85da..0d57c740e 100644 --- a/Modules/Bar/Widgets/ActiveWindow.qml +++ b/Modules/Bar/Widgets/ActiveWindow.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Effects import QtQuick.Layouts import Quickshell import Quickshell.Wayland @@ -255,6 +256,9 @@ Item { id: titleContainer text: windowTitle Layout.alignment: Qt.AlignVCenter + Layout.preferredHeight: root.capsuleHeight + fadeRoundLeftCorners: !showIcon + maxWidth: { // Calculate available width based on other elements var iconWidth = (showIcon && windowIcon.visible ? (iconSize + Style.marginS) : 0); @@ -270,9 +274,8 @@ Item { return NScrollText.ScrollMode.Never; } forcedHover: mainMouseArea.containsMouse - gradientColor: Style.capsuleColor - gradientWidth: Math.round(8 * Style.uiScaleRatio) - cornerRadius: Style.radiusM + fadeExtent: 0.1 + fadeCornerRadius: Style.radiusM NText { text: windowTitle diff --git a/Modules/Bar/Widgets/MediaMini.qml b/Modules/Bar/Widgets/MediaMini.qml index 0afb5831a..16473fbd8 100644 --- a/Modules/Bar/Widgets/MediaMini.qml +++ b/Modules/Bar/Widgets/MediaMini.qml @@ -1,5 +1,6 @@ import QtQuick import QtQuick.Controls +import QtQuick.Effects import QtQuick.Layouts import Quickshell import qs.Commons @@ -320,6 +321,7 @@ Item { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: capsuleHeight + fadeRoundLeftCorners: !(showAlbumArt || showProgressRing) text: title @@ -333,9 +335,8 @@ Item { cursorShape: hasPlayer ? Qt.PointingHandCursor : Qt.ArrowCursor maxWidth: root.maxWidth - root.mainContentWidth forcedHover: mainMouseArea.containsMouse - gradientColor: Style.capsuleColor - gradientWidth: Math.round(8 * Style.uiScaleRatio) - cornerRadius: Style.radiusM + fadeExtent: 0.1 + fadeCornerRadius: Style.radiusM NText { color: hasPlayer ? root.textColor : Color.mOnSurfaceVariant diff --git a/Modules/Panels/Media/MediaPlayerPanel.qml b/Modules/Panels/Media/MediaPlayerPanel.qml index 728a0ca2e..400738f9e 100644 --- a/Modules/Panels/Media/MediaPlayerPanel.qml +++ b/Modules/Panels/Media/MediaPlayerPanel.qml @@ -340,8 +340,8 @@ SmartPanel { return NScrollText.ScrollMode.Hover; return NScrollText.ScrollMode.Never; } - gradientColor: Color.mSurfaceVariant - cornerRadius: Style.radiusM + fadeExtent: 0.01 + fadeCornerRadius: Style.radiusM delegate: NText { pointSize: root.compactMode ? Style.fontSizeL : Style.fontSizeXL @@ -371,8 +371,8 @@ SmartPanel { return NScrollText.ScrollMode.Hover; return NScrollText.ScrollMode.Never; } - gradientColor: Color.mSurfaceVariant - cornerRadius: Style.radiusM + fadeExtent: 0.01 + fadeCornerRadius: Style.radiusM delegate: NText { pointSize: root.compactMode ? Style.fontSizeS : Style.fontSizeM diff --git a/Modules/Panels/Wallpaper/WallpaperPanel.qml b/Modules/Panels/Wallpaper/WallpaperPanel.qml index 4134db987..220654c2d 100644 --- a/Modules/Panels/Wallpaper/WallpaperPanel.qml +++ b/Modules/Panels/Wallpaper/WallpaperPanel.qml @@ -924,8 +924,7 @@ SmartPanel { text: isBrowseMode ? currentBrowsePath : WallpaperService.getMonitorDirectory(targetScreen?.name ?? "") Layout.fillWidth: true scrollMode: NScrollText.ScrollMode.Hover - gradientColor: Color.mSurfaceVariant - cornerRadius: Style.radiusM + fadeCornerRadius: Style.radiusM NText { text: isBrowseMode ? currentBrowsePath : WallpaperService.getMonitorDirectory(targetScreen?.name ?? "") diff --git a/Widgets/NScrollText.qml b/Widgets/NScrollText.qml index 553d21640..f9059d3b6 100644 --- a/Widgets/NScrollText.qml +++ b/Widgets/NScrollText.qml @@ -1,4 +1,5 @@ import QtQuick +import QtQuick.Effects import QtQuick.Layouts import qs.Commons @@ -39,13 +40,10 @@ Item { property real scrollCycleDuration: Math.max(4000, root.text.length * 120) property real resettingDuration: 300 - // gradient controls - property bool showGradients: true - property real gradientWidth: Math.round(12 * Style.uiScaleRatio) - property color gradientColor: Color.mSurfaceVariant - property real cornerRadius: 0 - - readonly property bool gradientsEnabled: root.showGradients && Settings.data.bar.capsuleOpacity >= 1.0 + // Fade controls + property real fadeExtent: 0.1 + property real fadeCornerRadius: 0 + property bool fadeRoundLeftCorners: true readonly property real contentWidth: { if (!titleText.item) @@ -55,10 +53,17 @@ Item { } readonly property real measuredWidth: scrollContainer.width - clip: true implicitWidth: alwaysMaxWidth ? maxWidth : Math.min(maxWidth, contentWidth) implicitHeight: titleText.height + layer.enabled: true + layer.effect: MultiEffect { + maskEnabled: true + maskThresholdMin: 0.5 + maskSpreadAtMin: 1.0 + maskSource: fadeMask + } + enum ScrollState { None = 0, Scrolling = 1, @@ -178,62 +183,36 @@ Item { } } - // Fade Gradients + // Transparency Fade Rectangle Rectangle { - id: leftGradient - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: root.gradientWidth - z: 2 - visible: root.gradientsEnabled && root.contentWidth > root.maxWidth - radius: root.cornerRadius - opacity: scrollContainer.x < -1 ? 1 : 0 + id: fadeMask + width: root.width + height: root.height + topLeftRadius: fadeRoundLeftCorners ? fadeCornerRadius : 0 + bottomLeftRadius: fadeRoundLeftCorners ? fadeCornerRadius : 0 + topRightRadius: fadeCornerRadius + bottomRightRadius: fadeCornerRadius gradient: Gradient { - orientation: Gradient.Horizontal - GradientStop { - position: 0.0 - color: root.gradientColor - } - GradientStop { - position: 1.0 - color: "transparent" - } - } - Behavior on opacity { - NumberAnimation { - duration: Style.animationFast - easing.type: Easing.InOutQuad - } - } - } - - Rectangle { - id: rightGradient - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - width: root.gradientWidth - z: 2 - visible: root.gradientsEnabled && root.contentWidth > root.maxWidth - radius: root.cornerRadius - opacity: 1 // Always show if overflowing as it loops - gradient: Gradient { - orientation: Gradient.Horizontal GradientStop { position: 0.0 color: "transparent" } + GradientStop { + position: fadeExtent + color: "white" + } + GradientStop { + position: 1 - fadeExtent + color: "white" + } GradientStop { position: 1.0 - color: root.gradientColor - } - } - Behavior on opacity { - NumberAnimation { - duration: Style.animationFast - easing.type: Easing.InOutQuad + color: "transparent" } + orientation: Gradient.Horizontal } + layer.enabled: true + layer.smooth: true + opacity: 0 // Great for debugging! Will show the white masks } }