Let OWE own video backgrounds while it runs

The background plugin now watches for the OWE daemon socket. While OWE is
running, the desktop yields video playback to it and the shell keeps
stills. The lock screen keeps its own playback.

This lets Omarchy cooperate with OWE without OWE editing shell.json, so
the engine can ship as a package.

Add a package-list note that owe-wallpaper-engine must be added once it is
packaged.
This commit is contained in:
Bjarne Oeverli committed 2026-09-18 18:23:21 +02:00
1 parent d174d4aa27
commit d01ef2d5d0
5 files changed
+41 -3

No files matched your search

+2
View File
@@ -107,6 +107,8 @@ python-poetry-core
ttfx ttfx
qemu-user-static-binfmt qemu-user-static-binfmt
qrencode qrencode
# TODO: add owe-wallpaper-engine here once it is packaged. The shell yields
# video backgrounds to it while its daemon runs.
qt6-imageformats qt6-imageformats
qt6-multimedia qt6-multimedia
qt6-multimedia-ffmpeg qt6-multimedia-ffmpeg
+1 -1
View File
@@ -4,6 +4,6 @@ Every theme ships with its own set of backgrounds, and you can add extras of you
You can do this most easily by going to _Install > Style > Background_ in the Omarchy Menu. That'll bring up the folder where the backgrounds for that theme is stored. Hit `Super + Shift + F` to start another file manager, find your background, copy it over. Now it'll be included in the choices of backgrounds you can select between using `Super + Ctrl + Space`. You can do this most easily by going to _Install > Style > Background_ in the Omarchy Menu. That'll bring up the folder where the backgrounds for that theme is stored. Hit `Super + Shift + F` to start another file manager, find your background, copy it over. Now it'll be included in the choices of backgrounds you can select between using `Super + Ctrl + Space`.
Backgrounds can be videos as well as stills. Drop an `mp4`, `m4v`, `mov`, `webm`, `mkv`, or `avi` file in the same folder and it appears alongside the images, playing on a loop. Only your first monitor's wallpaper plays a video's sound track, through the default audio output at the system volume, and the lock screen stays silent. Playback stops on its own whenever nothing can see it — while a fullscreen window covers that monitor, while the screensaver is up, and once a locked screen has gone dark — but a video wallpaper still costs far more power than a still one, and each monitor decodes its own copy. Backgrounds can be videos as well as stills. Drop an `mp4`, `m4v`, `mov`, `webm`, `mkv`, or `avi` file in the same folder and it appears alongside the images, playing on a loop. Only your first monitor's wallpaper plays a video's sound track, through the default audio output at the system volume, and the lock screen stays silent. Playback stops on its own whenever nothing can see it — while a fullscreen window covers that monitor, while the screensaver is up, and once a locked screen has gone dark — but a video wallpaper still costs far more power than a still one, and each monitor decodes its own copy. When the OWE wallpaper engine is running, it takes over video backgrounds and the shell keeps only stills.
You can find a huge collection of cool curated backgrounds on https://github.com/dharmx/walls. You can find a huge collection of cool curated backgrounds on https://github.com/dharmx/walls.
+5 -1
View File
@@ -8,6 +8,10 @@ Item {
property int version: 0 property int version: 0
property bool playbackEnabled: true property bool playbackEnabled: true
property bool audioEnabled: false property bool audioEnabled: false
// The desktop yields video playback to OWE while it runs, so two engines
// never decode the same file. The lock screen leaves this off and keeps its
// own playback.
property bool deferVideo: false
// Bumped when the file behind an unchanged path may have been replaced. // Bumped when the file behind an unchanged path may have been replaced.
// Images cache-bust through version; a video is rebuilt, since FFmpeg // Images cache-bust through version; a video is rebuilt, since FFmpeg
// would read a query as part of the filename. // would read a query as part of the filename.
@@ -37,7 +41,7 @@ Item {
Loader { Loader {
id: videoLoader id: videoLoader
anchors.fill: parent anchors.fill: parent
active: root.path !== "" && root.video && !root.reloading active: root.path !== "" && root.video && !root.reloading && !root.deferVideo
source: "BackgroundVideo.qml" source: "BackgroundVideo.qml"
} }
+24 -1
View File
@@ -32,6 +32,25 @@ Item {
// services so playback can stop whenever nothing can see the wallpaper. // services so playback can stop whenever nothing can see the wallpaper.
property var shell: null property var shell: null
// When the OWE wallpaper engine is running, it owns video backgrounds. This
// plugin keeps stills, which OWE hands back to it, and the lock screen keeps
// its own playback.
property bool oweActive: false
Process {
id: oweStatusProc
command: ["bash", "-c", "test -S \"${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/owe/owed.sock\""]
onExited: root.oweActive = (exitCode === 0)
}
Timer {
id: oweStatusTimer
interval: 5000
repeat: true
running: true
onTriggered: if (!oweStatusProc.running) oweStatusProc.running = true
}
// Stop a video wallpaper's decoding whenever it is covered. Qt's FFmpeg // Stop a video wallpaper's decoding whenever it is covered. Qt's FFmpeg
// engine drives its own clock, so an unseen player keeps decoding until it // engine drives its own clock, so an unseen player keeps decoding until it
// is told not to — a locked laptop would otherwise decode until it died. // is told not to — a locked laptop would otherwise decode until it died.
@@ -204,7 +223,10 @@ Item {
} }
} }
Component.onCompleted: refreshBackground() Component.onCompleted: {
oweStatusProc.running = true
refreshBackground()
}
Variants { Variants {
model: Quickshell.screens model: Quickshell.screens
@@ -264,6 +286,7 @@ Item {
anchors.fill: parent anchors.fill: parent
path: root.displayedBackground path: root.displayedBackground
reloads: root.displayedReloads reloads: root.displayedReloads
deferVideo: root.oweActive
playbackEnabled: !root.sessionObscured && !root.powerSaverActive && !panel.fullscreenHere playbackEnabled: !root.sessionObscured && !root.powerSaverActive && !panel.fullscreenHere
audioEnabled: panel.firstScreen audioEnabled: panel.firstScreen
onReadyChanged: { onReadyChanged: {
+9
View File
@@ -87,6 +87,15 @@ assert(
'video switches bypass the image-only reveal stack and use the durable background path' 'video switches bypass the image-only reveal stack and use the durable background path'
) )
assert(backgroundQml.includes('BackgroundMedia {') && lockQml.includes('BackgroundMedia {'), 'desktop and lock screen share video-capable media rendering') assert(backgroundQml.includes('BackgroundMedia {') && lockQml.includes('BackgroundMedia {'), 'desktop and lock screen share video-capable media rendering')
assert(
backgroundQml.includes('property bool oweActive: false') &&
backgroundQml.includes('/owe/owed.sock') &&
/deferVideo: root\.oweActive/.test(backgroundQml) &&
/property bool deferVideo: false/.test(mediaQml) &&
/active: root\.path !== "" && root\.video && !root\.reloading && !root\.deferVideo/.test(mediaQml) &&
!lockQml.includes('deferVideo'),
'the desktop yields video backgrounds to OWE while it is running, and the lock keeps its own playback'
)
assert( assert(
lockQml.includes('source: wallpaper.video ? null : wallpaper') && lockQml.includes('source: wallpaper.video ? null : wallpaper') &&
lockQml.includes('visible: !wallpaper.video') && lockQml.includes('visible: !wallpaper.video') &&