From 505c67d2923cd1830467a11db55c452cf31e93bc Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Thu, 9 Apr 2026 09:51:44 -0400 Subject: [PATCH] [gnome] Update extensions --- .../Vitals@CoreCoding.com/extension.js | 331 +++++++++++++++--- .../Vitals@CoreCoding.com/history.js | 157 +++++++++ .../locale/my_MM/LC_MESSAGES/vitals.mo | Bin 0 -> 17140 bytes .../Vitals@CoreCoding.com/metadata.json | 5 +- .../extensions/Vitals@CoreCoding.com/prefs.js | 3 +- .../extensions/Vitals@CoreCoding.com/prefs.ui | 29 ++ .../schemas/gschemas.compiled | Bin 1972 -> 2084 bytes ....gnome.shell.extensions.vitals.gschema.xml | 10 + .../Vitals@CoreCoding.com/sensors.js | 73 +++- .../Vitals@CoreCoding.com/stylesheet.css | 84 ++++- .../Vitals@CoreCoding.com/values.js | 151 +++++++- .../appIndicator.js | 7 +- .../dbusMenu.js | 47 ++- .../dbusProxy.js | 9 +- .../dbusUtils.js | 121 +++++++ .../extension.js | 7 +- .../iconTheme.js | 12 + .../indicatorStatusIcon.js | 4 + .../logger.js | 105 ++++++ .../metadata.json | 2 +- .../statusNotifierWatcher.js | 69 +++- .../tools/busAnalyzer.js | 46 +++ .../util.js | 182 +--------- .../components/applications.js | 228 ++++++++++-- .../components/coverflow_alt_tab.js | 2 +- .../blur-my-shell@aunetx/components/panel.js | 48 ++- .../blur-my-shell@aunetx/conveniences/keys.js | 2 + .../blur-my-shell@aunetx/effects/color.glsl | 100 +++++- .../blur-my-shell@aunetx/effects/color.js | 32 +- .../blur-my-shell@aunetx/effects/effects.js | 25 ++ .../blur-my-shell@aunetx/extension.js | 12 + .../ar/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 9972 -> 16821 bytes .../ca/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 3708 -> 17615 bytes .../de/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17569 -> 17826 bytes .../he/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 616 -> 592 bytes .../hu/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 8673 -> 17520 bytes .../id/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 10446 -> 16481 bytes .../it/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 17382 -> 17361 bytes .../ml/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 547 -> 523 bytes .../mrh/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 400 -> 521 bytes .../my/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 394 -> 362 bytes .../pl/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 15181 -> 15190 bytes .../pt/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 16592 -> 16967 bytes .../pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 14643 -> 17153 bytes .../ro/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 3643 -> 10249 bytes .../sv/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 16943 -> 16934 bytes .../th/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 362 bytes .../blur-my-shell@aunetx/metadata.json | 5 +- .../preferences/applications.js | 33 +- .../extensions/blur-my-shell@aunetx/prefs.js | 2 +- .../schemas/gschemas.compiled | Bin 9848 -> 9976 bytes ...shell.extensions.blur-my-shell.gschema.xml | 10 + .../blur-my-shell@aunetx/ui/applications.ui | 61 +++- .../impatience@gfxmonk.net/metadata.json | 5 +- .../extension.js | 16 +- .../metadata.json | 2 +- .../prefs.js | 40 ++- .../metadata.json | 6 +- .../gnome-shell-extension-screen-rotate.mo | Bin 4542 -> 0 bytes .../manualOrientationMenuToggle.js | 5 +- .../metadata.json | 6 +- 61 files changed, 1729 insertions(+), 365 deletions(-) create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/history.js create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/my_MM/LC_MESSAGES/vitals.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js create mode 100644 gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconTheme.js create mode 100644 gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/logger.js create mode 100644 gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/tools/busAnalyzer.js create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo delete mode 100644 gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/locale/ru/LC_MESSAGES/gnome-shell-extension-screen-rotate.mo diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js index 6f14df7..470b28d 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js @@ -17,6 +17,7 @@ import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; import * as Values from './values.js'; import * as Config from 'resource:///org/gnome/shell/misc/config.js'; import * as MenuItem from './menuItem.js'; +import * as HistoryGraph from './history.js'; let vitalsMenu; @@ -51,23 +52,30 @@ var VitalsMenuButton = GObject.registerClass({ this._warnings = []; this._sensorMenuItems = {}; this._hotLabels = {}; - this._hotIcons = {}; + this._hotItems = {}; this._groups = {}; this._widths = {}; this._numGpus = 1; this._newGpuDetected = false; this._newGpuDetectedCount = 0; this._last_query = new Date().getTime(); + this._historyPopout = null; + this._historyHideTimeoutId = null; + this._historyPopoutSensorKey = null; + this._historyPopoutLabel = null; this._sensors = new Sensors.Sensors(this._settings, this._sensorIcons); this._values = new Values.Values(this._settings, this._sensorIcons); + this._historyCachePath = GLib.get_user_cache_dir() + '/vitals/history.json'; + this._values.loadTimeSeries(this._historyCachePath); this._menuLayout = new St.BoxLayout({ vertical: false, clip_to_allocation: true, x_align: Clutter.ActorAlign.START, y_align: Clutter.ActorAlign.CENTER, reactive: true, - x_expand: true + x_expand: true, + style_class: 'vitals-panel-menu' }); this._drawMenu(); @@ -75,12 +83,12 @@ var VitalsMenuButton = GObject.registerClass({ this._settingChangedSignals = []; this._refreshTimeoutId = null; - this._addSettingChangedSignal('update-time', this._updateTimeChanged.bind(this)); + this._addSettingChangedSignal('update-time', this._updateTimeSettingChanged.bind(this)); this._addSettingChangedSignal('position-in-panel', this._positionInPanelChanged.bind(this)); this._addSettingChangedSignal('menu-centered', this._positionInPanelChanged.bind(this)); this._addSettingChangedSignal('icon-style', this._iconStyleChanged.bind(this)); - let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info', 'include-static-gpu-info' ]; + let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info', 'include-static-gpu-info', 'show-sensor-history-graph' ]; for (let setting of Object.values(settings)) this._addSettingChangedSignal(setting, this._redrawMenu.bind(this)); @@ -89,6 +97,7 @@ var VitalsMenuButton = GObject.registerClass({ this._addSettingChangedSignal('show-' + sensor, this._showHideSensorsChanged.bind(this)); this._initializeMenu(); + this._createHistoryPopout(); // start off with fresh sensors this._querySensors(); @@ -175,10 +184,216 @@ var VitalsMenuButton = GObject.registerClass({ // refresh sensors now this._querySensors(); + } else { + this._hideHistoryPopout(); } }); } + _createHistoryPopout() { + const popoutWidth = 280; + const popoutHeight = 145; + this._historyPopout = new St.BoxLayout({ + vertical: true, + style_class: 'vitals-history-popout', + width: popoutWidth, + height: popoutHeight, + reactive: true, + visible: false + }); + this._historyPopout.clip_to_allocation = true; + this._historyGraph = new HistoryGraph.HistoryGraph(); + this._historyTitleLabel = new St.Label({ + text: '', + style_class: 'vitals-history-popout-label', + x_align: Clutter.ActorAlign.END + }); + this._historyPopout.add_child(this._historyTitleLabel); + this._historyGraphRow = new St.BoxLayout({ + vertical: false, + x_expand: true, + style_class: 'vitals-history-graph-row' + }); + this._historyYAxis = new St.BoxLayout({ + vertical: true, + width: 56, + style_class: 'vitals-history-y-axis' + }); + this._historyYMax = new St.Label({ + text: '', + style_class: 'vitals-history-popout-axis', + x_align: Clutter.ActorAlign.END + }); + this._historyYMin = new St.Label({ + text: '', + style_class: 'vitals-history-popout-axis', + x_align: Clutter.ActorAlign.END + }); + this._historyYSpacer = new St.BoxLayout({ vertical: true, y_expand: true }); + this._historyYAxis.add_child(this._historyYMax); + this._historyYAxis.add_child(this._historyYSpacer); + this._historyYAxis.add_child(this._historyYMin); + this._historyGraphRow.add_child(this._historyYAxis); + this._historyGraphRow.add_child(this._historyGraph); + this._historyGraphRightSpacer = new St.BoxLayout({ + vertical: true, + width: 18, + style_class: 'vitals-history-graph-right-spacer' + }); + this._historyGraphRow.add_child(this._historyGraphRightSpacer); + this._historyPopout.add_child(this._historyGraphRow); + this._historyXWrap = new St.BoxLayout({ + vertical: false, + x_expand: true, + style_class: 'vitals-history-x-wrap' + }); + this._historyXSpacer = new St.BoxLayout({ + vertical: true, + width: 62, + style_class: 'vitals-history-x-spacer' + }); + this._historyXRow = new St.BoxLayout({ + vertical: false, + x_expand: true, + style_class: 'vitals-history-x-row' + }); + this._historyXLeft = new St.Label({ + text: '', + style_class: 'vitals-history-popout-axis', + x_align: Clutter.ActorAlign.START, + x_expand: true + }); + this._historyXRight = new St.Label({ + text: _('now'), + style_class: 'vitals-history-popout-axis', + x_align: Clutter.ActorAlign.END + }); + this._historyXRow.add_child(this._historyXLeft); + this._historyXRow.add_child(this._historyXRight); + this._historyXWrap.add_child(this._historyXSpacer); + this._historyXWrap.add_child(this._historyXRow); + this._historyPopout.add_child(this._historyXWrap); + this._historyPopout.connect('enter-event', () => { + if (this._historyHideTimeoutId) { + GLib.Source.remove(this._historyHideTimeoutId); + this._historyHideTimeoutId = null; + } + }); + this._historyPopout.connect('leave-event', () => { + this._scheduleHistoryPopoutHide(); + }); + } + + _updateHistoryGraph(key, label, samples) { + const historyDuration = Math.max(60, this._settings.get_int('sensor-history-duration')); + const nowSec = Date.now() / 1000; + const cutoff = nowSec - historyDuration; + const windowed = samples.filter(s => s.t >= cutoff); + while (windowed.length > 0 && windowed[0].v === null) windowed.shift(); + const base = Math.max(1, Math.ceil(windowed.length / 200)); + this._historyGraph.setData(windowed, label, '', base); + const actualSpan = this._historyGraph.getTimeSpan(); + const displayDuration = actualSpan > 0 ? Math.min(historyDuration, Math.round(actualSpan)) : historyDuration; + this._historyXLeft.text = this._values.formatDuration(displayDuration) + ' ' + _('ago'); + const rawRange = this._historyGraph.getRawRange(); + if (rawRange) { + this._historyYMax.text = this._values.formatValue(key, rawRange.max); + this._historyYMin.text = this._values.formatValue(key, rawRange.min); + this._historyYAxis.show(); + } else { + this._historyYMax.text = ''; + this._historyYMin.text = ''; + this._historyYAxis.hide(); + } + } + + _showHistoryPopout(key, label, itemActor) { + if (!this._settings.get_boolean('show-sensor-history-graph')) return; + const samples = this._values.getTimeSeries(key); + if (samples.length === 0) return; + this._historyPopoutSensorKey = key; + this._historyPopoutLabel = label; + try { + this._historyTitleLabel.text = label + ' ' + _('history'); + this._historyTitleLabel.show(); + this._updateHistoryGraph(key, label, samples); + } catch (e) { + this._historyYMax.text = ''; + this._historyYMin.text = ''; + } + const parent = this.menu.actor.get_parent(); + if (!parent) return; + if (this._historyPopout.get_parent() !== parent) { + if (this._historyPopout.get_parent()) + this._historyPopout.get_parent().remove_child(this._historyPopout); + parent.add_child(this._historyPopout); + } + const menuX = this.menu.actor.get_x(); + const menuY = this.menu.actor.get_y(); + let popoutY = menuY; + if (itemActor) { + let relY = 0; + let node = itemActor; + while (node && node !== this.menu.actor) { + relY += node.get_y(); + node = node.get_parent(); + } + const rowH = itemActor.get_height(); + const popoutH = this._historyPopout.get_height(); + popoutY = menuY + relY + Math.round((rowH - popoutH) / 2); + popoutY = Math.max(0, popoutY); + } + const popoutW = this._historyPopout.get_width(); + const menuW = this.menu.actor.get_width(); + let popoutX = menuX - popoutW - 8; + if (popoutX < 0) + popoutX = menuX + menuW + 8; + this._historyPopout.set_position(popoutX, popoutY); + this._historyPopout.show(); + if (this._historyHideTimeoutId) { + GLib.Source.remove(this._historyHideTimeoutId); + this._historyHideTimeoutId = null; + } + } + + _scheduleHistoryPopoutHide() { + if (this._historyHideTimeoutId) return; + this._historyHideTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => { + this._hideHistoryPopout(); + this._historyHideTimeoutId = null; + return GLib.SOURCE_REMOVE; + }); + } + + _hideHistoryPopout() { + if (this._historyHideTimeoutId) { + GLib.Source.remove(this._historyHideTimeoutId); + this._historyHideTimeoutId = null; + } + if (this._historyPopout && this._historyPopout.get_parent()) { + this._historyPopout.hide(); + this._historyPopout.get_parent().remove_child(this._historyPopout); + } + this._historyPopoutSensorKey = null; + this._historyPopoutLabel = null; + } + + _refreshHistoryPopout() { + const key = this._historyPopoutSensorKey; + const label = this._historyPopoutLabel; + if (!key || !label) return; + if (!this._historyPopout || !this._historyPopout.visible) return; + + const samples = this._values.getTimeSeries(key); + if (samples.length === 0) return; + + try { + this._updateHistoryGraph(key, label, samples); + } catch (e) { + // ignore + } + } + _initializeMenuGroup(groupName, optionName, menuSuffix = '', position = -1) { this._groups[groupName] = new PopupMenu.PopupSubMenuMenuItem(_(this._ucFirst(groupName) + menuSuffix), true); this._groups[groupName].icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(groupName)); @@ -219,8 +434,7 @@ var VitalsMenuButton = GObject.registerClass({ // removes sensors that are no longer available if (!this._sensorMenuItems[sensor]) { hotSensors.splice(i, 1); - this._removeHotLabel(sensor); - this._removeHotIcon(sensor); + this._removeHotItem(sensor); } } @@ -245,19 +459,24 @@ var VitalsMenuButton = GObject.registerClass({ GLib.PRIORITY_DEFAULT, update_time, (self) => { - // only update menu if we have hot sensors - if (Object.values(this._hotLabels).length > 0) - this._querySensors(); - // keep the timer running - return GLib.SOURCE_CONTINUE; + // always query sensors (for panel display when hot, and for history graph data) + this._querySensors(); + return GLib.SOURCE_CONTINUE; } ); } _createHotItem(key, value) { - let icon = this._defaultIcon(key); - this._hotIcons[key] = icon; - this._menuLayout.add_child(icon) + let item = new St.BoxLayout({ + style_class: 'vitals-panel-item', + }); + this._hotItems[key] = item; + this._menuLayout.add_child(item); + + if (!this._settings.get_boolean('hide-icons') || key == '_default_icon_') { + let icon = this._defaultIcon(key); + item.add_child(icon); + } // don't add a label when no sensors are in the panel if (key == '_default_icon_') return; @@ -268,18 +487,15 @@ var VitalsMenuButton = GObject.registerClass({ y_expand: true, y_align: Clutter.ActorAlign.CENTER }); - // attempt to prevent ellipsizes label.get_clutter_text().ellipsize = 0; - // keep track of label for removal later this._hotLabels[key] = label; - // prevent "called on the widget" "which is not in the stage" errors by adding before width below - this._menuLayout.add_child(label); + item.add_child(label); // support for fixed widths #55, save label (text) width - this._widths[key] = label.width; + this._widths[key] = label.get_clutter_text().width; } _showHideSensorsChanged(self, sensor) { @@ -329,35 +545,24 @@ var VitalsMenuButton = GObject.registerClass({ this._redrawMenu(); } - _removeHotLabel(key) { - if (key in this._hotLabels) { - let label = this._hotLabels[key]; + _removeHotItems(){ + for (let key in this._hotItems) { + this._removeHotItem(key); + } + } + + _removeHotItem(key) { + if (key in this._hotItems) { + this._hotItems[key].destroy(); + delete this._hotItems[key]; delete this._hotLabels[key]; - // make sure set_label is not called on non existent actor - label.destroy(); + delete this._widths[key]; } } - _removeHotLabels() { - for (let key in this._hotLabels) - this._removeHotLabel(key); - } - - _removeHotIcon(key) { - if (key in this._hotIcons) { - this._hotIcons[key].destroy(); - delete this._hotIcons[key]; - } - } - - _removeHotIcons() { - for (let key in this._hotIcons) - this._removeHotIcon(key); - } - _redrawMenu() { - this._removeHotIcons(); - this._removeHotLabels(); + this._hideHistoryPopout(); + this._removeHotItems(); for (let key in this._sensorMenuItems) { if (key.includes('-group')) continue; @@ -391,6 +596,12 @@ var VitalsMenuButton = GObject.registerClass({ } } + _updateTimeSettingChanged() { + this._destroyTimer(); + this._values.clearTimeSeries(this._historyCachePath); + this._initializeTimer(); + } + _updateTimeChanged() { this._destroyTimer(); this._initializeTimer(); @@ -452,8 +663,7 @@ var VitalsMenuButton = GObject.registerClass({ } else { // remove selected sensor from panel hotSensors.splice(hotSensors.indexOf(self.key), 1); - this._removeHotLabel(self.key); - this._removeHotIcon(self.key); + this._removeHotItem(self.key); } if (hotSensors.length <= 0) { @@ -465,7 +675,7 @@ var VitalsMenuButton = GObject.registerClass({ if (defIconPos >= 0) { // remove generic icon from panel when sensors are selected hotSensors.splice(defIconPos, 1); - this._removeHotIcon('_default_icon_'); + this._removeHotItem('_default_icon_'); } } @@ -486,6 +696,25 @@ var VitalsMenuButton = GObject.registerClass({ } this._groups[type].menu.addMenuItem(item, i); + + if (this._settings.get_boolean('show-sensor-history-graph')) { + const key = item.key; + const label = item.label; + item.actor.connect('enter-event', () => { + const samples = this._values.getTimeSeries(key); + if (this._historyHideTimeoutId) { + GLib.Source.remove(this._historyHideTimeoutId); + this._historyHideTimeoutId = null; + } + if (samples.length > 0) + this._showHistoryPopout(key, label, item.actor); + else + this._hideHistoryPopout(); + }); + item.actor.connect('leave-event', () => { + this._scheduleHistoryPopoutHide(); + }); + } } _defaultLabel() { @@ -508,7 +737,7 @@ var VitalsMenuButton = GObject.registerClass({ // don't use the default system icon if the type is a gpu; use the universal gpu icon instead if (type == 'default' || (!(type in this._sensorIcons) && !type.startsWith('gpu'))) { icon.gicon = Gio.icon_new_for_string(this._sensorIconPath('system')); - } else if (!this._settings.get_boolean('hide-icons')) { // support for hide icons #80 + } else { // support for hide icons #80 let iconObj = (split.length == 2)?'icon-' + split[1]:'icon'; icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(type, iconObj)); } @@ -627,6 +856,8 @@ var VitalsMenuButton = GObject.registerClass({ this._notify('Vitals', this._warnings.join("\n"), 'folder-symbolic'); this._warnings = []; } + + this._refreshHistoryPopout(); } _notify(msg, details, icon) { @@ -638,7 +869,13 @@ var VitalsMenuButton = GObject.registerClass({ } destroy() { + this._hideHistoryPopout(); + if (this._historyPopout) { + this._historyPopout.destroy(); + this._historyPopout = null; + } this._destroyTimer(); + this._values.saveTimeSeries(this._historyCachePath); this._sensors.destroy(); for (let signal of Object.values(this._settingChangedSignals)) diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/history.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/history.js new file mode 100644 index 0000000..2c065b5 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/history.js @@ -0,0 +1,157 @@ +/* + Copyright (c) 2018, Chris Monahan + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the GNOME nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import GObject from 'gi://GObject'; +import St from 'gi://St'; + +const GRAPH_WIDTH = 208; +const GRAPH_HEIGHT = 90; +const PADDING = 4; +const MIN_BAR_WIDTH = 1; + +export const HistoryGraph = GObject.registerClass({ + GTypeName: 'HistoryGraph', +}, class HistoryGraph extends St.Widget { + + _init(params = {}) { + super._init({ + width: GRAPH_WIDTH, + height: GRAPH_HEIGHT, + style_class: 'vitals-history-graph', + ...params + }); + this._samples = []; + this._label = ''; + this._unit = ''; + this._vMin = 0; + this._vMax = 0; + this._base = 1; + this._dataOffset = 0; + this.clip_to_allocation = true; + this._barContainer = new St.Widget({ + x_expand: true, + y_expand: true + }); + this._barContainer.clip_to_allocation = true; + this.add_child(this._barContainer); + } + + setData(samples, label, unit, base) { + this._samples = Array.isArray(samples) ? samples : []; + this._label = label || ''; + this._unit = unit || ''; + this._base = Math.max(1, base); + this._rebuildBars(); + } + + _rebuildBars() { + try { + const children = this._barContainer.get_children(); + if (children && children.length > 0) { + for (let i = children.length - 1; i >= 0; i--) + children[i].destroy(); + } + } catch (e) { + // ignore + } + const data = this._samples; + if (data.length === 0) return; + + const graphW = GRAPH_WIDTH - 2 * PADDING; + const graphH = GRAPH_HEIGHT - PADDING; + if (graphW <= 0 || graphH <= 0) return; + + const base = this._base; + const maxBars = Math.floor(graphW / MIN_BAR_WIDTH); + const totalBars = Math.ceil(data.length / base); + const numBars = Math.min(totalBars, maxBars); + const dataOffset = (totalBars - numBars) * base; + this._dataOffset = dataOffset; + const barWidth = graphW / numBars; + + let vMin = Infinity, vMax = -Infinity; + for (let i = dataOffset; i < data.length; i++) { + if (data[i].v === null) continue; + if (data[i].v < vMin) vMin = data[i].v; + if (data[i].v > vMax) vMax = data[i].v; + } + if (vMin === Infinity) { + vMin = 0; + vMax = 1; + } else if (vMax <= vMin) { + const v = vMin; + if (v >= 0 && v <= 1) { + const margin = 0.05; + vMin = Math.max(0, v - margin); + vMax = Math.min(1, v + margin); + if (vMax <= vMin) vMax = vMin + margin; + } else { + vMin -= 1; + vMax += 1; + } + } + this._vMin = vMin; + this._vMax = vMax; + const vRange = vMax - vMin; + + for (let b = 0; b < numBars; b++) { + const iStart = dataOffset + b * base; + const iEnd = Math.min(iStart + base, data.length); + let sum = 0; + let count = 0; + for (let i = iStart; i < iEnd; i++) { + if (data[i].v !== null) { + sum += data[i].v; + count++; + } + } + if (count === 0) continue; + const avg = sum / count; + const norm = (avg - vMin) / vRange; + const barH = Math.max(1, Math.round(norm * graphH)); + const x = Math.round(b * barWidth); + const w = Math.round((b + 1) * barWidth) - x; + const bar = new St.Bin({ + width: w, + height: barH, + style_class: 'vitals-history-graph-bar' + }); + bar.set_position(x, graphH - barH); + this._barContainer.add_child(bar); + } + } + + getRawRange() { + if (this._samples.length === 0) return null; + return { min: this._vMin, max: this._vMax }; + } + + getTimeSpan() { + const start = this._dataOffset; + if (this._samples.length - start < 2) return 0; + return this._samples[this._samples.length - 1].t - this._samples[start].t; + } +}); diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/my_MM/LC_MESSAGES/vitals.mo b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/my_MM/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000000000000000000000000000000000000..e194797aaf82c8fae117fe847e20183432142531 GIT binary patch literal 17140 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 + + + 100 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Show sensor history graph on hover + + + + + end + 5 + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled index 936fdb3a506ffb8d2405e995628fbde747e729c0..e60cb0f1a650ca893c3a45db007e3a7cdee12b84 100644 GIT binary patch literal 2084 zcmZ8iL1-LR7=G2p)}(2+X>AiVn%FA4%Iq4d)uM=?#T+~oY^C%veY^XzGj?X)IBzD| zja3BOgCbb)Qcy_`ih`)|AcjiCi`a`0p)Fpdh?gKXr3Yzp(D;3CW}C)^kMEmr{`~K~ z|NZmlg_mXG%P1AaZwP!O*X7#^Zv*&p_4j>bz8e!0;sp5VjY9O?CB!Ozqnlxf7X^6_ zpp#a$73ok_ji-X3s@kcFjISe8o$^x|7={Z`ejsPT++6SW|DgxZn*gT2vp^qs3$V37 z2|NgF2X+A1(oO7y-c^8S8wTzM?g8!t?k_M3UaGxvnCtLdePT*XfF*DxJMbNS>R$LU zI0N3*Zy%*k&Gy?2E^HRDf%&j963?h<|K&G65HKLK9bx3Zr;^)~qP;Pb$> z2jgD))H~q+3jPgv_`;`O)2HUTi{RZTRQE2Zc^7-Y9|H%npQag4y#?`e;BSEUZ~S?X zKJ`}k7r;LQKfL}%AMcd9hwFm>1+tSL*!oa2Pw5WS85o&;Y=wEK>6gI{@KocWGJR^E z>sjywaBX({GJR^s9|0c&zI<-AMxUDJioqH1x~!KZ*^_vr{0D5v*6E& zuS)0WQ?vf_;Pb$ZcfQ|ApL#p|1@I-{;_OEY^r^X@Meq`EeP*w{FY12yY{VX5?Bo-V zFrK;ue+WDRES~%JL;BRr^C88Sjj$=~x9*sZNmb|+FVOL(;`vSG%&0^c zU%V*SE5_5)PN+hibT;tWZ|KM|X(v!v1;4VNhfK;Se;+l13~A!59{3H%j|Juh{w_1h z@%)yj5+_bn!{>a-GcZZL;_1{e7&|&KZoZtG8QD^>T0T838zN_!|Q_pE#E|WAKTJQGhe9 zALs=*i#U_E0i02sZ}$S6Uz|^zQ)oS5%QdBg6kE6Fwnm)jhB7!CB8qxcW0`vPQPePi zYxYuVb^zDb25>DOz%?YE^xLZGO#98$E3RiPe^HM-U0&~48$U&j9Y1nn8L1#Y5AUlk z(^MrL#{~N3{}TE#h&@?XsXvq7?OOi)2J&ZnN4QFZcIr6IERkG>OP5$g@Tn9j>~nXEp^^qGVq^Jh_7>ywcEv}s{x$OF s@BQ^hZ^c=0eAdPGM{y&Jx4*8B(C%}$A<7EvzB+z~1|PRe;k)nKZ)azIzu)Zq z?zxxzEc6pA%IkjcbfK$vm)>3A8?_(D$$WNHoD%22eSJdgI3UCwTq`?ai08#B_;WyK z?OHq0v8tIsMNv(4tV&F%6H}WFtsfZ<7ovK^kr14l>k;<=m|Aek9{Qn)ff9q@J-}XI zAFv-dSmF?vd5n~J0Q}%K9EK(yF7e&@HwKu4%SX(L3Kky+j$U~B$$K$|x&r?c_yypn zM6J-L-VZ+jr$B40(WOs40RK(!Md0el(mDFneef@V7l6t9+8llA-SC&eE5K$=pX$(ti5XtbYf59$0-V_=`UEA@~d6 zMc|M5W3CR=gYZ|uUjVNi-xvltJq&*hH`jp=ZvQexpL!4cAHY8Y-!CoFa+>jQvA==* z!iO$jYWfv?v!x%5&!Y5MrNw_r> z1ojB_6rTSIa38>P&pyH)z@D)SV2@xAVm$0E>>)gU>_x*s5Vn*Io9JJ-aToG+K^m*G zGD!F?PUp|~N$)<;RvNTFof$7yvCg_)Zt#vLJkvF(qZetv<&DKKyj~Hrju-nK&l5vO zj)|&oiq(qO%XJu!G`1TRwPbzEXk@H>gN=z*+1i;KpT`=7)|qU^Ejq$&wJf5Lk<_;D Zqul5J`KW^Pu%7$q=2fN{9PZ1p{{VT+hkyV8 diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml index 7a0decd..72f8f40 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml @@ -151,5 +151,15 @@ Icon styles Set the style for the displayed sensor icons ('original', 'updated') + + true + Show sensor history graph on hover + When hovering a sensor row in the menu, show a pop-out graph of its history to the left + + + 3600 + Sensor history duration (seconds) + How many seconds of history to keep and display in the hover graph (e.g. 3600 for 1 hour) + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js index f310161..be8df5d 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js @@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import GLib from 'gi://GLib'; import GObject from 'gi://GObject'; import * as SubProcessModule from './helpers/subprocess.js'; import * as FileModule from './helpers/file.js'; @@ -60,6 +61,12 @@ export const Sensors = GObject.registerClass({ this._nvidia_labels = []; this._bad_split_count = 0; + this._frameMonitorSignalId = 0; + this._frameMonitorLastTime = 0; + this._frameMonitorFrameCount = 0; + this._frameMonitorAccTime = 0; + this._frameMonitorCurrentHz = 0; + if (hasGTop) { this.storage = new GTop.glibtop_fsusage(); this._storageDevice = ''; @@ -370,11 +377,19 @@ export const Sensors = GObject.registerClass({ let free = this.storage.bfree * this.storage.block_size; let used = total - free; let reserved = (total - avail) - used; + let freePercent = 0; + let usedPercent = 0; + if (total > 0) { + freePercent = Math.round((free / total) * 100); + usedPercent = Math.round((used / total) * 100); + } this._returnValue(callback, 'Total', total, 'storage', 'storage'); this._returnValue(callback, 'Used', used, 'storage', 'storage'); this._returnValue(callback, 'Reserved', reserved, 'storage', 'storage'); this._returnValue(callback, 'Free', avail, 'storage', 'storage'); + this._returnValue(callback, 'Used %', usedPercent + '%', 'storage', 'string'); + this._returnValue(callback, 'Free %', freePercent + '%', 'storage', 'string'); this._returnValue(callback, 'storage', avail, 'storage-group', 'storage'); } @@ -427,8 +442,11 @@ export const Sensors = GObject.registerClass({ } if ('POWER_NOW' in output) { - this._returnValue(callback, 'Rate', output['POWER_NOW'], 'battery', 'watt'); - this._returnValue(callback, 'battery', output['POWER_NOW'], 'battery-group', 'watt'); + const powerValue = ( + parseFloat(output['POWER_NOW']) * (output['STATUS'] === 'Discharging' ? -1 : 1) + ); + this._returnValue(callback, 'Power Rate', powerValue, 'battery', 'watt'); + this._returnValue(callback, 'battery', powerValue, 'battery-group', 'watt'); } if ('CHARGE_FULL' in output && 'VOLTAGE_MIN_DESIGN' in output && (!('ENERGY_FULL' in output))) { @@ -500,10 +518,56 @@ export const Sensors = GObject.registerClass({ }).catch(err => { }); } + _initFrameMonitor() { + if (this._frameMonitorSignalId) return; + this._frameMonitorLastTime = 0; + this._frameMonitorFrameCount = 0; + this._frameMonitorAccTime = 0; + this._frameMonitorCurrentHz = 0; + this._frameMonitorSignalId = global.stage.connect('after-paint', () => { + this._onAfterPaint(); + }); + } + + _destroyFrameMonitor() { + if (this._frameMonitorSignalId) { + global.stage.disconnect(this._frameMonitorSignalId); + this._frameMonitorSignalId = 0; + } + this._frameMonitorLastTime = 0; + this._frameMonitorCurrentHz = 0; + } + + _onAfterPaint() { + const now = GLib.get_monotonic_time(); + + if (this._frameMonitorLastTime === 0) { + this._frameMonitorLastTime = now; + return; + } + + const delta = now - this._frameMonitorLastTime; + this._frameMonitorLastTime = now; + + this._frameMonitorFrameCount++; + this._frameMonitorAccTime += delta; + + if (this._frameMonitorAccTime >= 500000) { + this._frameMonitorCurrentHz = this._frameMonitorFrameCount / (this._frameMonitorAccTime / 1000000); + this._frameMonitorFrameCount = 0; + this._frameMonitorAccTime = 0; + } + } + _queryGpu(callback) { + if (this._frameMonitorCurrentHz > 0) + this._returnValue(callback, 'Refresh Rate', this._frameMonitorCurrentHz, 'gpu#1', 'hertz'); + if (!this._nvidia_smi_process) { // no nvidia-smi, so we use sysfs DRM if any cards was discovered if (!this._gpu_drm_indices){ + if (this._frameMonitorCurrentHz > 0) + this._returnValue(callback, 'Refresh Rate', this._frameMonitorCurrentHz, 'gpu#1-group', 'hertz'); this._disableGpuLabels(callback); return; } else { @@ -801,6 +865,7 @@ export const Sensors = GObject.registerClass({ // Launch nvidia-smi subprocess if nvidia querying is enabled this._reconfigureNvidiaSmiProcess(); this._discoverGpuDrm(); + this._initFrameMonitor(); } _discoverGpuDrm() { @@ -992,9 +1057,13 @@ export const Sensors = GObject.registerClass({ this._battery_charge_status = ''; this._nvidia_labels = []; this._bad_split_count = 0; + this._frameMonitorLastTime = 0; + this._frameMonitorFrameCount = 0; + this._frameMonitorAccTime = 0; } destroy() { + this._destroyFrameMonitor(); this._terminateNvidiaSmiProcess(); for (let signal of Object.values(this._settingChangedSignals)) diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css index adec425..e4e3d1b 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/stylesheet.css @@ -1,16 +1,80 @@ .vitals-icon { icon-size: 16px; } .vitals-menu-button-container {} -.vitals-panel-icon-temperature { margin: 0 1px 0 8px; padding: 0; } -.vitals-panel-icon-voltage { margin: 0 0 0 8px; padding: 0; } -.vitals-panel-icon-fan { margin: 0 4px 0 8px; padding: 0; } -.vitals-panel-icon-memory { margin: 0 2px 0 8px; padding: 0; } -.vitals-panel-icon-processor { margin: 0 3px 0 8px; padding: 0; } -.vitals-panel-icon-system { margin: 0 3px 0 8px; padding: 0; } -.vitals-panel-icon-network { margin: 0 3px 0 8px; padding: 0; } -.vitals-panel-icon-storage { margin: 0 2px 0 8px; padding: 0; } -.vitals-panel-icon-battery { margin: 0 4px 0 8px; padding: 0; } -.vitals-panel-label { margin: 0 3px 0 0; padding: 0; } +.vitals-panel-item{spacing: 0;} +.vitals-panel-menu{spacing: 11px; padding: 3px; } +.vitals-panel-icon-default {} +.vitals-panel-icon-temperature { margin: 0 1px 0 0; padding: 0; } +.vitals-panel-icon-voltage { margin: 0 0 0 0; padding: 0; } +.vitals-panel-icon-fan { margin: 0 4px 0 0; padding: 0; } +.vitals-panel-icon-memory { margin: 0 2px 0 0; padding: 0; } +.vitals-panel-icon-processor { margin: 0 3px 0 0; padding: 0; } +.vitals-panel-icon-system { margin: 0 3px 0 0; padding: 0; } +.vitals-panel-icon-network { margin: 0 3px 0 0; padding: 0; } +.vitals-panel-icon-storage { margin: 0 2px 0 0; padding: 0; } +.vitals-panel-icon-battery { margin: 0 4px 0 0; padding: 0; } +.vitals-panel-label {} .vitals-button-action { -st-icon-style: symbolic; border-radius: 32px; margin: 0px; min-height: 22px; min-width: 22px; padding: 10px; font-size: 100%; border: 1px solid transparent; } .vitals-button-action:hover, .vitals-button-action:focus { border-color: #777; } .vitals-button-action > StIcon { icon-size: 16px; } .vitals-button-box { padding: 0px; spacing: 22px; } + +.vitals-history-popout { + padding: 6px 14px 6px 6px; + border-radius: 8px; + border: 1px solid rgba(128, 128, 128, 0.4); + background-color: rgba(30, 30, 30, 0.95); +} + +.vitals-history-popout-label { + font-size: 10px; + color: rgba(200, 200, 200, 0.9); +} + +.vitals-history-popout-axis { + font-size: 9px; + color: rgba(180, 180, 180, 0.85); +} + +.vitals-history-graph-row { + margin-top: 2px; + margin-bottom: 2px; +} + +.vitals-history-y-axis { + margin-right: 6px; + padding-top: 2px; + padding-bottom: 2px; +} + +.vitals-history-x-wrap { + margin-top: 2px; +} + +.vitals-history-x-spacer { + width: 62px; + min-width: 62px; +} + +.vitals-history-x-row { + min-width: 0; +} + +.vitals-history-x-row .vitals-history-popout-axis { + margin-left: 0; + margin-right: 4px; +} + +.vitals-history-graph { + background-color: rgba(0, 0, 0, 0.25); + border-radius: 4px; + padding: 4px 4px 0 4px; + margin: 2px 0 2px 0; +} + +.vitals-history-graph-bars { + spacing: 0px; +} + +.vitals-history-graph-bar { + background-color: rgba(51, 128, 230, 0.87); +} diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js index a7cabb0..97ad2ab 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js @@ -24,6 +24,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; import GObject from 'gi://GObject'; const cbFun = (d, c) => { @@ -47,9 +49,138 @@ export const Values = GObject.registerClass({ this._history = {}; //this._history2 = {}; + this._timeSeries = {}; + this._timeSeriesFormat = {}; + this._graphableFormats = ['temp', 'in', 'fan', 'percent', 'hertz', 'memory', 'speed', 'storage', 'watt', 'watt-gpu', 'milliamp', 'milliamp-hour', 'load']; this.resetHistory(); } + _getHistoryDurationSeconds() { + if (this._settings && this._settings.get_int) + return Math.max(60, this._settings.get_int('sensor-history-duration')); + return 3600; + } + + _pushTimePoint(key, value, format) { + if (!this._graphableFormats.includes(format)) return; + const num = typeof value === 'number' ? value : parseFloat(value); + if (num !== num) return; // NaN check + this._timeSeriesFormat[key] = format; + const now = Date.now() / 1000; + if (!(key in this._timeSeries)) this._timeSeries[key] = []; + const buf = this._timeSeries[key]; + const interval = Math.max(1, this._settings.get_int('update-time')); + const minInterval = interval - 0.5; + if (buf.length > 0 && buf[buf.length - 1].v !== null && (now - buf[buf.length - 1].t) < minInterval) { + buf[buf.length - 1].v = num; + return; + } + if (buf.length > 0) { + const lastT = buf[buf.length - 1].t; + const gap = now - lastT; + if (gap > interval * 3) { + let fillT = lastT + interval; + while (fillT < now - interval * 0.5) { + buf.push({ t: fillT, v: null }); + fillT += interval; + } + } + } + buf.push({ t: now, v: num }); + const maxAge = this._getHistoryDurationSeconds(); + while (buf.length > 0 && buf[0].t < now - maxAge) buf.shift(); + const maxPoints = 3600; + while (buf.length > maxPoints) buf.shift(); + } + + clearTimeSeries(cachePath) { + this._timeSeries = {}; + this._timeSeriesFormat = {}; + if (cachePath) { + try { + const file = Gio.File.new_for_path(cachePath); + if (file.query_exists(null)) + file.delete(null); + } catch (e) { + // ignore + } + } + } + + saveTimeSeries(path) { + try { + const obj = { + version: 1, + timeSeries: this._timeSeries, + timeSeriesFormat: this._timeSeriesFormat + }; + const json = JSON.stringify(obj); + const dir = GLib.path_get_dirname(path); + GLib.mkdir_with_parents(dir, 0o755); + GLib.file_set_contents(path, json); + } catch (e) { + // ignore write failures + } + } + + loadTimeSeries(path) { + try { + const file = Gio.File.new_for_path(path); + if (!file.query_exists(null)) return; + const [ok, contents] = GLib.file_get_contents(path); + if (!ok) return; + const decoder = new TextDecoder('utf-8'); + const json = decoder.decode(contents); + const obj = JSON.parse(json); + if (!obj || obj.version !== 1) return; + if (obj.timeSeries && typeof obj.timeSeries === 'object') + this._timeSeries = obj.timeSeries; + if (obj.timeSeriesFormat && typeof obj.timeSeriesFormat === 'object') + this._timeSeriesFormat = obj.timeSeriesFormat; + const now = Date.now() / 1000; + const maxAge = this._getHistoryDurationSeconds(); + const cutoff = now - maxAge; + for (const key in this._timeSeries) { + const buf = this._timeSeries[key]; + if (!Array.isArray(buf)) { + delete this._timeSeries[key]; + continue; + } + while (buf.length > 0 && buf[0].t < cutoff) + buf.shift(); + while (buf.length > 0 && buf[0].v === null) + buf.shift(); + if (buf.length === 0) { + delete this._timeSeries[key]; + delete this._timeSeriesFormat[key]; + } + } + } catch (e) { + // ignore corrupt or missing file + } + } + + getTimeSeries(key) { + if (!(key in this._timeSeries)) return []; + return this._timeSeries[key].slice(); + } + + formatValue(key, rawValue) { + const format = key in this._timeSeriesFormat ? this._timeSeriesFormat[key] : 'percent'; + return this._legible(rawValue, format); + } + + formatDuration(seconds) { + seconds = Math.round(Math.abs(seconds)); + if (seconds < 60) return seconds + 's'; + const m = Math.floor(seconds / 60); + if (m < 60) return m + 'm'; + const h = Math.floor(m / 60); + const rm = m % 60; + if (rm === 0) return h + 'h'; + return h + 'h ' + rm + 'm'; + } + _legible(value, sensorClass) { let unit = 1000; if (value === null) return 'N/A'; @@ -186,7 +317,9 @@ export const Values = GObject.registerClass({ ending = 'mAh'; break; case 'watt': - format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + format = ( + ((value > 0) ? '+' : '') + ((use_higher_precision)?'%.2f %s':'%.1f %s') + ); value = value / 1000000; ending = 'W'; break; @@ -212,7 +345,7 @@ export const Values = GObject.registerClass({ break; } - return format.format(value, ending); + return format.format(value, ending).trim(); } returnIfDifferent(dwell, label, value, type, format, key) { @@ -242,6 +375,8 @@ export const Values = GObject.registerClass({ // save previous values to update screen on changes only let previousValue = this._history[type][key]; this._history[type][key] = [legible, value]; + if (type !== 'network-rx' && type !== 'network-tx') + this._pushTimePoint(key, value, format); // process average, min and max values if (type == 'temperature' || type == 'voltage' || type == 'fan') { @@ -272,6 +407,8 @@ export const Values = GObject.registerClass({ // appends total upload and download for all interfaces for #216 let vals = Object.values(this._history[type]).map(x => parseFloat(x[1])); let sum = vals.reduce((partialSum, a) => partialSum + a, 0); + const memUnit = this._settings.get_int('memory-measurement') ? 1000 : 1024; + this._pushTimePoint('__' + type + '_boot__', sum / memUnit, 'memory'); output.push(['Boot ' + direction, this._legible(sum, format), type, '__' + type + '_boot__']); // keeps track of session start point @@ -279,11 +416,14 @@ export const Values = GObject.registerClass({ this._networkSpeedOffset[key] = sum; // outputs session upload and download for all interfaces for #234 + const sessionVal = sum - this._networkSpeedOffset[key]; + this._pushTimePoint('__' + type + '_ses__', sessionVal / memUnit, 'memory'); output.push(['Session ' + direction, this._legible(sum - this._networkSpeedOffset[key], format), type, '__' + type + '_ses__']); // calculate speed for this interface let speed = (value - previousValue[1]) / dwell; output.push([label, this._legible(speed, 'speed'), type, key]); + this._pushTimePoint(key, speed, 'speed'); // store speed for Device report if (!(direction in this._networkSpeeds)) this._networkSpeeds[direction] = {}; @@ -295,11 +435,12 @@ export const Values = GObject.registerClass({ // calculate total upload and download device speed for (let direction in this._networkSpeeds) { - let sum = 0; + let sumNum = 0; for (let iface in this._networkSpeeds[direction]) - sum += parseFloat(this._networkSpeeds[direction][iface]); + sumNum += parseFloat(this._networkSpeeds[direction][iface]); - sum = this._legible(sum, 'speed'); + this._pushTimePoint('__network-' + direction + '_max__', sumNum, 'speed'); + let sum = this._legible(sumNum, 'speed'); output.push(['Device ' + direction, sum, 'network-' + direction, '__network-' + direction + '_max__']); // append download speed to group itself if (direction == 'rx') output.push([type, sum, type + '-group', '']); diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js index 0c6ee59..7efded2 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/appIndicator.js @@ -24,6 +24,7 @@ import St from 'gi://St'; import * as Params from 'resource:///org/gnome/shell/misc/params.js'; import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; +import * as DBusUtils from './dbusUtils.js'; import * as IconCache from './iconCache.js'; import * as Util from './util.js'; import * as Interfaces from './interfaces.js'; @@ -218,6 +219,8 @@ class AppIndicatorProxy extends DBusProxy { return; } + const cancellable = this._cancellable; + if (!params.get_type().equal(AppIndicatorProxy.TUPLE_TYPE)) { // If the property includes arguments, we can just queue the signal emission const [value] = params.unpack(); @@ -238,7 +241,7 @@ class AppIndicatorProxy extends DBusProxy { return; this._signalsAccumulator = new PromiseUtils.TimeoutPromise( - MAX_UPDATE_FREQUENCY, GLib.PRIORITY_DEFAULT_IDLE, this._cancellable); + MAX_UPDATE_FREQUENCY, GLib.PRIORITY_DEFAULT_IDLE, cancellable); try { await this._signalsAccumulator; const refreshPropertiesPromises = @@ -460,7 +463,7 @@ export class AppIndicator extends Signals.EventEmitter { } try { - this._commandLine = await Util.getProcessName(this.busName, + this._commandLine = await DBusUtils.getProcessName(this.busName, cancellable, GLib.PRIORITY_LOW); } catch (e) { if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js index 2beb796..52c812d 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusMenu.js @@ -196,7 +196,7 @@ export class DbusMenuItem extends Signals.EventEmitter { if (!data) data = GLib.Variant.new_int32(0); - this._client.sendEvent(this._id, event, data, timestamp); + return this._client.sendEvent(this._id, event, data, timestamp); } getId() { @@ -533,14 +533,18 @@ export const DBusClient = GObject.registerClass({ } } - sendEvent(id, event, params, timestamp) { + async sendEvent(id, event, params, timestamp) { if (!this.gNameOwner) return; - this.EventAsync(id, event, params, timestamp, this._cancellable).catch(e => { - if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) - logError(e); - }); + try { + await this.EventAsync(id, event, params, timestamp, this._cancellable); + } catch (e) { + if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + return; + + throw e; + } } _onPropertiesUpdated([changed, removed]) { @@ -628,6 +632,8 @@ const MenuItemFactory = { shellItem, MenuItemFactory._onActivate); shellItem.connect('destroy', () => { + shellItem._dbusItemCancellable?.cancel(); + shellItem._dbusItemCancellable = null; shellItem._dbusItem = null; shellItem._dbusClient = null; shellItem._icon = null; @@ -655,7 +661,7 @@ const MenuItemFactory = { menu._parent._openedSubMenu = menu; } - this._dbusItem.handleEvent('opened', null, 0); + this._dbusItem.handleEvent('opened', null, 0).catch(logError); this._dbusItem.sendAboutToShow(); } else { if (NEED_NESTED_SUBMENU_FIX) { @@ -664,7 +670,7 @@ const MenuItemFactory = { menu._openedSubMenu.close(false); } - this._dbusItem.handleEvent('closed', null, 0); + this._dbusItem.handleEvent('closed', null, 0).catch(logError); } }, @@ -674,7 +680,7 @@ const MenuItemFactory = { this._dbusClient.indicator.provideActivationToken(timestamp); this._dbusItem.handleEvent('clicked', GLib.Variant.new('i', 0), - timestamp); + timestamp).catch(logError); }, _onPropertyChanged(dbusItem, prop, _value) { @@ -756,10 +762,15 @@ const MenuItemFactory = { this._icon.icon_name = iconName; } else if (iconData) { try { + if (!this._dbusItemCancellable) { + this._dbusItemCancellable = new Util.CancellableChild( + this._dbusClient.cancellable); + } + const inputStream = Gio.MemoryInputStream.new_from_bytes( iconData.get_data_as_bytes()); this._icon.gicon = await GdkPixbuf.Pixbuf.new_from_stream_async( - inputStream, this._dbusClient.cancellable); + inputStream, this._dbusItemCancellable); } catch (e) { if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) logError(e); @@ -872,7 +883,7 @@ export class Client extends Signals.EventEmitter { menu._setOpenedSubMenu = this._setOpenedSubmenu.bind(this); // connect handlers - Util.connectSmart(menu, 'open-state-changed', this, this._onMenuOpened); + Util.connectSmart(menu, 'open-state-changed', this, this._onMenuOpenStateChanged); Util.connectSmart(menu, 'destroy', this, this.destroy); Util.connectSmart(this._rootItem, 'child-added', this, this._onRootChildAdded); @@ -939,7 +950,7 @@ export class Client extends Signals.EventEmitter { MenuUtils.moveItemInMenu(this._rootMenu, dbusItem, newpos); } - _onMenuOpened(menu, state) { + _onMenuOpenStateChanged(menu, state) { if (!this._rootItem) return; @@ -949,10 +960,18 @@ export class Client extends Signals.EventEmitter { if (this._openedSubMenu && this._openedSubMenu.isOpen) this._openedSubMenu.close(); - this._rootItem.handleEvent('opened', null, 0); + this._rootItem.handleEvent('opened', null, 0).catch(logError); this._rootItem.sendAboutToShow(); } else { - this._rootItem.handleEvent('closed', null, 0); + this._rootItem.handleEvent('closed', null, 0).catch(e => { + if (e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_OBJECT)) { + // The menu hay have been removed at this point, thus do not + // spam the users about this if it happens. + return; + } + + logError(e); + }); } } diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js index edf16fc..047f2d2 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusProxy.js @@ -40,8 +40,13 @@ export const DBusProxy = GObject.registerClass({ (_proxy, ...args) => this._onSignal(...args))); } - this._signalIds.push(this.connect('notify::g-name-owner', () => - this._onNameOwnerChanged())); + this._signalIds.push(this.connect('notify::g-name-owner', () => { + if (!this.gNameOwner) { + this._cancellable.cancel(); + this._cancellable = new Gio.Cancellable(); + } + this._onNameOwnerChanged(); + })); } async initAsync(cancellable) { diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js new file mode 100644 index 0000000..d4d7a96 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js @@ -0,0 +1,121 @@ +// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension +// +// This program 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 2 +// of the License, or (at your option) any later version. +// +// This program 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 this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; + +import {Logger} from './logger.js'; + +export const BUS_ADDRESS_REGEX = /([a-zA-Z0-9._-]+\.[a-zA-Z0-9.-]+)|(:[0-9]+\.[0-9]+)$/; + +Gio._promisify(Gio.DBusConnection.prototype, 'call'); + +export async function getUniqueBusName(bus, name, cancellable) { + if (name[0] === ':') + return name; + + if (!bus) + bus = Gio.DBus.session; + + const variantName = new GLib.Variant('(s)', [name]); + const [unique] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', + 'GetNameOwner', variantName, new GLib.VariantType('(s)'), + Gio.DBusCallFlags.NONE, -1, cancellable)).deep_unpack(); + + return unique; +} + +export async function getBusNames(bus, cancellable) { + if (!bus) + bus = Gio.DBus.session; + + const [names] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', + 'ListNames', null, new GLib.VariantType('(as)'), Gio.DBusCallFlags.NONE, + -1, cancellable)).deep_unpack(); + + const uniqueNames = new Map(); + const requests = names.map(name => getUniqueBusName(bus, name, cancellable)); + const results = await Promise.allSettled(requests); + + for (let i = 0; i < results.length; i++) { + const result = results[i]; + if (result.status === 'fulfilled') { + let namesForBus = uniqueNames.get(result.value); + if (!namesForBus) { + namesForBus = new Set(); + uniqueNames.set(result.value, namesForBus); + } + if (result.value !== names[i]) + namesForBus.add(names[i]); + } else if (!result.reason.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { + Logger.debug(`Impossible to get the unique name of ${names[i]}: ${result.reason}`); + } + } + + return uniqueNames; +} + +async function getProcessId(connectionName, cancellable = null, bus = Gio.DBus.session) { + const res = await bus.call('org.freedesktop.DBus', '/', + 'org.freedesktop.DBus', 'GetConnectionUnixProcessID', + new GLib.Variant('(s)', [connectionName]), + new GLib.VariantType('(u)'), + Gio.DBusCallFlags.NONE, + -1, + cancellable); + const [pid] = res.deepUnpack(); + return pid; +} + +export async function getProcessName(connectionName, cancellable = null, + priority = GLib.PRIORITY_DEFAULT, bus = Gio.DBus.session) { + const pid = await getProcessId(connectionName, cancellable, bus); + const cmdFile = Gio.File.new_for_path(`/proc/${pid}/cmdline`); + const inputStream = await cmdFile.read_async(priority, cancellable); + const bytes = await inputStream.read_bytes_async(2048, priority, cancellable); + const textDecoder = new TextDecoder(); + return textDecoder.decode(bytes.toArray().map(v => !v ? 0x20 : v)); +} + +export async function* introspectBusObject(bus, name, cancellable, + interfaces = undefined, path = undefined) { + if (!path) + path = '/'; + + const [introspection] = (await bus.call(name, path, 'org.freedesktop.DBus.Introspectable', + 'Introspect', null, new GLib.VariantType('(s)'), Gio.DBusCallFlags.NONE, + 5000, cancellable)).deep_unpack(); + + const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspection); + + if (!interfaces || dbusNodeImplementsInterfaces(nodeInfo, interfaces)) + yield {nodeInfo, path}; + + if (path === '/') + path = ''; + + for (const subNodeInfo of nodeInfo.nodes) { + const subPath = `${path}/${subNodeInfo.path}`; + yield* introspectBusObject(bus, name, cancellable, interfaces, subPath); + } +} + +function dbusNodeImplementsInterfaces(nodeInfo, interfaces) { + if (!(nodeInfo instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces)) + return false; + + return interfaces.some(iface => nodeInfo.lookup_interface(iface)); +} diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js index 6f69aa1..6321077 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/extension.js @@ -20,13 +20,14 @@ import * as StatusNotifierWatcher from './statusNotifierWatcher.js'; import * as Interfaces from './interfaces.js'; import * as TrayIconsManager from './trayIconsManager.js'; import * as Util from './util.js'; +import {Logger} from './logger.js'; import {SettingsManager} from './settingsManager.js'; export default class AppIndicatorExtension extends Extension.Extension { constructor(...args) { super(...args); - Util.Logger.init(this); + Logger.init(this); Interfaces.initialize(this); this._isEnabled = false; @@ -42,7 +43,7 @@ export default class AppIndicatorExtension extends Extension.Extension { global['--appindicator-extension-on-reload'](); global['--appindicator-extension-on-reload'] = () => { - Util.Logger.debug('Reload detected, destroying old watchdog'); + Logger.debug('Reload detected, destroying old watchdog'); this._watchDog.destroy(); this._watchDog = null; }; @@ -84,6 +85,6 @@ export default class AppIndicatorExtension extends Extension.Extension { return; this._statusNotifierWatcher = new StatusNotifierWatcher.StatusNotifierWatcher( - this._watchDog); + this, this._watchDog); } } diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconTheme.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconTheme.js new file mode 100644 index 0000000..cdd6540 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/iconTheme.js @@ -0,0 +1,12 @@ +let _defaultTheme; +export function getDefaultTheme() { + if (_defaultTheme) + return _defaultTheme; + + _defaultTheme = new St.IconTheme(); + return _defaultTheme; +} + +export function destroyDefaultTheme() { + _defaultTheme = null; +} diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js index 3f2c740..a80339a 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/indicatorStatusIcon.js @@ -246,6 +246,10 @@ class IndicatorStatusIcon extends BaseStatusIcon { _init(indicator) { super._init(0.5, indicator.accessibleName, new AppIndicator.IconActor(indicator, DEFAULT_ICON_SIZE)); + + // Disable upstream's click gesture and fall back to vfunc_button_press_event etc. + this._clickGesture?.set_enabled(false); + this._indicator = indicator; this._lastClickTime = -1; diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/logger.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/logger.js new file mode 100644 index 0000000..3c60400 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/logger.js @@ -0,0 +1,105 @@ +// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension +// +// This program 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 2 +// of the License, or (at your option) any later version. +// +// This program 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 this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import GLib from 'gi://GLib'; + +/** + * Helper class for logging stuff + */ +export class Logger { + static _logStructured(logLevel, message, extraFields = {}) { + if (!Object.values(GLib.LogLevelFlags).includes(logLevel)) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, + 'logLevel is not a valid GLib.LogLevelFlags'); + return; + } + + if (!Logger._levels.includes(logLevel)) + return; + + let fields = { + 'SYSLOG_IDENTIFIER': Logger._uuid, + 'MESSAGE': `${message}`, + }; + + let thisFile = null; + const {stack} = new Error(); + for (let stackLine of stack.split('\n')) { + stackLine = stackLine.replace('resource:///org/gnome/Shell/', ''); + const [code, line] = stackLine.split(':'); + const [func, file] = code.split(/@(.+)/); + + if (!thisFile || thisFile === file) { + thisFile = file; + continue; + } + + fields = Object.assign(fields, { + 'CODE_FILE': file || '', + 'CODE_LINE': line || '', + 'CODE_FUNC': func || '', + }); + + break; + } + + GLib.log_structured(Logger._domain, logLevel, Object.assign(fields, extraFields)); + } + + static init(extension) { + if (Logger._domain) + return; + + const allLevels = Object.values(GLib.LogLevelFlags); + const domains = GLib.getenv('G_MESSAGES_DEBUG'); + const {name: domain} = extension.metadata; + Logger._uuid = extension.metadata.uuid; + Logger._domain = domain.replaceAll(' ', '-'); + + if (domains === 'all' || (domains && domains.split(' ').includes(Logger._domain))) { + Logger._levels = allLevels; + } else { + Logger._levels = allLevels.filter( + l => l <= GLib.LogLevelFlags.LEVEL_WARNING); + } + } + + static destroy() { + delete Logger._domain; + delete Logger._uuid; + delete Logger._levels; + } + + static debug(message) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_DEBUG, message); + } + + static message(message) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_MESSAGE, message); + } + + static warn(message) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, message); + } + + static error(message) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_ERROR, message); + } + + static critical(message) { + Logger._logStructured(GLib.LogLevelFlags.LEVEL_CRITICAL, message); + } +} diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json index 1d34f21..96e3e2d 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/metadata.json @@ -14,5 +14,5 @@ ], "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator", "uuid": "appindicatorsupport@rgcjonas.gmail.com", - "version": 63 + "version": 64 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js index 915c860..2c5e54f 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/statusNotifierWatcher.js @@ -22,10 +22,15 @@ import * as IndicatorStatusIcon from './indicatorStatusIcon.js'; import * as Interfaces from './interfaces.js'; import * as PromiseUtils from './promiseUtils.js'; import * as Util from './util.js'; +import * as DBusUtils from './dbusUtils.js'; import * as DBusMenu from './dbusMenu.js'; import {DBusProxy} from './dbusProxy.js'; +Gio._promisify(Gio.Subprocess.prototype, 'wait_async'); +Gio._promisify(Gio.Subprocess.prototype, 'communicate_async'); +Gio._promisify(Gio.DataInputStream.prototype, 'read_line_async', 'read_line_finish_utf8'); + // TODO: replace with org.freedesktop and /org/freedesktop when approved const KDE_PREFIX = 'org.kde'; @@ -39,7 +44,7 @@ const DEFAULT_ITEM_OBJECT_PATH = '/StatusNotifierItem'; * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object */ export class StatusNotifierWatcher { - constructor(watchDog) { + constructor(extension, watchDog) { this._watchDog = watchDog; this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(Interfaces.StatusNotifierWatcher, this); try { @@ -62,7 +67,7 @@ export class StatusNotifierWatcher { Util.Logger.warn(`Failed to notify registered host ${WATCHER_OBJECT}`); } - this._seekStatusNotifierItems().catch(e => { + this._seekStatusNotifierItems(extension).catch(e => { if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) logError(e, 'Looking for StatusNotifierItem\'s'); }); @@ -140,23 +145,38 @@ export class StatusNotifierWatcher { await this._registerItem(service, busName, objPath); } - async _seekStatusNotifierItems() { + async _seekStatusNotifierItems(extension) { // Some indicators (*coff*, dropbox, *coff*) do not re-register again // when the plugin is enabled/disabled, thus we need to manually look // for the objects in the session bus that implements the // StatusNotifierItem interface... However let's do it after a low - // priority idle, so that it won't affect startup. + // priority timeout, and using an external process so that it won't + // affect startup or memory (as it seems that gjs is not great at + // handling the memory of the bus analyzer async code). const cancellable = this._cancellable; - const bus = Gio.DBus.session; - const uniqueNames = await Util.getBusNames(bus, cancellable); - const introspectName = async name => { - const nodes = Util.introspectBusObject(bus, name, cancellable, - ['org.kde.StatusNotifierItem']); - const services = [...uniqueNames.get(name)]; + await new PromiseUtils.TimeoutSecondsPromise(2, GLib.PRIORITY_LOW, cancellable); + const busAnalyzer = GLib.build_filenamev([ + extension.path, 'tools', 'busAnalyzer.js', + ]); + + const subProcess = Gio.Subprocess.new(['gjs', '-m', busAnalyzer], + Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE); + + const stdOut = subProcess.get_stdout_pipe(); + const dataInputStream = new Gio.DataInputStream({base_stream: stdOut}); + const textDecoder = new TextDecoder(); + + while (true) { + // eslint-disable-next-line no-await-in-loop + const [line] = await dataInputStream.read_line_async(GLib.PRIORITY_DEFAULT, + cancellable); + if (!line) + break; + + try { + const {services, name, path} = JSON.parse(textDecoder.decode(line)); + const ids = [null, ...services].map(s => Util.indicatorId(s, name, path)); - for await (const node of nodes) { - const {path} = node; - const ids = services.map(s => Util.indicatorId(s, name, path)); if (ids.every(id => !this._items.has(id))) { const service = services.find(s => s && s.startsWith('org.kde.StatusNotifierItem')) || services[0]; @@ -164,11 +184,24 @@ export class StatusNotifierWatcher { path === DEFAULT_ITEM_OBJECT_PATH ? service : null, name, path); Util.Logger.warn(`Using Brute-force mode for StatusNotifierItem ${id}`); - this._registerItem(service, name, path); + // eslint-disable-next-line no-await-in-loop + await this._registerItem(service, name, path); } + } catch (e) { + logError(e); } - }; - await Promise.allSettled([...uniqueNames.keys()].map(n => introspectName(n))); + } + + const [, stdErr] = await subProcess.communicate_async(null, cancellable); + await subProcess.wait_async(cancellable); + + if (subProcess.get_exit_status() !== 0) { + const errorLines = textDecoder.decode(stdErr.toArray()).split('\n'); + const error = new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED, + errorLines[0]); + error.stack = `${errorLines.slice(3).join('\n')}${error.stack}`; + throw error; + } } async RegisterStatusNotifierItemAsync(params, invocation) { @@ -181,9 +214,9 @@ export class StatusNotifierWatcher { if (service.charAt(0) === '/') { // looks like a path busName = invocation.get_sender(); objPath = service; - } else if (service.match(Util.BUS_ADDRESS_REGEX)) { + } else if (service.match(DBusUtils.BUS_ADDRESS_REGEX)) { try { - busName = await Util.getUniqueBusName(invocation.get_connection(), + busName = await DBusUtils.getUniqueBusName(invocation.get_connection(), service, this._cancellable); } catch (e) { logError(e); diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/tools/busAnalyzer.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/tools/busAnalyzer.js new file mode 100644 index 0000000..969f4e6 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/tools/busAnalyzer.js @@ -0,0 +1,46 @@ +#!/usr/bin/env gjs -m + +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; +import GioUnix from 'gi://GioUnix'; + +import * as DBusUtils from '../dbusUtils.js'; + +async function seekStatusNotifierItems() { + // Some indicators (*coff*, dropbox, *coff*) do not re-register again + // when the plugin is enabled/disabled, thus we need to manually look + // for the objects in the session bus that implements the StatusNotifierItem + // interface... + const cancellable = null; + const bus = Gio.DBus.session; + const uniqueNames = await DBusUtils.getBusNames(bus, cancellable); + + const stdErrOutputStream = new GioUnix.OutputStream({fd: 1, closeFd: true}); + const introspectName = async name => { + const nodes = DBusUtils.introspectBusObject(bus, name, cancellable, + ['org.kde.StatusNotifierItem']); + const services = [...uniqueNames.get(name)]; + + for await (const node of nodes) { + const {path} = node; + stdErrOutputStream.write(`${JSON.stringify({services, name, path})}\n`, + cancellable); + } + }; + await Promise.allSettled([...uniqueNames.keys()].map(n => introspectName(n))); +} + +function main(_argv) { + const loop = new GLib.MainLoop(null, false); + + let exitCode = 0; + seekStatusNotifierItems().catch(e => { + logError(e); + exitCode = 1; + }).finally(() => loop.quit()); + loop.run(); + + return exitCode; +} + +imports.system.exit(main(ARGV)); diff --git a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js index 0aba244..7ec25b5 100644 --- a/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js +++ b/gnome/.local/share/gnome-shell/extensions/appindicatorsupport@rgcjonas.gmail.com/util.js @@ -23,11 +23,10 @@ import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as Config from 'resource:///org/gnome/shell/misc/config.js'; import * as Signals from 'resource:///org/gnome/shell/misc/signals.js'; +import {Logger} from './logger.js'; import {BaseStatusIcon} from './indicatorStatusIcon.js'; +import {BUS_ADDRESS_REGEX} from './dbusUtils.js'; -export const BUS_ADDRESS_REGEX = /([a-zA-Z0-9._-]+\.[a-zA-Z0-9.-]+)|(:[0-9]+\.[0-9]+)$/; - -Gio._promisify(Gio.DBusConnection.prototype, 'call'); Gio._promisify(Gio._LocalFilePrototype, 'read'); Gio._promisify(Gio.InputStream.prototype, 'read_bytes_async'); @@ -38,101 +37,6 @@ export function indicatorId(service, busName, objectPath) { return `${busName}@${objectPath}`; } -export async function getUniqueBusName(bus, name, cancellable) { - if (name[0] === ':') - return name; - - if (!bus) - bus = Gio.DBus.session; - - const variantName = new GLib.Variant('(s)', [name]); - const [unique] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'GetNameOwner', variantName, new GLib.VariantType('(s)'), - Gio.DBusCallFlags.NONE, -1, cancellable)).deep_unpack(); - - return unique; -} - -export async function getBusNames(bus, cancellable) { - if (!bus) - bus = Gio.DBus.session; - - const [names] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus', - 'ListNames', null, new GLib.VariantType('(as)'), Gio.DBusCallFlags.NONE, - -1, cancellable)).deep_unpack(); - - const uniqueNames = new Map(); - const requests = names.map(name => getUniqueBusName(bus, name, cancellable)); - const results = await Promise.allSettled(requests); - - for (let i = 0; i < results.length; i++) { - const result = results[i]; - if (result.status === 'fulfilled') { - let namesForBus = uniqueNames.get(result.value); - if (!namesForBus) { - namesForBus = new Set(); - uniqueNames.set(result.value, namesForBus); - } - namesForBus.add(result.value !== names[i] ? names[i] : null); - } else if (!result.reason.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { - Logger.debug(`Impossible to get the unique name of ${names[i]}: ${result.reason}`); - } - } - - return uniqueNames; -} - -async function getProcessId(connectionName, cancellable = null, bus = Gio.DBus.session) { - const res = await bus.call('org.freedesktop.DBus', '/', - 'org.freedesktop.DBus', 'GetConnectionUnixProcessID', - new GLib.Variant('(s)', [connectionName]), - new GLib.VariantType('(u)'), - Gio.DBusCallFlags.NONE, - -1, - cancellable); - const [pid] = res.deepUnpack(); - return pid; -} - -export async function getProcessName(connectionName, cancellable = null, - priority = GLib.PRIORITY_DEFAULT, bus = Gio.DBus.session) { - const pid = await getProcessId(connectionName, cancellable, bus); - const cmdFile = Gio.File.new_for_path(`/proc/${pid}/cmdline`); - const inputStream = await cmdFile.read_async(priority, cancellable); - const bytes = await inputStream.read_bytes_async(2048, priority, cancellable); - const textDecoder = new TextDecoder(); - return textDecoder.decode(bytes.toArray().map(v => !v ? 0x20 : v)); -} - -export async function* introspectBusObject(bus, name, cancellable, - interfaces = undefined, path = undefined) { - if (!path) - path = '/'; - - const [introspection] = (await bus.call(name, path, 'org.freedesktop.DBus.Introspectable', - 'Introspect', null, new GLib.VariantType('(s)'), Gio.DBusCallFlags.NONE, - 5000, cancellable)).deep_unpack(); - - const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspection); - - if (!interfaces || dbusNodeImplementsInterfaces(nodeInfo, interfaces)) - yield {nodeInfo, path}; - - if (path === '/') - path = ''; - - for (const subNodeInfo of nodeInfo.nodes) { - const subPath = `${path}/${subNodeInfo.path}`; - yield* introspectBusObject(bus, name, cancellable, interfaces, subPath); - } -} - -function dbusNodeImplementsInterfaces(nodeInfo, interfaces) { - if (!(nodeInfo instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces)) - return false; - - return interfaces.some(iface => nodeInfo.lookup_interface(iface)); -} export class NameWatcher extends Signals.EventEmitter { constructor(name) { @@ -268,87 +172,7 @@ export async function waitForStartupCompletion(cancellable) { await Main.layoutManager.connect_once('startup-complete', cancellable); } -/** - * Helper class for logging stuff - */ -export class Logger { - static _logStructured(logLevel, message, extraFields = {}) { - if (!Object.values(GLib.LogLevelFlags).includes(logLevel)) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, - 'logLevel is not a valid GLib.LogLevelFlags'); - return; - } - - if (!Logger._levels.includes(logLevel)) - return; - - let fields = { - 'SYSLOG_IDENTIFIER': this.uuid, - 'MESSAGE': `${message}`, - }; - - let thisFile = null; - const {stack} = new Error(); - for (let stackLine of stack.split('\n')) { - stackLine = stackLine.replace('resource:///org/gnome/Shell/', ''); - const [code, line] = stackLine.split(':'); - const [func, file] = code.split(/@(.+)/); - - if (!thisFile || thisFile === file) { - thisFile = file; - continue; - } - - fields = Object.assign(fields, { - 'CODE_FILE': file || '', - 'CODE_LINE': line || '', - 'CODE_FUNC': func || '', - }); - - break; - } - - GLib.log_structured(Logger._domain, logLevel, Object.assign(fields, extraFields)); - } - - static init(extension) { - if (Logger._domain) - return; - - const allLevels = Object.values(GLib.LogLevelFlags); - const domains = GLib.getenv('G_MESSAGES_DEBUG'); - const {name: domain} = extension.metadata; - this.uuid = extension.metadata.uuid; - Logger._domain = domain.replaceAll(' ', '-'); - - if (domains === 'all' || (domains && domains.split(' ').includes(Logger._domain))) { - Logger._levels = allLevels; - } else { - Logger._levels = allLevels.filter( - l => l <= GLib.LogLevelFlags.LEVEL_WARNING); - } - } - - static debug(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_DEBUG, message); - } - - static message(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_MESSAGE, message); - } - - static warn(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_WARNING, message); - } - - static error(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_ERROR, message); - } - - static critical(message) { - Logger._logStructured(GLib.LogLevelFlags.LEVEL_CRITICAL, message); - } -} +export {Logger}; export function versionCheck(required) { const current = Config.PACKAGE_VERSION; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js index e2a8bdf..af55247 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js @@ -1,10 +1,58 @@ import Meta from 'gi://Meta'; import Gio from 'gi://Gio'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as Config from 'resource:///org/gnome/shell/misc/config.js'; import { ApplicationsService } from '../dbus/services.js'; import { PaintSignals } from '../conveniences/paint_signals.js'; import { DummyPipeline } from '../conveniences/dummy_pipeline.js'; +import { Pipeline } from '../conveniences/pipeline.js'; + + +/// Converts a wildcard pattern to a RegExp object. +/// Supports * (matches any sequence) and ? (matches any single character). +/// Matching is case-insensitive. +/// +/// @param {string} pattern - The wildcard pattern (e.g., "Firefox*", "*Code*") +/// @returns {RegExp} The compiled regex pattern +function wildcardToRegex(pattern) { + // Escape special regex characters except * and ? + const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&'); + // Convert wildcards: * -> .*, ? -> . + const regex = '^' + escaped.replace(/\*/g, '.*').replace(/\?/g, '.') + '$'; + return new RegExp(regex, 'i'); +} + + +/// Compiles an array of wildcard patterns into RegExp objects. +/// Caches the results to avoid recompilation on every check. +/// +/// @param {string[]} patterns - Array of wildcard patterns +/// @param {Map} cache - Cache map storing pattern -> regex mappings +/// @returns {RegExp[]} Array of compiled regex patterns +function compilePatterns(patterns, cache) { + return patterns.map(pattern => { + if (cache.has(pattern)) { + return cache.get(pattern); + } + const regex = wildcardToRegex(pattern); + cache.set(pattern, regex); + return regex; + }); +} + + +/// Tests if a value matches any of the compiled patterns. +/// +/// @param {string} value - The value to test (e.g., wm_class) +/// @param {RegExp[]} patterns - Array of compiled regex patterns +/// @returns {boolean} True if value matches any pattern +function matchesAnyPattern(value, patterns) { + if (!value || patterns.length === 0) { + return false; + } + return patterns.some(pattern => pattern.test(value)); +} export const ApplicationsBlur = class ApplicationsBlur { constructor(connections, settings, effects_manager) { @@ -15,6 +63,27 @@ export const ApplicationsBlur = class ApplicationsBlur { // stores every blurred meta window this.meta_window_map = new Map(); + + // cache for compiled patterns to avoid recompilation + this._whitelist_pattern_cache = new Map(); + this._blacklist_pattern_cache = new Map(); + this._compiled_whitelist = []; + this._compiled_blacklist = []; + + // compile initial patterns + this._update_patterns(); + } + + /// Updates the compiled whitelist and blacklist patterns from settings. + /// Called during initialization and when whitelist/blacklist settings change. + _update_patterns() { + const whitelist = this.settings.applications.WHITELIST || []; + const blacklist = this.settings.applications.BLACKLIST || []; + + this._compiled_whitelist = compilePatterns(whitelist, this._whitelist_pattern_cache); + this._compiled_blacklist = compilePatterns(blacklist, this._blacklist_pattern_cache); + + this._log(`Patterns updated - whitelist: ${whitelist.length}, blacklist: ${blacklist.length}`); } enable() { @@ -97,7 +166,7 @@ export const ApplicationsBlur = class ApplicationsBlur { let window_actor = meta_window.get_compositor_private(); if ( - !meta_window.get_workspace().active + (!meta_window.get_workspace().active) || meta_window.minimized ) window_actor.hide(); }); @@ -108,6 +177,9 @@ export const ApplicationsBlur = class ApplicationsBlur { /// Iterate through all existing windows and add blur as needed. update_all_windows() { + // Recompile patterns in case whitelist/blacklist changed + this._update_patterns(); + // remove all previously blurred windows, in the case where the // whitelist was changed this.meta_window_map.forEach(((_meta_window, pid) => { @@ -145,11 +217,17 @@ export const ApplicationsBlur = class ApplicationsBlur { _ => this.check_blur(meta_window) ); - // update the position and size when the window size changes + // update the clip, position, and/or size when the window changes this.connections.connect( meta_window, 'size-changed', _ => this.update_size(pid) ); + if (this.settings.applications.STATIC_BLUR) { + this.connections.connect( + meta_window, 'position-changed', + _ => this.update_size(pid) + ); + } // remove the blur when the window is unmanaged this.connections.connect( @@ -158,6 +236,18 @@ export const ApplicationsBlur = class ApplicationsBlur { ); this.check_blur(meta_window); + + if (this.settings.applications.STATIC_BLUR && meta_window.get_client_type() === Meta.WindowClientType.X11) { + const window_actor = meta_window.get_compositor_private(); + window_actor.connect('child-added', _ => { + if (!meta_window.blur_actor) { + this._warn("can't move blur actor to back, it doesn't exist"); + return; + } + + window_actor.set_child_below_sibling(meta_window.blur_actor, null); + }); + } } /// Updates the size of the blur actor associated to a meta window from its pid. @@ -167,11 +257,39 @@ export const ApplicationsBlur = class ApplicationsBlur { const meta_window = this.meta_window_map.get(pid); const blur_actor = meta_window.blur_actor; if (blur_actor) { - const allocation = this.compute_allocation(meta_window); - blur_actor.x = allocation.x; - blur_actor.y = allocation.y; - blur_actor.width = allocation.width; - blur_actor.height = allocation.height; + if (this.settings.applications.STATIC_BLUR) { + const bg_manager = meta_window.bg_manager; + const bg_actor_monitor_index = bg_manager.backgroundActor.monitor; + const window_monitor_index = meta_window.get_monitor(); + const monitor = Main.layoutManager.monitors[window_monitor_index]; + + if (bg_actor_monitor_index !== window_monitor_index) { + this._log(`application (pid ${pid}) switching to monitor: ${window_monitor_index}`); + + // Recreate the BackgroundActor on the right monitor. This is necessary to make sure differently + // sized monitors have the correct scaled image of the wallpaper. + bg_manager._monitorIndex = window_monitor_index; + bg_manager._updateBackgroundActor(); + + // Also to fix differently sized monitor issues. + blur_actor.width = monitor.width; + blur_actor.height = monitor.height; + } + + const frame = meta_window.get_frame_rect(); + const buffer = meta_window.get_buffer_rect(); + blur_actor.x = monitor.x - buffer.x; + blur_actor.y = monitor.y - buffer.y; + + // set_clip(x-offset, y-offset, width, height) + blur_actor.set_clip(frame.x - monitor.x, frame.y - monitor.y, frame.width, frame.height); + } else { + const allocation = this.compute_allocation(meta_window); + blur_actor.x = allocation.x; + blur_actor.y = allocation.y; + blur_actor.width = allocation.width; + blur_actor.height = allocation.height; + } } } else // the pid was visibly not removed @@ -184,11 +302,14 @@ export const ApplicationsBlur = class ApplicationsBlur { /// In order to be blurred, a window either: /// - is whitelisted in the user preferences if not enable-all /// - is not blacklisted if enable-all + /// + /// Whitelist and blacklist support wildcard patterns: + /// - * matches any sequence of characters + /// - ? matches any single character + /// - Matching is case-insensitive check_blur(meta_window) { const window_wm_class = meta_window.get_wm_class(); const enable_all = this.settings.applications.ENABLE_ALL; - const whitelist = this.settings.applications.WHITELIST; - const blacklist = this.settings.applications.BLACKLIST; if (window_wm_class) this._log(`pid ${meta_window.bms_pid} associated to wm class name ${window_wm_class}`); @@ -197,8 +318,8 @@ export const ApplicationsBlur = class ApplicationsBlur { // or if we are in whitelist mode and the window is whitelisted if ( window_wm_class !== "" - && ((enable_all && !blacklist.includes(window_wm_class)) - || (!enable_all && whitelist.includes(window_wm_class)) + && ((enable_all && !matchesAnyPattern(window_wm_class, this._compiled_blacklist)) + || (!enable_all && matchesAnyPattern(window_wm_class, this._compiled_whitelist)) ) && [ Meta.FrameType.NORMAL, @@ -222,23 +343,37 @@ export const ApplicationsBlur = class ApplicationsBlur { const pid = meta_window.bms_pid; const window_actor = meta_window.get_compositor_private(); - const pipeline = new DummyPipeline(this.effects_manager, this.settings.applications); - let [blur_actor, bg_manager] = pipeline.create_background_with_effect( - window_actor, 'bms-application-blurred-widget' - ); + let blur_actor; + + if (this.settings.applications.STATIC_BLUR) { + const pipeline = new Pipeline(this.effects_manager, global.blur_my_shell._pipelines_manager, this.settings.applications.PIPELINE); + const bg_managers = []; + blur_actor = pipeline.create_background_with_effects( + meta_window.get_monitor(), bg_managers, window_actor, + 'bms-application-blurred-widget' + ); + + if (bg_managers.length > 0) meta_window.bg_manager = bg_managers[0]; + else // I've never seen this happen, but just in case + this._warn(`no bg_manager on blur creation for pid ${pid}`); + } else { + const pipeline = new DummyPipeline(this.effects_manager, this.settings.applications); + [blur_actor, meta_window.bg_manager] = pipeline.create_background_with_effect( + window_actor, 'bms-application-blurred-widget' + ); + + // if hacks are selected, force to repaint the window + if (this.settings.HACKS_LEVEL === 1) { + this._log("hack level 1"); + + this.paint_signals.disconnect_all_for_actor(blur_actor); + this.paint_signals.connect(blur_actor, pipeline.effect); + } else { + this.paint_signals.disconnect_all_for_actor(blur_actor); + } + } meta_window.blur_actor = blur_actor; - meta_window.bg_manager = bg_manager; - - // if hacks are selected, force to repaint the window - if (this.settings.HACKS_LEVEL === 1) { - this._log("hack level 1"); - - this.paint_signals.disconnect_all_for_actor(blur_actor); - this.paint_signals.connect(blur_actor, pipeline.effect); - } else { - this.paint_signals.disconnect_all_for_actor(blur_actor); - } // make sure window is blurred in overview if (this.settings.applications.BLUR_ON_OVERVIEW) @@ -328,8 +463,7 @@ export const ApplicationsBlur = class ApplicationsBlur { ) { window_actor.show(); window_actor.get_last_child().hide(); - } - else if ( + } else if ( window_actor.visible ) window_actor.get_last_child().show(); @@ -358,18 +492,29 @@ export const ApplicationsBlur = class ApplicationsBlur { })); } - /// Compute the size and position for a blur actor. + /// Find the system's window scaling. /// If `scale-monitor-framebuffer` experimental feature if on, we don't need to manage scaling. /// Else, on wayland, we need to divide by the scale to get the correct result. - compute_allocation(meta_window) { - const scale_monitor_framebuffer = this.mutter_gsettings.get_strv('experimental-features') - .includes('scale-monitor-framebuffer'); - const is_wayland = Meta.is_wayland_compositor(); + compute_scale(meta_window) { + // TODO: Drop GNOME <50 compatibility + const gnome_shell_major_version = parseInt(Config.PACKAGE_VERSION.split('.')[0]); + const scale_monitor_framebuffer = + gnome_shell_major_version >= 50 || + this.mutter_gsettings + .get_strv('experimental-features') + .includes('scale-monitor-framebuffer'); + const is_wayland = gnome_shell_major_version >= 50 || Meta.is_wayland_compositor(); const monitor_index = meta_window.get_monitor(); // check if the window is using wayland, or xwayland/xorg for rendering - const scale = !scale_monitor_framebuffer && is_wayland && meta_window.get_client_type() == 0 + return !scale_monitor_framebuffer && is_wayland && meta_window.get_client_type() == 0 ? Main.layoutManager.monitors[monitor_index].geometry_scale : 1; + } + + /// Compute the size and position for a blur actor. + /// Coordinates are relative to window buffer's corner. + compute_allocation(meta_window) { + const scale = this.compute_scale(meta_window); let frame = meta_window.get_frame_rect(); let buffer = meta_window.get_buffer_rect(); @@ -382,6 +527,17 @@ export const ApplicationsBlur = class ApplicationsBlur { }; } + change_blur_type() { + this._log("resetting..."); + + this.disable(); + setTimeout(_ => this.enable(), 1); + } + + change_pipeline() { + this.update_all_windows(); + } + /// Removes the blur actor to make a blurred window become normal again. /// It however does not untrack the meta window itself. /// Accepts a pid corresponding (or not) to a blurred (or not) meta window. @@ -448,4 +604,8 @@ export const ApplicationsBlur = class ApplicationsBlur { if (this.settings.DEBUG) console.log(`[Blur my Shell > applications] ${str}`); } + + _warn(str) { + console.warn(`[Blur my Shell > applications] ${str}`); + } }; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/coverflow_alt_tab.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/coverflow_alt_tab.js index e4b0f19..4e6062a 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/coverflow_alt_tab.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/coverflow_alt_tab.js @@ -66,7 +66,7 @@ export const CoverflowAltTabBlur = class CoverflowAltTabBlur { } remove_background_actors() { - this.background_actors.forEach((actor) => actor.destroy); + this.background_actors.forEach((actor) => actor.destroy()); this.background_actors = []; this.background_managers.forEach((background_manager) => { diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js index a78317c..6c084cf 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js @@ -16,6 +16,9 @@ const PANEL_STYLES = [ "contrasted-panel" ]; +// global listener, so we don't miss the panel destruction event +let isMainPanelAlive = true; +Main.panel.connect('destroy', () => isMainPanelAlive = false); export const PanelBlur = class PanelBlur { constructor(connections, settings, effects_manager) { @@ -28,6 +31,11 @@ export const PanelBlur = class PanelBlur { } enable() { + if (this.enabled) { + this._log("blur already enabled"); + return; + } + this._log("blurring top panel"); // check for panels when Dash to Panel is activated @@ -64,6 +72,11 @@ export const PanelBlur = class PanelBlur { } reset() { + if (!this.enabled) { + this._log("reset called but blur is not enabled"); + return; + } + this._log("resetting..."); this.disable(); @@ -77,6 +90,10 @@ export const PanelBlur = class PanelBlur { // blur already existing ones if (global.dashToPanel.panels) this.blur_dtp_panels(); + + // blur main panel if requested in settings + if (this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL && isMainPanelAlive) + this.maybe_blur_panel(Main.panel); } else { // if no dash-to-panel, blur the main and only panel this.maybe_blur_panel(Main.panel); @@ -92,24 +109,15 @@ export const PanelBlur = class PanelBlur { if (!global.dashToPanel?.panels) { return GLib.SOURCE_REMOVE; } - + this._log("Blurring Dash to Panel panels after idle."); - // blur every panel found + // blur every panel, except Main.panel (this is handled in blur_existing_panels() method above) global.dashToPanel.panels.forEach(p => { - this.maybe_blur_panel(p.panel); + if (p.panel != Main.panel) + this.maybe_blur_panel(p.panel); }); - - // if main panel is not included in the previous panels, blur it - if ( - !global.dashToPanel.panels - .map(p => p.panel) - .includes(Main.panel) - && - this.settings.dash_to_panel.BLUR_ORIGINAL_PANEL - ) - this.maybe_blur_panel(Main.panel); - + return GLib.SOURCE_REMOVE; }); }; @@ -377,6 +385,11 @@ export const PanelBlur = class PanelBlur { /// Update the css classname of the panel for light theme update_light_text_classname(disable = false) { + if (!isMainPanelAlive) { + this._log("cannot update light text classname, Main.panel is not alive"); + return; + } + if (this.settings.panel.FORCE_LIGHT_TEXT && !disable) Main.panel.add_style_class_name("panel-light-text"); else @@ -408,7 +421,7 @@ export const PanelBlur = class PanelBlur { /// Update the visibility of the blur effect update_visibility() { if ( - Main.panel.has_style_pseudo_class('overview') + isMainPanelAlive && Main.panel.has_style_pseudo_class('overview') || !Main.sessionMode.hasWindows ) { this.actors_list.forEach( @@ -533,6 +546,11 @@ export const PanelBlur = class PanelBlur { } disable() { + if (!this.enabled) { + this._log("blur already removed"); + return; + } + this._log("removing blur from top panel"); this.disconnect_from_windows_and_overview(); diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js index 1e1dba8..fcde72b 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js @@ -53,6 +53,8 @@ export const KEYS = [ { component: "applications", schemas: [ { type: Type.B, name: "blur" }, + { type: Type.B, name: "static-blur" }, + { type: Type.S, name: "pipeline" }, { type: Type.I, name: "sigma" }, { type: Type.D, name: "brightness" }, { type: Type.I, name: "opacity" }, diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.glsl b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.glsl index 142b89b..5df6512 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.glsl +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.glsl @@ -3,11 +3,109 @@ uniform float red; uniform float green; uniform float blue; uniform float blend; +uniform int mode; + +const int NORMAL = 0; +const int MULTIPLY = 1; +const int SCREEN = 2; +const int OVERLAY = 3; +const int DARKEN = 4; +const int LIGHTEN = 5; +const int PLUS_DARKER = 6; +const int PLUS_LIGHTER = 7; +const int COLOR_DODGE = 8; +const int COLOR_BURN = 9; +const int HARD_LIGHT = 10; +const int SOFT_LIGHT = 11; +const int DIFFERENCE = 12; +const int EXCLUSION = 13; +const int HUE = 14; +const int SATURATION = 15; +const int COLOR = 16; +const int LUMINOSITY = 17; + +vec3 rgb_to_hsl(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +vec3 hsl_to_rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +float soft_light_channel(float base, float _blend) { + if (_blend < 0.5) { + return base - (1.0 - 2.0 * _blend) * base * (1.0 - base); + } else { + float d = (base < 0.25) + ? ((16.0 * base - 12.0) * base + 4.0) * base + : sqrt(base); + return base + (2.0 * _blend - 1.0) * (d - base); + } +} + +vec3 get_blend(vec3 base, vec3 _blend) { + if (mode == MULTIPLY) return base * _blend; + if (mode == SCREEN) return 1 - (1 - base) * (1 - _blend); + if (mode == OVERLAY) { + vec3 result; + result.r = base.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r)); + result.g = base.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g)); + result.b = base.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b)); + return result; + } + if (mode == DARKEN) return min(base, _blend); + if (mode == LIGHTEN) return max(base, _blend); + if (mode == PLUS_DARKER) return base + _blend - 1; + if (mode == PLUS_LIGHTER) return base + _blend; + if (mode == COLOR_DODGE) return base / (1 - _blend); + if (mode == COLOR_BURN) return 1 - (1 - base) / _blend; + if (mode == HARD_LIGHT) { + vec3 result; + result.r = _blend.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r)); + result.g = _blend.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g)); + result.b = _blend.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b)); + return result; + } + if (mode == SOFT_LIGHT) { + return vec3(soft_light_channel(base.r, _blend.r), soft_light_channel(base.g, _blend.g), soft_light_channel(base.b, _blend.b)); + } + if (mode == DIFFERENCE) return abs(base - _blend); + if (mode == EXCLUSION) return 0.5 - 2 * (base - 0.5) * (_blend - 0.5); + if (mode == HUE) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(blend_hsl.x, base_hsl.y, base_hsl.z)); + } + if (mode == SATURATION) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(base_hsl.x, blend_hsl.y, base_hsl.z)); + } + if (mode == COLOR) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(blend_hsl.x, blend_hsl.y, base_hsl.z)); + } + if (mode == LUMINOSITY) { + vec3 base_hsl = rgb_to_hsl(base); + vec3 blend_hsl = rgb_to_hsl(_blend); + return hsl_to_rgb(vec3(base_hsl.x, base_hsl.y, blend_hsl.z)); + } + return _blend; // For NORMAL +} void main() { vec4 c = texture2D(tex, cogl_tex_coord_in[0].st); vec3 pix_color = c.xyz; - vec3 color = vec3(red, green, blue); + vec3 color = get_blend(pix_color, vec3(red, green, blue)); cogl_color_out = vec4(mix(pix_color, color, blend), 1.); } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.js index 7de753d..1f4bdf4 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/color.js @@ -1,12 +1,14 @@ import GObject from 'gi://GObject'; import * as utils from '../conveniences/utils.js'; + const Shell = await utils.import_in_shell_only('gi://Shell'); const Clutter = await utils.import_in_shell_only('gi://Clutter'); const SHADER_FILENAME = 'color.glsl'; const DEFAULT_PARAMS = { - color: [0.0, 0.0, 0.0, 0.0] + color: [0.0, 0.0, 0.0, 0.0], + blend_mode: 0 }; @@ -47,7 +49,18 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? 0.0, 1.0, 0.0, ), + 'blend_mode': GObject.ParamSpec.int( + `blend_mode`, + `Blend mode`, + `Blend mode`, + GObject.ParamFlags.READWRITE, + 0, 17, + 0, + ) } + // Normal (0), Multiply (1), Screen (2), Overlay (3), Darken (4), Lighten (5), Plus darker (6), Plus lighter (7), Color dodge (8), + // Color burn (9), Hard light (10), Soft light (11), Difference (12), Exclusion (13), Hue (14), Saturation (15), Color (16), + // Luminosity (17) }, class ColorEffect extends Clutter.ShaderEffect { constructor(params) { // initialize without color as a parameter @@ -58,14 +71,16 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? this._green = null; this._blue = null; this._blend = null; + this._blend_mode = null; // set shader source this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url); if (this._source) this.set_shader_source(this._source); - // set shader color + // set params; utils.setup_params doesn't work here with color this.color = 'color' in params ? color : this.constructor.default_params.color; + this.blend_mode = 'blend_mode' in params ? params.blend_mode : this.constructor.default_params.blend_mode; } static get default_params() { @@ -121,6 +136,18 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? } } + get blend_mode() { + return this._blend_mode; + } + + set blend_mode(value) { + if (this._blend_mode !== value) { + this._blend_mode = value; + + this.set_uniform_value('mode', this._blend_mode); + } + } + set color(rgba) { let [r, g, b, a] = rgba; this.red = r; @@ -136,5 +163,6 @@ export const ColorEffect = utils.IS_IN_PREFERENCES ? /// False set function, only cares about the color. Too hard to change. set(params) { this.color = params.color; + this.blend_mode = params.blend_mode; } }); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/effects.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/effects.js index 931d345..e35588d 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/effects.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/effects.js @@ -168,6 +168,31 @@ export function get_supported_effects(_ = () => "") { name: _("Color"), description: _("The color to blend in. The blending amount is controled by the opacity of the color."), type: "rgba" + }, + blend_mode: { + name: _("Blend mode"), + description: _("How the color is blended in."), + type: "dropdown", + options: [ + _("Normal"), + _("Multiply"), + _("Screen"), + _("Overlay"), + _("Darken"), + _("Lighten"), + _("Plus darker"), + _("Plus lighter"), + _("Color dodge"), + _("Color burn"), + _("Hard light"), + _("Soft light"), + _("Difference"), + _("Exclusion"), + _("Hue"), + _("Saturation"), + _("Color"), + _("Luminosity") + ] } } }, diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js index 5dfb2f2..fbfb54c 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js @@ -476,6 +476,18 @@ export default class BlurMyShell extends Extension { this._applications_blur.disable(); }); + // static blur toggled on/off + this._settings.applications.STATIC_BLUR_changed(() => { + if (this._settings.applications.BLUR) + this._applications_blur.change_blur_type(); + }); + + // pipeline changed + this._settings.applications.PIPELINE_changed(() => { + if (this._settings.applications.BLUR) + this._applications_blur.change_pipeline(); + }); + // application opacity changed this._settings.applications.OPACITY_changed(() => { if (this._settings.applications.BLUR) diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo index 05ebeaa1586ccc10e500bc077b293d734a18d843..aac168e36525bedad5afe2be89c2889e30a33c99 100644 GIT binary patch literal 16821 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 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo index 71efa48c1e345307bad8bafc65c05a8d79d8376a..f804035e4c67b39a2128c0928a884d05f85cf3ff 100644 GIT binary patch literal 17615 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 bg^%nF-otSHZZ*G$-7uX8OWf#%sc-xbJ5Q0! delta 3018 zcmXxkdrX&A9LMo53UcvB$VHS;K@>y~1<4zT{=DLaXq_K;T#R0;7eHE#Vi}I<3#Mp=<{$2_Q6w_kC$;OhQ^q6!&#V&%TNQ? zAV0B#n2GNrLs&D?wY6Y4%SOuTUK}V<_H2b@-Fl zejgdz{=%LZ5pOmc({Us&Mn9fJE%;{)jHU1g1x;WmdDK7!n26I+11-Z^T;bKjyPGkF zMdL#3hkAb(Dz&w^8sEVr?3v)6tpe19=OW3m1qtL|1Fol`H`btD_z-#5uA*LOL8bn8 z)P(*;Wg?gpr}hZc-o~L;+82jnDOTVC)S2nbs-|Nh&c^+TBA!=qmK84QM z8#PcCYT#Vd%JWeJ&+z_Vf=YcU?!;9Xh8@`l=4w7vKWV514M6ojEI?rZg>k4CmZJ{K zI@AD_Ui%)@p4B0J+bLAa8@=|+r~z)EGI|?x@IERtDSV^qcd(})_4~jy3hHP!>W3vr z5^NdH!b()CzQa_^W`FeA6{EK7I8MPvB+C|+Oja-h`{D*%j>oVNV|Zx}&P5g;u#YKB zq~UuUh3P3~&*CB+jh~|*AEQ#{=Ms=bs8l|ON^uz$;YQS!euH}dCice!W~2LM9A@IX zn6B@?iGou72-R^Y%hXC@@pKU1J}NUe)7&%i3!b6=4?1|dpV_j~m zwH0|-j1w@9%pJxM>SyUJ3eTY?b_w~HeVa}GRp`i34aQs~OEw(UajDn77`c0_9M$1A z48t9$1?=dmN3Jwi<&EHKplE|ZY$wJc;i zZ4PQHwxd$^Hg>@?sDUn^GIq&pzk)inw{RXlKz&8e4C5SNJ&weT;T%w0go`k6k3uws z*(2P;vJjK0Z$jY1CI49LLc>F)C9^<16N}#?#4(wfroH*fUzuJhc^qA zQ9p+0`!AxP70yI;P=ft&309!v*{Q(2(bnN&+K-@q7s{EdNqW#hSXry_BR`4bJ{QGx1Q!TlQ^%m0XGvx#CD>D*yw!G zxm)iYl-eI{nI7#a8MO68ozvDiF|~#gd-VUai@$pa-4-!~Zi6?7T4#hWDSRKL5W<{N z-_)R^PQ5QT`Uut62#$@dAu60!Us6z&6CK$n$Qp)3R(5H)*0V>bvpm(;@O0|l_=bo1 Lbzx5H__O~3nczxn diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo index a140ba0e019da790698fce30856959598a1a8b93..c00a0b06b175d770899d635759bc36d64fd90ca6 100644 GIT binary patch delta 64 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 TOB;9Vl%|#XYU8LbZEpM*j~zL~ diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo index cad32d55350b792319a6dfd298a9bb5c1715f8f2..034f55a0b8fb9be39c5479fd72caa66859131ead 100644 GIT binary patch literal 16481 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 delta 2689 zcmXxlc}x^n9Ki86RYVaghpXJIC@Lbj90GzMDBuAq07$jP-a0Cu7ohrQAyOt9&ZaG&JD^+=Q{%h4iHcoZt65?L#=7_OmDtx`ufeMO7S=8a_q2;R;6Lbxgopn1;XN0*s-z`M4aba6j^s z`Vtr7*C>mZ@}yEO%)~8Niqd`xWrAmLJI_}iQ^~+QrY|#CffI2p%D{Y1`vA(o4xkKF zBY)}yhhiK?KiFB8kz=@2qT5HZo~d;8=&U1?y0@stqL>{V4su zj54AA5h?{#en*+fG*Z15^H7#Ph%&%Flw8^8v>!%!jfPP6@}$%LKFW0;A&aCgpc}8_ zeEbvVVm==c&ihpx73ttKuE6ssNfVI~{vbu8m-B3t_Cb{EU&Yt(3}#}rJ3Ql7l$CfM zC8u6O8PHM3*HQX;3uAe{dY6if>@y7DBP>TBnI*5!I~XhNC~v`do+bmxLRqmAlm}EJ z+pU)35Sl1C@et*{2tI?dq8TV#l7*2xUwNn$VkydAcA_kK56VbiMA^#&PWy3`4&O!@ z_+^xw_!s5vNthOX@D!8>=AztRi1k>7&3F(c|I{5S)%Z8cOe?a&S-S#dC9dIW96vpr zD_)eh;~19VU980P8Q}+Qz!uK8p$zOIR^bh#E9D{s*JJri)?Y?8M1y!5Q*i_hxqy)J zEFnwFR@*m%y)x37lzCz7e_}GQEd-wk`&DI5Y7|jINRbt5C1k~$W&fqfKFXd-nMEwI zYvF_J)#DODMY4JwAp_n>Nb!cTKW1~NOCn2IOVkmv%2LQ}JNsplZepT5KaVITEaGvI zceThlVb$z^p}aZva?2h{Sw?IoB8de=4Iv3vL6EEVcSI66hj^NhE#5##j>wx)O7u&j z$(}DH9+$;VWeu((B-xe{iG-BVM1oxlAD#kIz}{nNSx!7bXUq@)L6ny(=ky=F*_$H-qh6zJO|I_gcPyg>74ds-er<5%Bsg z%je$Q+2aolB$paGH8nqSWw+^V5B7%oQWK4YomOXipQRf8UE3^g(A{meS^7cRVf{+_ zM13iJSpSoerXOT1#FJ^ZlHe;gf=r(6Z?hj4=hdt=9Ia&4e;$b$VW-uAGymf0&aKO7}Dxq1u8qhW?~5f0Dfdfp(@H zVEXN9k-63EHTCYIAC3IEmns+XmtdFJ$^kf?+tyZ%opk{cNuzKMXJuMxE*cJ%3gp#d#J3E6_{03@;??M BSrh;O diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo index b9f23036fdcea395b80e926529ecff4a5afaf193..a6fc86a9f5388ec3cf71ce70015be0b52559ac40 100644 GIT binary patch delta 1391 zcmXZcOGuPa6u|K_ruixzUnygnmG4O%A2~Uhjap_YSfqua)mRjgjx>Hj=wcv3Nuotc zVA#Tq*dkB{lb)L%&;vym844yKo=74ZcpHat6qEBs7$VcS6Bp2qzcB%A1*S>pr=5dsIEKym6F;H5P-GC} zoFaT>#3?~(B6v*eDu(S5$wmWPa2&gF4R_$lB9RL0$1OOG+i?zExQyFyQ?W=qIxrdw zF&Qh+fk%;{av$NwWg>@g z2z5grupPgkW}>3p%w!E}=7MJlbb&#f#G4q2xon?uNip_dJ8J)1Ou+?wfIl!7Z|pTE zerWj)b=(@-aRc@4*egXcunf~!Uyc*R(9vyape__dP3^GNe+PHd9>-dIfpxfny;$ew ze&7stU^w;EwhxnW&hkC#9r%uR)|Y<-x=?JDnTbTy0qLk4t3)kHEhgd-oWL{I^L0$8 z9p*8ApNTpy54D6Itj7k_5{zIHj$st*%e3`i7ImU$)_@h%8vR1uVAOuIrtzo~WnvoU z;{mKi2L@3$a33}Gk5CWr5;e20F&;l+Fo)nP!4(Xv7CD7})Ysz;cH$r0g(p}=FPDKC z_ykYm3hF#1HQWPi!zTQUKFmI7zMeyPj`lpZVXBw>Um)o9ny=v!@|8FWtUGT(P2qXV z9@G!4&Dlg4)xjn8br;ATav#;MMY7O}O{XIUTFW|{CE(NlTZoiRLO{9VMa;PIW-ez-$ Vdh#lgB3rL@`3AcCLQ@`Z^nW=tt;zrZ delta 1412 zcmYk+OGs2<6u|K_kfu}SJIzN~zMswL*uzJSX(Fa1AmoA3MXIrq-{0o&q$?NM4# z;HgdIS-MD^i1;!^qHqu|;V@psoGcNh$OLZ0d5pl|Y>`Nev&_aG@=|QV2Uv%aBk~dI z@eHQritv?@TnWe?f@!i77@x;Q9K^jih8|qT4d}@iap6T=jT4xJQ|Q1YT#M@pM8eU5 zq3FgKti=TEK&Hy+f`CXF!6*aUZ~^s>)^9fN(1EMSD=h1=le`sUsoZl6CjY?hYj75I z{u1gze_3Wb&3Ok=Z?Fr4a4I zqu5;drR5jYdCM4qv0Kb%Cj*noYcQVurJKOcK)`Ykb))O3r5(1$?_nzW7*^m6?!wru zBFAw*?!!rJ!vy-N`6-OSDa)^@&%ketV1J3&Zf>*@wGvsV6P&0At3&No3r1l(-o`%b zdRU1_B6&RO?_H?#%28X`fR)&0T_3?{^81>zzq}yO-b|t{^v;^_4Yfy7Y925dwWn#Q z^NTPZ%ds4rF#)fk9$*Z$^si8FU#kC`O{42Z6mL3Hhs#1L(sGSc`u#7pv)m>O-yIol5EuMli|%ud+ND z&$cfn))(hHT=`B{inFk!s3_OL$6jaj`|}%pMo+)j@b~&kQVegW(bL;$`2C)Kf0x&5 nq?DOM9siBFkM#P-t24rFHs^SArYkzQ!PD2}^^6adxI_N|O^dnQ diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ml/LC_MESSAGES/blur-my-shell@aunetx.mo index 6573c2cef938e5d2a29584136e4265b9c55846c0..a03d7766b0ac48d5bc67e070ac1e3128ec775bf1 100644 GIT binary patch delta 56 xcmZ3?(#3@h*vN&Fhl@pP9SDv0%9P|v@!A&BLJ(}1=Rom delta 80 zcmeBXS3`h*vN&Fcbi3P9Ti{tbL;$fFP%;uogVYcUCdLK_MY=i$>H7NX zx;QF$_*?mUYDf9|xpMg=7MJLT6eZ>r=OmWo7g;GdmX_q_CYEF-C+6f-Dx|08r4}WY gq^1BB=B1Y=rl;zLq$cKCDdgqnrA`iFoW#fg0Ce{wYybcN diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/my/LC_MESSAGES/blur-my-shell@aunetx.mo index 9123894a445768bc7dfc2b013abf50a570886e17..0d81fb0bd9162ef7cbbc1e35761e91896678c326 100644 GIT binary patch delta 36 kcmeBTe#JCFM3R|-fk6j|LBIlt4Hy|1EP*uRMqgV-09&X8MF0Q* delta 68 ncmaFG)WtkO#FCqVfk6j|K_CK%4Hy|1B7roJ!Vfm;+A;zF(hdZT diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo index 0487afe0fb8d96cf0b06c729e34071b5901c80da..47fc350cffe0d1c238e6742f800b0a978fba0f12 100644 GIT binary patch delta 1298 zcmXZbT}YEr7{Kx8?L(cbWmbM8%;@ zaYJOWTjYd@O!J7G$CFryzpwyvOGTXM!&w-{Y^=dLtjBFQh*da&_poT0NE;3zONqZs zWHau>eR!=*;9xo6Q41?Z9j`<^z(!=M zG+;IMq89iDb^dQ}TqK7eV|jWZ+)G}JDLjiavBhW4i=lR+2WQ|V%)qPZ{5tB!H_?gD z(Sff~3m?U$_!(E?zc@i7LC`O<6|Z0&j$t;sD?}`;zcZ!c=E*fI#bMOKQkaWBQ47iD1!|{q(8d0;kU$@e7wd5g?!g4|Kia9)JXa2skz8c|zj zAs>XC!Unv9dH5UkyUw8sFYdyF*n@giU$6v?b#_NeQ6Ft+9gQy_*pMuAG!{C8p^9L@ z3`W)l0*Sage`$47^r*SL`LuPo-7?olD`R#TsoHepXw-@&pSWucqbl*EV3N_!S>ue5Ob{P9a-MW|qia zti%&Ink8OIAy{BSHweuZsm7z2jQ5b*b@^f3!la?LR*aO8>{!i!jivlxL%c_M9S$2h!-+OhlS#A(!ZOE`|Js0EF0 zGZQ|<(~KuE29vj&^Er5pvA2wXYnFGYomj>M49Pbarl7&tiJG_u!>}jdAZmw(QBQga z4fLTNm$)Ix%If!e7sj3K{R3G~sV;t?#xTD**zIFE-h++}vC7CF3h zU=rTN5}d?lTtae5U9m_Dj-r8!s8Q&95e*b?_JCa;#K3Yd9jZb8v$Zrd8utnw<<>k8! zXK_iP%jZo?u+?^Z+^x+W#_oPID0la{o4UH)P5z0r0~U+Zw~{{M8^|v3O=MWDXJ;-n zwRE+$w)YNtjHb?3quc)}qdv%AkhRa^AIP4G2{Zbd2R*Ft?Jv%;wEBCBzpeQX+Rv)6 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo index def333ff40441de99fedba28292ad3d377a245a5..10d3aa18be23e39b3cef3a8af52a754296baa3d0 100644 GIT binary patch delta 3767 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 YHTw3e=-k*cq}r?QVRA^_-Q>0Z0c){Y_5c6? diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo index a76994e93dd74b6ff286bcaa2a98b1f758b6104a..3dcad8da2a46c03fd98212ffbf83c9ebf606ebcf 100644 GIT binary patch delta 5593 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 delta 3200 zcmYk-d2AGA7{~EvN;!H^p%vN!m6ckkg-R=BE$s>gg$e~kC<;>46}DI`-LhQ{5m>Q+ zL9N$_M4}u#cZlmoWMiEzMnt9khh!0wAj@dSxg6r@#ya=mv%|_q?%*NZ1KU<$Z?#4!r zAHeDOIhJG5V6&q*9aoyA>>QmcPTZ7d)`AaWDSnSlIOGDeLTtehCXsvDZXAjSkUx8w zk0E#*v+y(2b>F1Ve~)81{tGpsOSt$l#v7p|vukk=He(+uqY>6m6KO&X+=7&mtt}+~8ej`2G+;M!FS`$Q zen0YXb`X2;HB?>BE;1{|g{bS=Q4>#~ZoCC2;4aklM^H=Fi+Yfc(&tYWk$|tYxq22_L~(*o#wfK#AE6I1^P|I%b zb1@aBqc!SAec=(j6hB4wr~QfJF*-WfzdfiF9zoscE!2ch;8BM)$45Ed$5ZXXnlZum z-b8KdK2$B_a6o;hY!n@xn20fKz$N%BPQml|HBPz2Y!eoh1ru^nRo;ss96L66e>5U< zu%~en9!E{|EUNf2#|0BE#v<+i8aldQ9;(=u`u{LngG%vEoPi$J;IF6&kLPu!+KAu) zoR3wvoBE>{(=M1sR*h)3;DBB zKBnS)ti>K|#P?83nKz#QVF~KK?U;pYaSz^!x^Dqbr~0#zbXH&(m4UtZ1Rg?moHbPj zsat`1;*Cfl+r5~BPvamwjC!(HF&BH0y0jCh34e!4EWeCw;A0$Dq9$@2S$_Kj_5HI*@!9z*@}Es7 zzdCrMm7t!a8HeC<)Ic3+H=@3HH!8KeF%S2q|Nk5+V;-tzK16n`^6Vp#gPIc*(oB=l6%2ohpE zoOKa56C}=**XfmXdC%Ae;$lK=d4LU1tE^~E)!K+|VhK@Cv=dv1 z^~Ci=6ETa>ldHaz8MT4{zb2HuPR93tGB;xbF^14qRJ)4M60n5+&n);Y$>$E@E<)Q+ z?d|~oa}b{sh;m{r!LIX{PW7YhxQ$R_(^-m_ng3g^6Dp*w>d>?uwMSKi)x`f>AqQG> zy>#>FkMX?y8L>Xc3Pq_uD?R2z1 z{%PyzEF$_5YY1&Zwb23pey*n1|KFpaGaa-SI*8fC)r9uQO5#F7Yq5&ZHYg%^sr*w5 z!Diu{-&DsL#2tipV(_Yd?xvwhw<3SP`&<4W-noJsoqmaqnES=BO0RHuqvPFQSn9Y( zitceY6*p(kPR0_^WLvzW%N;r5a_`;|ryOtds0JrHzB;xd8S0F#ig{;C5{~!K=y8ts zW$48W@1@du$L%c3br+PqU0YRCSrradUr{$HJidySJvZ8wtZYt1JG$DV$#|kJ)D^!q z)|TvuZ>S1I{_A_o#*T5asw-E<)@R$|HSWXp1>Ui7#hGr!gzfIU@?7`)gx9^(m0`y# zpSan{jCLgBZlpTm?W%5dyzrz7$8D`S?6yo^n&Usgv4h86iFLU-;X1D;T$bUzQM=9= wdTjrywvK3MWjxfG;Bk_1Z(H39j<+IG?|AQCc{0O0*${Euo*84@tuwm+2ClVu^#A|> diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo index 74b52b7aae950a1c0bb07fabbcb044dfebf9ce21..dd7822e927da990958646de11806cc9fd24c2738 100644 GIT binary patch literal 10249 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 THRz3bX-nAfZ({dP=jeX{JOWlJ delta 975 zcmXxiPe@cj90%~EuZ280usj##p!=elkDLsU4X#6 zwYO>tlx|(DOCZ}N@{}En!B+zn5`0m%2? zg`0_H=^;Axn3yYFcmer=S8xY>2e-hlumb*sHEq&FdXB#cdg)Zu) zkmz*fWX5+a&!c{2E0+cwF=1P#ux)eVnwhfFBCvfr?OU$!rE)y|zV=|#h)Bu6qtT3* zvP>(Twvs+ZaxyFQw>qiEBK7)TILOaOY78BZjvwpp=saR}_4FR@+24t%9u}V8k#L3M z*}_+DubIe5=gNpuzIohJNh$2Uq$|Db0axXhqeqR3u8x#7U9FcIV)+vd2}3_^jOcx_ z%lcRBMr1h1N=MB|U-%aF2euNf?rv$TD&)NKL`uEb+SfiJW(2lliX^52$D#qw+Ty9S ZaT)LiH?C~5{PkRZ|` zw2MA4?CV0yAc`P}D55a0w7QVMNbChoNcF~$KDacr3sqEXEvkqY=HKCg3y%(Xd%$175^5e1tmj z2Ta5f)XGevJ~xND#cQ_AFC-u?0$p)6#$W^LM1Is2pFyp_c}&3$EW}>ql5zezFeOjK zsr^`qW9Y?vPM{`y2bbd$OvZP(g!3og2qNhCg<6Tfs2To4O(<<^C;dLqywk}592Z%K|N$Y zQMYIo_o0#HYsqU-OWub1+y&J4yHG3H9ln1X18eB$C#b+7+>7Szp$eS98rogB4u4}A zCh^IvKrbG|cFe?4JdFzqs1BaRMtp;IwC@b{yOB%o@1*_*2qtJ1qLV+ykkhCYd4^hv z*I|b+mG)Px#92(jQkMwT7Z37j%T27uk64AdeA}8}C+hu|s9P~v#0F}K{?L(*GH8kY zk-96-YIj&24pWZZX?JAV`NfvFTm9DZ7I$-NliTlWahi6!o4uYUQ-#;tXxdR{JB2Ra rNq>{i*JwNHJ3e^W9Bo**#pW2S-`Efp|I^*L?Dw2=?>*-^&pG#6%yKJc87xRP z1}q}?7mH+yNPD4a7hb1*5|5#)NMsqtu>?P27G@Ni+7njccKX-gCcKKvaRMKrlb4U; z2$o_;sTi`3-~z2y{DKRyajA$G+i?TlKpRe?CNR$-l8&n}2e+ULLpT#JV>%9^6(8XY ze1`LJ7+Hh-bQmIa1hz7f25iOYcm>n3A5-x@>OfC$GrqtdXs0a6nC+w*n2Y*;F=|3p z34^H5T|%9>4^!~DL6Ai78g(T@I1NWI4S%5~Fs0laz>2zpOk9FxxE8l0?89c--%%5; zB@5k(M$`!};!NztJT&42I?+o!i|-QcU>bj5pcDt4kybOg0zG1Lm2#JPA5S7JYM$v6JG(OxCu z(SB^f&lp56Cr}fMV1D^ZkVMA>Y9;=l9>SDrGod2X1YD>Ccu*^~4)sud zz(qKU|Ib2=d3JJ97gU6rs0(%c_Qd@IdY}2lAkdO^;~YGXT9EXt3A&0QYSy_T3=_>u{q)kcXs%q`y(FPu3$78443=;yWQ^P{%V)I y!dAsWz diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/th/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..e04e4a5a68f3dfc9f4f2f4ab5a3711008bcf7343 GIT binary patch literal 362 zcmYL^!A`?442Fl`lp|*jIdB8Rb{m-{F<2)mQ94Zp32s?yx}Y?v5*KX`!t3o>a6#IB z=~Ep0ckJxX&wd816Xt@sWKNlDrq`Gma`BGO-gD40_%AF8(hA-%MB|;3Yug2Ab`Upc z?Y-_C(pIdn^?@LZwW;8tt0NR%NwLgfh2N%cgt;bE@;#ZYAj@GslTW$I(yNdBB@xd$ z5)?tZXf^quI3+;wy_6p!8! zI(~lF@_fQA-L_U6H<9H=hln(NEfz37`ua6KF+k! this.preferences.applications.STATIC_BLUR = this._mode_static.active + ); + this.preferences.applications.STATIC_BLUR_changed( + () => this.change_blur_mode(this.preferences.applications.STATIC_BLUR, false) + ); + this.preferences.applications.settings.bind( 'opacity', this._opacity, 'value', Gio.SettingsBindFlags.DEFAULT @@ -183,4 +204,14 @@ export const Applications = GObject.registerClass({ this._blacklist.remove(widget); this.update_blacklist_titles(); } + + change_blur_mode(is_static_blur, first_run) { + this._mode_static.set_active(is_static_blur); + if (first_run) + this._mode_dynamic.set_active(!is_static_blur); + + this._pipeline_choose_row.set_visible(is_static_blur); + this._sigma_row.set_visible(!is_static_blur); + this._brightness_row.set_visible(!is_static_blur); + } }); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js index d90bdda..43c4889 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/prefs.js @@ -43,7 +43,7 @@ export default class BlurMyShellPreferences extends ExtensionPreferences { window.add(new Panel(preferences, pipelines_manager, pipelines_page)); window.add(new Overview(preferences, pipelines_manager, pipelines_page)); window.add(new Dash(preferences, pipelines_manager, pipelines_page)); - window.add(new Applications(preferences, window)); + window.add(new Applications(preferences, window, pipelines_manager, pipelines_page)); window.add(new Other(preferences, pipelines_manager, pipelines_page)); window.search_enabled = true; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled index 6f781f41c934e0bd159f143f60f2c83e4a608699..c2b6708cbe48e9f52d9b6d58eca0cb21d9831a7c 100644 GIT binary patch delta 1867 zcmZ{lUuau(9L2wxi|y9Lc4}>C(l)m1mOz7bTF^qV4;%Qf&9VoXa}00Vutd`&ENQyw zX8NFz2mjRF4aTq#aK%2T6e}`NMhmToKG-6%svFF=J`A7s5MQe2lX}4yFC5Of=l8q6 zKj-(o_tuZrkImLAi=Ae*E1jW$nSB*8d&XY0E%D(lvnl`a&+zA^pO(KVe!R!5Y58sq zzZ^9imcJ;DJ!y9E&$*RGe`&_q6xVyr?z9h{z#rPbdelvf&J!XIFT05XtJ8IvH z>j&KJrs1VkU!cRk58LeubX0ar_=SgsCSi}TS7;F!+C!`Khu{79aowUGV?eMX3I|e*_=hCchw_63VAuZNo>?e@0wIw_76?G_h2}6|+^{tUvL?n>>JK zrJLfrLifjyzJ!lvpgHTA)9=N&ai%v@p@Tv5Aik$UiTB zN4Q@3^vXpVxY@0Ss`z~&=^pzAAI-$q#B;)}fje*EqltP!Om!7YPAM~`+3e1JE}to;64}hzbSalA7U|{I`T}kwyw4p9McvVkcpp7u6T0GY2212~ ziF`SAuAE6t)1S-T2zH#IMjjEUn>K+OdPtytd_qvzB~U-q7`4Sk9Zg)wIg?s#zTk{! zN*5Zwj|C^Q&iEVIOtIvC5kBaS>>BEE3WaQDTzkvsice{q|9!;lw);^}Uub93dVD&a zDW!N^BgUMfI}i@J1%KQ<6A8MnM>AgLI=D#P10&Y!6>$59px!*TnPg zO62DXFDWBL#WCT!j*p$AIle*hkU)jwqdC4&@ezUJ!$)&`W8%{Sg^!P>@YCW;g117n zR#>qai5mj177w5)*qh>2fj0#o%|h43e+hdY9J!5;=1pmfnuP=k6CX`s#>CGGUV)<- zXH;B{E?w@v^8(@cM*Ob8X7SN%c2+zuxXYb~+~1;K zSNOCsfvFms1=6IJ(4-j>cM0CaXeN$|M+H)*Ke~~!__W|{3eEUwaZMmJ`lIDnY(Zi} zARQXeq;pSvUtkCLXm(H+2legcRPfQ9N>n@`kOV%uQ6^%(*~QG+Nk@LSV6jYme5zQ= zPcD7Xd)ZfMe8)A$Y`@tx!3zOR2n*uR1uq0NAuNj51uq0NA>0$+7rYSAgisd`>i6J< zfNq5FoP;BIA)pDNAigMgA)pDNDxMR(5YU9MDE?OPLO>J3vY7wV|Af%pf6Dg{ebj?e delta 1748 zcmZ{lUuaup9EN|Xt4;r;jnkUgrfa)3TLQ*qiZF}C37zbsn^h3XyjhwSb1-etd$y)FtwGkJ%CBW75TaW=-|mHS+tt zW`oMpeP%1-(67rkyzBcPj58*!>^Ix&OutHg^}vICOB#%uHFnyg_P37X2X)p)?1Z#( z(A{YoTw4#cMUoxFIvRG_BZY@W(=N@@7B|!xsm`8$J=~(dc%(*~wR6%1_;Fx}93NJ` zBwZF?+<5LMa(s*O73pQM(|w^xj&D+aO?zW6RVevk5;bV{f{ zuRgr)KVn6hi(=m=dtc@Ucy7EZ{ay?|J=8&t=Lvr1ycT-gJ^3X$p6jF19K znNV8FCMh{@Ol6d7FPJ5q|ohr;uo}G0j=iGW%XS7hvWS#On*WB8@@Tp>^ zoO3Tfk`CpaY^LlKrb~x4ocmTJ;{M+Cn7bT{xa;i$FKN{Aq<+&XSm1zQ!P!MDe!E~( zG>V{jNN|M2cs`STGw+nj=Kj)s$UPQG9#NV|Oz21^=W#o*3d)psfvQP_KYrJDy#Owuu*Z1}`vCd`Q>#N#pK|J>OM%X&9j< zT@frOQ^&KQtJ1524MUD+9qQ7Xf(=8CXTxkrH%0e1H|NOlLFHT0zl1+Syk=N6)0;XV z*kSwt&w?J64uduZIi87*O6NuMAIEQz<9T(?OP2&&o*d7PUy)uB{wsoKoVxUW@7mtp z>w(w!LXfRWf5Y$YUOYA4lWq&jp+-FASii0nJS;h$hYd^PZoL0)m2V6qpOY?tYGild zsc}iVEc`p-xnoUQ7u4IJ1n<==-4y=Q;2D2Q+NW<9Z8hk6yz;6gWL^=}!U;UJoRQ`Q zQzyqW^@{WZ!E%t}S&o|YlAr=|ythB3d_4dA-eqS><-*ij`+<)FRqunUF~V`PsPId` zQ$j+T5`GDIN=Qpbgfalse Boolean, whether to blur activate the blur for this component or not + + + "pipeline_default" + String, the name of the pipeline to use. It must exist, else "pipeline_default" will be used + + + + false + Boolean, whether to use static or dynamic blur for this component + true diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui index 452a6b6..14c9364 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui @@ -18,6 +18,57 @@ To get the best results possible, although with reduced performances, you can ch + Blur type + The dynamic blur is slower and only compatible with a gaussian blur effect, but shows content behind windows. + blur_mode_choose + + + + + center + false + + + + + center + true + mode_dynamic + + + static-mode-symbolic + Static + + + + + + + center + true + + + dynamic-mode-symbolic + Dynamic + + + + + + + + + + + + + + + + + Sigma The intensity of the blur. sigma_scale @@ -38,7 +89,7 @@ To get the best results possible, although with reduced performances, you can ch - + Brightness The brightness of the blur effect, a high value might make the text harder to read. brightness_scale @@ -131,7 +182,8 @@ This may cause some latency or performance issues. Whitelist - A list of windows to blur. + A list of windows to blur. +Use * to match any sequence of characters (e.g., Firefox* or *Code*), and ? for a single one. @@ -168,7 +220,8 @@ This may cause some latency or performance issues. Blacklist - A list of windows not to blur. + A list of windows not to blur. +Use * to match any sequence of characters (e.g., Firefox* or *Code*), and ? for a single one. @@ -220,4 +273,4 @@ This may cause some latency or performance issues. 255 1 - \ No newline at end of file + diff --git a/gnome/.local/share/gnome-shell/extensions/impatience@gfxmonk.net/metadata.json b/gnome/.local/share/gnome-shell/extensions/impatience@gfxmonk.net/metadata.json index 05f8853..4a28d70 100644 --- a/gnome/.local/share/gnome-shell/extensions/impatience@gfxmonk.net/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/impatience@gfxmonk.net/metadata.json @@ -8,9 +8,10 @@ "46", "47", "48", - "49" + "49", + "50" ], "url": "http://gfxmonk.net/dist/0install/gnome-shell-impatience.xml", "uuid": "impatience@gfxmonk.net", - "version": 29 + "version": 30 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/extension.js b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/extension.js index 727b06d..d5a5681 100644 --- a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/extension.js @@ -14,6 +14,14 @@ function getObjectLabel(name, values) { .map(([label, value]) => `${label}: '${value}'`); return `${name}(${labels.join(", ")})`; } +function safeRegexTest(pattern, value) { + try { + return new RegExp(pattern).test(value); + } + catch { + return null; + } +} function getWindowLabel(window) { return getObjectLabel("Window", { ["Title"]: window.title, @@ -46,7 +54,11 @@ export default class JunkNotificationCleaner extends Extension { this.log(LogLevel.DEBUG, `${windowLabel}: received ${event}`); const excludedApps = this.settings.get_strv("excluded-apps"); for (const wmClassPattern of excludedApps) { - if (new RegExp(wmClassPattern).test(window.wmClass)) { + const result = safeRegexTest(wmClassPattern, window.wmClass); + if (result === null) { + this.log(LogLevel.WARN, `${windowLabel}: invalid regex '${wmClassPattern}'`); + } + else if (result) { this.log(LogLevel.DEBUG, `${windowLabel}: excluded by '${wmClassPattern}'`); return; } @@ -78,9 +90,11 @@ export default class JunkNotificationCleaner extends Extension { disable() { if (this.focusListenerId !== null) { global.display.disconnect(this.focusListenerId); + this.focusListenerId = null; } if (this.closeListenerId !== null) { global.window_manager.disconnect(this.closeListenerId); + this.closeListenerId = null; } if (this.settings) { this.settings = null; diff --git a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/metadata.json b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/metadata.json index 279cd61..937c0e5 100644 --- a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/metadata.json @@ -11,5 +11,5 @@ ], "url": "https://github.com/murar8/junk-notification-cleaner", "uuid": "junk-notification-cleaner@murar8.github.com", - "version": 6 + "version": 10 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/prefs.js b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/prefs.js index 23d7ceb..4b22d05 100644 --- a/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/prefs.js +++ b/gnome/.local/share/gnome-shell/extensions/junk-notification-cleaner@murar8.github.com/prefs.js @@ -3,6 +3,15 @@ import Gio from "gi://Gio"; import Gtk from "gi://Gtk"; import { ExtensionPreferences } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js"; const LOG_LEVELS = ["debug", "info", "warn", "error"]; +function isValidRegex(pattern) { + try { + new RegExp(pattern); + return true; + } + catch { + return false; + } +} export default class JunkNotificationCleanerPreferences extends ExtensionPreferences { async fillPreferencesWindow(window) { const settings = this.getSettings(); @@ -90,24 +99,43 @@ export default class JunkNotificationCleanerPreferences extends ExtensionPrefere placeholder_text: "Enter WM Class regex (e.g. .*firefox.*)", hexpand: true, }); + const errorLabel = new Gtk.Label({ + label: "Invalid regular expression", + css_classes: ["error"], + xalign: 0, + visible: false, + }); const addButton = new Gtk.Button({ label: "Add", css_classes: ["suggested-action"], }); + entry.connect("changed", () => { + entry.remove_css_class("error"); + errorLabel.set_visible(false); + }); addButton.connect("clicked", () => { const text = entry.get_text().trim(); if (!text) return; - const currentApps = settings.get_strv("excluded-apps"); - if (currentApps.includes(text)) - return; - settings.set_strv("excluded-apps", [...currentApps, text]); - this.addExcludedAppRow(text, listBox, settings); - entry.set_text(""); + if (!isValidRegex(text)) { + entry.add_css_class("error"); + errorLabel.set_visible(true); + } + else { + entry.remove_css_class("error"); + errorLabel.set_visible(false); + const currentApps = settings.get_strv("excluded-apps"); + if (currentApps.includes(text)) + return; + settings.set_strv("excluded-apps", [...currentApps, text]); + this.addExcludedAppRow(text, listBox, settings); + entry.set_text(""); + } }); addBox.append(entry); addBox.append(addButton); excludedBox.append(addBox); + excludedBox.append(errorLabel); excludedGroup.add(excludedBox); } addExcludedAppRow(app, listBox, settings) { diff --git a/gnome/.local/share/gnome-shell/extensions/quicklaunch@comitanigiacomo.github.com/metadata.json b/gnome/.local/share/gnome-shell/extensions/quicklaunch@comitanigiacomo.github.com/metadata.json index 9655af5..f5d990a 100644 --- a/gnome/.local/share/gnome-shell/extensions/quicklaunch@comitanigiacomo.github.com/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/quicklaunch@comitanigiacomo.github.com/metadata.json @@ -9,10 +9,10 @@ "46", "47", "48", - "49" + "49", + "50" ], - "stylesheet": "stylesheet.css", "url": "https://github.com/comitanigiacomo/quicklaunch", "uuid": "quicklaunch@comitanigiacomo.github.com", - "version": 15 + "version": 16 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/locale/ru/LC_MESSAGES/gnome-shell-extension-screen-rotate.mo b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/locale/ru/LC_MESSAGES/gnome-shell-extension-screen-rotate.mo deleted file mode 100644 index 6df96773e1116a0552892d86bafa077bace59d2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4542 zcmcJRTWlOx8OIN#u@Pj1+)b!AwdOlOdLCL>_~Y+LWtRiiib)(@Bk7|NJzZ!!tXn?-b?I- zmon1&Kj)n9{{7E4{`2j({7~`S!|#*)4!%vP&wyWkJAZfzyOg>UEQ0R`$3T($3iws< zo8X7RH^JM%e}E~t>y~^y2Y!I{^WYue%iyQMRq*5Bo8WHnU*NmI+iq3r-QaHUgJ3WC z32+}Me#XJuKm&^16nr0e4wU#_1m6L^*4Y0Q_)*qt;2!Xg;N9TA!TZ5G5$*#=!H<9e z_#Ai^wDG)CsROKcgCaKx7QkhwEM>iQ>8^#2LQ;2j)(348%8gMS4L_yvl-A6x=o1OEo%TAil}Rq!S7 zFepuv{yzp%p5`Mx7JrmgeT<)QMdFoM#Ex)59_hg@ep35S@$2O$kK`hca8Vx0XY24G zkWlO+e34v*XASz=eW?fKY(BKaa;Le`c)16JhW3FTiq=|gX;3(CA8iJzdfW@lq&qdF z!$=<?N#X_7SdDnGJLMZ^EO3s8iJN#~&^jCqft_AB42EnOm}U)aci1Ch}%Ykm%E1GD8qvEWwoB*pQ&dK_0o? zE{9QM%89O|MnaN^D_&gl-8llngPsl3ATbrO;OZa@oK}2o#_*b$Anqv0A<3#;ro9xl z2F=1g=2dWy@7_mJqOip^z4~jZS3cROr#cdxGEt&uu=tIT9DE%$da!jQ=U%z};BhlI z6}nMH9o;Hw>rG31HB(V^bD|tkdS^?#)zq=JdNrdRZ}dd>9W~QQziO?Id)1lt4LNTe z+f$V%r*fB#R28<{OQpl<>DVM{VkSJT$0i<^>bL6NCww9D{&tlvvhDS6x3r*AGwWgB81cIJL`xFz^|K51|!QQ@3iIN#o9z^zk%~JvV4>mvof&96NGsv=wx5 zpwRPqE+w*pid5rcLCG2Ia8As43|Or@W+R z+)pFdcMgToY+TYo%`W5Ny$5vuI@}lBTPzF@7xjJjX?ZQ&JzOm6&(RaaSwA#9v~_fF zc%Qsljl#iVK|l3Wu7XUVADtpPL;VMO)B`%($d8}&tv`}O(-U7xQn;8+fS zn{95lXCp$+>Rrw*)fco4euLNVklR_Ti}DpMsSz&*CEJzOzJyOwcs+x{Is1NPKxN-= z2HnWzGNH_4Z7EydR;8ad!^BfZSyc8a{-q<7roNC}k$j0JTg`LLD@Eg0D2Fu2*0UoZ z$uBptLRqAI7bF2n$H4|0%eKnoY3(|gUa|+axJ!s!A~O=VrI0!j4SlzPu4DSLq)#B2 zyCf~)U>%be)DHZ}RVnToZw)n-{j5Eiol;m-*-u2A*0y~>Me!<;ozK~F)dqN-tp$DK z_3XRZGBJ}mzb4IYtgGxLY zhHSr=Oe48V(vejf+U)tZy2un*?luVepg}&A+AGe8=>Pxud<&9+yB#f+nbzLYw<7p% zKAIivS|V5@6KcUuoW{Hq);>e8y5F8xg}YkDRjx~GR~oaabHK=_Vzd5j%gv4U=_e7( z*p$J@f!va9ypc`3Fetfftw1f0w#I0Six}V&#`q9t11kHu&Eh&CUSeY443{>g)#fn2 z@%sP%pX>(TjQo?9$AF=0_>gZAv%2lmVx7u&v{}vU8e}K-RZ@_OHij<$zWrtX2mJRY vmqHT^_6STWF0*`*f8}I+TX&6r21@q((CuQ#mAQ!lG<31M13Qkk54!&Vm}U>y diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/manualOrientationMenuToggle.js b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/manualOrientationMenuToggle.js index 9266a8c..3d732e2 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/manualOrientationMenuToggle.js +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/manualOrientationMenuToggle.js @@ -80,8 +80,9 @@ class ManualOrientationMenuToggle extends QuickMenuToggle { this._section.addMenuItem(this.portraitRightItem); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - this.menu.addSettingsAction(_('Extension Settings'), - 'com.mattjakeman.ExtensionManager.desktop'); + const settingsItem = new PopupMenu.PopupMenuItem(_('Extension Settings')); + settingsItem.connect('activate', () => ext.openPreferences()); + this.menu.addMenuItem(settingsItem); this.connect('clicked', () => { if (this.checked === true) { diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json index 8304a97..91db876 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json @@ -1,6 +1,5 @@ { "_generated": "Generated by SweetTooth, do not edit", - "commit": "d22c7f03313b06b2af6b9d7becfef9f248351dc5", "description": "Enable screen rotation regardless of touch mode. Fork of Screen Autorotate by Kosmospredanie.", "donations": { "github": "shyzus" @@ -17,9 +16,10 @@ "46", "47", "48", - "49" + "49", + "50" ], "url": "https://github.com/shyzus/gnome-shell-extension-screen-autorotate", "uuid": "screen-rotate@shyzus.github.io", - "version": 28 + "version": 29 } \ No newline at end of file