Skip to content

Commit

Permalink
Add simple message tray notifications handling
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesg99 committed Feb 9, 2025
1 parent a08805d commit fa92d91
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 1,030 deletions.
491 changes: 211 additions & 280 deletions src/appIcons.js

Large diffs are not rendered by default.

159 changes: 159 additions & 0 deletions src/notificationsMonitor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* This file is part of the Dash-To-Panel extension for Gnome 3
*
* 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, see <http://www.gnu.org/licenses/>.
*/

import Gio from 'gi://Gio'
import Shell from 'gi://Shell'

import * as Main from 'resource:///org/gnome/shell/ui/main.js'
import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'
import { EventEmitter } from 'resource:///org/gnome/shell/misc/signals.js'

import * as Utils from './utils.js'

const tracker = Shell.WindowTracker.get_default()
const knownCorrespondances = {
'org.gnome.Evolution': [/^org\.gnome\.[eE]volution([.-].+)?$/g],
}

export const NotificationsMonitor = class extends EventEmitter {
constructor() {
super()

this._signalsHandler = new Utils.GlobalSignalsHandler()

// pretty much useless, but might as well keep it for now
this._launcherEntryId = Gio.DBus.session.signal_subscribe(
null, // sender
'com.canonical.Unity.LauncherEntry', // iface
'Update', // member
null, // path
null, // arg0
Gio.DBusSignalFlags.NONE,
(
connection,
senderName,
objectPath,
interfaceName,
signalName,
parameters,
) => this._handleLauncherUpdate(senderName, parameters),
)

this._signalsHandler.add([
tracker,
'notify::focus-app',
() => {
// reset notifications from message tray on app focus
if (tracker.focus_app)
this.dispatch(tracker.focus_app.id, { trayCount: 0 }, true)
},
])
this._acquireUnityDBus()

this._checkNotifications()
}

destroy() {
if (this._launcherEntryId)
Gio.DBus.session.signal_unsubscribe(this._launcherEntryId)

this._releaseUnityDBus()
this._signalsHandler.destroy()
}

dispatch(appId, state, ignoreMapping) {
// depending of the notification source, some app id end
// with ".desktop" and some don't ¯\_(ツ)_/¯
appId = appId.replace('.desktop', '')

// some app have different source app id, deamon and such,
// but it maps to a desktop app so match those here
if (!ignoreMapping && !knownCorrespondances[appId])
appId =
Object.keys(knownCorrespondances).find((k) =>
knownCorrespondances[k].some((regex) => appId.match(regex)),
) || appId

this.emit(`update-${appId}.desktop`, state)
}

_acquireUnityDBus() {
if (!this._unityBusId) {
this._unityBusId = Gio.DBus.session.own_name(
'com.canonical.Unity',
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT,
null,
null,
)
}
}

_releaseUnityDBus() {
if (this._unityBusId) {
Gio.DBus.session.unown_name(this._unityBusId)
this._unityBusId = 0
}
}

_handleLauncherUpdate(senderName, parameters) {
if (!senderName || !parameters) return

let [appUri, properties] = parameters.deep_unpack()
let appId = appUri.replace(/(^\w+:|^)\/\//, '')
let updates = {}

// https://wiki.ubuntu.com/Unity/LauncherAPI#Low_level_DBus_API:_com.canonical.Unity.LauncherEntry
for (let property in properties)
updates[property] = properties[property].unpack()

this.dispatch(appId, updates)
}

_checkNotifications() {
let addSource = (tray, source) => {
let appId = source?._appId || source?.app?.id

if (!appId) return

this._signalsHandler.addWithLabel(appId, [
source,
'notify::count',
() =>
this.dispatch(appId, {
trayCount: source.count, // source.unseenCount might be less annoying
urgent: !source.notifications.find(
(n) => n.urgency > MessageTray.Urgency.NORMAL,
),
}),
])
}

this._signalsHandler.add(
[Main.messageTray, 'source-added', addSource],
[
Main.messageTray,
'source-removed',
(tray, source) => {
if (source?._appId)
this._signalsHandler.removeWithLabel(source._appId)
},
],
)

Main.messageTray.getSources().forEach((s) => addSource(null, s))
}
}
12 changes: 6 additions & 6 deletions src/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ export const Overview = class {
this._hotKeysEnabled = true

if (SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS')
this.taskbar.toggleNumberOverlay(true)
this.taskbar.toggleHotkeysNumberOverlay(true)
}

_disableHotKeys() {
Expand Down Expand Up @@ -418,7 +418,7 @@ export const Overview = class {

this._hotKeysEnabled = false

this.taskbar.toggleNumberOverlay(false)
this.taskbar.toggleHotkeysNumberOverlay(false)
}

_optionalNumberOverlay() {
Expand All @@ -435,8 +435,8 @@ export const Overview = class {
SETTINGS.get_boolean('hot-keys') &&
SETTINGS.get_string('hotkeys-overlay-combo') === 'ALWAYS'
)
this.taskbar.toggleNumberOverlay(true)
else this.taskbar.toggleNumberOverlay(false)
this.taskbar.toggleHotkeysNumberOverlay(true)
else this.taskbar.toggleHotkeysNumberOverlay(false)
},
],
[SETTINGS, 'changed::shortcut-num-keys', () => this._resetHotkeys()],
Expand Down Expand Up @@ -468,7 +468,7 @@ export const Overview = class {
if (hotkey_option === 'NEVER') return

if (hotkey_option === 'TEMPORARILY' || overlayFromShortcut)
this.taskbar.toggleNumberOverlay(true)
this.taskbar.toggleHotkeysNumberOverlay(true)

this._panel.intellihide.revealAndHold(Intellihide.Hold.TEMPORARY)

Expand All @@ -484,7 +484,7 @@ export const Overview = class {
timeout,
() => {
if (hotkey_option != 'ALWAYS') {
this.taskbar.toggleNumberOverlay(false)
this.taskbar.toggleHotkeysNumberOverlay(false)
}

this._panel.intellihide.release(Intellihide.Hold.TEMPORARY)
Expand Down
28 changes: 0 additions & 28 deletions src/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import Shell from 'gi://Shell'
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'
import * as DateMenu from 'resource:///org/gnome/shell/ui/dateMenu.js'
import * as Volume from 'resource:///org/gnome/shell/ui/status/volume.js'
import * as Progress from './progress.js'

import * as Intellihide from './intellihide.js'
import * as Transparency from './transparency.js'
Expand Down Expand Up @@ -359,8 +358,6 @@ export const Panel = GObject.registerClass(
// most repaint requests don't actually require us to repaint anything.
// This saves significant CPU when repainting the screen.
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS)

this._initProgressManager()
}

disable() {
Expand All @@ -377,8 +374,6 @@ export const Panel = GObject.registerClass(

this.dynamicTransparency.destroy()

this.progressManager.destroy()

this.taskbar.destroy()
this.showAppsIconWrapper.destroy()

Expand Down Expand Up @@ -610,16 +605,6 @@ export const Panel = GObject.registerClass(
}
},
],
[
SETTINGS,
'changed::progress-show-bar',
() => this._initProgressManager(),
],
[
SETTINGS,
'changed::progress-show-count',
() => this._initProgressManager(),
],
)

if (isVertical) {
Expand Down Expand Up @@ -1494,19 +1479,6 @@ export const Panel = GObject.registerClass(
ignoredConstr.indexOf(source.constructor.name) >= 0
)
}

_initProgressManager() {
const progressVisible = SETTINGS.get_boolean('progress-show-bar')
const countVisible = SETTINGS.get_boolean('progress-show-count')
const pm = this.progressManager

if (!pm && (progressVisible || countVisible))
this.progressManager = new Progress.ProgressManager()
else if (pm)
Object.keys(pm._entriesByDBusName).forEach((k) =>
pm._entriesByDBusName[k].setCountVisible(countVisible),
)
}
},
)

Expand Down
8 changes: 8 additions & 0 deletions src/panelManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'
import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js'
import * as Main from 'resource:///org/gnome/shell/ui/main.js'
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'
import { NotificationsMonitor } from './notificationsMonitor.js'
import * as Layout from 'resource:///org/gnome/shell/ui/layout.js'
import { InjectionManager } from 'resource:///org/gnome/shell/extensions/extension.js'
import { SETTINGS } from './extension.js'
Expand Down Expand Up @@ -133,6 +134,8 @@ export const PanelManager = class {

if (reset) return

this.notificationsMonitor = new NotificationsMonitor()

this._desktopIconsUsableArea =
new DesktopIconsIntegration.DesktopIconsUsableAreaClass()

Expand Down Expand Up @@ -337,6 +340,8 @@ export const PanelManager = class {

this._setKeyBindings(false)

this.notificationsMonitor.destroy()

this._signalsHandler.destroy()

Main.layoutManager._updateHotCorners = this._oldUpdateHotCorners
Expand Down Expand Up @@ -716,6 +721,9 @@ export const IconAnimator = class {
if (this._started && this._count === 0) {
this._timeline.stop()
}

if (name == 'dance') target.rotation_angle_z = 0

return
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,18 +255,18 @@ const Preferences = class {
this._setMonitorsInfo()
},
)

let maybeGoToPage = () => {
let targetPageName = settings.get_string('target-prefs-page')

if (targetPageName) {
window.set_visible_page_name(targetPageName)
settings.set_string('target-prefs-page', '')
}
}

settings.connect('changed::target-prefs-page', maybeGoToPage)

maybeGoToPage()
})
}
Expand Down
Loading

0 comments on commit fa92d91

Please sign in to comment.