Claude 2365d303f3 Fix frame upload: Clutter.Image isn't constructible from GJS anymore
The polling fix worked and pinpointed the real, final bug: appsink was
delivering frames correctly (confirmed by the polling infrastructure
itself running fine), but every single upload attempt threw
"(intermediate value).Image is not a constructor" from `new
Clutter.Image()`. In current Mutter, Clutter.Image apparently isn't
directly constructible via `new` from GJS anymore, and the resulting
exception was also flooding the log at ~30/sec with no rate limiting.

Adds St.ImageContent.new_with_preferred_size() + set_bytes(GLib.Bytes)
as the primary path — the same mechanism gnome-shell's own code uses
for uploading raw pixel buffers onto actors — with the old
Clutter.Image/set_data() path kept only as a fallback for older
shells. The two are tried in order per frame size change and "pinned"
once one works, avoiding a live per-frame strategy search. Also
rate-limits the poll error log to the 1st and every 300th failure
instead of every single one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RDqbdjsiisSU7CbQke4g8
2026-08-04 01:26:38 +00:00
2026-08-04 01:48:27 +02:00

BenthicBloom

A GNOME Shell 50 extension that automatically rotates your wallpaper, supports looping video (live) wallpapers, and includes built-in protection against OLED burn-in.

Features

  • Auto rotation — pick one or more folders and BenthicBloom cycles through the images inside them on a timer, in sequential or shuffled order, with an optional crossfade between changes. The chosen wallpaper can also be applied to the lock screen.
  • Live wallpapers — play a looping video or animated GIF as your desktop background. Frames are decoded with GStreamer and rendered directly by GNOME Shell's own Clutter stage (no external, incompatible Clutter build involved). Playback can automatically pause on battery power or while a window is fullscreen. Automatic rotation is automatically suspended while a live wallpaper is actually on screen (and resumes afterward), since changing the static wallpaper would otherwise repaint over the video.
  • OLED burn-in protection — three independent, individually toggled techniques:
    • Pixel shifting: nudges the background a few pixels on a slow drift cycle so the same subpixels aren't lit continuously.
    • Idle dimming: fades the background to a configurable lower brightness after the system has been idle for a while, and restores it the moment you're back.
    • Forced rotation: guarantees the wallpaper changes after a maximum static duration, even if automatic rotation is otherwise switched off.
  • A top-bar indicator for quick access to rotation, live wallpaper, and OLED protection toggles, plus a "Next Wallpaper" action, and a full libadwaita preferences window.

Requirements

  • GNOME Shell 50.
  • For live wallpapers: GStreamer with its good and base plugin sets (e.g. gstreamer1.0-plugins-good and gstreamer1.0-plugins-base, or your distribution's equivalent) — the good set is also what provides animated GIF decoding. If these aren't installed, the live wallpaper toggle stays disabled and BenthicBloom's other features work normally.

Installation

From source

git clone https://github.com/quinta0/benthicbloom.git
cd benthicbloom
make install

Then reload GNOME Shell — press Alt+F2, type r, press Enter on X11, or log out and back in on Wayland — and enable the extension:

gnome-extensions enable benthicbloom@quinta0.github.io

Packaging a zip

make pack

produces dist/benthicbloom@quinta0.github.io.shell-extension.zip, installable via gnome-extensions install <file> or the Extensions app.

Configuration

Open preferences from the panel indicator's "Wallpaper Settings…" entry, or run:

gnome-extensions prefs benthicbloom@quinta0.github.io
  • General — panel indicator visibility, lock screen syncing, debug logging, and the folders scanned for wallpapers.
  • Rotation — enable/disable, interval, shuffle vs. sequential order, and crossfade transition settings.
  • Live Wallpaper — enable/disable, video file, mute, playback speed, and power-saving pause behavior.
  • OLED Protection — master switch plus independent controls for pixel shifting, idle dimming, and forced periodic rotation.

Architecture

extension.js            Entry point: wires up the three managers + indicator
prefs.js                 libadwaita preferences window
lib/settingsKeys.js       GSettings key name constants
lib/logger.js             Small logging wrapper gated by the debug-logging setting
lib/wallpaperSource.js    Async folder scanning for image files
lib/shuffleBag.js         No-immediate-repeat random ordering for shuffle mode
lib/rotationManager.js    Timer-driven wallpaper rotation + crossfade overlay
lib/liveWallpaper.js      GStreamer video playback rendered onto a Clutter actor
lib/oledProtection.js     Pixel shifting, idle dimming, forced rotation
lib/indicator.js          Top-bar quick-access menu
schemas/                  GSettings schema

Known limitations

  • The live wallpaper currently renders across the full stage as a single layer, so on multi-monitor setups the video spans across all monitors as one canvas rather than being tiled per-monitor.
  • Pixel shifting and idle dimming rely on GNOME Shell's private Main.layoutManager._backgroundGroup and Meta.IdleMonitor APIs, which are not part of the stable extension API and could change in future shell versions.

Testing

This was developed and validated (JSON, GSettings schema compilation, and JavaScript syntax) without a live GNOME Shell 50 session available in the development environment. Before relying on it, test in a nested session:

dbus-run-session -- gnome-shell --nested --wayland

or on a real GNOME 50 desktop, and please file an issue with any problems you hit.

License

GPL-3.0-or-later — see LICENSE.

S
Description
A GNOME Shell 50 extension that rotates your wallpaper, supports looping video (live) wallpapers, and protects OLED displays from burn-in.
Readme GPL-3.0
118 KiB
Latest
2026-08-11 17:41:35 +02:00
Languages
JavaScript 98.9%
Makefile 1%
CSS 0.1%