diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index ef6cd39..b896099 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -5,6 +5,7 @@ import qs.Commons import qs.Services Variants { + id: backgroundVariants model: Quickshell.screens delegate: Loader { @@ -14,6 +15,25 @@ Variants { active: Settings.isLoaded && WallpaperService.getWallpaper(modelData.name) sourceComponent: PanelWindow { + id: root + + readonly property real transitionDuration: Settings.data.wallpaper.transitionDuration + readonly property real transitionType: Settings.data.wallpaper.transitionType + + property string servicedWallpaper: WallpaperService.getWallpaper(modelData.name) + onServicedWallpaperChanged: { + if (servicedWallpaper && servicedWallpaper !== currentWallpaper.source) { + if (Settings.data.wallpaper.transitionType == 'fade') { + setWallpaperWithTransition(servicedWallpaper) + } else { + setWallpaperImmediate(servicedWallpaper) + } + } + } + + // Internal state management + property bool transitioning: false + property real fadeValue: 0.0 color: Color.transparent screen: modelData @@ -29,12 +49,74 @@ Variants { } Image { + id: currentWallpaper anchors.fill: parent fillMode: Image.PreserveAspectCrop - source: WallpaperService.getWallpaper(modelData.name) + source: "" cache: true smooth: true mipmap: false + visible: false + } + + Image { + id: nextWallpaper + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: "" + cache: true + smooth: true + mipmap: false + visible: false + } + + ShaderEffect { + id: shaderEffect + anchors.fill: parent + + property variant source1: currentWallpaper + property variant source2: nextWallpaper + property real fade: fadeValue + fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/mix_images.frag.qsb") + } + + // Animation for the fade value + NumberAnimation { + id: fadeAnimation + target: root + property: "fadeValue" + from: 0.0 + to: 1.0 + duration: Settings.data.wallpaper.transitionDuration + easing.type: Easing.InOutQuad + + onFinished: { + // Swap images after transition completes + currentWallpaper.source = nextWallpaper.source + fadeValue = 0.0 + transitioning = false + } + } + + function startTransition() { + if (!transitioning && nextWallpaper.source != currentWallpaper.source) { + transitioning = true + fadeAnimation.start() + } + } + + function setWallpaperImmediate(source) { + currentWallpaper.source = source + nextWallpaper.source = source + fadeValue = 0.0 + transitioning = false + } + + function setWallpaperWithTransition(source) { + if (source != currentWallpaper.source) { + nextWallpaper.source = source + startTransition() + } } } } diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index daafb97..ea3a594 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -163,9 +163,8 @@ Singleton { changeWallpaper(screenName, randomPath) } } - } - else { - // Pick a random wallpaper for all screens + } else { + // Pick a random wallpaper common to all screens // We can use any screenName here, so we just pick the primary one. var wallpaperList = getWallpapersList(Screen.name) if (wallpaperList.length > 0) { diff --git a/Shaders/frag/mix_images.frag b/Shaders/frag/mix_images.frag new file mode 100644 index 0000000..10c3a63 --- /dev/null +++ b/Shaders/frag/mix_images.frag @@ -0,0 +1,22 @@ +#version 450 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; +layout(binding = 1) uniform sampler2D source1; +layout(binding = 2) uniform sampler2D source2; +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + float fade; +}; + +void main() { + vec4 color1 = texture(source1, qt_TexCoord0); + vec4 color2 = texture(source2, qt_TexCoord0); + + // Smooth cross-fade using smoothstep for better visual quality + float smoothFade = smoothstep(0.0, 1.0, fade); + + // Mix the two textures based on fade value + fragColor = mix(color1, color2, smoothFade) * qt_Opacity; +} \ No newline at end of file diff --git a/Shaders/qsb/mix_images.frag.qsb b/Shaders/qsb/mix_images.frag.qsb new file mode 100644 index 0000000..e06417c Binary files /dev/null and b/Shaders/qsb/mix_images.frag.qsb differ