Jump to content

# Desktop notifications

1 language

- 日本語

From ArchWiki

Related articles

- GTK
- Libcanberra

Desktop notifications are small, passive popup dialogs that notify the user of particular events in an asynchronous manner.

## Libnotify

Libnotify is an implementation of the Desktop Notifications Specification which provides support for GTK and Qt applications and is desktop independent: it is already used by many open source applications like Evolution and Pidgin. Libnotify can be installed with the libnotify package.

In order to use libnotify, you have to install a notification server.

## Notification servers

### Built-in

Cinnamon, Deepin, Enlightenment, GNOME, GNOME Flashback and KDE Plasma use their own implementations to display notifications, and it cannot be replaced. Their notification servers are started automatically on login to receive notifications from applications via DBus.

### Standalone

In other desktop environments, the notification server needs to be launched using an autostarting option.

Alternatively, making the notification server as a D-Bus service, the notification server can be launched automatically on the first call to it. For example, after installing the notification-daemon package, add the following configuration to D-Bus services directory (`/usr/share/dbus-1/services` or `$XDG_DATA_HOME/dbus-1/services`):

    org.freedesktop.Notifications.service

    [D-BUS Service]
    Name=org.freedesktop.Notifications
    Exec=/usr/lib/notification-daemon-1.0/notification-daemon

Whenever an application sends a notification by sending a signal to `org.freedesktop.Notifications`, D-Bus activates `/usr/lib/notification-daemon-1.0/notification-daemon` if it has not already been activated.

You can also choose one of the following implementations:

- Deadd Notification Center — A notification-daemon with notification center inspired by Dunst.

  https://github.com/phuhl/linux_notification_center || deadd-notification-centerAUR

- Dunst — Minimalist notification daemon for Linux designed to fit nicely into minimalist window managers like dwm. Includes Wayland support since 1.6.

  https://dunst-project.org/ || dunst

- fnott — Keyboard driven and lightweight Wayland notification daemon for wlroots-based compositors.

  https://codeberg.org/dnkl/fnott || fnott

- LXQt Notification Daemon — Notification server for LXQt.

  https://github.com/lxde/lxqt-notificationd || lxqt-notificationd

- mako — A lightweight notification daemon for Wayland; it currently works on Sway and river.

  https://github.com/emersion/mako || mako

- MATE Notification Daemon — Notification server for MATE.

  https://github.com/mate-desktop/mate-notification-daemon/ || mate-notification-daemon

- Notification Daemon — The original notification server.

  https://gitlab.gnome.org/Archive/notification-daemon || notification-daemon
  You can run it manually using `/usr/lib/notification-daemon-1.0/notification-daemon`.

- Notify OSD — Notification server for Unity.

  https://launchpad.net/notify-osd || notify-osd

- sandsmark-notificationd — Minimalistic notification-daemon with muting support.

  https://github.com/sandsmark/sandsmark-notificationd || sandsmark-notificationd-gitAUR[broken link: package not found]

- statnot — Small, lightweight notification daemon that can output notifications to the root window's title, stdout or FIFO pipes, making it integrate very well with tiling window managers.

  https://github.com/halhen/statnot || statnotAUR

- swaync — A simple GTK based notification daemon for Sway.

  https://github.com/ErikReider/SwayNotificationCenter || swaync

- twmn — Notification system for tiling window managers.

  https://github.com/sboli/twmn || twmn-gitAUR

- wired — Lightweight notification daemon with highly customizable layout blocks, written in Rust.

  https://github.com/Toqozz/wired-notify || wiredAUR

- Xfce Notification Daemon — Notification server for Xfce.

  https://docs.xfce.org/apps/notifyd/start || xfce4-notifyd
  You can run it manually using `/usr/lib/xfce4/notifyd/xfce4-notifyd`.
  Tip: To configure xfce4-notifyd, run the following command: `xfce4-notifyd-config`.

## Usage in programming

You can write your own libnotify display messages easily in many programming languages through GObject-Introspection or bindings, or you can simply use bash.

The following examples display a simple "Hello world" notification.

### Bash

- Dependency: libnotify

    hello_world.sh

    #!/bin/bash
    notify-send 'Hello world!' 'This is an example notification.' --icon=dialog-information

Tip:

- An overview on the available icons can be found here.
- To send desktop notification from a background script running as root (replace `X_user` and `X_userid` with the user and userid running X respectively):

      # sudo -u X_user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/X_userid/bus notify-send 'Hello world!' 'This is an example notification.'

- Dependency: glib2

    hello_world.sh

    #!/bin/bash
    gdbus call --session \
        --dest=org.freedesktop.Notifications \
        --object-path=/org/freedesktop/Notifications \
        --method=org.freedesktop.Notifications.Notify \
        "" 0 "" 'Hello world!' 'This is an example notification.' \
        '[]' '{"urgency": <1>}' 5000

Tip:

- See org.freedesktop.Notifications.Notify for more details about the D-Bus interface.
- `dbus-send`, though being similar to `gdbus`, does not work because one of the arguments in the method `org.freedesktop.Notifications.Notify` requires data type `variant`, which is not supported by `dbus-send`.

### C

- Dependency: glib2
- Build with: `gcc -o hello_world `pkg-config --cflags --libs gio-2.0` hello_world.c`

    hello_world.c

    #include <gio/gio.h>
    int main() {
    	GApplication *application = g_application_new ("hello.world", G_APPLICATION_FLAGS_NONE);
    	g_application_register (application, NULL, NULL);
    	GNotification *notification = g_notification_new ("Hello world!");
    	g_notification_set_body (notification, "This is an example notification.");
    	GIcon *icon = g_themed_icon_new ("dialog-information");
    	g_notification_set_icon (notification, icon);
    	g_application_send_notification (application, NULL, notification);
    	g_object_unref (icon);
    	g_object_unref (notification);
    	g_object_unref (application);
    	return 0;
    }

- Dependency: libnotify
- Build with: `gcc -o hello_world `pkg-config --cflags --libs libnotify` hello_world.c`

    hello_world.c

    #include <libnotify/notify.h>
    int main() {
    	notify_init ("Hello world!");
    	NotifyNotification * Hello = notify_notification_new ("Hello world", "This is an example notification.", "dialog-information");
    	notify_notification_show (Hello, NULL);
    	g_object_unref(G_OBJECT(Hello));
    	notify_uninit();
    	return 0;
    }

- Dependency: dbus
- Build with: `gcc -o hello_world $(pkg-config --cflags --libs dbus-1) hello_world.c`

    hello_world.c

    #include <dbus-1.0/dbus/dbus.h>
    int main()
    {
    	DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, 0);
    	DBusMessage *message = dbus_message_new_method_call(
    		"org.freedesktop.Notifications",
    		"/org/freedesktop/Notifications",
    		"org.freedesktop.Notifications",
    		"Notify");
    	DBusMessageIter iter[4];
    	dbus_message_iter_init_append(message, iter);
    	char *application = "hello.world";
    	dbus_message_iter_append_basic(iter, 's', &application);
    	unsigned id = 0;
    	dbus_message_iter_append_basic(iter, 'u', &id);
    	char *icon = "dialog-information";
    	dbus_message_iter_append_basic(iter, 's', &icon);
    	char *summary = "Hello world!";
    	dbus_message_iter_append_basic(iter, 's', &summary);
    	char *body = "This is an example notification.";
    	dbus_message_iter_append_basic(iter, 's', &body);
    	dbus_message_iter_open_container(iter, 'a', "s", iter + 1);
    	dbus_message_iter_close_container(iter, iter + 1);
    	dbus_message_iter_open_container(iter, 'a', "{sv}", iter + 1);
    	dbus_message_iter_open_container(iter + 1, 'e', 0, iter + 2);
    	char *urgency = "urgency";
    	dbus_message_iter_append_basic(iter + 2, 's', &urgency);
    	dbus_message_iter_open_container(iter + 2, 'v', "y", iter + 3);
    	enum {LOW, NORMAL, CRITICAL};
    	unsigned char level = LOW;
    	dbus_message_iter_append_basic(iter + 3, 'y', &level);
    	dbus_message_iter_close_container(iter + 2, iter + 3);
    	dbus_message_iter_close_container(iter + 1, iter + 2);
    	dbus_message_iter_close_container(iter, iter + 1);
    	int timeout = 5 * 1000;
    	dbus_message_iter_append_basic(iter, 'i', &timeout);
    	dbus_connection_send(connection, message, 0);
    	dbus_connection_flush(connection);
    	dbus_message_unref(message);
    	dbus_connection_unref(connection);
    }

### C++

- Dependency: glibmm
- Build with: `g++ -o hello_world `pkg-config --cflags --libs giomm-2.4` hello_world.cc`

    hello_world.cc

    #include <giomm-2.4/giomm.h>
    int main(int argc, char *argv[]) {
    	auto Application = Gio::Application::create("hello.world", Gio::APPLICATION_FLAGS_NONE);
    	Application->register_application();
    	auto Notification = Gio::Notification::create("Hello world");
    	Notification->set_body("This is an example notification.");
    	auto Icon = Gio::ThemedIcon::create("dialog-information");
    	Notification->set_icon (Icon);
    	Application->send_notification(Notification);
    	return 0;
    }

- Dependency: libnotifymmAUR[broken link: package not found]
- Build with: `g++ -o hello_world `pkg-config --cflags --libs libnotifymm-1.0` hello_world.cc`

    hello_world.cc

    #include <libnotifymm.h>
    int main(int argc, char *argv[]) {
    	Notify::init("Hello world!");
    	Notify::Notification Hello("Hello world", "This is an example notification.", "dialog-information");
    	Hello.show();
    	return 0;
    }

### C#

- Dependency: notify-sharp-3AUR
- Build with: `mcs -pkg:notify-sharp-3.0 hello_world.cs`
- Run with: `mono hello_world.exe`

    hello_world.cs

    using Notifications;
    public class HelloWorld {
    	static void Main() {
    		var Hello = new Notification();
    		Hello.Summary  = "Hello world!";
    		Hello.Body     = "This is an example notification.";
    		Hello.IconName = "dialog-information";
    		Hello.Show();
    	}
    }

### Common Lisp

- Dependency: dbus, death/dbus (from quicklisp)

    hello_world.lisp

    (defun hello ()
      "send notification with dbus"
      (let ((app_name "hello.world")
            (replaces_id 0)
            (app_icon "dialog-information")
            (summary "hello.world")
            (body "Hello world!")
            (expire_timeout -1))
        (dbus:with-open-bus (bus (dbus:session-server-addresses))
          (dbus:with-introspected-object
              (notif bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
            (notif "org.freedesktop.Notifications" "Notify"
                   app_name replaces_id app_icon summary body '() '() expire_timeout)))))

    (hello)

### Crystal

- Dependency: woodruffw/notify.cr (from shards)
- Build with: shards build

    hello_world.fs

    require "notify"
    notifier = Notify.new
    notifier.notify "Hello", body: "World!"

### F#

- Dependency: notify-sharp-3AUR
- Makedependency: dotnet-sdk
- Build with: `fsharpc -r:notify-sharp.dll -I:/usr/lib/mono/notify-sharp-3.0/ -I:/usr/lib/mono/gtk-sharp-3.0/ hello_world.fs`
- Run with: `mono hello_world.exe`

    hello_world.fs

    open Notifications
    let Hello = new Notification()
    Hello.Summary  <- "Hello world!"
    Hello.Body     <- "This is an example notification."
    Hello.IconName <- "dialog-information"
    Hello.Show()

### Genie

- Dependency: glib2
- Makedependency: vala
- Build with: `valac --pkg gio-2.0 hello_world.gs`

    hello_world.gs

    uses
    	GLib

    init
    	var Application = new GLib.Application ("hello.world", GLib.ApplicationFlags.FLAGS_NONE);
    	Application.register ();
    	var Notification = new GLib.Notification ("Hello world");
    	Notification.set_body ("This is an example notification.");
    	var Icon = new GLib.ThemedIcon ("dialog-information");
    	Notification.set_icon (Icon);
    	Application.send_notification (null, Notification);

- Dependency: libnotify
- Makedependency: vala
- Build with: `valac --pkg libnotify hello_world.gs`

    hello_world.gs

    uses
    	Notify

    init
    	Notify.init ("Hello world")
    	var Hello=new Notify.Notification ("Hello world!","This is an example notification.","dialog-information")
    	Hello.show ()

### Go

- Dependency: libnotify
- Makedependency: go-notify-gitAUR[broken link: package not found]
- Build with: `go build hello_world.go`
- (Or run with: `go run hello_world.go`)

    hello_world.go

    package main
    import ("github.com/mqu/go-notify")

    func main() {
    	notify.Init("Hello world")
    	hello := notify.NotificationNew("Hello World!", "This is an example notification.","dialog-information")
    	hello.Show()
    }

### Groovy

- Dependencies: groovy, java-gnomeAUR
- Build with: `groovyc -cp /usr/share/java/gtk.jar HelloWorld.groovy && jar cfe HelloWorld.jar HelloWorld HelloWorld.class`
- Run with: `java -cp /usr/share/groovy/embeddable/groovy-all.jar:/usr/share/java/gtk.jar:HelloWorld.jar HelloWorld` or `groovy -cp /usr/share/java/gtk.jar HelloWorld.groovy`

    HelloWorld.groovy

    import org.gnome.gtk.*
    import org.gnome.notify.*

    Gtk.init()
    Notify.init("Hello world")
    def Hello = new Notification("Hello world!", "This is an example notification.", "dialog-information")
    Hello.show()

### Haskell

- Makedependency: haskell-fdo-notify
- Build with: `ghc -dynamic hello_world`

    hello_world.hs

    import DBus.Notify
    main = do
             client <- connectSession
             let hello = blankNote { summary="Hello world!",
                                     body=(Just $ Text "This is an example notification."),
                                     appImage=(Just $ Icon "dialog-information") }
             notification <- notify client hello
             return 0

### IronPython

- Dependencies: notify-sharp-3AUR, ironpythonAUR
- Run with: `ipy hello_world.py`

    hello_world.py

    import clr
    clr.AddReference('notify-sharp')
    import Notifications
    Hello = Notifications.Notification()
    Hello.Summary  = "Hello world!"
    Hello.Body     = "This is an example notification."
    Hello.IconName = "dialog-information"
    Hello.Show()

### Java

- Dependency: java-gnomeAUR
- Makedependency: java-environment
- Build with: `javac -cp /usr/share/java/gtk.jar HelloWorld.java && jar cfe HelloWorld.jar HelloWorld HelloWorld.class`
- Run with: `java -cp /usr/share/java/gtk.jar:HelloWorld.jar HelloWorld`

    HelloWorld.java

    import org.gnome.gtk.Gtk;
    import org.gnome.notify.Notify;
    import org.gnome.notify.Notification;

    public class HelloWorld
    {
        public static void main(String[] args) {
            Gtk.init(args);
            Notify.init("Hello world");
            Notification Hello = new Notification("Hello world!", "This is an example notification.", "dialog-information");
            Hello.show();
        }
    }

### JavaScript

- Dependency: gjs

    hello_world.js

    #!/usr/bin/gjs
    const Gio = imports.gi.Gio;
    var Application = new Gio.Application ({application_id: "hello.world"});
    Application.register (null);
    var Notification = new Gio.Notification ();
    Notification.set_title ("Hello world");
    Notification.set_body ("This is an example notification.");
    var Icon = new Gio.ThemedIcon ({name: "dialog-information"});
    Notification.set_icon (Icon);
    Application.send_notification (null, Notification);

- Dependencies: libnotify, gjs

    hello_world.js

    #!/usr/bin/gjs
    const Notify = imports.gi.Notify;
    Notify.init ("Hello world");
    var Hello=new Notify.Notification ({summary: "Hello world!",
                                        body: "This is an example notification.",
                                        "icon-name": "dialog-information"});
    Hello.show ();

- Dependencies: nodejs, node-dbus-notifier

    hello_world.js

    #!/usr/bin/env node
    const notifier = require("node-dbus-notifier");

    const notify = new notifier.Notify({
      appName: "JavaScript",
      appIcon: "archlinux-logo",
      summary: "Hello world!",
      hints: {
        urgency: 2,
      },
      body: "This is an example notification.",
      timeout: 5000,
    });

    notify.addAction("Click Me", () => {
      console.log("Click Click");
    });

    notify.show()
      .then(() => {
        console.log("notify is closed");
      });

### JRuby

- Dependencies: java-gnomeAUR, jruby
- Build with: `jrubyc hello_world.rb && jar cfe hello_world.jar hello_world hello_world.class`
- Run with: `java -cp /opt/jruby/lib/jruby.jar:hello_world.jar hello_world` or `jruby hello_world.rb`

    hello_world.rb

    require '/usr/share/java/gtk.jar'
    import Java::OrgGnomeGtk::Gtk
    import Java::OrgGnomeNotify::Notify
    import Java::OrgGnomeNotify::Notification

    Gtk.init(nil)
    Notify.init("Hello world")
    Hello = Notification.new("Hello world!", "This is an example notification.", "dialog-information")
    Hello.show

### Jython

- Dependencies: java-gnomeAUR, jython
- Run with: `jython -Dpython.path=/usr/share/java/gtk.jar hello_world.py`

    hello_world.py

    from org.gnome.gtk import Gtk
    from org.gnome.notify import Notify, Notification
    Gtk.init(None)
    Notify.init("Hello world")
    Hello=Notification("Hello world!", "This is an example notification.", "dialog-information")
    Hello.show()

### Lua

- Dependency: lua-lgi-gitAUR

    hello_world.lua

    #!/usr/bin/lua
    lgi = require 'lgi'
    Gio = lgi.require('Gio')
    Application = Gio.Application.new("hello.world",Gio.ApplicationFlags.FLAGS_NONE);
    Application:register();
    Notification = Gio.Notification.new("Hello world");
    Notification:set_body("This is an example notification.");
    Icon = Gio.ThemedIcon.new("dialog-information");
    Notification:set_icon(Icon);
    Application:send_notification(nil, Notification);

- Dependencies: libnotify, lua-lgi-gitAUR

    hello_world.lua

    #!/usr/bin/lua
    lgi = require 'lgi'
    Notify = lgi.require('Notify')
    Notify.init("Hello world")
    Hello=Notify.Notification.new("Hello world","This is an example notification.","dialog-information")
    Hello:show()

### Nemerle

- Dependency: notify-sharp-3AUR
- Makedependency: nemerleAUR
- Build with: `ncc -pkg:notify-sharp-3.0 -out:hello_world.exe hello_world.n`
- Run with: `mono hello_world.exe`

    hello_world.n

    using Notifications;
    public class HelloWorld {
    	static Main() : void {
    		def Hello = Notification();
    		Hello.Summary  = "Hello world!";
    		Hello.Body     = "This is an example notification.";
    		Hello.IconName = "dialog-information";
    		Hello.Show();
    	}
    }

### Pascal

- Dependency: libnotify
- Makedependency: fpc, libnotify binding
- Build with: `fpc hello_world`

    hello_world.pas

    program	hello_world;
    uses	libnotify;
    var	hello : PNotifyNotification;
    begin
    	notify_init(argv[0]);
    	hello := notify_notification_new ('Hello world', 'This is an example notification.', 'dialog-information');
    	notify_notification_show (hello, nil);
    end.

### Perl

#### Using libnotify

- Dependencies: libnotify, perl-glib-object-introspection

    hello_world.pl

    #!/usr/bin/perl
    use Glib::Object::Introspection;
    Glib::Object::Introspection->setup(basename => 'Notify',
                                       version => '0.7',
                                       package => 'Notify');
    Notify->init;
    my $hello = Notify::Notification->new('Hello world!',
                                          'This is an example notification.',
                                          'dialog-information');
    $hello->show;

#### Using direct D-Bus calls

- Dependencies: perl-net-dbus

    hello_world.pl

    #!/usr/bin/perl
    use Net::DBus;
    my $bus = Net::DBus->session;
    my $svc = $bus->get_service('org.freedesktop.Notifications');
    my $obj = $svc->get_object('/org/freedesktop/Notifications');
    my $id = $obj->Notify('myapp', 0,
                          'dialog-information',
                          'Hello world!',
                          'This is an example notification.',
                          [], {}, 0);

### Python

- Dependency: python-gobject

    hello_world.py

    #!/usr/bin/python3
    import gi
    gi.require_version('Gio', '2.0')
    from gi.repository import Gio
    Application = Gio.Application.new("hello.world", Gio.ApplicationFlags.FLAGS_NONE)
    Application.register()
    Notification = Gio.Notification.new("Hello world")
    Notification.set_body("This is an example notification.")
    Icon = Gio.ThemedIcon.new("dialog-information")
    Notification.set_icon(Icon)
    Application.send_notification(None, Notification)

- Dependencies: libnotify, python-gobject

    hello_world.py

    #!/usr/bin/python3
    import gi
    gi.require_version('Notify', '0.7')
    from gi.repository import Notify
    Notify.init("Hello world")
    Hello = Notify.Notification.new("Hello world", "This is an example notification.", "dialog-information")
    Hello.show()

- Dependency: python-dbus

    hello_world.py

    #!/usr/bin/env python3
    import dbus

    obj = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
    obj = dbus.Interface(obj, "org.freedesktop.Notifications")
    obj.Notify("", 0, "", "Hello world", "This is an example notification.", [], {"urgency": 1}, 10000)

For the arguments in the method `Notify`, please refer to the section of org.freedesktop.Notifications.Notify at Desktop Notifications Specification.

### Ruby

- Dependencies: libnotify, ruby-gir_ffiAUR[broken link: package not found]

    hello_world.rb

    #!/usr/bin/ruby
    require 'gir_ffi'
    GirFFI.setup :Notify
    Notify.init("Hello world")
    Hello = Notify::Notification.new("Hello world!", "This is an example notification.", "dialog-information")
    Hello.show

### Rust

Using notify-rust.

- Makedependency: rust
- Build with: `cargo build`
- Run with: `target/debug/hello_world` or `cargo run`

    Cargo.toml

    [package]
    name = "hello_world"
    version = "0.1.0"

    [dependencies]
    notify-rust = "^3"

    src/main.rs

    extern crate notify_rust;
    use notify_rust::Notification;
    fn main(){
        Notification::new()
            .summary("Hello world")
            .body("This is an example notification.")
            .icon("dialog-information")
            .show().unwrap();
    }

### Scala

- Dependency: java-gnomeAUR (and scalaAUR)
- Makedependency: scalaAUR
- Build with: `scalac -cp /usr/share/java/gtk.jar -d HelloWorld.jar HelloWorld.scala`
- Run with: `java -cp /usr/share/java/gtk.jar:HelloWorld.jar HelloWorld` (or `scala -cp /usr/share/java/gtk.jar HelloWorld.scala`)

    HelloWorld.scala

    import org.gnome.gtk._
    import org.gnome.notify._

    object HelloWorld {
      def main(args: Array[String]) {
        Gtk.init(args)
        Notify.init("Hello world")
        var Hello = new Notification("Hello world!", "This is an example notification.", "dialog-information")
        Hello.show()
      }
    }

### Vala

- Dependency: glib2
- Makedependency: vala
- Build with: `valac --pkg gio-2.0 hello_world.vala`

    hello_world.vala

    using GLib;
    public class HelloWorld {
    	static void main () {
    		var Application = new GLib.Application ("hello.world", GLib.ApplicationFlags.FLAGS_NONE);
    		Application.register ();
    		var Notification = new GLib.Notification ("Hello world");
    		Notification.set_body ("This is an example notification.");
    		var Icon = new GLib.ThemedIcon ("dialog-information");
    		Notification.set_icon (Icon);
    		Application.send_notification (null, Notification);
    	}
    }

- Dependency: libnotify
- Makedependency: vala
- Build with: `valac --pkg libnotify hello_world.vala`

    hello_world.vala

    using Notify;
    public class HelloWorld {
    	static void main () {
    		Notify.init ("Hello world");
    		var Hello = new Notify.Notification("Hello world!", "This is an example notification.", "dialog-information");
    		Hello.show ();
    	}
    }

### Visual Basic .NET

- Dependency: notify-sharp-3AUR
- Makedependency: mono-basicAUR
- Build with: `vbnc -r:/usr/lib/mono/notify-sharp-3.0/notify-sharp.dll hello_world.vb`
- Run with: `mono hello_world.exe`

    hello_world.vb

    Imports Notifications
    Public Class Hello
    	Public Shared Sub Main
    		Dim Hello As New Notification
    		Hello.Summary  = "Hello world!"
    		Hello.Body     = "This is an example notification."
    		Hello.IconName = "dialog-information"
    		Hello.Show
    	End Sub
    End Class

## Tips and tricks

### Replace previous notification

Notifications can be replaced if their ID is known; if a new notification request specifies the same ID, it will always replace the old notification. (The libnotify bindings shown above handle this automatically.) Unfortunately notify-send does not report this ID, so alternative tools are required to do this on CLI. One capable CLI-tool is the notify-send.py python script, which provides notify-send syntax with additional ID-reporting and replacing capabilities.

However, with some notification servers (such as Notify-OSD), you can use the `string:x-canonical-private-synchronous:` hint with notify-send to achieve the same result.

For example, to get a notification displaying time:

    while true; do
      date=$(date)
      notify-send "$date" -h string:x-canonical-private-synchronous:my-notification
      sleep 1
    done

### Include Buttons or listen for close/on-click of the notification

With the notify-send.py script, actions can be used to display buttons or to listen for the default-action of the notification (usually, when the user clicks on it) and the close-action. When the action-icons hint is set to true and the notification daemon supports this, the buttons will display icons instead of text. The script prints the action identifier or "close" to the command line when the corresponding event has occured. To listen for the default action (on-click), one has to use the action-identfier "default".

Example with icons on buttons:

    notify-send.py "Buttons" "Do you like em?" --hint boolean:action-icons:true --action yes:face-cool no:face-sick

### Multiple notification servers with D-Bus services

As described in the section Standalone, users can create a D-Bus service so that a notification server can be launched automatically. Some implementations already include the D-Bus service files. However, this causes a problem when multiple notification servers are installed and when some of them come with the service files. For example, installing both dunst and mako without explicitly specifying the desired server, D-Bus then chooses one for the users, and the decision is out of users' control. To avoid the situation, you can override the service used by creating a `org.freedesktop.Notifications.service` (see #Standalone) and pointing to the service you want to use, then restarting the session.

### Notifications on failed Systemd services

To get notified by failed services, install and run systembus-notify on the target user and follow the instructions given in Systemd#Notifying_about_failed_services, but replace the `failure-notification@` template unit with this one:

    /etc/systemd/system/failure-notification@.service

    [Unit]
    Description=Send a notification about a failed systemd unit
    After=Graphical.target

    [Service]
    Type=simple
    ExecStart=/usr/bin/dbus-send --system / net.nuetzlich.SystemNotifications.Notify 'string:%i' 'string:Unit failed'

Sadly, this solution does not yet support setting the urgency or timeout of the notifications, see this issue.

## Troubleshooting

### Applications hanging for exactly one minute

If applications hang when attempting to show notifications, it might be because of a notification service falsely advertising its availability through the D-Bus service.

For instance, suppose a user recently installed a KDE component that requires plasma-workspace, but the user is still running XFCE. In this case, the KDE notifier will be prioritized, but the user is not running it. The application will hang while waiting for the service, and only after a timeout will it fall back to xfce4-notifyd.

The most noticeable hanging might come from the volume indicator scroll adjustment.

If you are in this situation, you should have two notification handlers:

    $ find /usr/share/dbus-1/services/ -name '*Notif*'

    org.kde.plasma.Notifications.service
    org.xfce.xfce4-notifyd.Notifications.service

Of those two, one fails regularly after a 1-minute timeout, as seen in the journal:

    # journalctl -g notif

    Jul 01 09:40:49 laptop dbus-daemon[866]: [session uid=1000 pid=866] Activating service name='org.freedesktop.Notifications' requested by ':1.193' (uid=1000 pid=5432 comm="/usr/lib/xfce4/panel/wrapper-2.0 /usr/lib/xfce4/pa")
    Jul 01 09:41:49 laptop plasma_waitforname[6093]: org.kde.knotifications: WaitForName: Service was not registered within timeout
    Jul 01 09:41:49 laptop dbus-daemon[866]: [session uid=1000 pid=866] Activated service 'org.freedesktop.Notifications' failed: Process org.freedesktop.Notifications exited with status 1

Choosing the service you want to use as described in #Multiple notification servers with D-Bus services will fix the problem.

## See also

- Libnotify Reference Manual[dead link 2024-07-30 ⓘ]
- C example (archived version)
- Python notification examples
- Python notify example (french article)

Categories:

- X server
- Notification
- Development
- Lists of software

Hidden categories:

- Pages with broken package links
- Pages with dead links