Decode wallpapers at the size the screen can show - #9417
Open
VykosMolt wants to merge 1 commit into
Open
Conversation
The three `Image` elements in `Background.qml` set no `sourceSize`, so each one decodes its wallpaper at the file's native resolution and keeps it that way for as long as the background is up. A decoded image is uncompressed regardless of how small the file on disk is: `retro-82/5-zen-boat.webp` is 10456x3455, which is 138MB of RGBA held for a 2560x1600 screen that can show 16MB of it. 37 of the 92 wallpapers shipped in `themes/` are larger than the screens they are drawn on, and the two transition frames carry `mipmap: true`, which asks for another third on top of whatever was decoded. Each `Image` now caps `sourceSize`, so the decoder scales the image down as it reads it and the oversized buffer is never allocated. `oldFrame` and `incomingFrame` take their size from `base` so the three frames of a cross-fade always agree. The cap is 1.6x the screen rather than exactly the screen because setting both `sourceSize` dimensions makes Qt fit the image inside that box while preserving aspect. A box exactly the size of the screen would decode a 2.39:1 wallpaper too short to cover a 16:10 display, and `PreserveAspectCrop` would scale it back up to fill, which is the blur this is meant to avoid. 1.6x covers every aspect ratio up to 1.6 times the screen's own and still leaves the largest wallpapers well under their native size. The multiplier is the attached `Screen.devicePixelRatio`, matching `Menu.qml`, `Tray.qml` and `NotificationCard.qml`. `parent.screen` is not an option here: a child declared inside a `PanelWindow` is reparented to the window's `contentItem`, and a `QQuickItem` has no `screen` property, so reading it would silently yield `undefined` and decode every wallpaper at 1x.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The three
Imageelements inBackground.qmlset nosourceSize, so each decodes its wallpaper at the file's native resolution and holds it that way for as long as the background is up. A decoded image is uncompressed no matter how small the file on disk is:retro-82/5-zen-boat.webpis 10456x3455, which is 138MB of RGBA sitting in memory for a 2560x1600 screen that can show 16MB of it. 37 of the 92 wallpapers shipped inthemes/are larger than the screen they get drawn on, and the two transition frames carrymipmap: true, which asks for roughly another third on top of whatever was decoded.Each
Imagenow capssourceSize, so the decoder scales the image down as it reads it and the oversized buffer is never allocated in the first place.oldFrameandincomingFrametake their size frombase, so the three frames of a cross-fade always agree on one size.The cap is 1.6x the screen rather than exactly the screen, because setting both
sourceSizedimensions makes Qt fit the image inside that box while preserving aspect. A box exactly the size of the screen would decode a 2.39:1 wallpaper too short to cover a 16:10 display, andPreserveAspectCropwould then scale it back up to fill, which is the blur this is meant to avoid. 1.6x covers every aspect ratio up to 1.6 times the screen's own and still leaves the largest wallpapers far under their native size.The multiplier is the attached
Screen.devicePixelRatio, which is whatMenu.qml,Tray.qmlandNotificationCard.qmlalready use.parent.screenis not an option here: a child declared inside aPanelWindowis reparented to the window'scontentItem, and aQQuickItemhas noscreenproperty, so reading it yieldsundefinedand would quietly decode every wallpaper at 1x. I had that wrong in a first draft and the attached property is the one that resolves.This is independent of #9312 and #9313, which change which background file gets resolved and served. This caps how large whatever is served decodes, so it still applies on top of either.
Testing
background-test.shgains three assertions: the base image caps its decode against the screen size and device pixel ratio, the two transition frames decode at the same size as the wallpaper they cross-fade, and everyImagein the file caps its decode. The first fails on current quattro, which sets nosourceSizeanywhere in the file.Decoded RGBA for the wallpapers shipped in
themes/, measured against a 2560x1600 screen:37 of the 92 shipped wallpapers shrink like this. The other 55 are already inside the box and decode exactly as they do today, so this caps the tail rather than changing the common case. On a smaller or lower-DPI screen the box is smaller and more of them are affected.
./test/shell— 217 of 221 files pass; the four failures (config-test,runtime-smoke-test,snapper-test,unowned-system-paths-test) fail identically on unmodified quattro on this machine.This comes out of https://github.com/VykosMolt/omarchy-desktop, where I have been running the Quattro shell as a plain Arch session and fixing what turned up.