aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/modules/appearance/WallShader.qml27
-rw-r--r--desktop/modules/appearance/WallpaperSpread.qml38
-rw-r--r--desktop/modules/appearance/Wallpapers.qml9
-rw-r--r--desktop/modules/appearance/burn.frag4
-rw-r--r--desktop/modules/appearance/burn.frag.qsbbin3983 -> 4027 bytes
5 files changed, 56 insertions, 22 deletions
diff --git a/desktop/modules/appearance/WallShader.qml b/desktop/modules/appearance/WallShader.qml
new file mode 100644
index 0000000..19826ac
--- /dev/null
+++ b/desktop/modules/appearance/WallShader.qml
@@ -0,0 +1,27 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+import QtQuick
+
+// One transition, by name, for the cover and the settings page's thumbnails.
+// Goes in the old picture's layer.effect, which fills in source. Every shader
+// draws the old picture at progress 0 and the new one at 1, and picks what it
+// needs from these properties. target must be an item with a layer: an Image
+// sampled directly gives the whole picture, not its PreserveAspectCrop crop.
+ShaderEffect {
+ property string name: "burn"
+ property var source
+ property var target
+ property real progress: 0
+ property real aspect: 1
+ property point origin: Qt.point(0.5, 0.5)
+ fragmentShader: Qt.resolvedUrl(name + ".frag.qsb")
+}
diff --git a/desktop/modules/appearance/WallpaperSpread.qml b/desktop/modules/appearance/WallpaperSpread.qml
index 02e5f94..f9e484b 100644
--- a/desktop/modules/appearance/WallpaperSpread.qml
+++ b/desktop/modules/appearance/WallpaperSpread.qml
@@ -16,8 +16,8 @@ import QtQuick
// The transition when Apply sets a wallpaper. swaybg has none: wallp kills
// the old one and starts a new one, which can show a frame of nothing. A
// surface on the bottom layer, above swaybg and below every window, covers
-// the swap: the old picture burns away over the new one, and the
-// surface goes once wallp has finished, by when the new swaybg is drawing
+// the swap: the old picture gives way to the new one, through the transition
+// Transitions picked, and the surface goes once wallp has finished, by when the new swaybg is drawing
// the same picture underneath. Sets from a terminal get no transition: by
// the time wall_h changes, swaybg has already swapped.
Scope {
@@ -34,6 +34,7 @@ Scope {
property bool running: false
property bool done: false
property real progress: 0
+ property string effect: "burn"
property point origin: Qt.point(0.5, 0.5)
visible: running
@@ -47,12 +48,12 @@ Scope {
Connections {
target: Wallpapers
- function onSwapping(which, from, to) {
+ function onSwapping(which, from, to, effect) {
if (which !== win.modelData.which || !win.screen) return;
anim.stop();
- // Behind the char band, so no pixel starts out scorched.
- win.progress = -0.05;
- // A different place each time the fire starts.
+ win.effect = effect;
+ win.progress = 0;
+ // A different place each time it starts.
win.origin = Qt.point(Math.random(), Math.random());
win.done = false;
oldImg.source = from;
@@ -69,7 +70,7 @@ Scope {
}
}
- // Both decoded before the first block drops, or the old one
+ // Both decoded before anything moves, or the old one
// would pop in late over a half-drawn screen.
readonly property bool ready: running && oldImg.status === Image.Ready
&& newImg.status === Image.Ready
@@ -88,7 +89,7 @@ Scope {
// -m fill is a centred crop, which is what PreserveAspectCrop does.
// Both hidden until both are decoded: the new one usually lands
// first, and drawn under an old one still loading it flashed
- // the new picture before the burn. Until then the surface is
+ // the new picture before the transition. Until then the surface is
// clear and swaybg shows the old picture itself.
Image {
id: newImg
@@ -98,6 +99,8 @@ Scope {
sourceSize: Qt.size(win.width, win.height)
asynchronous: true
cache: false
+ // A layer, so the shaders that read it get the crop.
+ layer.enabled: win.running
}
Image {
@@ -109,11 +112,12 @@ Scope {
asynchronous: true
cache: false
layer.enabled: win.running
- layer.effect: ShaderEffect {
- property real progress: win.progress
- property real aspect: win.width / Math.max(1, win.height)
- property point origin: win.origin
- fragmentShader: Qt.resolvedUrl("burn.frag.qsb")
+ layer.effect: WallShader {
+ name: win.effect
+ target: newImg
+ progress: win.progress
+ aspect: win.width / Math.max(1, win.height)
+ origin: win.origin
}
}
@@ -121,10 +125,10 @@ Scope {
id: anim
target: win
property: "progress"
- // Past 1: fbm can push a threshold a little over it. Linear,
- // since an ease spends its slow ends where nothing burns.
- to: 1.05
- duration: 3500
+ // Linear, since an ease spends its slow ends where nothing
+ // happens.
+ to: 1
+ duration: Transitions.duration
easing.type: Easing.Linear
onFinished: if (win.done) win.running = false
}
diff --git a/desktop/modules/appearance/Wallpapers.qml b/desktop/modules/appearance/Wallpapers.qml
index 582fb22..2b8faf7 100644
--- a/desktop/modules/appearance/Wallpapers.qml
+++ b/desktop/modules/appearance/Wallpapers.qml
@@ -59,7 +59,7 @@ Singleton {
signal applied(bool ok, string message)
// Sent before wallp runs, while current still names the old picture, so
// WallpaperSpread can cover the swap with it.
- signal swapping(string which, string from, string to)
+ signal swapping(string which, string from, string to, string effect)
// Every run's end, Apply's or the engine's. applied is Apply's alone: it
// reports to the save bar and closes the window.
signal finished(bool ok)
@@ -333,8 +333,9 @@ Singleton {
applying = true;
root.kind = kind;
let covers = 0;
- if (h !== "" && currentH !== "" && h !== currentH) { covers++; swapping("H", currentH, h); }
- if (v !== "" && currentV !== "" && v !== currentV) { covers++; swapping("V", currentV, v); }
+ const effect = Transitions.next();
+ if (h !== "" && currentH !== "" && h !== currentH) { covers++; swapping("H", currentH, h, effect); }
+ if (v !== "" && currentV !== "" && v !== currentV) { covers++; swapping("V", currentV, v, effect); }
const args = [];
if (h !== "") args.push(`H=${JSON.stringify(h)}`);
if (v !== "") args.push(`V=${JSON.stringify(v)}`);
@@ -349,7 +350,7 @@ Singleton {
// Covers still to come up before wallp may swap swaybg under them. The
// cover decodes its pictures asynchronously, and starting wallp with
// swapping showed the new picture through the still empty cover for a
- // moment, then the old one over it, then the burn. WallpaperSpread
+ // moment, then the old one over it, then the transition. WallpaperSpread
// calls covered() once it is drawing; a cover that never comes (a
// screen missing, a picture that fails to load) is waited out.
property int uncovered: 0
diff --git a/desktop/modules/appearance/burn.frag b/desktop/modules/appearance/burn.frag
index a5cb9c3..4f91a81 100644
--- a/desktop/modules/appearance/burn.frag
+++ b/desktop/modules/appearance/burn.frag
@@ -45,7 +45,9 @@ void main() {
vec2 asp = vec2(aspect, 1.0);
float d = length((qt_TexCoord0 - origin) * asp) / length(max(origin, 1.0 - origin) * asp);
float t = mix(d, fbm(qt_TexCoord0 * asp * 5.0), 0.5);
- float e = t - progress;
+ // Starts behind the char band, so no pixel starts out scorched, and ends
+ // past 1, since fbm can push a threshold a little over it.
+ float e = t - (progress * 1.1 - 0.05);
if (e <= 0.0) { fragColor = vec4(0.0); return; }
// Front to intact paper: flame, then char, then the picture.
diff --git a/desktop/modules/appearance/burn.frag.qsb b/desktop/modules/appearance/burn.frag.qsb
index 599a911..5344661 100644
--- a/desktop/modules/appearance/burn.frag.qsb
+++ b/desktop/modules/appearance/burn.frag.qsb
Binary files differ