From 59259e88b578224a7e669f289fdd532488df2ea0 Mon Sep 17 00:00:00 2001 From: SirBlobby Date: Thu, 24 Sep 2026 12:37:35 -0400 Subject: [PATCH] Animate GIF wallpapers in the shell --- bin/blob-wallpaper-set | 23 ----------------------- docs/packages.md | 1 - docs/shell.md | 10 ++++++++++ packages/blob.packages | 3 --- shell/plugins/background/Background.qml | 17 +++++++++++++++++ 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/bin/blob-wallpaper-set b/bin/blob-wallpaper-set index 41305ba..d26008d 100755 --- a/bin/blob-wallpaper-set +++ b/bin/blob-wallpaper-set @@ -107,32 +107,9 @@ fi NEW_BACKGROUND="$THEME_DIR/backgrounds/$(basename "$IMAGE_PATH")" -# Stop a gif daemon left over from a previous wallpaper. `awww kill` shuts the -# daemon down via its own IPC so it cleans up its socket, unlike a raw `pkill`. awww kill --all >/dev/null 2>&1 pkill -x awww-daemon 2>/dev/null -# blob-bg-set updates ~/.local/state/blob/current/background and -# tells the running Blob shell to repaint, which is what draws the desktop -# background in Blob 4 (swaybg is no longer involved). blob-bg-set "$NEW_BACKGROUND" -if [[ "${IMAGE_PATH,,}" == *.gif ]]; then - # The shell renders a still frame from the symlink above; awww layers the - # animation on top of it. - echo "GIF detected, using awww for animation..." - setsid uwsm-app -- awww-daemon >>"$HOME/.cache/awww-daemon.log" 2>&1 & - - # Poll until the daemon's IPC socket is ready instead of guessing a fixed sleep - IMG_ERROR="" - for _ in {1..15}; do - IMG_ERROR=$(awww img "$NEW_BACKGROUND" 2>&1) && break - sleep 0.3 - done - if [[ -n "$IMG_ERROR" ]]; then - echo "awww failed to set the wallpaper: $IMG_ERROR" - echo "See $HOME/.cache/awww-daemon.log for daemon output." - fi -fi - echo "Wallpaper and dynamic theme applied successfully: $IMAGE_PATH" diff --git a/docs/packages.md b/docs/packages.md index b2385b0..cfd3313 100644 --- a/docs/packages.md +++ b/docs/packages.md @@ -133,7 +133,6 @@ Omarchy's own package list, because they were installed by hand on this machine: | --- | --- | | `python-pywal16` | `blob-wallpaper-set`, palette extraction | | `python-terminaltexteffects` | `blob-screensaver`, the effects it draws | -| `awww` | the wallpaper daemon `blob-wallpaper-set` and `blob-theme-menu` drive | | `playerctl` | the quick settings media row | `playerctl` is in official `extra`, so it sits in the repo list. diff --git a/docs/shell.md b/docs/shell.md index 9b91090..31d81d8 100644 --- a/docs/shell.md +++ b/docs/shell.md @@ -88,6 +88,16 @@ Keys in the clock popup: | Enter | back to today, or pick the highlighted month | | Esc | close the month picker, then the popup | +## Animated wallpapers + +The background plugin draws a GIF wallpaper with `AnimatedImage`, so it moves +however it was set: the wallpaper picker, `blob wallpaper set`, `blob bg set`, +or a theme's own background. The transition into it shows the first frame, and +the animation starts once the transition finishes. Per-monitor wallpapers from +`blob bg monitor` animate the same way. `awww` is no longer needed; +`blob-wallpaper-set` and `blob-theme-menu` still stop a leftover `awww-daemon` +so it cannot paint over the shell. + ## Differences from upstream This shell was forked from Omarchy 4.0.4 and is not tracked against it. The diff --git a/packages/blob.packages b/packages/blob.packages index 188ad70..fec6616 100644 --- a/packages/blob.packages +++ b/packages/blob.packages @@ -114,9 +114,6 @@ libvips webp-pixbuf-loader ffmpegthumbnailer -# Theming -awww - # Capture grim slurp diff --git a/shell/plugins/background/Background.qml b/shell/plugins/background/Background.qml index 226ce59..4bc8cd0 100644 --- a/shell/plugins/background/Background.qml +++ b/shell/plugins/background/Background.qml @@ -41,6 +41,10 @@ Item { return Util.fileUrl(path) } + function isAnimated(path) { + return /\.gif$/i.test(String(path || "")) + } + function refreshBackground() { if (!readlinkProc.running) readlinkProc.running = true if (!monitorBackgroundProc.running) monitorBackgroundProc.running = true @@ -274,6 +278,19 @@ Item { } } + AnimatedImage { + id: animatedBase + readonly property string path: panel.hasAssignment ? panel.assignedBackground : root.displayedBackground + readonly property bool wanted: root.isAnimated(path) + anchors.fill: parent + source: wanted ? root.imageUrl(path) : "" + fillMode: Image.PreserveAspectCrop + asynchronous: true + cache: false + visible: wanted && status === AnimatedImage.Ready + playing: visible + } + Image { id: oldFrame anchors.fill: parent