diff --git a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml index fc3243a..6eba5d2 100644 --- a/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +++ b/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml @@ -363,9 +363,13 @@ false - Intellihide pressure + Allow revealing the panel while in fullscreen Allow the panel to be revealed while an application is in fullscreen mode + + false + Reveal the panel on notification + false Intellihide only secondary diff --git a/src/appIcons.js b/src/appIcons.js index 00cd8dd..592c90c 100644 --- a/src/appIcons.js +++ b/src/appIcons.js @@ -40,6 +40,7 @@ import * as Util from 'resource:///org/gnome/shell/misc/util.js' import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js' import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js' +import { Hold } from './intellihide.js' import * as Utils from './utils.js' import * as Taskbar from './taskbar.js' import { @@ -224,7 +225,10 @@ export const TaskbarAppIcon = GObject.registerClass( [ this, 'notify::mapped', - () => (this.mapped ? this._handleNotifications() : null), + () => + this.mapped && !this.dtpPanel.intellihide.enabled + ? this._handleNotifications() + : null, ], [ Utils.getStageTheme(), @@ -1614,7 +1618,10 @@ export const TaskbarAppIcon = GObject.registerClass( 'dance', ) - if (state.total) count = state.total > 9 ? '9+' : state.total + if (state.total) { + count = state.total > 9 ? '9+' : state.total + this.dtpPanel.intellihide.revealAndHold(Hold.NOTIFY) + } else this.dtpPanel.intellihide.release(Hold.NOTIFY) } this._notificationsCount = count diff --git a/src/intellihide.js b/src/intellihide.js index 0790e61..557b1d7 100644 --- a/src/intellihide.js +++ b/src/intellihide.js @@ -50,6 +50,7 @@ export const Hold = { NONE: 0, TEMPORARY: 1, PERMANENT: 2, + NOTIFY: 4, } export const Intellihide = class { @@ -59,6 +60,7 @@ export const Intellihide = class { this._panelManager = dtpPanel.panelManager this._proximityManager = this._panelManager.proximityManager this._holdStatus = Hold.NONE + this._holdCount = {} this._signalsHandler = new Utils.GlobalSignalsHandler() this._timeoutsHandler = new Utils.TimeoutsHandler() @@ -129,6 +131,8 @@ export const Intellihide = class { } disable(reset) { + this.enabled = false + if (this._proximityWatchId) { this._proximityManager.removeWatch(this._proximityWatchId) } @@ -141,8 +145,6 @@ export const Intellihide = class { this._removeRevealMechanism() this._revealPanel(!reset) - - this.enabled = false } destroy() { @@ -161,18 +163,35 @@ export const Intellihide = class { } revealAndHold(holdStatus) { - if (this.enabled && !this._holdStatus) { - this._revealPanel() - } + if ( + !this.enabled || + (holdStatus == Hold.NOTIFY && + !SETTINGS.get_boolean('intellihide-show-on-notification')) + ) + return + + if (!this._holdStatus) this._revealPanel() this._holdStatus |= holdStatus + this._holdCount[holdStatus] = (this._holdCount[holdStatus] || 0) + 1 + this._maybePersistHoldStatus() } release(holdStatus) { - this._holdStatus -= holdStatus + if (!this.enabled) return - if (this.enabled && !this._holdStatus) { + if (this._holdStatus & holdStatus && !--this._holdCount[holdStatus]) + this._holdStatus -= holdStatus + + if (holdStatus == Hold.PERMANENT && this._holdStatus & Hold.NOTIFY) { + // the user pressed the keyboard shortcut to hide the panel while a + // notification hold is present, clear it to hide the panel + this._holdStatus -= Hold.NOTIFY + this._holdCount[Hold.NOTIFY] = 0 + } + + if (!this._holdStatus) { this._maybePersistHoldStatus() this._queueUpdatePanelPosition() } diff --git a/src/notificationsMonitor.js b/src/notificationsMonitor.js index 44c5402..b805aad 100644 --- a/src/notificationsMonitor.js +++ b/src/notificationsMonitor.js @@ -58,9 +58,11 @@ export const NotificationsMonitor = class extends EventEmitter { tracker, 'notify::focus-app', () => { + let appId = tracker.focus_app?.id + // reset notifications from message tray on app focus - if (tracker.focus_app) - this._updateState(tracker.focus_app.id, { trayCount: 0 }, true) + if (tracker.focus_app && this._state[appId]) + this._updateState(tracker.focus_app.id, this._getDefaultState(), true) }, ]) this._acquireUnityDBus() @@ -90,10 +92,13 @@ export const NotificationsMonitor = class extends EventEmitter { ) || appId appId = `${appId}.desktop` - this._state[appId] = this._state[appId] || {} - this._mergeState(appId, state) + this._state[appId] = this._state[appId] || this._getDefaultState() - this.emit(`update-${appId}`) + if (this._mergeState(appId, state)) this.emit(`update-${appId}`) + } + + _getDefaultState() { + return { trayCount: 0, trayUrgent: false, urgent: false, total: 0 } } getState(app) { @@ -101,6 +106,8 @@ export const NotificationsMonitor = class extends EventEmitter { } _mergeState(appId, state) { + let currenState = JSON.stringify(this._state[appId]) + this._state[appId] = Object.assign(this._state[appId], state) if (tracker.focus_app?.id == appId) this._state[appId].trayCount = 0 @@ -113,6 +120,8 @@ export const NotificationsMonitor = class extends EventEmitter { this._state[appId].total = ((this._state[appId]['count-visible'] || 0) && (this._state[appId].count || 0)) + (this._state[appId].trayCount || 0) + + return currenState != JSON.stringify(this._state[appId]) } _acquireUnityDBus() { diff --git a/src/panelManager.js b/src/panelManager.js index db60755..ce1a772 100755 --- a/src/panelManager.js +++ b/src/panelManager.js @@ -803,6 +803,22 @@ export const IconAnimator = class { } addAnimation(target, name) { + // before adding a new animation, remove previous one to only have one running + let animationNames = Object.keys(this._animations) + + for (let i = 0; i < animationNames.length; ++i) { + let n = animationNames[i] + let currentAnimationPair = this._animations[n].find( + (p) => p.target == target, + ) + + if (currentAnimationPair) { + if (n == name) return // already have this animation running, nothing else to do + + this.removeAnimation(currentAnimationPair.target, n) + } + } + const targetDestroyId = target.connect('destroy', () => this.removeAnimation(target, name), ) diff --git a/src/prefs.js b/src/prefs.js index f98d01c..9a5771b 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -1695,6 +1695,13 @@ const Preferences = class { ) }) + this._settings.bind( + 'intellihide-show-on-notification', + this._builder.get_object('intellihide_show_on_notification_switch'), + 'active', + Gio.SettingsBindFlags.DEFAULT, + ) + this._builder .get_object('intellihide_animation_time_spinbutton') .set_value(this._settings.get_int('intellihide-animation-time')) @@ -1751,6 +1758,16 @@ const Preferences = class { 'intellihide-show-in-fullscreen', ), ) + this._settings.set_value( + 'intellihide-show-on-notification', + this._settings.get_default_value( + 'intellihide-show-on-notification', + ), + ) + this._settings.set_value( + 'intellihide-persisted-state', + this._settings.get_default_value('intellihide-persisted-state'), + ) this._settings.set_value( 'intellihide-only-secondary', this._settings.get_default_value('intellihide-only-secondary'), diff --git a/ui/BoxIntellihideOptions.ui b/ui/BoxIntellihideOptions.ui index a141604..9ea6037 100644 --- a/ui/BoxIntellihideOptions.ui +++ b/ui/BoxIntellihideOptions.ui @@ -157,6 +157,17 @@ + + + (requires show notification counter badge option) + Reveal and hold the panel on notification + + + center + + + +