[gnome] Update extensions

This commit is contained in:
2026-06-10 11:03:09 -04:00
parent 20fc1e4e75
commit 6c973853c6
394 changed files with 12513 additions and 1340 deletions

View File

@ -1,34 +0,0 @@
// Bing Wallpaper GNOME extension
// Copyright (C) 2017-2025 Michael Carroll
// This extension is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// See the GNU General Public License, version 3 or later for details.
import St from 'gi://St';
import Gio from 'gi://Gio';
const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD;
export default class BWClipboard {
constructor() {
this.clipboard = St.Clipboard.get_default();
}
setImage(filename) {
try {
let file = Gio.File.new_for_path(filename);
let [success, image_data] = file.load_contents(null);
//console.log('error: '+success);
if (success)
this.clipboard.set_content(CLIPBOARD_TYPE, 'image/jpeg', image_data);
} catch (err) {
console.log('unable to set clipboard to data in '+filename);
}
}
setText(text) {
this.clipboard.set_text(CLIPBOARD_TYPE, text);
}
};

View File

@ -15,11 +15,9 @@ Also, check out my related [Google Earth View wallpaper extension](https://githu
* Automatically sets the Bing [Image of the Day](https://www.microsoft.com/en-us/bing/bing-wallpaper) as both lock screen and desktop wallpapers
* Only attempts to download wallpapers when they have been updated - doesn't poll continuously
* Shuffle/randomise wallpapers at adjustable intervals (including from your stored Bing images)
* Image gallery to view, select and curate stored images
* Optionally delete old images after a week, or you can keep (and curate) them forever
* Override the lockscreen blur (NEW: lockscreen blur is now dynamic!)
* Language support: English (en), German (de), Dutch (nl), Italian (it), Polish (pl), Chinese (zh_CN, zh_TW), French (fr_FR), Portuguese (pt, pt_BR), Ukrainian (uk), Russian (ru_RU), Spanish (es), Korean (ko), Indonesian (id), Catalan (ca), Norwegian Bokmål (nb) & Nynorsk (nn), Swedish (sv), Arabic (ar), Hungarian (hu), Japanese (ja), Czech (cs_CZ), Finnish (fi_FI) and Turkish (tr), Persian (fa_ir) - a HUGE thanks to the translators
* Image preview in menus & ability to manually set wallpapers individually or copy image to clipboard
* Image preview in menus & ability to manually set wallpapers individually
* A selection of different theme-aware indicator (tray) icons to choose (or hide it completely)
## Quickstart guide
@ -69,7 +67,7 @@ The 5 buttons in the gallery (3rd page in the preferences) do have tool-tips but
## System Requirements
GNOME 3.36+ or 40+ (Ubuntu 20.04 LTS or later, older versions of the extension work with 3.18+, but are no longer supported).
GNOME 45+ (Ubuntu 24.04 LTS or later, older versions of the extension work with 3.18+, but are no longer supported).
## Package dependencies
@ -110,26 +108,12 @@ GSETTINGS_SCHEMA_DIR=$HOME/.local/share/gnome-shell/extensions/BingWallpaper@ine
Please include logs from your journal when submitting bug notices (make sure nothing sensitive is included in the text!).
## Screenshots
### Image gallery
![Settings](/screenshot/settings5.png)
### Preferences
![Settings](/screenshot/settings.png)
![Settings](/screenshot/settings2.png)
![Settings](/screenshot/settings3.png)
![Settings](/screenshot/settings4.png)
### Lockscreen blur control
From left to right:
* no blur/no dimming
* slight blur/default dimming
* default blur/default dimming
![Blur example](/screenshot/blurexample.jpg)
## Toss a coin to your coder
Do you like this extension and want to show that you appreciate the work that goes into adding new features and keeping it maintained? Please consider buying me a coffee on [GitHub Sponsors](https://github.com/sponsors/neffo) or on [Flattr](https://flattr.com/@neffo).
@ -141,7 +125,7 @@ This extension is unofficial and not affiliated with Bing or Microsoft in any wa
## Special Thanks
This extension is based on the NASA APOD extension by [Elinvention](https://github.com/Elinvention)
and inspired by Bing Desktop WallpaperChanger by [Utkarsh Gupta](https://github.com/UtkarshGpta). Lockscreen blur code is based on [Pratap-Kumar's extension](https://github.com/PRATAP-KUMAR/Control_Blur_Effect_On_Lock_Screen). I'd like to give a special shout out to those who have [contributed code and translations](https://github.com/neffo/bing-wallpaper-gnome-extension/graphs/contributors) as well as everyone who has reported bugs or provided feedback and suggestions for improvements. Also, thanks to Microsoft for this great API and wallpaper collection.
and inspired by Bing Desktop WallpaperChanger by [Utkarsh Gupta](https://github.com/UtkarshGpta). I'd like to give a special shout out to those who have [contributed code and translations](https://github.com/neffo/bing-wallpaper-gnome-extension/graphs/contributors) as well as everyone who has reported bugs or provided feedback and suggestions for improvements. Also, thanks to Microsoft for this great API and wallpaper collection.
## License

View File

@ -1,159 +0,0 @@
// Bing Wallpaper GNOME extension
// Copyright (C) 2017-2025 Michael Carroll
// This extension is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// See the GNU General Public License, version 3 or later for details.
// Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod
// This code based on https://github.com/PRATAP-KUMAR/Control_Blur_Effect_On_Lock_Screen
// and https://github.com/sunwxg/gnome-shell-extension-unlockDialogBackground
import St from 'gi://St';
import * as UnlockDialog from 'resource:///org/gnome/shell/ui/unlockDialog.js';
import * as Config from 'resource:///org/gnome/shell/misc/config.js';
var _updateBackgroundEffects = UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects;
var _showClock = UnlockDialog.UnlockDialog.prototype._showClock;
var _showPrompt = UnlockDialog.UnlockDialog.prototype._showPrompt;
var shellVersionMajor = parseInt(Config.PACKAGE_VERSION.split('.')[0]);
var shellVersionMinor = parseInt(Config.PACKAGE_VERSION.split('.')[1]);
var shellVersionPoint = parseInt(Config.PACKAGE_VERSION.split('.')[2]);
var blurField = shellVersionMajor >= 46 ? "radius" : "sigma";
// default BWP mild blur
var BWP_BLUR_SIGMA = 2;
var BWP_BLUR_BRIGHTNESS = 55;
// GNOME defaults
var BLUR_BRIGHTNESS = 0.55;
var BLUR_SIGMA = 60;
var debug = false;
var promptActive = false; // default GNOME method of testing this relies on state of a transisiton
// so we are being explicit here (do not want any races, thanks)
function BingLog(msg) {
if (debug) // set 'debug' above to false to keep the noise down in journal
console.log("BingWallpaper extension/Blur: " + msg);
}
// we patch UnlockDialog._updateBackgroundEffects()
export function _updateBackgroundEffects_BWP(monitorIndex) {
// GNOME shell 3.36.4 and above
BingLog("_updateBackgroundEffects_BWP() called for shell >= 3.36.4");
const themeContext = St.ThemeContext.get_for_stage(global.stage);
for (const widget of this._backgroundGroup.get_children()) {
// set blur effects, we have two modes in lockscreen: login prompt or clock
// blur on when clock is visible is adjustable
const effect = widget.get_effect('blur');
if (promptActive) {
BingLog('default blur active');
if (effect) {
effect.set({ // GNOME defaults when login prompt is visible
brightness: BLUR_BRIGHTNESS,
[blurField]: BLUR_SIGMA * themeContext.scale_factor,
});
}
}
else {
BingLog('adjustable blur active');
if (effect) {
effect.set({ // adjustable blur when clock is visible
brightness: BWP_BLUR_BRIGHTNESS * 0.01, // we use 0-100 rather than 0-1, so divide by 100
[blurField]: BWP_BLUR_SIGMA * themeContext.scale_factor,
});
}
}
}
}
// we patch both UnlockDialog._showClock() and UnlockDialog._showPrompt() to let us
// adjustable blur in a Windows-like way (this ensures login prompt is readable)
export function _showClock_BWP() {
promptActive = false;
this._showClock_GNOME(); // pass to default GNOME function
this._updateBackgroundEffects();
}
export function _showPrompt_BWP() {
promptActive = true;
this._showPrompt_GNOME(); // pass to default GNOME function
this._updateBackgroundEffects();
}
export function _clampValue(value) {
// valid values are 0 to 100
if (value > 100)
value = 100;
if (value < 0 )
value = 0;
return value;
}
export default class Blur {
constructor() {
this.enabled = false;
BingLog('Bing Wallpaper adjustable blur is '+(supportedVersion()?'available':'not available'));
}
set_blur_strength(value) {
BWP_BLUR_SIGMA = _clampValue(value);
BingLog("lockscreen blur strength set to "+BWP_BLUR_SIGMA);
}
set_blur_brightness(value) {
BWP_BLUR_BRIGHTNESS = _clampValue(value);
BingLog("lockscreen brightness set to " + BWP_BLUR_BRIGHTNESS);
}
_switch(enabled) {
if (enabled && !this.enabled) {
this._enable();
}
else {
this._disable();
}
}
_enable() {
if (supportedVersion()) {
BingLog("Blur._enable() called on GNOME "+Config.PACKAGE_VERSION);
UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects_BWP;
// we override _showClock and _showPrompt to patch in updates to blur effect before calling the GNOME functions
UnlockDialog.UnlockDialog.prototype._showClock = _showClock_BWP;
UnlockDialog.UnlockDialog.prototype._showPrompt = _showPrompt_BWP;
// this are the original functions which we call into from our versions above
UnlockDialog.UnlockDialog.prototype._showClock_GNOME = _showClock;
UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME = _showPrompt;
}
this.enabled = true;
}
_disable() {
if (!this.enabled)
return;
BingLog("_lockscreen_blur_disable() called");
if (supportedVersion()) {
// restore default functions
UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects;
UnlockDialog.UnlockDialog.prototype._showClock = _showClock;
UnlockDialog.UnlockDialog.prototype._showPrompt = _showPrompt;
// clean up unused functions we created
UnlockDialog.UnlockDialog.prototype._showClock_GNOME = null;
delete UnlockDialog.UnlockDialog.prototype._showClock_GNOME;
UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME = null;
delete UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME;
}
this.enabled = false;
}
};
function supportedVersion() { // when current lockscren blur implementation was first shipped (we ignore earlier weird version)
if (shellVersionMajor >= 40 ||
(shellVersionMajor == 3 && shellVersionMinor == 36 && shellVersionPoint >= 4)) {
return true;
}
return false;
}

View File

@ -1,203 +0,0 @@
// Bing Wallpaper GNOME extension
// Copyright (C) 2017-2025 Michael Carroll
// This extension is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// See the GNU General Public License, version 3 or later for details.
// Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod
import Gtk from 'gi://Gtk';
import GdkPixbuf from 'gi://GdkPixbuf';
import Gio from 'gi://Gio';
import * as Utils from './utils.js';
import {gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
const default_dimensions = [30, 30, 1650, 800]; // TODO: pull from and save dimensions to settings, but perhaps verify that dimensions are ok
const GALLERY_THUMB_WIDTH = 320;
const GALLERY_THUMB_HEIGHT = 180;
export default class Carousel {
constructor(settings, button = null, callbackfunc = null, prefs_flowbox = null, extensionPath = null) {
//create_gallery(widget, settings);
this.settings = settings;
this.button = button;
this.callbackfunc = callbackfunc;
this.flowBox = null;
this.window = null;
this.imageList = Utils.imageListSortByDate(Utils.getImageList(this.settings)).reverse(); // get images and reverse order
this.searchEntry = null;
this.extensionPath = extensionPath
this._log('create carousel...');
this.flowBox = prefs_flowbox;
this.flowBox.insert(this._create_placeholder_item(), -1);
}
_enable_button() {
if (this.button) {
this.button.set_sensitive(state);
}
}
_create_gallery() {
this.imageList.forEach((image) => {
let item = this._create_gallery_item(image);
this.flowBox.insert(item, -1);
});
}
_create_gallery_item(image) {
let buildable = new Gtk.Builder();
// grab appropriate object from UI file
buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ["flowBoxChild"]);
// assign variables to the UI objects we've just loaded
let galleryImage = buildable.get_object('galleryImage');
let filename = Utils.imageToFilename(this.settings, image);
let viewButton = buildable.get_object('viewButton');
let applyButton = buildable.get_object('applyButton');
let infoButton = buildable.get_object('infoButton');
let deleteButton = buildable.get_object('deleteButton');
let favButton = buildable.get_object('favButton');
let unfavButton = buildable.get_object('unfavButton');
if (Utils.isFavourite(image)) {
favButton.set_visible(false);
this._log('image is favourited');
}
else {
unfavButton.set_visible(false);
}
try {
this._load_image(galleryImage, filename);
}
catch (e) {
galleryImage.set_from_icon_name('image-missing');
galleryImage.set_icon_size = 2; // Gtk.GTK_ICON_SIZE_LARGE;
this._log('create_gallery_image: '+e);
}
galleryImage.set_tooltip_text(image.copyright);
// set up actions for when a image button is clicked
viewButton.connect('clicked', () => {
Utils.openInSystemViewer(filename);
});
applyButton.connect('clicked', () => {
this.settings.set_string('selected-image', Utils.getImageUrlBase(image));
this._log('gallery selected '+Utils.getImageUrlBase(image));
});
infoButton.connect('clicked', () => {
Utils.openInSystemViewer(image.copyrightlink, false);
this._log('info page link opened '+image.copyrightlink);
});
deleteButton.connect('clicked', (widget) => {
this._log('Delete requested for '+filename);
Utils.deleteImage(filename);
Utils.setImageHiddenStatus(this.settings, image.urlbase, true);
Utils.purgeImages(this.settings); // hide image instead
widget.get_parent().get_parent().set_visible(false); // bit of a hack
if (this.callbackfunc)
this.callbackfunc();
});
// button is unchecked, so we want to make the checked one visible
favButton.connect('clicked', (widget) => {
this._log('favourited '+Utils.getImageUrlBase(image));
widget.set_visible(false);
unfavButton.set_visible(true);
Utils.setImageFavouriteStatus(this.settings, image.urlbase, true);
});
// button is checked, so we want to make the unchecked one visible
unfavButton.connect('clicked', (widget) => {
this._log('unfavourited '+Utils.getImageUrlBase(image));
widget.set_visible(false);
favButton.set_visible(true);
Utils.setImageFavouriteStatus(this.settings, image.urlbase, false);
});
let item = buildable.get_object('flowBoxChild');
return item;
}
_create_placeholder_item() {
let buildable = new Gtk.Builder();
this.flowBox.set_max_children_per_line(1);
// grab appropriate object from UI file
buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ["flowBoxPlaceholder"]);
let loadButton = buildable.get_object('loadButton');
loadButton.connect('clicked', (widget) => {
widget.set_label(_("Loading...")); // does this work???
this.flowBox.remove(widget.get_parent());
this.flowBox.set_max_children_per_line(2);
this._create_gallery();
});
let item = buildable.get_object('flowBoxPlaceholder');
return item;
}
_load_image(galleryImage, filename) {
let thumb_path = Utils.getWallpaperDir(this.settings)+'.thumbs/';
let thumb_dir = Gio.file_new_for_path(thumb_path);
let save_thumbs = !this.settings.get_boolean('delete-previous') && this.settings.get_boolean('create-thumbs'); // create thumbs only if not deleting previous and thumbs are enabled
if (!thumb_dir.query_exists(null)) {
thumb_dir.make_directory_with_parents(null);
}
let image_file = Gio.file_new_for_path(filename);
// load gallery image or create new thumbnail if it doesn't
if (!image_file.query_exists(null)){
this._set_blank_image(galleryImage);
}
else {
let image_thumb_path = thumb_path + image_file.get_basename();
let image_thumb = Gio.file_new_for_path(image_thumb_path);
try {
let pixbuf;
// use thumbnail if available
if (image_thumb.query_exists(null)) {
pixbuf = GdkPixbuf.Pixbuf.new_from_file(image_thumb_path);
}
else { // save changed thumbnail significantly speeds up gallery loading, but costs some addtional disk space
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filename, GALLERY_THUMB_WIDTH, GALLERY_THUMB_HEIGHT);
if (save_thumbs)
pixbuf.savev(image_thumb_path,'jpeg',['quality'], ['90']);
}
galleryImage.set_pixbuf(pixbuf);
}
catch (e) {
this._set_blank_image(galleryImage);
this._log('create_gallery_image: '+e);
}
}
}
_set_blank_image(galleryImage) {
//galleryImage.set_from_icon_name('image-missing');
//galleryImage.set_icon_size = 2; // Gtk.GTK_ICON_SIZE_LARGE;
}
_log(msg) {
if (this.settings.get_boolean('debug-logging'))
console.log("BingWallpaper extension: " + msg); // disable to keep the noise down in journal
}
};

View File

@ -23,9 +23,7 @@ import * as Config from 'resource:///org/gnome/shell/misc/config.js';
import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
import * as Utils from './utils.js';
import Blur from './blur.js';
import Thumbnail from './thumbnail.js';
import BWClipboard from './BWClipboard.js';
const BingImageURL = Utils.BingImageURL;
const BingURL = 'https://www.bing.com';
@ -38,7 +36,6 @@ const ICON_NEXT_BUTTON = 'media-seek-forward-symbolic';
const ICON_CURRENT_BUTTON = 'media-skip-forward-symbolic';
let bingWallpaperIndicator = null;
let blur = null;
const newMenuItem = (label) => {
return new PopupMenu.PopupMenuItem(label);
@ -107,7 +104,6 @@ class BingWallpaperIndicator extends Button {
this.thumbnail = null;
this.thumbnailItem = null;
this.selected_image = "current";
this.clipboard = new BWClipboard();
this.imageIndex = null;
this.logger = null;
this.favourite_status = false;
@ -121,9 +117,6 @@ class BingWallpaperIndicator extends Button {
this.ICON_UNFAVE_BUTTON = extensionIconsPath + '/'+'unfav-symbolic.svg';
this.ICON_TRASH_BUTTON = extensionIconsPath + '/'+'trash-empty-symbolic.svg';
this.ICON_UNTRASH_BUTTON = extensionIconsPath + '/'+'trash-full-symbolic.svg';
if (!blur) // as Blur isn't disabled on screen lock (like the rest of the extension is)
blur = new Blur();
// take a variety of actions when the gsettings values are modified by prefs
this._settings = this._extension.getSettings();
@ -136,8 +129,6 @@ class BingWallpaperIndicator extends Button {
this.refreshDueItem = newMenuItem(_("<No refresh scheduled>"));
this.explainItem = newMenuItem(_("Awaiting refresh..."));
this.copyrightItem = newMenuItem(_("Awaiting refresh..."));
this.clipboardImageItem = newMenuItem(_("Copy image to clipboard"));
this.clipboardURLItem = newMenuItem(_("Copy image URL to clipboard"));
this.folderItem = newMenuItem(_("Open image folder"));
this.dwallpaperItem = newMenuItem(_("Set background image"));
this.swallpaperItem = newMenuItem(_("Set lock screen image"));
@ -149,7 +140,7 @@ class BingWallpaperIndicator extends Button {
this.titleItem = new PopupMenu.PopupSubMenuMenuItem(_("Awaiting refresh..."), false);
[this.imageResolutionItem, this.openImageInfoLinkItem, this.openImageItem, this.folderItem,
this.clipboardImageItem, this.clipboardURLItem, this.dwallpaperItem]
this.dwallpaperItem]
.forEach(e => this.titleItem.menu.addMenuItem(e));
// quick settings submenu
@ -238,9 +229,6 @@ class BingWallpaperIndicator extends Button {
{signal: 'changed::icon-name', call: this._setIcon},
{signal: 'changed::market', call: this._refresh},
{signal: 'changed::set-background', call: this._setBackground},
{signal: 'changed::override-lockscreen-blur', call: this._setBlur},
{signal: 'changed::lockscreen-blur-strength', call: this._setBlur},
{signal: 'changed::lockscreen-blur-brightness', call: this._setBlur},
{signal: 'changed::selected-image', call: this._setImage},
{signal: 'changed::delete-previous', call: this._cleanUpImages},
{signal: 'changed::notify', call: this._notifyCurrentImage},
@ -263,7 +251,6 @@ class BingWallpaperIndicator extends Button {
// ensure we're in a sensible initial state
this._setIcon();
this._setBlur();
this._setImage();
this._cleanUpImages();
@ -307,14 +294,6 @@ class BingWallpaperIndicator extends Button {
});
this.folderItem.connect('activate', Utils.openImageFolder.bind(this, this._settings));
if (this.clipboard.clipboard) { // only if we have a clipboard
this.clipboardImageItem.connect('activate', this._copyImageToClipboard.bind(this));
this.clipboardURLItem.connect('activate', this._copyURLToClipboard.bind(this));
}
else {
[this.clipboardImageItem, this.clipboardURLItem].
forEach(e => e.setSensitive(false));
}
}
_setBooleanSetting(key, state) {
@ -349,8 +328,6 @@ class BingWallpaperIndicator extends Button {
_openMenu() {
// Grey out menu items if an update is pending
this.refreshItem.setSensitive(!this._updatePending);
this.clipboardImageItem.setSensitive(!this._updatePending && this.imageURL != "");
this.clipboardURLItem.setSensitive(!this._updatePending && this.imageURL != "");
this.thumbnailItem.setSensitive(!this._updatePending && this.imageURL != "");
this.dwallpaperItem.setSensitive(!this._updatePending && this.filename != "");
this.swallpaperItem.setSensitive(!this._updatePending && this.filename != "");
@ -370,12 +347,6 @@ class BingWallpaperIndicator extends Button {
this.refreshDueItem.label.set_text(this.refreshduetext);
}
_setBlur() {
blur._switch(this._settings.get_boolean('override-lockscreen-blur'));
blur.set_blur_strength(this._settings.get_int('lockscreen-blur-strength'));
blur.set_blur_brightness(this._settings.get_int('lockscreen-blur-brightness'));
}
_setImage() {
Utils.validate_imagename(this._settings);
this.selected_image = this._settings.get_string('selected-image');
@ -421,14 +392,6 @@ class BingWallpaperIndicator extends Button {
doSetBackground(this.filename, Utils.DESKTOP_SCHEMA);
}
_copyURLToClipboard() {
this.clipboard.setText(this.imageURL);
}
_copyImageToClipboard() {
this.clipboard.setImage(this.filename);
}
// set a timer on when the current image is going to expire
_restartTimeoutFromLongDate(longdate) {
// all Bing times are in UTC (+0)
@ -680,7 +643,7 @@ class BingWallpaperIndicator extends Button {
}
// download Bing metadata
_refresh() {
async _refresh() {
if (this._updatePending)
return;
this._updatePending = true;
@ -703,7 +666,7 @@ class BingWallpaperIndicator extends Button {
request.request_headers.append('Accept', 'application/json');
try {
this.httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
await this.httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
this._processMessageRefresh(message);
});
}
@ -1074,7 +1037,7 @@ class BingWallpaperIndicator extends Button {
// download and process new image
// FIXME: improve error handling
_downloadImage(url, file, set_background) {
async _downloadImage(url, file, set_background) {
let BingWallpaperDir = Utils.getWallpaperDir(this._settings);
let dir = Gio.file_new_for_path(BingWallpaperDir);
if (!dir.query_exists(null)) {
@ -1088,7 +1051,7 @@ class BingWallpaperIndicator extends Button {
// queue the http request
try {
if (Soup.MAJOR_VERSION >= 3) {
this.httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
await this.httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
this._processFileDownload(message, file, set_background);
});
}
@ -1104,13 +1067,13 @@ class BingWallpaperIndicator extends Button {
}
}
_processFileDownload(message, file, set_background) {
async _processFileDownload(message, file, set_background) {
try {
let data = (Soup.MAJOR_VERSION >= 3) ?
this.httpSession.send_and_read_finish(message).get_data():
message.response_body.flatten().get_as_bytes();
file.replace_contents_bytes_async(
const [etag] = await file.replace_contents_bytes_async(
data,
null,
false,
@ -1157,8 +1120,6 @@ class BingWallpaperIndicator extends Button {
this._timeout = undefined;
this._shuffleTimeout = undefined;
this.menu.removeAll();
blur._disable(); // disable blur (blur.js) override and cleanup
blur = null;
}
});

View File

@ -1,6 +1,6 @@
{
"_generated": "Generated by SweetTooth, do not edit",
"description": "Sync your wallpaper to today's Microsoft Bing image of the day (the image you see when you visit Bing.com).\n\n *Disclaimer*: this extension is unofficial and not affiliated with Bing or Microsoft in any way. Images are protected by copyright and are licensed only for use as wallpapers.\n\nFeatures:\n* UHD resolution wallpapers\n* Automatically fetches current Bing wallpaper of the day and sets as both lock screen and desktop wallpaper (user selectable on GNOME versions that support it)\n* Doesn't poll continuously - only once per day and on startup (schedules a refresh when Bing is due to update)\n * random mode (from previously downloaded wallpapers)\n *NEW: select/cycle wallpaper through previously downloaded images\n* Language support: English (en), German (de), Dutch (nl), Italian (it), Polish (pl), Chinese (zh_CN, zh_TW), French (fr), Portuguese (pt), Ukrainian (uk), Russian (ru_RU), Spanish (es), Korean (ko), Indonesian (id), Catalan (ca), Norwegian Bokm\u00e5l (nb) & Nynorsk (ni), Swedish (sv), Arabic (ar), Hungarian (hu) and Japanese (ja) - a HUGE thanks to the translators\n\nThis extension was forked from the NASA APOD extension by Elinvention (https://github.com/Elinvention) and inspired by Bing Desktop Wallpaper Changer by Utkarsh Gupta (https://github.com/UtkarshGpta).\n\nAlways restart GNOME after manually updating extensions. Please report bugs to the GitHub page below:",
"description": "Sync your wallpaper to today's Microsoft Bing image of the day (the image you see when you visit Bing.com).\n\n *Disclaimer*: this extension is unofficial and not affiliated with Bing or Microsoft in any way. Images are protected by copyright and are licensed only for use as wallpapers.\n\nFeatures:\n* UHD resolution wallpapers\n* Automatically fetches current Bing wallpaper of the day and sets as both lock screen and desktop wallpaper (user selectable on GNOME versions that support it)\n* Doesn't poll continuously - only once per day and on startup (schedules a refresh when Bing is due to update)\n * random mode (from previously downloaded wallpapers)\n * select/cycle wallpaper through previously downloaded images\n* Language support: English (en), German (de), Dutch (nl), Italian (it), Polish (pl), Chinese (zh_CN, zh_TW), French (fr), Portuguese (pt), Ukrainian (uk), Russian (ru_RU), Spanish (es), Korean (ko), Indonesian (id), Catalan (ca), Norwegian Bokm\u00e5l (nb) & Nynorsk (ni), Swedish (sv), Arabic (ar), Hungarian (hu) and Japanese (ja) - a HUGE thanks to the translators\n\nThis extension was forked from the NASA APOD extension by Elinvention (https://github.com/Elinvention) and inspired by Bing Desktop Wallpaper Changer by Utkarsh Gupta (https://github.com/UtkarshGpta).\n\nAlways restart GNOME after manually updating extensions. Please report bugs to the GitHub page below:",
"gettext-domain": "BingWallpaper",
"name": "Bing Wallpaper",
"settings-schema": "org.gnome.shell.extensions.bingwallpaper",
@ -14,5 +14,5 @@
],
"url": "https://github.com/neffo/bing-wallpaper-gnome-extension",
"uuid": "BingWallpaper@ineffable-gmail.com",
"version": 52
}
"version": 53
}

View File

@ -15,7 +15,7 @@ import Adw from 'gi://Adw';
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js';
import * as Utils from './utils.js';
import Carousel from './carousel.js';
/*import Carousel from './carousel.js';*/
const BingImageURL = Utils.BingImageURL;
@ -41,7 +41,7 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
let carousel = null;
/*let carousel = null;*/
let httpSession = null;
let BingLog = (msg) => { // avoids need for globals
@ -62,13 +62,6 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
const shuffleSwitch = buildable.get_object('shuffleSwitch');
const shuffleInterval = buildable.get_object('shuffleInterval');
const folderRow = buildable.get_object('folderRow');
const lockscreen_page = buildable.get_object('lockscreen_page');
const overrideSwitch = buildable.get_object('overrideSwitch');
const blurPresets = buildable.get_object('blurPresets');
const strengthEntry = buildable.get_object('strengthEntry');
const brightnessEntry = buildable.get_object('brightnessEntry');
const blurAdjustment = buildable.get_object('blurAdjustment');
const brightnessAdjustment = buildable.get_object('brightnessAdjustment');
const resolutionEntry = buildable.get_object('resolutionEntry');
const debugSwitch = buildable.get_object('debug_switch');
const revertSwitch = buildable.get_object('revert_switch');
@ -76,8 +69,6 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
const delete_previous_switch = buildable.get_object('delete_previous_switch');
const delete_previous_adjustment = buildable.get_object('delete_previous_adjustment');
const always_export_switch = buildable.get_object('always_export_switch');
const gallery_page = buildable.get_object('gallery_page');
const carouselFlowBox = buildable.get_object('carouselFlowBox');
const randomIntervalEntry = buildable.get_object('entry_random_interval');
const debug_page = buildable.get_object('debug_page');
const json_actionrow = buildable.get_object('json_actionrow');
@ -86,8 +77,8 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
const change_log = buildable.get_object('change_log');
window.add(settings_page);
window.add(lockscreen_page);
window.add(gallery_page);
/*window.add(lockscreen_page);
window.add(gallery_page);*/
window.add(debug_page);
window.add(about_page);
@ -116,30 +107,6 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
folderRow.add_suffix(openBtn);
folderRow.add_suffix(changeBtn);
blurAdjustment.set_value(settings.get_int('lockscreen-blur-strength'));
brightnessAdjustment.set_value(settings.get_int('lockscreen-blur-brightness'));
const defaultBtn = new Gtk.Button( {
label: _('Default'),
valign: Gtk.Align.CENTER,
halign: Gtk.Align.CENTER,
});
const noBlurBtn = new Gtk.Button( {
label: _('No blur, slight dim'),
valign: Gtk.Align.CENTER,
halign: Gtk.Align.CENTER,
});
const slightBlurBtn = new Gtk.Button( {
label: _('Slight blur & dim'),
valign: Gtk.Align.CENTER,
halign: Gtk.Align.CENTER,
});
// add to presets row
blurPresets.add_suffix(defaultBtn);
blurPresets.add_suffix(noBlurBtn);
blurPresets.add_suffix(slightBlurBtn);
randomIntervalEntry.set_value(settings.get_int('random-interval'));
@ -201,10 +168,7 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
openBtn.connect('clicked', (widget) => {
Utils.openImageFolder(settings);
});
// we populate the tab (gtk4+, gnome 40+), this was previously a button to open a new window in gtk3
carousel = new Carousel(settings, null, null, carouselFlowBox, this.dir.get_path()); // auto load carousel
// this is intended for migrating image folders between computers (or even sharing) or backups
// we export the Bing JSON data to the image directory, so this folder becomes portable
buttonImportData.connect('clicked', () => {
@ -254,24 +218,7 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen
settings.connect('changed::random-interval-mode', () => {
shuffleInterval.set_selected(Utils.randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode')));
});
// GDM3 lockscreen blur override
settings.bind('override-lockscreen-blur', overrideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT);
settings.bind('lockscreen-blur-strength', strengthEntry, 'value', Gio.SettingsBindFlags.DEFAULT);
settings.bind('lockscreen-blur-brightness', brightnessEntry, 'value', Gio.SettingsBindFlags.DEFAULT);
settings.bind('previous-days', delete_previous_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT);
// add a couple of preset buttons
defaultBtn.connect('clicked', (widget) => {
Utils.set_blur_preset(settings, Utils.PRESET_GNOME_DEFAULT);
});
noBlurBtn.connect('clicked', (widget) => {
Utils.set_blur_preset(settings, Utils.PRESET_NO_BLUR);
});
slightBlurBtn.connect('clicked', (widget) => {
Utils.set_blur_preset(settings, Utils.PRESET_SLIGHT_BLUR);
});
// fetch change log (on about page)
if (httpSession)

View File

@ -1,212 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2
Copyright (C) 2017-2021
This file is part of Bing Wallpaper.
Bing Wallpaper is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bing Wallpaper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bing Wallpaper. If not, see <http://www.gnu.org/licenses/>.
Author: Michael Carroll
-->
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkScrolledWindow" id="carouselScrollable">
<property name="hscrollbar-policy">never</property>
<property name="child">
<object class="GtkViewport" id="carouselViewPort">
<property name="can-focus">0</property>
<property name="vexpand">0</property>
<property name="height-request">500</property>
<property name="child">
<object class="GtkFlowBox" id="carouselFlowBox">
<property name="can-focus">0</property>
<property name="halign">center</property>
<property name="homogeneous">1</property>
<!-- <property name="max-children-per-line">5</property> -->
<property name="min-children-per-line">2</property>
<property name="row-spacing">10</property>
<property name="column-spacing">4</property>
</object>
</property>
</object>
</property>
</object>
<object class="GtkFlowBoxChild" id="flowBoxChild">
<property name="can-focus">0</property>
<property name="child">
<object class="GtkBox" id="imageGrid">
<property name="can-focus">0</property>
<property name="homogeneous">0</property>
<property name="spacing">5</property>
<!-- <property name="orientation">vertical</property> -->
<child>
<object class="GtkPicture" id="galleryImage">
<property name="width-request">320</property>
<property name="height-request">120</property>
<property name="can-focus">0</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
</object>
</child>
<child>
<object class="GtkBox" id="buttonBar">
<property name="can-focus">0</property>
<property name="orientation">vertical</property>
<property name="vexpand">1</property>
<property name="valign">center</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkButton" id="favButton">
<property name="tooltip-text" translatable="yes">Favorite</property>
<property name='icon-name'>checkbox</property>
<!-- <property name='icon-name'>checkbox-checked</property> -->
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="unfavButton">
<property name="tooltip-text" translatable="yes">Favorite</property>
<property name='icon-name'>checkbox-checked</property>
<!-- <property name='icon-name'>checkbox-checked</property> -->
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="applyButton">
<property name="tooltip-text" translatable="yes">Apply</property>
<property name='icon-name'>preferences-desktop-wallpaper</property>
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="viewButton">
<property name="tooltip-text" translatable="yes">View</property>
<property name='icon-name'>view-reveal</property>
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="infoButton">
<property name="tooltip-text" translatable="yes">Info</property>
<property name='icon-name'>preferences-system-details</property>
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="deleteButton">
<property name="tooltip-text" translatable="yes">Delete</property>
<property name='icon-name'>edit-delete</property>
<property name="receives-default">1</property>
<property name="hexpand">0</property>
<property name="halign">center</property>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
<object class="GtkFlowBoxChild" id="flowBoxRandom">
<property name="can-focus">0</property>
<property name="child">
<object class="GtkGrid" id="imageGrid">
<property name="can-focus">0</property>
<property name="halign">center</property>
<child>
<object class="GtkImage" id="randomImage">
<property name="width-request">320</property>
<property name="height-request">120</property>
<property name="can-focus">0</property>
<property name="icon-name">media-playlist-shuffle</property>
<property name="icon_size">2</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="randomLabel">
<property name="can-focus">0</property>
<property name="label" translatable="yes">&lt;image name here&gt;</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="randomButton">
<property name="label" translatable="yes">Image shuffle mode</property>
<property name="receives-default">1</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</property>
</object>
<object class="GtkFlowBoxChild" id="flowBoxPlaceholder">
<property name="can-focus">0</property>
<property name="child">
<object class="GtkGrid" id="loadGrid">
<property name="can-focus">0</property>
<property name="halign">center</property>
<child>
<object class="GtkImage" id="loadImage">
<property name="width-request">320</property>
<property name="height-request">120</property>
<property name="can-focus">0</property>
<property name="icon-name">preferences-desktop-wallpaper-symbolic</property>
<property name="icon_size">2</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="loadButton">
<property name="label" translatable="yes">Load image gallery</property>
<property name="receives-default">1</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
</object>
</property>
</object>
</interface>

View File

@ -109,86 +109,6 @@ Bing Wallpaper GNOME extension by: Michael Carroll
</object>
</child>
</object>
<object class="AdwPreferencesPage" id="lockscreen_page">
<property name="icon-name">system-lock-screen-symbolic</property>
<property name="title" translatable="yes">Lock screen</property>
<child>
<object class="AdwPreferencesGroup" id="ls_group">
<property name="title" translatable="yes">Lockscreen blur</property>
<child>
<object class="AdwSwitchRow" id="overrideSwitch">
<property name="title" translatable="yes">Dynamic lockscreen blur</property>
<property name="subtitle" translatable="yes">Whether to enable dynamic blur mode on lock screen</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="strengthEntry">
<property name="title" translatable="yes">Blur strength</property>
<property name="subtitle" translatable="yes">Blur strength when login prompt is not visible</property>
<property name="adjustment">
<object class="GtkAdjustment" id="blurAdjustment">
<property name="lower">0</property>
<property name="upper">50</property>
<property name="page_increment">10</property>
<property name="step_increment">1</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwSpinRow" id="brightnessEntry">
<property name="title" translatable="yes">Wallpaper brightness</property>
<property name="subtitle" translatable="yes">Dim wallpaper when login prompt is not visible</property>
<property name="adjustment">
<object class="GtkAdjustment" id="brightnessAdjustment">
<property name="lower">0</property>
<property name="upper">100</property>
<property name="page_increment">10</property>
<property name="step_increment">1</property>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup" id="ps_group">
<!-- <property name="title" translatable="yes">Presets</property> -->
<child>
<object class="AdwActionRow" id="blurPresets">
<property name="title" translatable="yes">Presets</property>
</object>
</child>
</object>
</child>
</object>
<object class="AdwPreferencesPage" id="gallery_page">
<property name="icon-name">emblem-photos-symbolic</property>
<property name="title" translatable="yes">Gallery</property>
<child>
<object class="GtkScrolledWindow" id="carouselViewPort">
<property name="can-focus">0</property>
<property name="height_request">500</property>
<property name="hexpand">0</property>
<property name="vexpand">0</property>
<property name="child">
<object class="GtkBox">
<child>
<object class="GtkFlowBox" id="carouselFlowBox">
<property name="can-focus">0</property>
<property name="halign">center</property>
<property name="homogeneous">1</property>
<property name="max-children-per-line">2</property>
<property name="min-children-per-line">2</property>
<property name="row-spacing">2</property>
<property name="column-spacing">2</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
<object class="AdwPreferencesPage" id="debug_page">
<property name="icon-name">preferences-other-symbolic</property>
<property name="title" translatable="yes">Debug</property>

View File

@ -12,16 +12,9 @@ import GLib from 'gi://GLib';
import Soup from 'gi://Soup';
import GdkPixbuf from 'gi://GdkPixbuf';
export var PRESET_GNOME_DEFAULT = { blur: 45, dim: 65 }; // as at GNOME 40
export var PRESET_NO_BLUR = { blur: 0, dim: 65 };
export var PRESET_SLIGHT_BLUR = { blur: 2, dim: 30 };
export var BING_SCHEMA = 'org.gnome.shell.extensions.bingwallpaper';
export var DESKTOP_SCHEMA = 'org.gnome.desktop.background';
var vertical_blur = null;
var horizontal_blur = null;
let gitreleaseurl = 'https://api.github.com/repos/neffo/bing-wallpaper-gnome-extension/releases/tags/';
let debug = false;
@ -111,7 +104,7 @@ export function get_current_bg(schema) {
return (cur);
}
export function fetch_change_log(version, label, httpSession) {
export async function fetch_change_log(version, label, httpSession) {
const decoder = new TextDecoder();
// create an http message
let url = gitreleaseurl + "v" + version;
@ -121,7 +114,7 @@ export function fetch_change_log(version, label, httpSession) {
// queue the http request
try {
if (Soup.MAJOR_VERSION >= 3) {
httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
await httpSession.send_and_read_async(request, GLib.PRIORITY_DEFAULT, null, (httpSession, message) => {
let data = decoder.decode(httpSession.send_and_read_finish(message).get_data());
let text = JSON.parse(data).body;
if (text)
@ -143,12 +136,6 @@ export function fetch_change_log(version, label, httpSession) {
}
}
export function set_blur_preset(settings, preset) {
settings.set_int('lockscreen-blur-strength', preset.blur);
settings.set_int('lockscreen-blur-brightness', preset.dim);
BingLog("Set blur preset to " + preset.blur + " brightness to " + preset.dim);
}
export function imageHasBasename(image_item, i, b) {
//log("imageHasBasename : " + image_item.urlbase + " =? " + this);
if (this && this.search(image_item.urlbase.replace('th?id=OHR.', '')))
@ -595,33 +582,48 @@ export function openInSystemViewer(filename, is_file = true) {
Gio.AppInfo.launch_default_for_uri(filename, context);
}
export function exportBingJSON(settings) {
export async function exportBingJSON(settings) {
let json = settings.get_string('bing-json');
let filepath = getWallpaperDir(settings) + 'bing.json';
let file = Gio.file_new_for_path(filepath);
let [success, error] = file.replace_contents(json, null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null);
if (!success) {
BingLog('error saving bing-json from '+filepath+': '+error);
}
const [etag] = await file.replace_contents_async(
json,
null,
false,
Gio.FileCreateFlags.REPLACE_DESTINATION,
null,
(file, res) => {
try {
file.replace_contents_finish(res);
}
catch(e) {
BingLog('error saving bing-json from '+filepath+': '+e);
}
}
);
}
export function importBingJSON(settings) {
export async function importBingJSON(settings) {
const decoder = new TextDecoder();
let filepath = getWallpaperDir(settings) + 'bing.json';
let file = Gio.file_new_for_path(filepath);
if (file.query_exists(null)) {
let [success, contents, etag_out] = file.load_contents(null);
if (!success) {
BingLog('error loading bing-json '+filepath+' - '+etag_out);
}
else {
BingLog('JSON import success');
let parsed = JSON.parse(decoder.decode(contents)); // FIXME: triggers GJS warning without the conversion, need to investigate
// need to implement some checks for validity here
mergeImageLists(settings, parsed);
purgeImages(settings); // remove the older missing images
//cleanupImageList(settings);
}
const [contents, etag] = await file.load_contents_async(null,
(file, res) => {
try {
BingLog('JSON import success');
let parsed = JSON.parse(decoder.decode(contents)); // FIXME: triggers GJS warning without the conversion, need to investigate
// need to implement some checks for validity here
mergeImageLists(settings, parsed);
purgeImages(settings); // remove the older missing images
file.load_contents_finish(res);
}
catch (e) {
BingLog('error loading bing-json '+filepath+' - '+e);
}
}
);
}
else {
BingLog('JSON import file not found');