wallpaper: reverting to the usual battle tested implementation

This commit is contained in:
Lemmy
2026-02-17 15:30:17 -05:00
parent 2ba86f4eb6
commit 9ae8f17ffe
+46 -127
View File
@@ -61,18 +61,6 @@ Variants {
// Solid color mode - track whether current/next are solid colors
property bool isSolid1: false
property bool isSolid2: false
// Actual pixel dimensions of the cached image file, fetched asynchronously via
// getImageDimensions(). Decoupled from source1.sourceSize.* which reflects Qt's
// sourceSize-constrained decoded size and is NOT the same as the file's true
// dimensions when sourceSize constrains a non-native aspect ratio. Shaders need
// the true file dimensions for accurate fill-mode UV math (center, tile, and
// crop/fit for non-matching aspect ratios). Falls back to sourceSize when unknown.
property real _currentImageWidth: 0
property real _currentImageHeight: 0
property real _nextImageWidth: 0
property real _nextImageHeight: 0
property color _solidColor1: Settings.data.wallpaper.solidColor
property color _solidColor2: Settings.data.wallpaper.solidColor
property vector4d solidColor1: Qt.vector4d(_solidColor1.r, _solidColor1.g, _solidColor1.b, 1.0)
@@ -109,8 +97,6 @@ Variants {
Connections {
target: CompositorService
function onDisplayScalesChanged() {
root._targetPixelSize = Qt.size(Math.round(modelData.width * CompositorService.getDisplayScale(modelData.name)), Math.round(modelData.height * CompositorService.getDisplayScale(modelData.name)));
if (!WallpaperService.isInitialized) {
return;
}
@@ -122,8 +108,10 @@ Variants {
if (isStartupTransition) {
// During startup, just ensure the correct cache exists without visual changes
const startupSize = root._getMaxCacheSizeForOrientation();
ImageCacheService.getLarge(currentPath, startupSize.width, startupSize.height, function (cachedPath, success) {
const compositorScale = CompositorService.getDisplayScale(modelData.name);
const targetWidth = Math.round(modelData.width * compositorScale);
const targetHeight = Math.round(modelData.height * compositorScale);
ImageCacheService.getLarge(currentPath, targetWidth, targetHeight, function (cachedPath, success) {
WallpaperService.wallpaperProcessingComplete(modelData.name, currentPath, success ? cachedPath : "");
});
return;
@@ -133,42 +121,6 @@ Variants {
}
}
// Target pixel dimensions for this screen (physical pixels, accounting for compositor scaling).
// Used as sourceSize on wallpaper Image elements so Qt never decodes a source image to a
// resolution larger than what the display actually needs, which is the main source of
// avoidable VRAM waste (especially when ImageMagick is unavailable and the original file
// is a high-resolution image such as 4K).
property size _targetPixelSize: Qt.size(Math.round(modelData.width * CompositorService.getDisplayScale(modelData.name)), Math.round(modelData.height * CompositorService.getDisplayScale(modelData.name)))
// Largest pixel dimensions among monitors that share this screen's orientation
// (landscape vs portrait). Monitors of the same orientation reuse the same
// ImageMagick-cached file on disk, cutting redundant processing while avoiding
// the broken results that occur when a landscape-sized cache is fed to a portrait
// monitor (or vice versa). Qt's sourceSize (_targetPixelSize) still caps GPU
// decode to each monitor's own resolution, so smaller displays have no VRAM overhead.
function _getMaxCacheSizeForOrientation() {
const myIsPortrait = modelData.height > modelData.width;
let maxW = 0, maxH = 0;
for (let i = 0; i < Quickshell.screens.length; i++) {
const screen = Quickshell.screens[i];
const screenIsPortrait = screen.height > screen.width;
if (screenIsPortrait !== myIsPortrait)
continue;
const scale = CompositorService.getDisplayScale(screen.name);
const w = Math.round(screen.width * scale);
const h = Math.round(screen.height * scale);
if (w * h > maxW * maxH) {
maxW = w;
maxH = h;
}
}
if (maxW === 0 || maxH === 0) {
const scale = CompositorService.getDisplayScale(modelData.name);
return Qt.size(Math.round(modelData.width * scale), Math.round(modelData.height * scale));
}
return Qt.size(maxW, maxH);
}
color: "transparent"
screen: modelData
WlrLayershell.layer: WlrLayer.Background
@@ -203,7 +155,6 @@ Variants {
id: currentWallpaper
source: ""
sourceSize: root._targetPixelSize
smooth: true
mipmap: false
visible: false
@@ -224,7 +175,6 @@ Variants {
property bool pendingTransition: false
source: ""
sourceSize: root._targetPixelSize
smooth: true
mipmap: false
visible: false
@@ -280,16 +230,16 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -310,7 +260,7 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness
property real direction: root.wipeDirection
@@ -318,10 +268,10 @@ Variants {
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -342,7 +292,7 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness
property real aspectRatio: root.width / root.height
@@ -352,10 +302,10 @@ Variants {
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -376,7 +326,7 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
property real smoothness: root.edgeSmoothness
property real aspectRatio: root.width / root.height
@@ -386,10 +336,10 @@ Variants {
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -410,17 +360,17 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
property real maxBlockSize: root.pixelateMaxBlockSize
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -441,7 +391,7 @@ Variants {
anchors.fill: parent
property variant source1: currentWallpaper
property variant source2: root.transitioning ? nextWallpaper : null
property variant source2: nextWallpaper
property real progress: root.transitionProgress
property real cellSize: root.honeycombCellSize
property real centerX: root.honeycombCenterX
@@ -451,10 +401,10 @@ Variants {
// Fill mode properties
property real fillMode: root.fillMode
property vector4d fillColor: root.fillColor
property real imageWidth1: root._currentImageWidth > 0 ? root._currentImageWidth : source1.sourceSize.width
property real imageHeight1: root._currentImageHeight > 0 ? root._currentImageHeight : source1.sourceSize.height
property real imageWidth2: source2 ? (root._nextImageWidth > 0 ? root._nextImageWidth : source2.sourceSize.width) : 0.0
property real imageHeight2: source2 ? (root._nextImageHeight > 0 ? root._nextImageHeight : source2.sourceSize.height) : 0.0
property real imageWidth1: source1.sourceSize.width
property real imageHeight1: source1.sourceSize.height
property real imageWidth2: source2.sourceSize.width
property real imageHeight2: source2.sourceSize.height
property real screenWidth: width
property real screenHeight: height
@@ -490,12 +440,6 @@ Variants {
currentWallpaper.source = tempSource;
transitionProgress = 0.0;
// Promote next image dimensions to current
_currentImageWidth = _nextImageWidth;
_currentImageHeight = _nextImageHeight;
_nextImageWidth = 0;
_nextImageHeight = 0;
// Now clear nextWallpaper after currentWallpaper has the new source
// Force complete cleanup to free texture memory
Qt.callLater(() => {
@@ -551,8 +495,11 @@ Variants {
return;
}
const initialSize = _getMaxCacheSizeForOrientation();
ImageCacheService.getLarge(wallpaperPath, initialSize.width, initialSize.height, function (cachedPath, success) {
const compositorScale = CompositorService.getDisplayScale(modelData.name);
const targetWidth = Math.round(modelData.width * compositorScale);
const targetHeight = Math.round(modelData.height * compositorScale);
ImageCacheService.getLarge(wallpaperPath, targetWidth, targetHeight, function (cachedPath, success) {
if (success) {
futureWallpaper = cachedPath;
} else {
@@ -583,8 +530,11 @@ Variants {
return;
}
const cacheSize = _getMaxCacheSizeForOrientation();
ImageCacheService.getLarge(originalPath, cacheSize.width, cacheSize.height, function (cachedPath, success) {
const compositorScale = CompositorService.getDisplayScale(modelData.name);
const targetWidth = Math.round(modelData.width * compositorScale);
const targetHeight = Math.round(modelData.height * compositorScale);
ImageCacheService.getLarge(originalPath, targetWidth, targetHeight, function (cachedPath, success) {
// Ignore stale callback if we've moved on to a different wallpaper
if (originalPath !== transitioningToOriginalPath) {
return;
@@ -621,8 +571,6 @@ Variants {
if (isSolidSource) {
var colorStr = WallpaperService.getSolidColor(source);
_solidColor1 = colorStr;
_currentImageWidth = 0;
_currentImageHeight = 0;
// Clear image sources for memory efficiency
currentWallpaper.source = "";
nextWallpaper.source = "";
@@ -632,25 +580,12 @@ Variants {
return;
}
// Clear nextWallpaper to free texture memory
// Clear nextWallpaper completely to free texture memory
nextWallpaper.source = "";
_nextImageWidth = 0;
_nextImageHeight = 0;
nextWallpaper.sourceSize = undefined;
_currentImageWidth = 0;
_currentImageHeight = 0;
currentWallpaper.source = "";
// Fetch actual file dimensions for accurate fill-mode UV math in shaders.
// Runs concurrently with image loading; falls back to sourceSize until resolved.
const _immediateDimPath = source;
ImageCacheService.getImageDimensions(_immediateDimPath, function (w, h) {
if (w > 0)
_currentImageWidth = w;
if (h > 0)
_currentImageHeight = h;
});
Qt.callLater(() => {
currentWallpaper.source = source;
});
@@ -689,10 +624,6 @@ Variants {
_solidColor1 = _solidColor2;
const newCurrentSource = nextWallpaper.source;
currentWallpaper.source = newCurrentSource;
_currentImageWidth = _nextImageWidth;
_currentImageHeight = _nextImageHeight;
_nextImageWidth = 0;
_nextImageHeight = 0;
// Now clear nextWallpaper after current has the new source
Qt.callLater(() => {
@@ -717,8 +648,6 @@ Variants {
if (isSolidSource) {
var colorStr = WallpaperService.getSolidColor(source);
_solidColor2 = colorStr;
_nextImageWidth = 0;
_nextImageHeight = 0;
// No image to load, start transition immediately
nextWallpaper.source = "";
if (!wallpaperReady) {
@@ -728,16 +657,6 @@ Variants {
transitionAnimation.start();
} else {
nextWallpaper.source = source;
_nextImageWidth = 0;
_nextImageHeight = 0;
// Fetch actual file dimensions concurrently with image load
const _transitionDimPath = source;
ImageCacheService.getImageDimensions(_transitionDimPath, function (w, h) {
if (w > 0)
_nextImageWidth = w;
if (h > 0)
_nextImageHeight = h;
});
if (nextWallpaper.status === Image.Ready) {
if (!wallpaperReady) {
wallpaperReady = true;