Claude/gnome wallpaper auto rotation r1ailq #1
@@ -10,11 +10,11 @@ protection against OLED burn-in.
|
|||||||
through the images inside them on a timer, in sequential or shuffled
|
through the images inside them on a timer, in sequential or shuffled
|
||||||
order, with an optional crossfade between changes. The chosen wallpaper
|
order, with an optional crossfade between changes. The chosen wallpaper
|
||||||
can also be applied to the lock screen.
|
can also be applied to the lock screen.
|
||||||
- **Live wallpapers** — play a looping video file as your desktop
|
- **Live wallpapers** — play a looping video *or animated GIF* as your
|
||||||
background. Frames are decoded with GStreamer and rendered directly by
|
desktop background. Frames are decoded with GStreamer and rendered
|
||||||
GNOME Shell's own Clutter stage (no external, incompatible Clutter
|
directly by GNOME Shell's own Clutter stage (no external, incompatible
|
||||||
build involved). Playback can automatically pause on battery power or
|
Clutter build involved). Playback can automatically pause on battery
|
||||||
while a window is fullscreen.
|
power or while a window is fullscreen.
|
||||||
- **OLED burn-in protection** — three independent, individually toggled
|
- **OLED burn-in protection** — three independent, individually toggled
|
||||||
techniques:
|
techniques:
|
||||||
- *Pixel shifting*: nudges the background a few pixels on a slow drift
|
- *Pixel shifting*: nudges the background a few pixels on a slow drift
|
||||||
@@ -34,9 +34,9 @@ protection against OLED burn-in.
|
|||||||
- GNOME Shell 50.
|
- GNOME Shell 50.
|
||||||
- For live wallpapers: GStreamer with its `good` and `base` plugin sets
|
- For live wallpapers: GStreamer with its `good` and `base` plugin sets
|
||||||
(e.g. `gstreamer1.0-plugins-good` and `gstreamer1.0-plugins-base`, or
|
(e.g. `gstreamer1.0-plugins-good` and `gstreamer1.0-plugins-base`, or
|
||||||
your distribution's equivalent). If these aren't installed, the live
|
your distribution's equivalent) — the `good` set is also what provides
|
||||||
wallpaper toggle stays disabled and BenthicBloom's other features work
|
animated GIF decoding. If these aren't installed, the live wallpaper
|
||||||
normally.
|
toggle stays disabled and BenthicBloom's other features work normally.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js';
|
|||||||
import {SettingsKey} from './settingsKeys.js';
|
import {SettingsKey} from './settingsKeys.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays a video file as a looping animated background.
|
* Plays a video or animated GIF file as a looping animated background.
|
||||||
|
* `playbin` typefinds the source by content rather than extension, so GIFs
|
||||||
|
* are decoded through GStreamer's own GIF element (from the "good" plugin
|
||||||
|
* set) and handled exactly like any other video stream below this point.
|
||||||
*
|
*
|
||||||
* Mutter embeds its own private copy of Clutter, so GStreamer video sinks
|
* Mutter embeds its own private copy of Clutter, so GStreamer video sinks
|
||||||
* that hand back a Clutter actor from a *different* Clutter instance (e.g.
|
* that hand back a Clutter actor from a *different* Clutter instance (e.g.
|
||||||
|
|||||||
@@ -176,8 +176,9 @@ export default class BenthicBloomPreferences extends ExtensionPreferences {
|
|||||||
const group = new Adw.PreferencesGroup({
|
const group = new Adw.PreferencesGroup({
|
||||||
title: _('Video Wallpaper'),
|
title: _('Video Wallpaper'),
|
||||||
description: _(
|
description: _(
|
||||||
'Play a looping video as your desktop background instead of a static image. ' +
|
'Play a looping video or animated GIF as your desktop background instead of a static image. ' +
|
||||||
'Requires GStreamer (with its "good" and "base" plugin sets) to be installed on your system.'),
|
'Requires GStreamer (with its "good" and "base" plugin sets, which provide GIF decoding) ' +
|
||||||
|
'to be installed on your system.'),
|
||||||
});
|
});
|
||||||
page.add(group);
|
page.add(group);
|
||||||
group.add(this._switchRow(
|
group.add(this._switchRow(
|
||||||
@@ -185,17 +186,26 @@ export default class BenthicBloomPreferences extends ExtensionPreferences {
|
|||||||
_('Enable Live Wallpaper'), _('Overrides the static wallpaper while active')));
|
_('Enable Live Wallpaper'), _('Overrides the static wallpaper while active')));
|
||||||
|
|
||||||
const fileRow = new Adw.ActionRow({
|
const fileRow = new Adw.ActionRow({
|
||||||
title: _('Video File'),
|
title: _('Video / GIF File'),
|
||||||
subtitle: settings.get_string(SettingsKey.LIVE_WALLPAPER_PATH) || _('None selected'),
|
subtitle: settings.get_string(SettingsKey.LIVE_WALLPAPER_PATH) || _('None selected'),
|
||||||
});
|
});
|
||||||
const chooseButton = new Gtk.Button({label: _('Choose…'), valign: Gtk.Align.CENTER, css_classes: ['flat']});
|
const chooseButton = new Gtk.Button({label: _('Choose…'), valign: Gtk.Align.CENTER, css_classes: ['flat']});
|
||||||
chooseButton.connect('clicked', () => {
|
chooseButton.connect('clicked', () => {
|
||||||
const dialog = new Gtk.FileDialog({title: _('Select Wallpaper Video')});
|
const dialog = new Gtk.FileDialog({title: _('Select Wallpaper Video or GIF')});
|
||||||
const filter = new Gtk.FileFilter();
|
|
||||||
filter.add_mime_type('video/*');
|
const mediaFilter = new Gtk.FileFilter({name: _('Videos and animated GIFs')});
|
||||||
|
mediaFilter.add_mime_type('video/*');
|
||||||
|
mediaFilter.add_mime_type('image/gif');
|
||||||
|
mediaFilter.add_pattern('*.gif');
|
||||||
|
|
||||||
|
const allFilter = new Gtk.FileFilter({name: _('All files')});
|
||||||
|
allFilter.add_pattern('*');
|
||||||
|
|
||||||
const filterList = new Gio.ListStore({item_type: Gtk.FileFilter});
|
const filterList = new Gio.ListStore({item_type: Gtk.FileFilter});
|
||||||
filterList.append(filter);
|
filterList.append(mediaFilter);
|
||||||
|
filterList.append(allFilter);
|
||||||
dialog.filters = filterList;
|
dialog.filters = filterList;
|
||||||
|
dialog.default_filter = mediaFilter;
|
||||||
|
|
||||||
dialog.open(fileRow.get_root(), null, (source, result) => {
|
dialog.open(fileRow.get_root(), null, (source, result) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -70,13 +70,13 @@
|
|||||||
<key name="live-wallpaper-enabled" type="b">
|
<key name="live-wallpaper-enabled" type="b">
|
||||||
<default>false</default>
|
<default>false</default>
|
||||||
<summary>Enable live wallpaper</summary>
|
<summary>Enable live wallpaper</summary>
|
||||||
<description>Whether a video is played as an animated desktop background instead of a static image.</description>
|
<description>Whether a video or animated GIF is played as an animated desktop background instead of a static image.</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
<key name="live-wallpaper-path" type="s">
|
<key name="live-wallpaper-path" type="s">
|
||||||
<default>""</default>
|
<default>""</default>
|
||||||
<summary>Live wallpaper video file</summary>
|
<summary>Live wallpaper media file</summary>
|
||||||
<description>Path to the video file used as the live wallpaper.</description>
|
<description>Path to the video or animated GIF file used as the live wallpaper.</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
<key name="live-wallpaper-muted" type="b">
|
<key name="live-wallpaper-muted" type="b">
|
||||||
|
|||||||
Reference in New Issue
Block a user