Skip to content

Commit

Permalink
Add a tray icon to the application
Browse files Browse the repository at this point in the history
This commit adds a tray icon to the application, shown in the system
tray bar, that can be used to minimise the application window.  This
is a common feature on most desktop messaging apps (e.g. Telegram
Desktop or Slack) and allows to save space in the system task bar.

The tray icon provides a context menu that contains a button to
show/hide the application window, and a button to quit the
application. When the tray icon is clicked, the visibility of the
window is toggled.  When the close (x) button of the window is
pressed, the application is not terminated but minimised to the tray
icon instead (it can be terminated by using the "Quit" entry in the
File menu or in the context menu of the tray icon).

The tray icon is disabled by default, and two command line arguments
are available to enable it:
  --use-tray-icon: enables the tray icon
  --start-in-tray: enables the tray icon and the application starts
                   minimised in the tray bar

Resolves: signalapp#1480
  • Loading branch information
m-pilia committed Nov 23, 2017
1 parent 17f0bb4 commit 141eaef
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 1 deletion.
12 changes: 12 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,18 @@
"message": "Show",
"description": "Command under Window menu, to show the window"
},
"hide": {
"message": "Hide",
"description": "Command in the tray icon menu, to hide the window"
},
"quit": {
"message": "Quit",
"description": "Command in the tray icon menu, to quit the application"
},
"trayTooltip": {
"message": "Signal Desktop",
"description": "Tooltip for the tray icon"
},
"searchForPeopleOrGroups": {
"message": "Search...",
"description": "Placeholder text in the search input"
Expand Down
70 changes: 70 additions & 0 deletions app/tray_icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const electron = require('electron')
const path = require('path');

const app = electron.app;
const Menu = electron.Menu;
const Tray = electron.Tray;

let trayContextMenu = null;
let tray = null;

function createTrayIcon(getMainWindow, messages) {

// A smaller icon is needed on macOS
tray = new Tray(
process.platform == "darwin" ?
path.join(__dirname, '..', 'images', 'icon_16.png') :
path.join(__dirname, '..', 'images', 'icon_256.png'));

tray.toggleWindowVisibility = function () {
var mainWindow = getMainWindow();
if (mainWindow) {
if (mainWindow.isVisible()) {
mainWindow.hide();
} else {
mainWindow.show();

// On some versions of GNOME the window may not be on top when restored.
// This trick should fix it.
// Thanks to: https://github.com/Enrico204/Whatsapp-Desktop/commit/6b0dc86b64e481b455f8fce9b4d797e86d000dc1
mainWindow.setAlwaysOnTop(true);
mainWindow.focus();
mainWindow.setAlwaysOnTop(false);
}
}
tray.updateContextMenu();
}

tray.updateContextMenu = function () {

var mainWindow = getMainWindow();

// NOTE: we want to have the show/hide entry available in the tray icon
// context menu, since the 'click' event may not work on all platforms.
// For details please refer to:
// https://github.com/electron/electron/blob/master/docs/api/tray.md.
trayContextMenu = Menu.buildFromTemplate([
{
id: 'toggleWindowVisibility',
label: messages[mainWindow.isVisible() ? 'hide' : 'show'].message,
click: tray.toggleWindowVisibility
},
{
id: 'quit',
label: messages.quit.message,
click: app.quit.bind(app)
}
]);

tray.setContextMenu(trayContextMenu);
}

tray.on('click', tray.toggleWindowVisibility);

tray.setToolTip(messages.trayTooltip.message);
tray.updateContextMenu();

return tray;
}

module.exports = createTrayIcon;
31 changes: 30 additions & 1 deletion main.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ function getMainWindow() {
return mainWindow;
}

// Tray icon and related objects
let tray = null;
const startInTray = process.argv.find(arg => arg === '--start-in-tray');
const usingTrayIcon = startInTray || process.argv.find(arg => arg === '--use-tray-icon');

const config = require("./app/config");

// Very important to put before the single instance check, since it is based on the
Expand Down Expand Up @@ -107,6 +112,7 @@ function captureClicks(window) {

function createWindow () {
const windowOptions = Object.assign({
show: !startInTray, // allow to start minimised in tray
width: 800,
height: 610,
minWidth: 700,
Expand Down Expand Up @@ -187,9 +193,22 @@ function createWindow () {

// Emitted when the window is about to be closed.
mainWindow.on('close', function (e) {
if (process.platform === 'darwin' && !windowState.shouldQuit() && config.environment !== 'test') {

// If the application is terminating, just do the default
if (windowState.shouldQuit() || config.environment === 'test') {
return;
}

// On Mac, or on other platforms when the tray icon is in use, the window
// should be only hidden, not closed, when the user clicks the close button
if (usingTrayIcon || process.platform === 'darwin') {
e.preventDefault();
mainWindow.hide();

// toggle the visibility of the show/hide tray icon menu entries
if (tray) {
tray.updateContextMenu();
}
}
});

Expand All @@ -211,6 +230,11 @@ function createWindow () {
} else {
mainWindow.show();
}

// toggle the visibility of the show/hide tray icon menu entries
if (tray) {
tray.updateContextMenu();
}
});
}

Expand Down Expand Up @@ -296,6 +320,11 @@ app.on('ready', function() {

createWindow();

if (usingTrayIcon) {
const createTrayIcon = require("./app/tray_icon");
tray = createTrayIcon(getMainWindow, locale.messages);
}

const options = {
showDebugLog,
showWindow,
Expand Down

0 comments on commit 141eaef

Please sign in to comment.