mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
wallpaper: reverting to the usual battle tested implementation
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user