This is a quick tutorial on how to send notifications in gnome shell from an extension/javascript (you can also send them over DBus but that's for another day).
Recipe
For those of you who can't wait, here is the quick way to pop up a notification:
Main.notify('notification title', 'notification summary');
The above function Main.notify
does a number of things. I'll explain them in the next section:
Longer recipe
To make notifications in gnome shell, you essentially create a Source (a source of notifications) and add it to the message tray, and then make a Notification and notify it from the source.
The basic steps shown below demonstrate this, although in practice one may wish to use various subclasses of the Source or Notification classes.
Create a subclass of
MessageTray.Source
(in GNOME 3.2 or 3.4), or aMessageTray.Source
in GNOME 3.6:// example in GNOME 3.2 and 3.4. // SystemNotificationSource subclasses MessageTray.Source let source = new MessageTray.SystemNotificationSource(); // example in GNOME 3.6 - we can use MessageTray.Source() directly let source = new MessageTray.Source('source title', 'source-icon-name');
Create a Notification, passing in the source, title, and summary:
let notification = new MessageTray.Notification(source, 'notification title', 'notification summary');
Add the source to the message tray. This is so that the icon appears in the message tray (and no notification will pop up unless its source is added):
Main.messageTray.add(source);
Either notify the notification from the source, or simply add it (without notifying):
// adds the notification to the source and pops it up source.notify(notification); // OR: // just adds the notification to the source (doesn't pop it up) source.pushNotification(notification);
The example we will work through in this post |
Explanation
Here I'll explain the two main classes: a Source
and a Notification
.
Source
Think of a Source
as a source of notifications - many notifications can come from the same source (for example many email notifications coming from your one email client).
In fact, all notifications require a source.
You can also think of a Source
as the icon in the message tray (that you click on to show its notifications).
The basic Source
class is MessageTray.Source
. To be used, it needs to know what icon to show in the Message Tray.
The Source provides the icon in the message tray. |
GNOME 3.6
In GNOME 3.6, the way to do this is to feed the icon's name into MessageTray.Source
's constructor (along with the title of the source):
let source = new MessageTray.Source("Source title", 'avatar-default');
Alternatively if you wanted something more fancy, you could override Source.createIcon(size)
in a subclass to return an icon of the appropriate size for the source.
GNOME 3.2, 3.4
In GNOME 3.2 and 3.4, you tell the Source what icon it should show in the message tray with one of two methods:
a. when you create a notification for the source, set the icon explicitly in the notification, OR
b. subclass it, implement the createNotificationIcon()
function and call _setSummaryIcon
with it in the constructor.
Method b. is the one most commonly used, but to do method a) you feed in an object as the fourth parameter to MessageTray.Notification with an 'icon' property (explained a bit more in the Notification section):
let source = new MessageTray.Source("source title");
let notification = new MessageTray.Notification(source,
"notification title",
"notification message",
{icon: new St.Icon({
icon_name: 'avatar-default',
icon_size: source.ICON_SIZE})
});
// add the source to the message tray and pop up the notification
Main.messageTray.add(source);
source.notify(notification);
The bare minimum implementation of a subclass of MessageTray.Source (to demonstrate method b.) is:
const MySource = new Lang.Class({
Name: 'MySource',
Extends: MessageTray.Source,
_init: function (title) {
// call the parent constructor
this.parent(title);
// set our icon
this._setSummaryIcon(this.createNotificationIcon());
},
// this should return an icon to show in the message tray. You can use
// this.ICON_SIZE for a default icon size if you want.
createNotificationIcon: function () {
return new St.Icon({
icon_name: 'avatar-default',
icon_size: this.ICON_SIZE
});
}
});
One would use it like so:
let source = new MySource("source title");
let notification = new MessageTray.Notification(source, "title", "message");
// add the source to the message tray and pop up the notification
Main.messageTray.add(source);
source.notify(notification);
Notification
Recall that every notification must belong to a source. Once a notification is added to its source, it can also be "notified".
When a notification is "notified", it pops up from the bottom of the screen showing the user the notification's title and the first line of its details (if they fit).
A notification upon being notified (above); the same notification being opened from its source (below). |
Hovering the mouse over the notification will expand it, showing the full summary of the notification.
Actually clicking on the notification will usually dismiss it (unless you override this behaviour).
After a while the notification will time out, dropping back down off the screen.
After this happens there are a couple of options:
- if the notification is set as "transient", it will disappear forever. Make a notification transient with
notification.setTransient(true)
. - otherwise (the default), it will now reside in the message tray. Clicking on the notification's icon in the message tray will show the notification, from which it may be dismissed (by clicking on it).
- if you want a notification to never be able to be dismissed (by clicking on it after clicking on its source in the message tray), you can set the notification to be "resident". Do this with
notification.setResident(true)
.
The base notification class is MessageTray.Notification
, and it allows the construction of very versatile notifications.
At its most basic, the notification has a text title and a text summary:
let notification = new MessageTray.Notification(source,
'notification title',
'notification message');
One can also feed in an (optional) parameters object giving the notification's icon. One typically uses an icon size of source.ICON_SIZE
(24 pixels) to create the icon:
// source is whatever Source this notification belongs to
let notification = new MessageTray.Notification(
source,
'notification title',
'notification message', {
icon: new St.Icon({
icon_name: 'avatar-default',
icon_size: source.ICON_SIZE
})
});
However, it is also possible to construct much more complex notifications. One can add buttons to the notification with notification.addButton
, add extra text labels to it with notification.addBody
, or extra actors (entry boxes, pictures, ...) to it with notification.addActor
.
For an example of a notification with buttons on it, see the Telepathy Client AudieoVideoNotification
(in telepathyClient.js
), which has two buttons for the user to accept or reject a call.
AudioVideoNotification has had buttons added |
For an example of a very complex notification, see the TelepathyClient.ChatNotification
in telepathyClient.js
. This adds chat texts to a scrollable area, and adds an entry box for typing chat messages.
ChatNotifiation is a very complex custom notification |
Bringing it all together
Code snippet - notifying a notification with the 'avatar-default' icon. This will create the notification shown below.
GNOME 3.2 and 3.4
Where we give the source icon via the notification:
// 1. Make a source
let source = new MessageTray.Source("source title");
// 2. Make a notification
let notification = new MessageTray.Notification(source,
"notification title",
"notification message",
{icon: new St.Icon({
icon_name: 'avatar-default',
icon_size: source.ICON_SIZE
})});
// 3. Add the source to the message tray
Main.messageTray.add(source);
// 4. notify!
source.notify(notification);
Where we create our own source subclass:
const MySource = new Lang.Class({
Name: 'MySource',
Extends: MessageTray.Source,
_init: function (title) {
// call the parent constructor
this.parent(title);
// set our icon
this._setSummaryIcon(this.createNotificationIcon());
},
// this should return an icon to show in the message tray. You can use
// this.ICON_SIZE for a default icon size if you want.
createNotificationIcon: function () {
return new St.Icon({
icon_name: 'avatar-default',
icon_size: this.ICON_SIZE
});
}
});
// 1. Make a source
let source = new MySource("source title");
// 2. Make a notification
let notification = new MessageTray.Notification(source,
"notification title",
"notification message");
// 3. Add the source to the message tray
Main.messageTray.add(source);
// 4. notify!
source.notify(notification);
GNOME 3.6
// 1. Make a source
let source = new MessageTray.Source("source title", 'avatar-default');
// 2. Make a notification
let notification = new MessageTray.Notification(source,
"notification title",
"notification message");
// 3. Add the source to the message tray
Main.messageTray.add(source);
// 4. notify!
source.notify(notification);