Complete OWE service setup and lock feed fallback

This commit is contained in:
David Heinemeier Hansson committed 2026-09-20 20:36:19 -05:00
1 parent b0bf4876b1
commit b423f4993d
14 files changed
+289 -43

No files matched your search

-4
View File
@@ -4,8 +4,4 @@ import Owe.LockFeed
// Loaded through a Loader from LockView, so a system without the module shows
// no lock video instead of losing the whole lock screen.
LockFeed {
id: root
property bool feedEnabled: true
active: root.feedEnabled
}
+15 -22
View File
@@ -7,6 +7,7 @@ Item {
id: root
property string backgroundPath: ""
property string videoPosterPath: ""
property int backgroundVersion: 0
property bool fingerprintConfigured: false
property bool authenticatingPassword: false
@@ -91,34 +92,15 @@ Item {
BackgroundMedia {
id: wallpaper
objectName: "lockWallpaper"
anchors.fill: parent
path: root.video ? "" : root.backgroundPath
path: root.loadBackground ? (root.video ? root.videoPosterPath : root.backgroundPath) : ""
version: root.backgroundVersion
visible: !root.video
}
// OWE decodes the video once and feeds these frames to every lock surface.
// The feed pauses when this output blanks or on battery power saver.
Loader {
id: feedLoader
anchors.fill: parent
active: root.video
source: "LockFeedSurface.qml"
visible: status === Loader.Ready
Binding {
target: feedLoader.item
property: "feedEnabled"
value: root.feedActive
when: feedLoader.item !== null
restoreMode: Binding.RestoreNone
}
}
MultiEffect {
anchors.fill: wallpaper
source: root.video ? null : wallpaper
visible: !root.video
source: wallpaper
autoPaddingEnabled: false
blurEnabled: root.loadBackground && wallpaper.ready
blur: 1.0
@@ -127,6 +109,17 @@ Item {
contrast: -0.08
}
// The cached poster stays behind the feed when policy pauses playback,
// the module is unavailable, or a new connection has not received a frame.
Loader {
id: feedLoader
objectName: "lockFeedLoader"
anchors.fill: parent
active: root.feedActive
source: "LockFeedSurface.qml"
visible: status === Loader.Ready
}
// The feed item cannot be sampled by MultiEffect on every renderer.
// Keep video wallpapers visible and darken them slightly for legibility.
Rectangle {
+29
View File
@@ -28,6 +28,7 @@ Item {
property string failureMessage: ""
property int failedAttempts: 0
property string backgroundPath: ""
property string videoPosterPath: ""
property int backgroundVersion: 0
property string lastEvent: "init"
property string lastEventAt: ""
@@ -113,6 +114,16 @@ Item {
if (!readlinkProc.running) readlinkProc.running = true
}
function refreshPoster() {
if (!root.videoBackground) {
root.videoPosterPath = ""
return
}
if (posterProc.running) return
posterProc.sourcePath = root.backgroundPath
posterProc.running = true
}
function refreshFingerprintStatus() {
if (!fingerprintCheckProc.running) fingerprintCheckProc.running = true
}
@@ -307,6 +318,7 @@ Item {
id: lockView
anchors.fill: parent
backgroundPath: root.backgroundPath
videoPosterPath: root.videoPosterPath
backgroundVersion: root.backgroundVersion
fingerprintConfigured: root.fingerprintConfigured
authenticatingPassword: root.authenticatingPassword
@@ -339,6 +351,7 @@ Item {
LockView {
anchors.fill: parent
backgroundPath: root.backgroundPath
videoPosterPath: root.videoPosterPath
backgroundVersion: root.backgroundVersion
fingerprintConfigured: root.fingerprintConfigured
authenticatingPassword: false
@@ -409,9 +422,25 @@ Item {
onStreamFinished: {
var next = String(text || "").trim()
if (next !== root.backgroundPath) {
root.videoPosterPath = ""
root.backgroundPath = next
root.backgroundVersion += 1
}
root.refreshPoster()
}
}
}
Process {
id: posterProc
property string sourcePath: ""
command: ["bash", Quickshell.env("OMARCHY_PATH") + "/shell/plugins/lock/poster.sh", sourcePath]
stdout: StdioCollector { id: posterOutput; waitForEnd: true }
onExited: function(exitCode) {
if (sourcePath !== root.backgroundPath) {
root.refreshPoster()
} else {
root.videoPosterPath = exitCode === 0 ? String(posterOutput.text || "").trim() : ""
}
}
}
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
# One cached frame shared by all lock outputs, including when OWE is paused.
set -euo pipefail
source_path=$1
cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/lock-poster"
signature=$(stat -Lc '%s:%y:%z' "$source_path")
key=$(printf '%s\n%s' "$source_path" "$signature" | sha256sum | cut -d ' ' -f 1)
poster="$cache_dir/poster-$key.jpg"
mkdir -p "$cache_dir"
exec {lock_fd}>"$cache_dir/.lock"
flock -w 10 "$lock_fd"
if [[ ! -s $poster ]]; then
temporary=$(mktemp "$cache_dir/.poster-XXXXXX.jpg")
trap 'rm -f "$temporary"' EXIT
timeout -k 1 5 ffmpegthumbnailer -i "$source_path" -o "$temporary" -s 1920 -q 8 {lock_fd}>&-
[[ -s $temporary ]]
mv -f "$temporary" "$poster"
find "$cache_dir" -maxdepth 1 -type f -name 'poster-*.jpg' ! -name "poster-$key.jpg" -delete
fi
printf '%s\n' "$poster"