* Decode the next theme background while the theme stages The wipe waited 125-290ms after the transition arrived, decoding the new wallpaper. Most stock wallpapers are WebP, which Qt decodes at full size and scales afterwards, so a screen-sized sourceSize does not shorten it. Start the decode earlier instead. omarchy-theme-set chooses the next background and snapshots it before rendering templates, then sends a new background prepare call in the background. The shell loads it into the hidden incoming frame, so the transition finds it decoded. A prepare that arrives after its transition is ignored, and one no transition claims is dropped after five seconds. The wipe now starts ~255ms after omarchy-theme-set begins instead of ~345-490ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Decode the wallpaper at screen size instead of shipped size Wallpapers decoded at the resolution they were shipped at: a 5120x2880 stock wallpaper took 5120x2880 of RGBA on a 1920x1200 panel, and a transition held up to three such frames. Bind sourceSize on the displayed wallpaper and both transition frames to the screen's physical size. PreserveAspectCrop treats it as the area to cover, so the image still fills the screen. Qt scales a decode up as well as down to cover sourceSize, so the native size is read from the file header first with magick identify, and a wallpaper smaller than the screen decodes at its own size. The images wait for both sizes, so nothing decodes at native size first. Ported from #8324 onto BackgroundMedia and the prepared incoming frame. Measured with a 5120x2880 wallpaper, the shell's GPU memory at rest drops from 264 MiB to ~148 MiB. The size probe delays the reveal by ~30ms, which the earlier prepare still more than covers. Co-authored-by: Ryan Yogan <ryanyogan@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Ryan Yogan <ryanyogan@gmail.com>
44 lines
1.6 KiB
QML
44 lines
1.6 KiB
QML
import QtQuick
|
|
import qs.Commons
|
|
|
|
// The shell draws stills only. OWE owns video backgrounds on the desktop, and
|
|
// it feeds the lock screen through its own socket.
|
|
Item {
|
|
id: root
|
|
|
|
property string path: ""
|
|
property int version: 0
|
|
// A caller that knows the size its screen needs, in physical pixels, sets
|
|
// constrainDecode and decodeSize. The image then waits for that size rather
|
|
// than decoding at the file's native size first.
|
|
property bool constrainDecode: false
|
|
property size decodeSize: Qt.size(0, 0)
|
|
readonly property var current: imageLoader.item
|
|
readonly property bool ready: current ? current.ready : false
|
|
readonly property bool video: Util.isVideoPath(path)
|
|
// Cache-bust images selected in a running lock session, so a theme switch
|
|
// that replaces the file behind an unchanged path shows the new pixels.
|
|
readonly property url imageUrl: path && !video ? Util.fileUrl(path) + (version ? "?v=" + version : "") : ""
|
|
|
|
Loader {
|
|
id: imageLoader
|
|
anchors.fill: parent
|
|
active: root.path !== "" && !root.video
|
|
sourceComponent: imageComponent
|
|
}
|
|
|
|
Component {
|
|
id: imageComponent
|
|
|
|
Image {
|
|
readonly property bool ready: status === Image.Ready
|
|
source: !root.constrainDecode || root.decodeSize.width > 0 ? root.imageUrl : ""
|
|
fillMode: Image.PreserveAspectCrop
|
|
asynchronous: true
|
|
cache: root.version === 0
|
|
sourceSize.width: root.constrainDecode ? root.decodeSize.width : (root.version > 0 ? width : 0)
|
|
sourceSize.height: root.constrainDecode ? root.decodeSize.height : (root.version > 0 ? height : 0)
|
|
}
|
|
}
|
|
}
|