diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 4915386..fdca504 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -20,10 +20,11 @@ Variants { // Internal state management property bool firstWallpaper: true property string transitionType: "fade" - property bool transitioning: false property real transitionProgress: 0 - property real edgeSmoothness: Settings.data.wallpaper.transitionEdgeSmoothness + + readonly property real edgeSmoothness: Settings.data.wallpaper.transitionEdgeSmoothness readonly property var allTransitions: WallpaperService.allTransitions + readonly property bool transitioning: transitionAnimation.running // Wipe direction: 0=left, 1=right, 2=up, 3=down property real wipeDirection: 0 @@ -38,53 +39,15 @@ Variants { // External state management property string servicedWallpaper: WallpaperService.getWallpaper(modelData.name) + property string futureWallpaper: "" onServicedWallpaperChanged: { - if (servicedWallpaper && servicedWallpaper !== currentWallpaper.source) { - // Set wallpaper immediately on startup - if (firstWallpaper) { - firstWallpaper = false - setWallpaperImmediate(servicedWallpaper) - return - } - - // Get the transitionType from the settings - transitionType = Settings.data.wallpaper.transitionType - - if (transitionType == "random") { - var index = Math.floor(Math.random() * allTransitions.length) - transitionType = allTransitions[index] - } - - // Ensure the transition type really exists - if (transitionType !== "none" && !allTransitions.includes(transitionType)) { - transitionType = "fade" - } - - Logger.log("Background", "New wallpaper: ", servicedWallpaper, "On:", modelData.name, "Transition:", - transitionType) - - switch (transitionType) { - case "none": - setWallpaperImmediate(servicedWallpaper) - break - case "wipe": - wipeDirection = Math.random() * 4 - setWallpaperWithTransition(servicedWallpaper) - break - case "disc": - discCenterX = Math.random() - discCenterY = Math.random() - setWallpaperWithTransition(servicedWallpaper) - break - case "stripes": - stripesCount = Math.round(Math.random() * 24 + 6) - stripesAngle = Math.random() * 360 - setWallpaperWithTransition(servicedWallpaper) - break - default: - setWallpaperWithTransition(servicedWallpaper) - break - } + // Set wallpaper immediately on startup + if (firstWallpaper) { + firstWallpaper = false + setWallpaperImmediate(servicedWallpaper) + } else { + futureWallpaper = servicedWallpaper + debounceTimer.restart() } } @@ -101,6 +64,16 @@ Variants { left: true } + Timer { + id: debounceTimer + interval: 333 + running: false + repeat: false + onTriggered: { + changeWallpaper() + } + } + Image { id: currentWallpaper anchors.fill: parent @@ -110,6 +83,8 @@ Variants { mipmap: false visible: false cache: false + // currentWallpaper should not be asynchronous to avoid flickering when swapping next to current. + asynchronous: false } Image { @@ -121,6 +96,7 @@ Variants { mipmap: false visible: false cache: false + asynchronous: true } // Fade or None transition shader @@ -193,29 +169,27 @@ Variants { to: 1.0 // The stripes shader feels faster visually, we make it a bit slower here. duration: transitionType == "stripes" ? Settings.data.wallpaper.transitionDuration - * 1.4 : Settings.data.wallpaper.transitionDuration + * 1.6 : Settings.data.wallpaper.transitionDuration easing.type: Easing.InOutCubic onFinished: { // Swap images after transition completes currentWallpaper.source = nextWallpaper.source nextWallpaper.source = "" transitionProgress = 0.0 - transitioning = false } } function startTransition() { if (!transitioning && nextWallpaper.source != currentWallpaper.source) { - transitioning = true transitionAnimation.start() } } function setWallpaperImmediate(source) { + transitionAnimation.stop() + transitionProgress = 0.0 currentWallpaper.source = source nextWallpaper.source = "" - transitionProgress = 0.0 - transitioning = false } function setWallpaperWithTransition(source) { @@ -224,16 +198,55 @@ Variants { if (transitioning) { // We are interrupting a transition transitionAnimation.stop() + transitionProgress = 0 currentWallpaper.source = nextWallpaper.source nextWallpaper.source = "" - transitionProgress = 0 - transitioning = false } nextWallpaper.source = source startTransition() } } + + // Main method that actually trigger the wallpaper change + function changeWallpaper() { + // Get the transitionType from the settings + transitionType = Settings.data.wallpaper.transitionType + + if (transitionType == "random") { + var index = Math.floor(Math.random() * allTransitions.length) + transitionType = allTransitions[index] + } + + // Ensure the transition type really exists + if (transitionType !== "none" && !allTransitions.includes(transitionType)) { + transitionType = "fade" + } + + //Logger.log("Background", "New wallpaper: ", futureWallpaper, "On:", modelData.name, "Transition:", transitionType) + switch (transitionType) { + case "none": + setWallpaperImmediate(futureWallpaper) + break + case "wipe": + wipeDirection = Math.random() * 4 + setWallpaperWithTransition(futureWallpaper) + break + case "disc": + discCenterX = Math.random() + discCenterY = Math.random() + setWallpaperWithTransition(futureWallpaper) + break + case "stripes": + stripesCount = Math.round(Math.random() * 20 + 4) + stripesAngle = Math.random() * 360 + setWallpaperWithTransition(futureWallpaper) + break + default: + setWallpaperWithTransition(futureWallpaper) + break + } + } } } } diff --git a/Modules/SettingsPanel/Tabs/WallpaperSelectorTab.qml b/Modules/SettingsPanel/Tabs/WallpaperSelectorTab.qml index b708f9d..fcd9e50 100644 --- a/Modules/SettingsPanel/Tabs/WallpaperSelectorTab.qml +++ b/Modules/SettingsPanel/Tabs/WallpaperSelectorTab.qml @@ -8,6 +8,7 @@ import qs.Widgets ColumnLayout { id: root + width: parent.width spacing: Style.marginL * scaling @@ -94,12 +95,10 @@ ColumnLayout { GridView { id: wallpaperGridView anchors.fill: parent - clip: true model: wallpapersList - boundsBehavior: Flickable.StopAtBounds - flickableDirection: Flickable.VerticalFlick interactive: false + clip: true property int columns: 5 property int itemSize: Math.floor((width - leftMargin - rightMargin - (4 * Style.marginS * scaling)) / columns) @@ -180,7 +179,8 @@ ColumnLayout { anchors.fill: parent acceptedButtons: Qt.LeftButton hoverEnabled: true - onClicked: { + // Use on pressed instead of clicked to better register clicks + onPressed: { if (Settings.data.wallpaper.setWallpaperOnAllMonitors) { WallpaperService.changeWallpaper(undefined, wallpaperPath) } else { diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index 5e7bed6..b66ce2a 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -121,17 +121,17 @@ Singleton { // ------------------------------------------------------------------- function changeWallpaper(screenName, path) { if (screenName !== undefined) { - setWallpaper(screenName, path) + _setWallpaper(screenName, path) } else { // If no screenName specified change for all screens for (var i = 0; i < Quickshell.screens.length; i++) { - setWallpaper(Quickshell.screens[i].name, path) + _setWallpaper(Quickshell.screens[i].name, path) } } } // ------------------------------------------------------------------- - function setWallpaper(screenName, path) { + function _setWallpaper(screenName, path) { if (path === "" || path === undefined) { return } diff --git a/Shaders/frag/wp_stripes.frag b/Shaders/frag/wp_stripes.frag index 61a20f7..34df964 100644 --- a/Shaders/frag/wp_stripes.frag +++ b/Shaders/frag/wp_stripes.frag @@ -22,9 +22,9 @@ void main() { vec4 color1 = texture(source1, uv); // Current (old) wallpaper vec4 color2 = texture(source2, uv); // Next (new) wallpaper - // Map smoothness from 0.0-1.0 to 0.001-0.1 range + // Map smoothness from 0.0-1.0 to 0.001-0.3 range // Using a non-linear mapping for better control at low values - float mappedSmoothness = mix(0.001, 0.1, ubuf.smoothness * ubuf.smoothness); + float mappedSmoothness = mix(0.001, 0.3, ubuf.smoothness * ubuf.smoothness); // Use values directly without forcing defaults float stripes = (ubuf.stripeCount > 0.0) ? ubuf.stripeCount : 12.0; @@ -66,7 +66,7 @@ void main() { float normalizedStripePos = clamp(stripePos / stripes, 0.0, 1.0); // Increased delay and better distribution - float maxDelay = 0.15; + float maxDelay = 0.1; float stripeDelay = normalizedStripePos * maxDelay; // Better progress mapping that uses the full 0.0-1.0 range diff --git a/Shaders/qsb/wp_stripes.frag.qsb b/Shaders/qsb/wp_stripes.frag.qsb index 0d8d94e..4466bce 100644 Binary files a/Shaders/qsb/wp_stripes.frag.qsb and b/Shaders/qsb/wp_stripes.frag.qsb differ