diff --git a/shell/plugins/image-picker/ImagePicker.qml b/shell/plugins/image-picker/ImagePicker.qml index 9fcc1f1b..bb448692 100644 --- a/shell/plugins/image-picker/ImagePicker.qml +++ b/shell/plugins/image-picker/ImagePicker.qml @@ -603,13 +603,15 @@ Item { Image { id: image anchors.fill: parent - // Even an uncached 6K wallpaper decodes at card size, off the - // GUI thread. Departing cards release their images instead of - // retaining every preview visited in a large collection. + // Decode at the expanded card's physical size, off the GUI + // thread. Keep that size during navigation to avoid reloads. + // Departing cards release their images instead of retaining + // every preview visited in a large collection. // Queue the selected preview first; neighbors must not delay // the image the user opened the picker to see. source: (item.selected || root.neighborImagesEnabled) && item.thumbnailPath ? Util.fileUrl(item.thumbnailPath) : "" - sourceSize: Qt.size(root.expandedWidth, root.expandedHeight) + sourceSize.width: Math.ceil(root.expandedWidth * Screen.devicePixelRatio) + sourceSize.height: Math.ceil(root.expandedHeight * Screen.devicePixelRatio) fillMode: Image.PreserveAspectCrop asynchronous: true cache: false diff --git a/test/shell.d/image-picker-test.sh b/test/shell.d/image-picker-test.sh index 1527fc7b..c1cfc03e 100644 --- a/test/shell.d/image-picker-test.sh +++ b/test/shell.d/image-picker-test.sh @@ -151,10 +151,24 @@ assert( ) assert( /model: visibleImages/.test(imagePickerQml) && - /sourceSize: Qt\.size\(root\.expandedWidth, root\.expandedHeight\)/.test(imagePickerQml) && /asynchronous: true\s*cache: false/.test(imagePickerQml), 'image picker renders its window with bounded asynchronous decoding' ) +const sourceWidth = imagePickerQml.match(/sourceSize\.width: ([^\n]+)/)[1] +const sourceHeight = imagePickerQml.match(/sourceSize\.height: ([^\n]+)/)[1] +const decodeSize = new Function('root', 'Screen', `return [${sourceWidth}, ${sourceHeight}]`) +for (const [scale, expected] of [ + [1, [768, 475]], + [1.25, [960, 594]], + [1.5, [1152, 713]], + [2, [1536, 950]] +]) { + assertDeepEqual( + decodeSize({ expandedWidth: 768, expandedHeight: 475 }, { devicePixelRatio: scale }), + expected, + `image picker decodes enough physical pixels at ${scale}x display scale` + ) +} assert( imagePickerQml.includes('(item.selected || root.neighborImagesEnabled)') && /onStatusChanged: if \(item.selected && \(status === Image.Ready \|\| status === Image.Error\)\) root.neighborImagesEnabled = true/.test(imagePickerQml),