mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
233 lines
6.7 KiB
QML
233 lines
6.7 KiB
QML
import QtQuick
|
|
import QtQuick.Effects
|
|
import qs.Common
|
|
import qs.Services
|
|
|
|
Item {
|
|
id: root
|
|
|
|
readonly property var log: Log.scoped("BlurredWallpaperLive")
|
|
|
|
required property string wallpaperSource
|
|
required property string initialSource
|
|
required property string screenName
|
|
required property size blurTextureSize
|
|
|
|
readonly property bool currentFailed: currentWallpaper.status === Image.Error
|
|
readonly property bool displayableNow: currentWallpaper.status === Image.Ready || currentWallpaper.status === Image.Error
|
|
readonly property bool stable: isInitialized && !effectActive && !transitionAnimation.running && !transitionDelayTimer.running && currentWallpaper.status === Image.Ready && currentWallpaper.source.toString() === wallpaperSource && !nextWallpaper.source.toString()
|
|
|
|
signal becameDisplayable
|
|
|
|
property bool isInitialized: false
|
|
property real transitionProgress: 0
|
|
readonly property bool transitioning: transitionAnimation.running
|
|
property bool effectActive: false
|
|
property bool useNextForEffect: false
|
|
|
|
Component.onCompleted: {
|
|
if (initialSource && initialSource !== wallpaperSource && !(CompositorService.isNiri && SessionData.isSwitchingMode)) {
|
|
currentWallpaper.source = initialSource;
|
|
isInitialized = true;
|
|
changeWallpaper(wallpaperSource);
|
|
return;
|
|
}
|
|
currentWallpaper.source = wallpaperSource;
|
|
isInitialized = true;
|
|
}
|
|
|
|
onWallpaperSourceChanged: {
|
|
if (!isInitialized)
|
|
return;
|
|
if (!wallpaperSource) {
|
|
setWallpaperImmediate("");
|
|
return;
|
|
}
|
|
if (!currentWallpaper.source.toString()) {
|
|
setWallpaperImmediate(wallpaperSource);
|
|
return;
|
|
}
|
|
if (CompositorService.isNiri && SessionData.isSwitchingMode) {
|
|
setWallpaperImmediate(wallpaperSource);
|
|
return;
|
|
}
|
|
changeWallpaper(wallpaperSource);
|
|
}
|
|
|
|
function handleTransitionLoadError(failedSource) {
|
|
log.warn("failed to load candidate wallpaper for", screenName + ":", failedSource);
|
|
transitionDelayTimer.stop();
|
|
transitionAnimation.stop();
|
|
useNextForEffect = false;
|
|
effectActive = false;
|
|
transitionProgress = 0.0;
|
|
nextWallpaper.source = "";
|
|
}
|
|
|
|
function setWallpaperImmediate(newSource) {
|
|
transitionDelayTimer.stop();
|
|
transitionAnimation.stop();
|
|
transitionProgress = 0.0;
|
|
effectActive = false;
|
|
currentWallpaper.source = newSource;
|
|
nextWallpaper.source = "";
|
|
}
|
|
|
|
function startTransition() {
|
|
useNextForEffect = true;
|
|
effectActive = true;
|
|
if (srcNext.scheduleUpdate)
|
|
srcNext.scheduleUpdate();
|
|
transitionDelayTimer.start();
|
|
}
|
|
|
|
function changeWallpaper(newPath) {
|
|
if (!newPath)
|
|
return;
|
|
if (newPath === currentWallpaper.source.toString())
|
|
return;
|
|
if (transitioning) {
|
|
transitionAnimation.stop();
|
|
transitionProgress = 0;
|
|
effectActive = false;
|
|
currentWallpaper.source = nextWallpaper.source;
|
|
nextWallpaper.source = "";
|
|
}
|
|
if (!currentWallpaper.source.toString()) {
|
|
setWallpaperImmediate(newPath);
|
|
return;
|
|
}
|
|
|
|
nextWallpaper.source = newPath;
|
|
|
|
if (nextWallpaper.status === Image.Ready)
|
|
startTransition();
|
|
}
|
|
|
|
Timer {
|
|
id: transitionDelayTimer
|
|
interval: 16
|
|
repeat: false
|
|
onTriggered: transitionAnimation.start()
|
|
}
|
|
|
|
Image {
|
|
id: currentWallpaper
|
|
anchors.fill: parent
|
|
visible: false
|
|
opacity: 1
|
|
asynchronous: true
|
|
retainWhileLoading: true
|
|
smooth: true
|
|
cache: true
|
|
sourceSize: root.blurTextureSize
|
|
fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName))
|
|
|
|
onStatusChanged: {
|
|
if (status === Image.Error) {
|
|
root.log.warn("failed to load active wallpaper for", root.screenName + ":", source);
|
|
}
|
|
if (status === Image.Ready || status === Image.Error) {
|
|
root.becameDisplayable();
|
|
}
|
|
}
|
|
}
|
|
|
|
Image {
|
|
id: nextWallpaper
|
|
anchors.fill: parent
|
|
visible: false
|
|
opacity: 0
|
|
asynchronous: true
|
|
retainWhileLoading: true
|
|
smooth: true
|
|
cache: true
|
|
sourceSize: root.blurTextureSize
|
|
fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(root.screenName))
|
|
|
|
onStatusChanged: {
|
|
if (status === Image.Error) {
|
|
root.handleTransitionLoadError(source);
|
|
return;
|
|
}
|
|
if (status !== Image.Ready)
|
|
return;
|
|
if (!root.transitioning) {
|
|
root.startTransition();
|
|
}
|
|
}
|
|
}
|
|
|
|
ShaderEffectSource {
|
|
id: srcNext
|
|
sourceItem: root.effectActive ? nextWallpaper : null
|
|
hideSource: root.effectActive
|
|
live: root.effectActive
|
|
mipmap: false
|
|
recursive: false
|
|
textureSize: root.blurTextureSize
|
|
}
|
|
|
|
Rectangle {
|
|
id: dummyRect
|
|
width: 1
|
|
height: 1
|
|
visible: false
|
|
color: "transparent"
|
|
}
|
|
|
|
ShaderEffectSource {
|
|
id: srcDummy
|
|
sourceItem: dummyRect
|
|
hideSource: true
|
|
live: false
|
|
mipmap: false
|
|
recursive: false
|
|
}
|
|
|
|
Item {
|
|
id: blurredLayer
|
|
anchors.fill: parent
|
|
|
|
MultiEffect {
|
|
anchors.fill: parent
|
|
source: currentWallpaper
|
|
visible: currentWallpaper.source !== ""
|
|
blurEnabled: true
|
|
blur: 0.8
|
|
blurMax: 75
|
|
opacity: 1 - root.transitionProgress
|
|
autoPaddingEnabled: false
|
|
}
|
|
|
|
MultiEffect {
|
|
anchors.fill: parent
|
|
source: root.useNextForEffect ? srcNext : srcDummy
|
|
visible: nextWallpaper.source !== "" && root.useNextForEffect
|
|
blurEnabled: true
|
|
blur: 0.8
|
|
blurMax: 75
|
|
opacity: root.transitionProgress
|
|
autoPaddingEnabled: false
|
|
}
|
|
}
|
|
|
|
NumberAnimation {
|
|
id: transitionAnimation
|
|
target: root
|
|
property: "transitionProgress"
|
|
from: 0.0
|
|
to: 1.0
|
|
duration: 1000
|
|
easing.type: Easing.InOutCubic
|
|
onFinished: {
|
|
if (nextWallpaper.source && nextWallpaper.status === Image.Ready)
|
|
currentWallpaper.source = nextWallpaper.source;
|
|
root.useNextForEffect = false;
|
|
nextWallpaper.source = "";
|
|
root.transitionProgress = 0.0;
|
|
root.effectActive = false;
|
|
}
|
|
}
|
|
}
|