diff --git a/README.md b/README.md index eeb5c4bb..d0bc146b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Also, check out my related [Google Earth View wallpaper extension](https://githu * In China, users are limited to 'Chinese – China', 'English - International' markets (this is the way Bing handles the Chinese market/locale, not an extension 'bug' - sorry!) * Bing may detect your location incorrectly (and force a locale as above) - if you see this, please let me know what Bing.com itself does +* GNOME Shell themes can break some GNOME popup menu elements (toggle switches for example). This impacts GNOME more generally, not just this extension. Double check you are running latest versions of your themes (or disable them). ## Requirements diff --git a/blur.js b/blur.js index c86aa88e..659b6a7c 100644 --- a/blur.js +++ b/blur.js @@ -6,16 +6,19 @@ // (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 +// This code based on https://github.com/PRATAP-KUMAR/Control_Blur_Effect_On_Lock_Screen +// and https://github.com/sunwxg/gnome-shell-extension-unlockDialogBackground const St = imports.gi.St; const Main = imports.ui.main; const Shell = imports.gi.Shell; const Background = imports.ui.background; +const ScreenShield = imports.ui.screenShield; const UnlockDialog = imports.ui.unlockDialog.UnlockDialog; const ExtensionUtils = imports.misc.extensionUtils; -var _createBackground = UnlockDialog.prototype._createBackground; var _updateBackgroundEffects = UnlockDialog.prototype._updateBackgroundEffects; +var _showClock = UnlockDialog.prototype._showClock; +var _showPrompt = UnlockDialog.prototype._showPrompt; const Me = ExtensionUtils.getCurrentExtension(); const Utils = Me.imports.utils; @@ -23,83 +26,93 @@ var shellVersionMajor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[ var shellVersionMinor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[1]); var shellVersionPoint = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[2]); -var blur_strength = 2; -var blur_brightness = 55; +// 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; -let blurEnabled = false; -var blurMode = whichVersion(); +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 log(msg) { - if (debug) - print("BingWallpaper extension/Blur: " + msg); // disable to keep the noise down in journal + if (debug) // set 'debug' above to false to keep the noise down in journal + print("BingWallpaper extension/Blur: " + msg); } -var Blur = class Blur { - constructor() { - log('Blur mode is '+blurMode); +// we patch UnlockDialog._updateBackgroundEffects() +function _updateBackgroundEffects_BWP(monitorIndex) { + // GNOME shell 3.36.4 and above + log("_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) { + log('default blur active'); + if (effect) { + effect.set({ // GNOME defaults when login prompt is visible + brightness: BLUR_BRIGHTNESS, + sigma: BLUR_SIGMA * themeContext.scale_factor, + }); + } + } + else { + log('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 + sigma: BWP_BLUR_SIGMA * themeContext.scale_factor, + }); + } + } } +} - _do_blur_v1(monitorIndex) { - // GNOME shell 3.36.3 and below (FIXME: this needs work) - log("_do_blur() called for shell < 3.36.4"); - let monitor = Main.layoutManager.monitors[monitorIndex]; - let widget = new St.Widget({ - style_class: 'screen-shield-background', - x: monitor.x, - y: monitor.y, - width: monitor.width, - height: monitor.height, - }); - - let bgManager = new Background.BackgroundManager({ - container: widget, - monitorIndex, - controlPosition: false, - }); - this._bgManagers.push(bgManager); - this._backgroundGroup.add_child(widget); - const themeContext = St.ThemeContext.get_for_stage(global.stage); - log("blur strength: " + blur_strength +" blur brightness: "+blur_brightness); - let effect = new Shell.BlurEffect({ brightness: blur_brightness * 0.01, sigma: blur_strength * themeContext.scale_factor / 5 }); // fix me, should this be /5? - this._scaleChangedId = themeContext.connect('notify::scale-factor', () => { effect.sigma = blur_strength * themeContext.scale_factor / 5; }); - widget.add_effect(effect); - blurEnabled = true; - } +// we patch both UnlockDialog._showClock() and UnlockDialog._showPrompt() to let us +// adjustable blur in a Windows-like way (this ensures login prompt is readable) +function _showClock_BWP() { + promptActive = false; + this._showClock_GNOME(); // pass to default GNOME function + this._updateBackgroundEffects(); +} - _do_blur_v2(monitorIndex) { - // GNOME shell 3.36.4 and above - log("_do_blur() called for shell >= 3.36.4"); - const themeContext = St.ThemeContext.get_for_stage(global.stage); - for (const widget of this._backgroundGroup.get_children()) { - widget.get_effect('blur').set({ - brightness: blur_brightness * 0.01, - sigma: blur_strength * themeContext.scale_factor, - }); - } - blurEnabled = true; +function _showPrompt_BWP() { + promptActive = true; + this._showPrompt_GNOME(); // pass to default GNOME function + this._updateBackgroundEffects(); +} + +var Blur = class Blur { + constructor() { + this.enabled = false; + log('Bing Wallpaper adjustable blur is '+supportedVersion()?'available':'not available'); } set_blur_strength(value) { - if (value > 100 ) - value = 100; - if (value < 0 ) - value = 0; - blur_strength = value; - log("lockscreen blur strength set to "+value); + BWP_BLUR_SIGMA = this._clampValue(value); + log("lockscreen blur strength set to "+BWP_BLUR_SIGMA); } set_blur_brightness(value) { + BWP_BLUR_BRIGHTNESS = this._clampValue(value); + log("lockscreen brightness set to " + BWP_BLUR_BRIGHTNESS); + } + + // valid values are 0 to 100 + _clampValue(value) { if (value > 100) value = 100; if (value < 0 ) value = 0; - blur_brightness = value; - log("lockscreen brightness set to " + value); + return value; } _switch(enabled) { - if (enabled) { + if (enabled && !this.enabled) { this._enable(); } else { @@ -108,44 +121,45 @@ var Blur = class Blur { } _enable() { - log("_enable() called on GNOME "+imports.misc.config.PACKAGE_VERSION); - if (blurMode == 1) { - UnlockDialog.prototype._createBackground = this._do_blur_v1; - } - else if (blurMode == 2) { - UnlockDialog.prototype._updateBackgroundEffects = this._do_blur_v2; - } - else { - log("shell version too old, no overriding"); + if (supportedVersion()) { + log("Blur._enable() called on GNOME "+imports.misc.config.PACKAGE_VERSION); + UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects_BWP; + // we override _showClock and _showPrompt to patch in updates to blur effect before calling the GNOME functions + UnlockDialog.prototype._showClock = _showClock_BWP; + UnlockDialog.prototype._showPrompt = _showPrompt_BWP; + + // this are the original functions which we call into from our versions above + UnlockDialog.prototype._showClock_GNOME = _showClock; + UnlockDialog.prototype._showPrompt_GNOME = _showPrompt; + } + this.enabled = true; } _disable() { - if (blurEnabled == false) // nothing to do, don't clash without other extensions that do the same + if (!this.enabled) return; log("_lockscreen_blur_disable() called"); - if (blurMode == 1) { - UnlockDialog.prototype._createBackground = _createBackground; - } - else if (blurMode == 2) { + if (supportedVersion()) { + // restore default functions UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects; + UnlockDialog.prototype._showClock = _showClock; + UnlockDialog.prototype._showPrompt = _showPrompt; + // clean up unused functions we created + UnlockDialog.prototype._showClock_GNOME = null; + delete UnlockDialog.prototype._showClock_GNOME; + UnlockDialog.prototype._showPrompt_GNOME = null; + delete UnlockDialog.prototype._showPrompt_GNOME; } - else { - log("shell version too old, no overriding"); - } + this.enabled = false; } }; -function whichVersion() { - if ((shellVersionMajor == 3 && shellVersionMinor >= 36) || shellVersionMajor >= 40) { - if (shellVersionMajor == 3 && shellVersionMinor == 36 && shellVersionPoint <= 3) { - return 1; - } - else { - return 2; - } - } - else { - return 0; +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; } diff --git a/carousel.js b/carousel.js index 7bfed477..81804fc4 100644 --- a/carousel.js +++ b/carousel.js @@ -27,6 +27,7 @@ var Carousel = class Carousel { this.flowBox = null; this.window = null; this.imageList = Utils.imageListSortByDate(Utils.getImageList(this.settings)).reverse(); // get images and reverse order + this.searchEntry = null; this.log('create carousel...'); diff --git a/extension.js b/extension.js index 2761f419..70c81b51 100644 --- a/extension.js +++ b/extension.js @@ -39,17 +39,29 @@ const ICON_TIMED_MODE_BUTTON = 'document-open-recent-symbolic'; const ICON_PAUSE_MODE_BUTTON = 'media-playback-pause-symbolic'; const ICON_PLAY_MODE_BUTTON = 'media-playback-start-symbolic'; const ICON_REFRESH = 'view-refresh-symbolic'; - +const ICON_RANDOM = Me.dir.get_child('icons').get_path() + '/'+'game-die-symbolic.svg'; let bingWallpaperIndicator = null; let blur = null; -let blur_brightness = 0.55; -let blur_strength = 30; // remove this when dropping support for < 3.33, see https://github.com/OttoAllmendinger/ const getActorCompat = (obj) => Convenience.currentVersionGreaterEqual('3.33') ? obj : obj.actor; +const newMenuItem = (label) => { + return new PopupMenu.PopupMenuItem(label); +} + +const newMenuSwitchItem = (label, state) => { + let switchItem = new PopupMenu.PopupSwitchMenuItem( + label, + state, + {}); + switchItem.label.x_expand = true; + switchItem._statusBin.x_expand = false; + return switchItem; +} + function log(msg) { if (bingWallpaperIndicator && bingWallpaperIndicator._settings.get_boolean('debug-logging')) print('BingWallpaper extension: ' + msg); // disable to keep the noise down in journal @@ -99,9 +111,14 @@ class BingWallpaperIndicator extends PanelMenu.Button { this.clipboard = new BWClipboard.BWClipboard(); this.imageIndex = null; this.logger = null; - blur = new Blur.Blur(); - blur.blur_strength = 30; - blur.blur_brightness = 0.55; + + if (!blur) // as Blur isn't disabled on screen lock (like the rest of the extension is) + blur = new Blur.Blur(); + + /* + blur.BWP_BLUR_BRIGHTNESS = 2; + blur.BWP_BLUR_SIGMA = 55; + */ // take a variety of actions when the gsettings values are modified by prefs this._settings = ExtensionUtils.getSettings(Utils.BING_SCHEMA); @@ -115,88 +132,74 @@ class BingWallpaperIndicator extends PanelMenu.Button { Utils.is_x11 = Utils.enabled_unsafe; } - this.refreshDueItem = new PopupMenu.PopupMenuItem(_("")); - this._wrapLabelItem(this.refreshDueItem); - //this.showItem = new PopupMenu.PopupMenuItem(_("Show description")); - this.titleItem = new PopupMenu.PopupMenuItem(_("Awaiting refresh...")); //FIXME: clean this up - this._wrapLabelItem(this.titleItem); - this.explainItem = new PopupMenu.PopupMenuItem(_("Awaiting refresh...")); - this._wrapLabelItem(this.explainItem); - this.controlItem = new PopupMenu.PopupMenuItem(""); // blank - this.copyrightItem = new PopupMenu.PopupMenuItem(_("Awaiting refresh...")); - this._wrapLabelItem(this.copyrightItem); - this.clipboardImageItem = new PopupMenu.PopupMenuItem(_("Copy image to clipboard")); - this.clipboardURLItem = new PopupMenu.PopupMenuItem(_("Copy image URL to clipboard")); - this.folderItem = new PopupMenu.PopupMenuItem(_("Open image folder")); - this.dwallpaperItem = new PopupMenu.PopupMenuItem(_("Set background image")); - this.swallpaperItem = new PopupMenu.PopupMenuItem(_("Set lock screen image")); - this.refreshItem = new PopupMenu.PopupMenuItem(_("Refresh Now")); - this.settingsItem = new PopupMenu.PopupMenuItem(_("Settings")); - this.thumbnailItem = new PopupMenu.PopupBaseMenuItem({ style_class: 'wp-thumbnail-image'}); - this.menu.addMenuItem(this.refreshItem); - this.menu.addMenuItem(this.refreshDueItem); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - this.menu.addMenuItem(this.explainItem); - - // build the button bar - this.menu.addMenuItem(this.controlItem); - this.prevBtn = this._newMenuIcon( - ICON_PREVIOUS_BUTTON, - this.controlItem, - this._prevImage); - this.refreshBtn = this._newMenuIcon( - ICON_REFRESH, - this.controlItem, - this._shuffleImage); - this.nextBtn = this._newMenuIcon( - ICON_NEXT_BUTTON, - this.controlItem, - this._nextImage); - this.curBtn = this._newMenuIcon( - ICON_CURRENT_BUTTON, - this.controlItem, - this._curImage); - this.randomBtn = this._newMenuIcon( - this._settings.get_string('selected-image') == 'random' ? ICON_SHUFFLE_BUTTON: ICON_CONSEC_BUTTON, - this.controlItem, - this._toggleShuffle, - 6); - this.modeBtn = this._newMenuIcon( - this._settings.get_boolean('revert-to-current-image') ? ICON_PLAY_MODE_BUTTON : ICON_PAUSE_MODE_BUTTON, - this.controlItem, - this._togglePause); + this.refreshDueItem = newMenuItem(_("")); + this.titleItem = new PopupMenu.PopupSubMenuMenuItem(_("Awaiting refresh..."), false); + 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")); + this.refreshItem = newMenuItem(_("Refresh Now")); + this.settingsItem = newMenuItem(_("Settings")); + this.openImageItem = newMenuItem(_("Open in image viewer")); + this.openImageInfoLinkItem = newMenuItem(_("Open Bing image information page")); + + [this.openImageInfoLinkItem, this.openImageItem, this.folderItem, + this.clipboardImageItem, this.clipboardURLItem, this.dwallpaperItem] + .forEach(e => this.titleItem.menu.addMenuItem(e)); + + // quick settings submenu + this.settingsSubMenu = new PopupMenu.PopupSubMenuMenuItem(_("Quick settings"), false); + // toggles under the quick settings submenu + this.toggleSetBackground = newMenuSwitchItem(_("Set background image"), this._settings.get_boolean('set-background')); + this.toggleSelectNew = newMenuSwitchItem(_("Always show new images"), this._settings.get_boolean('revert-to-current-image')); + this.toggleShuffle = newMenuSwitchItem(_("Image shuffle mode"), true); + this.toggleNotifications = newMenuSwitchItem(_("Enable desktop notifications"), this._settings.get_boolean('notify')); + this.toggleImageCount = newMenuSwitchItem(_("Show image count"), this._settings.get_boolean('show-count-in-image-title')); - this.menu.addMenuItem(this.thumbnailItem); - this.menu.addMenuItem(this.titleItem); - this.menu.addMenuItem(this.copyrightItem); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - if (this.clipboard.clipboard) { // only if we have a clipboard - this.menu.addMenuItem(this.clipboardImageItem); - this.clipboardImageItem.connect('activate', this._copyImageToClipboard.bind(this)); - this.menu.addMenuItem(this.clipboardURLItem); - this.clipboardURLItem.connect('activate', this._copyURLToClipboard.bind(this)); - } - this.menu.addMenuItem(this.folderItem); - this.menu.addMenuItem(this.dwallpaperItem); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - this.menu.addMenuItem(this.settingsItem); - this.explainItem.setSensitive(false); - this.copyrightItem.setSensitive(false); - this.refreshDueItem.setSensitive(false); - this.thumbnailItem.setSensitive(false); + [this.toggleNotifications, this.toggleImageCount, this.toggleSetBackground, this.toggleSelectNew, + this.toggleShuffle] + .forEach(e => this.settingsSubMenu.menu.addMenuItem(e)); + + // these items are a bit unique, we'll populate them in _setControls() + this.controlItem = newMenuItem(""); + this.thumbnailItem = new PopupMenu.PopupBaseMenuItem({ style_class: 'wp-thumbnail-image'}); + this._setControls(); // build the button bar + + // we need to word-wrap these menu items to not overflow menu in case of long lines of text + [this.refreshDueItem, this.titleItem, this.explainItem, this.copyrightItem] + .forEach((e, i) => { + this._wrapLabelItem(e); + }); + + // set the order of menu items (including separators) + let allMenuItems = [ + this.refreshItem, + this.refreshDueItem, + new PopupMenu.PopupSeparatorMenuItem(), + this.controlItem, + new PopupMenu.PopupSeparatorMenuItem(), + this.explainItem, + this.thumbnailItem, + this.titleItem, + this.copyrightItem, + new PopupMenu.PopupSeparatorMenuItem(), + this.settingsSubMenu, + this.settingsItem + ]; + allMenuItems.forEach(e => this.menu.addMenuItem(e)); + + // non clickable information items + [this.explainItem, this.copyrightItem, this.refreshDueItem, this.thumbnailItem] + .forEach((e) => { + e.setSensitive(false); + }); this._setConnections(); - this.thumbnailItem.connect('activate', this._openInSystemViewer.bind(this)); - this.titleItem.connect('activate', () => { - if (this.imageinfolink) - Utils.openInSystemViewer(this.imageinfolink, false); - }); - this.folderItem.connect('activate', Utils.openImageFolder.bind(this, this._settings)); - this.dwallpaperItem.connect('activate', this._setBackgroundDesktop.bind(this)); - this.refreshItem.connect('activate', this._refresh.bind(this)); - this.settingsItem.connect('activate', this._openPrefs.bind(this)); - getActorCompat(this).connect('button-press-event', this._openMenu.bind(this)); - if (this._settings.get_string('state') != '[]') { + + if (this._settings.get_string('state') != '[]') { // setting state on reset or initial boot this._reStoreState(); } else { @@ -215,22 +218,91 @@ class BingWallpaperIndicator extends PanelMenu.Button { this._settings.connect('changed::hide', () => { getActorCompat(this).visible = !this._settings.get_boolean('hide'); }); - this._setIcon(); - this._settings.connect('changed::icon-name', this._setIcon.bind(this)); - this._settings.connect('changed::market', this._refresh.bind(this)); - this._settings.connect('changed::set-background', this._setBackground.bind(this)); - this._settings.connect('changed::set-lockscreen', this._setBackground.bind(this)); - this._settings.connect('changed::override-lockscreen-blur', this._setBlur.bind(this)); + + let settingConnections = [ + {signal: 'changed::icon-name', call: this._setIcon}, + {signal: 'changed::market', call: this._refresh}, + {signal: 'changed::set-background', call: this._setBackground}, + /*{signal: 'changed::set-lockscreen', call: this._setBackground},*/ + {signal: 'changed::override-lockscreen-blur', call: this._setBlur}, + {signal: 'changed::selected-image', call: this._setImage}, + {signal: 'changed::delete-previous', call: this._cleanUpImages}, + {signal: 'changed::notify', call: this._notifyCurrentImage}, + {signal: 'changed::always-export-bing-json', call: this._exportData}, + {signal: 'changed::bing-json', call: this._exportData}, + {signal: 'changed::controls-icon-size', call: this._setControls} + ]; + + // _setShuffleToggleState + settingConnections.forEach((e) => { + this._settings.connect(e.signal, e.call.bind(this)); + }); + this._settings.connect('changed::lockscreen-blur-strength', blur.set_blur_strength.bind(this, this._settings.get_int('lockscreen-blur-strength'))); - this._settings.connect('changed::lockscreen-blur-brightness', blur.set_blur_brightness.bind(this, this._settings.get_int('lockscreen-blur-brightness'))); + this._settings.connect('changed::lockscreen-blur-brightness', blur.set_blur_brightness.bind(this, this._settings.get_int('lockscreen-blur-brightness'))); + + // ensure we're in a sensible initial state + this._setIcon(); this._setBlur(); - this._settings.connect('changed::selected-image', this._setImage.bind(this)); this._setImage(); - this._settings.connect('changed::delete-previous', this._cleanUpImages.bind(this)); - this._settings.connect('changed::notify', this._notifyCurrentImage.bind(this)); - this._settings.connect('changed::always-export-bing-json', this._exportData.bind(this)); - this._settings.connect('changed::bing-json', this._exportData.bind(this)); this._cleanUpImages(); + + // menu connections + getActorCompat(this).connect('button-press-event', this._openMenu.bind(this)); + + // link menu items to functions + this.thumbnailItem.connect('activate', this._setBackgroundDesktop.bind(this)); + this.openImageItem.connect('activate', this._openInSystemViewer.bind(this)); + //this.titleItem.connect('activate', this._setBackgroundDesktop.bind(this)); + this.openImageInfoLinkItem.connect('activate', this._openImageInfoLink.bind(this)); + this.dwallpaperItem.connect('activate', this._setBackgroundDesktop.bind(this)); + this.refreshItem.connect('activate', this._refresh.bind(this)); + this.settingsItem.connect('activate', this._openPrefs.bind(this)); + + // unfortunately we can't bind like we can with prefs here, so we handle toggles in two steps + // first, we listen for changes to these toggle settings and update toggles + this._settings.connect('changed::set-background', () => { + this.toggleSetBackground.setToggleState(this._settings.get_boolean('set-background')); + }); + this._settings.connect('changed::revert-to-current-image', () => { + this.toggleSelectNew.setToggleState(this._settings.get_boolean('revert-to-current-image')); + }); + this._settings.connect('changed::notify', () => { + this.toggleNotifications.setToggleState(this._settings.get_boolean('notify')); + }); + this._settings.connect('changed::show-count-in-image-title', () => { + this.toggleImageCount.setToggleState(this._settings.get_boolean('show-count-in-image-title')); + this._setMenuText(); + }); + + // & then, link settings to toggle state (the other way) + this.toggleSetBackground.connect('toggled', (item, state) => { + this._settings.set_boolean('set-background', state); + }); + this.toggleSelectNew.connect('toggled', (item, state) => { + this._settings.set_boolean('revert-to-current-image', state); + }); + this.toggleNotifications.connect('toggled', (item, state) => { + this._settings.set_boolean('notify', state); + }); + this.toggleImageCount.connect('toggled', (item, state) => { + this._settings.set_boolean('show-count-in-image-title', state); + this._selectImage(false); + }); + + // shuffle is a special case + this._setShuffleToggleState(); + this.toggleShuffle.connect('toggled', this._toggleShuffle.bind(this)); + + 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)); + } } _openPrefs() { @@ -267,6 +339,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { this.selected_image = this._settings.get_string('selected-image'); log('selected image changed to: ' + this.selected_image); this._selectImage(); + this._setShuffleToggleState(); } _notifyCurrentImage() { @@ -346,9 +419,16 @@ class BingWallpaperIndicator extends PanelMenu.Button { // set menu text in lieu of a notification/popup _setMenuText() { - this.titleItem.label.set_text(this.title ? this.title : ''); - this.explainItem.label.set_text(this.explanation ? this.explanation : ''); + this.titleItem.label.set_text(this.title ? this.title : ''); this.copyrightItem.label.set_text(this.copyright ? this.copyright : ''); + if (this._settings.get_boolean('show-count-in-image-title') && this.explanation) { + let imageList = JSON.parse(this._settings.get_string('bing-json')); + if (imageList.length > 0) + this.explainItem.label.set_text( this.explanation + ' [' + (this.imageIndex + 1) + '/' + imageList.length + ']'); + } + else { + this.explainItem.label.set_text(this.explanation ? this.explanation : ''); + } } _wrapLabelItem(menuItem) { @@ -359,12 +439,34 @@ class BingWallpaperIndicator extends PanelMenu.Button { menuItem.label.set_style('max-width: 420px;'); } + _setControls() { + this.prevBtn = this._newMenuIcon( + ICON_PREVIOUS_BUTTON, + this.controlItem, + this._prevImage); + this.nextBtn = this._newMenuIcon( + ICON_NEXT_BUTTON, + this.controlItem, + this._nextImage); + this.curBtn = this._newMenuIcon( + ICON_CURRENT_BUTTON, + this.controlItem, + this._curImage); + this.randomizeBtn = this._newMenuIcon( + ICON_RANDOM, + this.controlItem, + this._shuffleImage); + } + _newMenuIcon(icon_name, parent, fn, position = null) { + let gicon = Gio.icon_new_for_string(icon_name); let icon = new St.Icon({ - icon_name: icon_name, + /*icon_name: icon_name,*/ + gicon: gicon, style_class: 'popup-menu-icon', - x_expand: false, - y_expand: false + x_expand: true, + y_expand: true, + icon_size: this._settings.get_int('controls-icon-size') }); let iconBtn = new St.Button({ @@ -440,16 +542,8 @@ class BingWallpaperIndicator extends PanelMenu.Button { this._selectImage(true); } - _togglePause() { - this._settings.set_boolean('revert-to-current-image', !this._settings.get_boolean('revert-to-current-image')); - getActorCompat(this.controlItem.remove_child(this.modeBtn)); - - this.modeBtn = this._newMenuIcon( - this._settings.get_boolean('revert-to-current-image') ? ICON_PLAY_MODE_BUTTON : ICON_PAUSE_MODE_BUTTON, - this.controlItem, - this._togglePause); - - log('switched mode to ' + this._settings.get_boolean('revert-to-current-image')); + _setShuffleToggleState() { + this.toggleShuffle.setToggleState(this._settings.get_string('selected-image') == 'random'); } _toggleShuffle() { @@ -459,16 +553,8 @@ class BingWallpaperIndicator extends PanelMenu.Button { else { this._settings.set_string('selected-image', 'random'); } - - getActorCompat(this.controlItem.remove_child(this.randomBtn)); - - this.randomBtn = this._newMenuIcon( - this._settings.get_string('selected-image') == 'random'? ICON_SHUFFLE_BUTTON: ICON_CONSEC_BUTTON, - this.controlItem, - this._toggleShuffle, - 6); - - log('switched mode to ' + this._settings.get_boolean('revert-to-current-image')); + this._setShuffleToggleState(); + log('switched mode to ' + this._settings.get_string('selected-image')); } _gotoImage(relativePos) { @@ -478,7 +564,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { if (this.selected_image == 'random') return; - if (this.selected_image == 'current') { + if (this.selected_image == 'current') { curIndex = Utils.getCurrentImageIndex(imageList); } else { @@ -527,7 +613,6 @@ class BingWallpaperIndicator extends PanelMenu.Button { let url = BingImageURL + '?format=js&idx=0&n=8&mbl=1&mkt=' + (market != 'auto' ? market : ''); let request = Soup.Message.new('GET', url); request.request_headers.append('Accept', 'application/json'); - //log('fetching: ' + message.get_uri().to_string(false)); // queue the http request try { @@ -673,8 +758,6 @@ class BingWallpaperIndicator extends PanelMenu.Button { // set current image details at extension scope this.title = image.copyright.replace(/\s*[\(\(].*?[\)\)]\s*/g, ''); this.explanation = _('Bing Wallpaper of the Day for') + ' ' + this._localeDate(image.startdate); - if (this._settings.get_boolean('show-count-in-image-title')) - this.explanation += ' [' + (this.imageIndex + 1) + '/' + imageList.length + ']'; this.copyright = image.copyright.match(/[\(\(]([^)]+)[\)\)]/)[1].replace('\*\*', ''); // Japan locale uses () rather than () this.longstartdate = image.fullstartdate; this.imageinfolink = image.copyrightlink.replace(/^http:\/\//i, 'https://'); @@ -827,6 +910,12 @@ class BingWallpaperIndicator extends PanelMenu.Button { Utils.openInSystemViewer(this.filename); } + // open Bing image information page + _openImageInfoLink() { + if (this.imageinfolink) + Utils.openInSystemViewer(this.imageinfolink, false); + } + stop() { if (this._timeout) GLib.source_remove(this._timeout); @@ -854,9 +943,13 @@ function disable() { bingWallpaperIndicator.destroy(); bingWallpaperIndicator = null; - // disable blur override and cleanup - blur._disable(); - blur = null; + // *** NOTE for EGO reviewers *** + // blur.js remains active during lockscreen, while the rest of the extension is disabled + // this code ONLY modifies the background blur effects for the lockscreen no web connectivity + if (!Main.sessionMode.isLocked) { + blur._disable(); // disable blur (blur.js) override and cleanup + blur = null; + } } function toFilename(wallpaperDir, startdate, imageURL, resolution) { diff --git a/icons/game-die-symbolic.svg b/icons/game-die-symbolic.svg new file mode 100644 index 00000000..698416ac --- /dev/null +++ b/icons/game-die-symbolic.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/install.sh b/install.sh index 9fe4ca56..8a90ef41 100755 --- a/install.sh +++ b/install.sh @@ -9,3 +9,5 @@ ZIP_NAME=BingWallpaper@ineffable-gmail.com.zip mkdir -p $INSTALL_PATH/$EXTENSION_NAME unzip -o $ZIP_NAME -d $INSTALL_PATH/$EXTENSION_NAME/ + +gnome-extensions enable $EXTENSION_NAME \ No newline at end of file diff --git a/locale/BingWallpaper.pot b/locale/BingWallpaper.pot index da9040af..5d693a09 100644 --- a/locale/BingWallpaper.pot +++ b/locale/BingWallpaper.pot @@ -6,11 +6,11 @@ msgstr "" msgid "Indicator icon" msgstr "" -#: ui/Settings.ui.h:3 ui/Settings4.ui.h:4 +#: ui/Settings.ui.h:3 ui/Settings4.ui.h:4 extension.js:159 msgid "Enable desktop notifications" msgstr "" -#: ui/Settings.ui.h:4 ui/Settings4.ui.h:5 extension.js:131 +#: ui/Settings.ui.h:4 ui/Settings4.ui.h:5 extension.js:142 extension.js:156 msgid "Set background image" msgstr "" @@ -46,7 +46,7 @@ msgstr "" msgid "Bing locale" msgstr "" -#: ui/Settings.ui.h:13 ui/Settings4.ui.h:12 extension.js:134 +#: ui/Settings.ui.h:13 ui/Settings4.ui.h:12 extension.js:145 msgid "Settings" msgstr "" @@ -106,7 +106,7 @@ msgstr "" msgid "Enable logging to system journal" msgstr "" -#: ui/Settings.ui.h:28 ui/Settings4.ui.h:27 +#: ui/Settings.ui.h:28 ui/Settings4.ui.h:27 extension.js:157 msgid "Always show new images" msgstr "" @@ -248,63 +248,83 @@ msgstr "" msgid "Load image gallery" msgstr "" -#: extension.js:118 +#: extension.js:135 msgid "" msgstr "" -#: extension.js:121 extension.js:123 extension.js:126 +#: extension.js:136 extension.js:137 extension.js:138 msgid "Awaiting refresh..." msgstr "" -#: extension.js:128 +#: extension.js:139 msgid "Copy image to clipboard" msgstr "" -#: extension.js:129 +#: extension.js:140 msgid "Copy image URL to clipboard" msgstr "" -#: extension.js:130 +#: extension.js:141 msgid "Open image folder" msgstr "" -#: extension.js:132 +#: extension.js:143 msgid "Set lock screen image" msgstr "" -#: extension.js:133 +#: extension.js:144 msgid "Refresh Now" msgstr "" -#: extension.js:254 +#: extension.js:146 +msgid "Open in image viewer" +msgstr "" + +#: extension.js:147 +msgid "Open Bing image information page" +msgstr "" + +#: extension.js:154 +msgid "Quick settings" +msgstr "" + +#: extension.js:158 +msgid "Image shuffle mode" +msgstr "" + +#: extension.js:160 +msgid "Show image count" +msgstr "" + +#: extension.js:326 msgid "Next refresh" msgstr "" -#: extension.js:255 +#: extension.js:327 msgid "Last refresh" msgstr "" -#: extension.js:639 extension.js:675 +#: extension.js:724 extension.js:760 msgid "Bing Wallpaper of the Day for" msgstr "" -#: extension.js:701 +#: extension.js:784 msgid "No wallpaper available" msgstr "" -#: extension.js:702 +#: extension.js:785 msgid "No picture for today." msgstr "" -#: prefs.js:177 +#: prefs.js:181 msgid "Select folder" msgstr "" -#: prefs.js:245 +#: prefs.js:249 msgid "Most recent image" msgstr "" -#: prefs.js:246 +#: prefs.js:250 msgid "Random image" msgstr "" diff --git a/locale/fr_FR/LC_MESSAGES/BingWallpaper.mo b/locale/fr_FR/LC_MESSAGES/BingWallpaper.mo index cf00b07b..0b280bb2 100644 Binary files a/locale/fr_FR/LC_MESSAGES/BingWallpaper.mo and b/locale/fr_FR/LC_MESSAGES/BingWallpaper.mo differ diff --git a/locale/fr_FR/LC_MESSAGES/BingWallpaper.po b/locale/fr_FR/LC_MESSAGES/BingWallpaper.po index fe046fc8..dfc3c10c 100644 --- a/locale/fr_FR/LC_MESSAGES/BingWallpaper.po +++ b/locale/fr_FR/LC_MESSAGES/BingWallpaper.po @@ -28,7 +28,7 @@ msgstr "Icône d'indicateur" #: Settings.ui.h:3 Settings4.ui.h:4 msgid "Enable desktop notifications" -msgstr "" +msgstr "Activer les notifications sur le bureau" #: Settings.ui.h:4 Settings4.ui.h:5 extension.js:129 msgid "Set background image" @@ -83,55 +83,55 @@ msgstr "Paramètres" #: Settings.ui.h:16 Settings4.ui.h:17 msgid "Use custom blur and brightness" -msgstr "" +msgstr "Personaliser le flou et la luminosité" #: Settings.ui.h:17 Settings4.ui.h:18 msgid "Override GDM3 lockscreen effects" -msgstr "" +msgstr "Passer outre les effets de l'écran de verouillage GDM3" #: Settings.ui.h:18 Settings4.ui.h:19 msgid "Blur can improve readability of login prompt" -msgstr "" +msgstr "Le flou peut améliorer la lisibilté sur l'invite de connexion" #: Settings.ui.h:19 Settings4.ui.h:20 msgid "Background blur intensity" -msgstr "" +msgstr "Intensité du flou de l'arrière plan" #: Settings.ui.h:20 Settings4.ui.h:21 msgid "Can improve contrast of login prompt" -msgstr "" +msgstr "Peut améliorer le contraste de l'invite de connexion" #: Settings.ui.h:21 Settings4.ui.h:22 msgid "Background brightness" -msgstr "" +msgstr "Luminosité de l'arrière plan" #: Settings.ui.h:22 Settings4.ui.h:23 msgid "Presets" -msgstr "" +msgstr "Pré-définis" #: Settings.ui.h:23 Settings4.ui.h:24 msgid "Commonly used presets" -msgstr "" +msgstr "Pré-définis courrament utilisés" #: Settings.ui.h:24 Settings4.ui.h:25 msgid "No blur, slight dim" -msgstr "" +msgstr "Pas de flou, léger dim" #: Settings.ui.h:25 Settings4.ui.h:26 msgid "GNOME default" -msgstr "" +msgstr "GNOME par défaut" #: Settings.ui.h:26 Settings4.ui.h:27 msgid "Slight blur, slight dim" -msgstr "" +msgstr "Léger flou, léger dim" #: Settings.ui.h:27 Settings4.ui.h:28 msgid "Lock Screen" -msgstr "" +msgstr "Ecran de verouillage" #: Settings.ui.h:28 Settings4.ui.h:29 msgid "New wallpaper images everyday from Bing" -msgstr "" +msgstr "Nouvelle image d'arrière plan chaque jour depuis Bing" #: Settings.ui.h:29 Settings4.ui.h:30 msgid "Gnome shell extension version " @@ -151,10 +151,13 @@ msgid "" "\">Flattr or Github " "Sponsors." msgstr "" +"Montrer votre support pour l'auteur sur Flattr ou sur Github " +"Sponsors." #: Settings.ui.h:33 Settings4.ui.h:34 msgid "Changes since last version" -msgstr "" +msgstr "Changements depuis la dernière version" #: Settings.ui.h:34 Settings4.ui.h:35 msgid "Based on NASA APOD Gnome shell extension by Elia Argentieri" @@ -215,7 +218,7 @@ msgstr "Actualiser maintenant" #: extension.js:137 msgid "Thumbnail disabled on Wayland" -msgstr "" +msgstr "Vignette désactivé sur Wayland" #: extension.js:203 msgid "Next refresh" @@ -233,7 +236,7 @@ msgstr "Définir le fond d'écran" #: extension.js:498 msgid "More info on Bing.com" -msgstr "" +msgstr "Plus d'info sur Bing.com" #: extension.js:553 msgid "No wallpaper available" @@ -255,7 +258,7 @@ msgstr "Image aléatoire" #: prefs.js:190 prefs.js:206 msgid "Disabled on current GNOME version" -msgstr "" +msgstr "Désactiver la version actuelle de GNOME" #: utils.js:139 msgid "Fetching data..." @@ -271,11 +274,11 @@ msgstr "Une erreur de réseau est survenue" #: utils.js:159 msgid "Too many requests in 5 seconds" -msgstr "" +msgstr "Trop de requêtes en 5 secondes" #: utils.js:186 msgid "No change log found for this release" -msgstr "" +msgstr "Pas de changements trouvé pour cette version" #: utils.js:366 utils.js:369 #, fuzzy diff --git a/metadata.json b/metadata.json index caa2ca91..01c998af 100644 --- a/metadata.json +++ b/metadata.json @@ -4,7 +4,7 @@ "name": "Bing Wallpaper", "settings-schema": "org.gnome.shell.extensions.bingwallpaper", "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_FR), Portuguese (pt, pt_BR), Ukrainian (uk), Russian (ru_RU), Spanish (es), Korean (ko), Indonesian (id), Catalan (ca), Norwegian Bokmål (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:", - "version": "43", + "version": "44", "url": "https://github.com/neffo/bing-wallpaper-gnome-extension", "gettext-domain": "BingWallpaper" } diff --git a/prefs.js b/prefs.js index 9c34a71b..3045def5 100644 --- a/prefs.js +++ b/prefs.js @@ -102,6 +102,8 @@ function buildPrefsWidget() { let buttonImportData = buildable.get_object('button_json_import'); let buttonExportData = buildable.get_object('button_json_export'); let switchAlwaysExport = buildable.get_object('always_export_switch'); + /*let searchEntry = buildable.get_object('searchEntry'); + let searchBuffer = buildable.get_object('searchBuffer');*/ let carouselFlowBox = (Gtk.get_major_version() == 4) ? buildable.get_object('carouselFlowBox'): null; try { @@ -148,11 +150,13 @@ function buildPrefsWidget() { // open image carousel (gallery) window (gtk3, gnome <40) or populate the tab (gtk4+, gnome 40+) if (Gtk.get_major_version() == 4) { carousel = new Carousel.Carousel(settings, null, null, carouselFlowBox); // auto load carousel + } else { galleryButton.connect('clicked', (widget) => { carousel = new Carousel.Carousel(settings, widget, null, carouselFlowBox); }); + } // this is intended for migrating image folders between computers (or even sharing) or backups diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index ced426e6..eb2969a5 100644 Binary files a/schemas/gschemas.compiled and b/schemas/gschemas.compiled differ diff --git a/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml b/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml index 94c8c94b..5aa1322c 100644 --- a/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml +++ b/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml @@ -160,6 +160,12 @@ false Include current index and total image count in image title + + + + 32 + Size of icons for controls in popup menu + + + 120 + 0 0 @@ -1237,25 +1240,41 @@ Bing Wallpaper GNOME extension by: Michael Carroll - + 3 - - 0 - 500 - 0 - 0 - - + + 0 + vertical + + + 0 - center - 1 - 2 - 2 - 2 - 2 + 500 + 0 + 0 + + + 0 + center + 1 + 2 + 2 + 2 + 2 + + - +