Implement BenthicBloom GNOME 50 wallpaper extension

Adds a complete GNOME Shell 50 extension with folder-based wallpaper
auto-rotation (shuffle/sequential, crossfade transitions, lock screen
sync), GStreamer-backed live/video wallpapers rendered onto the shell's
own Clutter stage, and OLED burn-in protection (pixel shifting, idle
dimming, forced periodic rotation). Includes a top-bar quick-access
indicator, a libadwaita preferences window, GSettings schema, and a
Makefile for install/packaging.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RDqbdjsiisSU7CbQke4g8
This commit is contained in:
Claude
2026-08-04 00:05:58 +00:00
parent 068c00c0ac
commit c0ec4a59d5
16 changed files with 1834 additions and 1 deletions
+76
View File
@@ -0,0 +1,76 @@
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
import {SettingsKey} from './lib/settingsKeys.js';
import {Logger} from './lib/logger.js';
import {RotationManager} from './lib/rotationManager.js';
import {LiveWallpaperManager} from './lib/liveWallpaper.js';
import {OledProtectionManager} from './lib/oledProtection.js';
import {BenthicBloomIndicator} from './lib/indicator.js';
export default class BenthicBloomExtension extends Extension {
enable() {
this._settings = this.getSettings();
this._logger = new Logger(this._settings, this.metadata.name);
this._rotationManager = new RotationManager(this._settings, this._logger);
this._liveWallpaperManager = new LiveWallpaperManager(this._settings, this._logger);
this._oledProtectionManager = new OledProtectionManager(this._settings, this._logger, {
forceNextWallpaper: maxSeconds => {
if (this._rotationManager.secondsSinceLastChange >= maxSeconds) {
this._rotationManager.next({forced: true})
.catch(e => this._logger.error(e, 'Forced OLED rotation failed'));
}
},
});
this._rotationManager.enable();
this._liveWallpaperManager.enable()
.catch(e => this._logger.error(e, 'Live wallpaper failed to initialize'));
this._oledProtectionManager.enable();
this._indicator = null;
this._showIndicatorSignalId = this._settings.connect(
`changed::${SettingsKey.SHOW_INDICATOR}`, () => this._syncIndicator());
this._syncIndicator();
}
disable() {
if (this._showIndicatorSignalId) {
this._settings.disconnect(this._showIndicatorSignalId);
this._showIndicatorSignalId = 0;
}
this._indicator?.destroy();
this._indicator = null;
this._oledProtectionManager?.disable();
this._oledProtectionManager = null;
this._liveWallpaperManager?.disable();
this._liveWallpaperManager = null;
this._rotationManager?.disable();
this._rotationManager = null;
this._logger = null;
this._settings = null;
}
_syncIndicator() {
const shouldShow = this._settings.get_boolean(SettingsKey.SHOW_INDICATOR);
if (shouldShow && !this._indicator) {
this._indicator = new BenthicBloomIndicator(this._settings, {
rotationManager: this._rotationManager,
liveWallpaperManager: this._liveWallpaperManager,
oledProtectionManager: this._oledProtectionManager,
openPreferences: () => this.openPreferences(),
});
Main.panel.addToStatusArea(this.uuid, this._indicator);
} else if (!shouldShow && this._indicator) {
this._indicator.destroy();
this._indicator = null;
}
}
}