From 4576a5080c51918907c89629cefe389945179d71 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 17 May 2020 15:17:07 +0200 Subject: Make Tray icons more robust on Linux (#748) --- src/lib/DBus.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/Tray.js | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/lib/DBus.js (limited to 'src/lib') diff --git a/src/lib/DBus.js b/src/lib/DBus.js new file mode 100644 index 000000000..957912efa --- /dev/null +++ b/src/lib/DBus.js @@ -0,0 +1,49 @@ +import { + sessionBus, +} from 'dbus-next'; +import { + isLinux, +} from '../environment'; + +export default class DBus { + bus = null; + + constructor(trayIcon) { + this.trayIcon = trayIcon; + } + + start() { + if (!isLinux || this.bus) return; + + try { + this.bus = sessionBus(); + } catch { + // Error connecting to the bus. + return; + } + + // HACK Hook onto the MessageBus to track StatusNotifierWatchers + this.bus._addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',path='/org/freedesktop/DBus',member='NameOwnerChanged'"); + const mangled = JSON.stringify({ + path: '/org/freedesktop/DBus', + interface: 'org.freedesktop.DBus', + member: 'NameOwnerChanged', + }); + this.bus._signals.on(mangled, (msg) => { + const [name, oldOwner, newOwner] = msg.body; + if (name === 'org.kde.StatusNotifierWatcher' && oldOwner !== newOwner && newOwner !== '') { + // Leave ample time for the StatusNotifierWatcher to be initialized + setTimeout(() => { + this.trayIcon.recreateIfVisible(); + }, 400); + } + }); + } + + stop() { + if (!this.bus) return; + + this.bus.disconnect(); + this.bus = null; + } +} diff --git a/src/lib/Tray.js b/src/lib/Tray.js index 0afb6289b..c6d9db004 100644 --- a/src/lib/Tray.js +++ b/src/lib/Tray.js @@ -22,6 +22,8 @@ export default class TrayIcon { trayMenu = null; + visible = false; + trayMenuTemplate = [ { label: 'Show Ferdi', @@ -50,7 +52,19 @@ export default class TrayIcon { }, ]; + constructor() { + ipcMain.on('initialAppSettings', (event, appSettings) => { + this._updateTrayMenu(appSettings); + }); + + ipcMain.on('updateAppSettings', (event, appSettings) => { + this._updateTrayMenu(appSettings); + }); + } + _updateTrayMenu(appSettings) { + if (!this.trayIcon) return; + if (appSettings.type === 'app') { const { isAppMuted } = appSettings.data; this.trayMenuTemplate[1].label = isAppMuted ? 'Enable Notifications && Audio' : 'Disable Notifications && Audio'; @@ -62,6 +76,11 @@ export default class TrayIcon { } show() { + this.visible = true; + this._show(); + } + + _show() { if (this.trayIcon) return; this.trayIcon = new Tray(this._getAsset('tray', INDICATOR_TRAY_PLAIN)); @@ -73,14 +92,6 @@ export default class TrayIcon { this.trayIcon.setContextMenu(this.trayMenu); } - ipcMain.on('initialAppSettings', (event, appSettings) => { - this._updateTrayMenu(appSettings); - }); - - ipcMain.on('updateAppSettings', (event, appSettings) => { - this._updateTrayMenu(appSettings); - }); - this.trayIcon.on('click', () => { if (app.mainWindow.isMinimized()) { app.mainWindow.restore(); @@ -106,6 +117,11 @@ export default class TrayIcon { } hide() { + this.visible = false; + this._hide(); + } + + _hide() { if (!this.trayIcon) return; this.trayIcon.destroy(); @@ -117,6 +133,17 @@ export default class TrayIcon { } } + recreateIfVisible() { + if (this.visible) { + this._hide(); + setTimeout(() => { + if (this.visible) { + this._show(); + } + }, 100); + } + } + setIndicator(indicator) { this.indicator = indicator; this._refreshIcon(); -- cgit v1.2.3-70-g09d2