This site is now 100% read-only, and retired.

Creating desktop notifications

Posted by Steve on Sun 18 Jun 2006 at 10:20

There are several times when you'll be writing a script, or a program, which needs to communicate with the desktop user and here we'll look at two of the more modern approaches.

On Screen Display

On-Screen display basically means that text is displayed over the top of your existing desktop - literally in your display, without a popup window of any type.

This might be familiar to you if you've used the xmms-osd-plugin plugin for XMMS.

Using the xosd-bin package it is very simple to send text to the screen:

droot@lappy:~# apt-get install xosd-bin
Reading package lists... Done
Building dependency tree... Done
The following extra packages will be installed:
  libxosd2

Once installed you can show text by running the osd_cat command with some text to display:

skx@lappy:~$ echo -e "Test Message from Steve\nTesting more" | osd_cat 

If all goes well you should see your message on your root window in the top-left corner of your screen.

The position of the message, and the colour/font used can both be modified. Here is what I tend use:

echo "Test" | osd_cat --font='-b&h-lucida-medium-r-normal-*-34-*-*-*-p-*-iso10646-1' \
   --color=green \
   --pos=top \
   --align=right \
   --offset=50 \
   --indent=50

The advantage of the xosd-bin package is that it is very simple to create a notification message without any real programming. The downside is that the message can't be dismissed early - or be interacted with by the user.

If you want your user to be able to cancel/respond to the message then you'll need something else. Something like the notification daemon.

notification-daemon

There is a new program which is intended to become the standard notification mediator which handles the display of popups and user interaction.

root@lappy:~# apt-get install libnotify1 notification-daemon dbus 

(Once installed you should probably logout + login again so that the dbus daemon is setup by your session manager.)

If you want to use the notification facilities in your code you'll need to install the libnotify-dev package which contains the appropriate header files and a shared library to link against. You will also need the GTK headers and the GLib development files. Altogether these are quite a hefty download:

apt-get install libgtk2.0-dev libglib2.0-dev libnotify-dev

Once you've installed the requirements you can compile the following sample program (actually taken from the libnotify source package):

#include <libnotify/notify.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char * argv[] ) 
{
    NotifyNotification *n;  

    notify_init("Basics");

    n = notify_notification_new ("Summary", 
                                 "This is the message that we want to display",
                                  NULL, NULL);
    notify_notification_set_timeout (n, 5000); // 5 seconds

    if (!notify_notification_show (n, NULL)) 
    {
        fprintf(stderr, "failed to send notification\n");
        return 1;
    }

    g_object_unref(G_OBJECT(n));

    return 0;
}

Compile it by running:

skx@lappy:~$ gcc `pkg-config --cflags gtk+-2.0`\
             `pkg-config --cflags glib-2.0` \
             test-basic.c -lnotify -o test-basic 

Once compiled execute it by running:

skx@lappy:~$ ./test-basic

All being well an attractive notification dialog should popup and disappear after five seconds - or when you click it.

If you are interested in compiling, or testing, the system without installing the large build-dependencies you can cheat and use runtime-loading! The following code does that:

/* 
 * Dynamic loading + use of the libnotify library.
 *
 * Steve
 * --
 * http://www.steve.org.uk/
 */
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main( int argc, char *argv[] )
{
  /* Library + notification handles */
  void *handle, *n;

  /* signatures of functions we're going to invoke dynamically. */
  typedef void  (*notify_init_t)(char *);
  typedef void *(*notify_notification_new_t)( char *, char *, char *, char *);
  typedef void  (*notify_notification_set_timeout_t)( void *, int );
  typedef void (*notify_notification_show_t)(void *, char *);

  /* open the library */
  handle= dlopen("libnotify.so.1", RTLD_LAZY);
  if ( handle == NULL )
  {
    printf("Failed to open library\n" );
    return 1;
  }

  /* Find the notify_init function and invoke it. */
  notify_init_t init = (notify_init_t)dlsym(handle, "notify_init");
  if ( init == NULL  )
  {
    printf("Library function not found: notify_init\n");
    dlclose( handle );
    return 1;
  }
  init("Basics");


  /* Find the notify_notification_new function, and invoke it. */
  notify_notification_new_t nnn = (notify_notification_new_t)dlsym(handle, "notify_notification_new");
  if ( nnn == NULL  )
  {
    printf("Library function not found: notify_notification_new\n");
    dlclose( handle );
    return 1;
  }
  n = nnn("Test subject", "Test body with <b>bold</b>, and <i>italic</i>!", NULL, NULL);

  /* Find the notify_notification_set_timeout function and invoke it. */
  notify_notification_set_timeout_t nnst = (notify_notification_set_timeout_t)dlsym(handle, "notify_notification_set_timeout");
  if ( nnst == NULL  )
    {
      printf("Library function not found: notify_notification_set_timeout\n");
      dlclose( handle );
      return 1;
    }
  /* invoke function, 3 second timeout. */
  nnst(n, 3000 );


  /* Finally shpow the notification. */
  notify_notification_show_t show = (notify_notification_show_t)dlsym(handle, "notify_notification_show");
  if ( init == NULL  )
  {
    printf("Library function not found: notify_notification_show\n");
    dlclose( handle );
    return 1;
  }
  /* invoke function, passing value of integer as a parameter */
  show(n, NULL );

  /* close the library and exit*/
  dlclose(handle );
  return 0;
}

You can compile this with:

skx@lappy:~$ gcc dynamic.c -o dynamic -ldl 
skx@lappy:~$ ./dynamic

This program could be easily adapted to read the message, and title, from command line arguments, but as a simple sample it has probably already done its job.

Note:

To use this program you'll still need to install the notification daemon, dbus, and etc. But you dont need to install the GTK, Glib, and LibNotify development packages - note that you probably should, this is just a simple hack which works only until the API changes.

 

 


Re: Creating desktop notifications
Posted by reluctant (65.78.xx.xx) on Sun 18 Jun 2006 at 20:11
For On Screen Display, don't forget xmessage and gmessage. For example:
$ gmessage "Test message from Steve." 
It's so simple, even a desktop user like me can have fun with it. :)
$ sleep 30m && music123 alert.wav && gmessage "Miller time!" & 
Also useful when logged in via ssh to a remote system to send a message to a desktop user. Example:
$ gmessage -display :0 -center "If you need more help, go here: http://www.debian-administration.org/" 
I like its simplicity; the user doesn't have to know anything or do anything to receive the message.

[ Parent ]

Re: Creating desktop notifications
Posted by Steve (62.30.xx.xx) on Sun 18 Jun 2006 at 20:18
[ View Weblogs ]

Definitely a good thing to remember. It is also worth mentioning xenity for giving alerts of different forms.

The reason I didn't mention them here was mostly because I was thinking of alerts which cancel themselves - so they're not focus-stealing, or unduly distracting.

Steve

[ Parent ]

Re: Creating desktop notifications
Posted by PJ_at_Belzabar_Software (59.176.xx.xx) on Mon 19 Jun 2006 at 06:32
[ View Weblogs ]
Sometimes when I'm in deep hack I forget to blink. To prevent my eyes from drying and shriveling up I added this to my xsession:


( while true ; do xmessage -timeout 3 -center " blink "; sleep 600; done ) &


The timeout means it distracts you, as well as removing itself. As a bonus, focus is restored to your app after 3 seconds.

When I see that message, I just blink for a bit, and think about getting my nipples pierced or similar eyewatering thoughts.

Yeah, it sounds stupid, but it works well for me.

YMMV

PJ

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (80.68.xx.xx) on Mon 19 Jun 2006 at 11:42

I've done similar things before. Mostly just 'sleep 600 && zenity zenity --info --text "Test"' or similar.

The reason that I no longer do that is I hate the focus-stealing, and the massive distraction they cause. This is why I prefer using the notification system, or OSD displays.

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (62.4.xx.xx) on Mon 19 Jun 2006 at 14:35
You might have noted that GNOME does in fact include a "Typing Break" feature. Enable it in "Desktop Preferences"->"Keyboard".

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (81.216.xx.xx) on Mon 19 Jun 2006 at 05:24
There's also the tool "notify-send" that's a little easier to invoke from a script. It's bundled with libnotify.

Check out my samples at http://linux.yes.nu/Code and then "nofity-scripts".


Patrik

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (64.81.xx.xx) on Mon 19 Jun 2006 at 06:49
An annoying thing about notify-send and libnotify is that they require access to the session DBUS. Using them from a crontab requires all sorts of contortions, mainly trying to figure a good way to write out the session DBUS identifiers to some secure tmp file during session start.

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (82.238.xx.xx) on Sat 31 Mar 2007 at 17:40
Unfortunately this tool doesn't seem to be bundled in the libnotify1 Debian package ?

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (82.238.xx.xx) on Sat 31 Mar 2007 at 17:42
Ok, responding to myself : it's in libnotify-bin

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (24.232.xx.xx) on Mon 19 Jun 2006 at 09:03
good for placing on songchange plugin of xmms

kdialog --title "Playing on xmms" --passivepopup "` xmms-shell -e status |grep Playing |cut -d":" -f2`" 5

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (70.173.xx.xx) on Tue 11 Dec 2007 at 15:10
you are aware of %s for the song change plugin for xmms?

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (131.154.xx.xx) on Mon 19 Jun 2006 at 09:57
How can I send notification over LAN? Currently I'm using smbclient (-M option) but it required winpopup (or like) is still open by users.

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (158.195.xx.xx) on Mon 19 Jun 2006 at 14:12
Zenity in GNOME 2.16 will include notifications via libnotify/notification-daemon. http://bugzilla.gnome.org/show_bug.cgi?id=329989 --- Jan

[ Parent ]

Re: Creating desktop notifications
Posted by solars (80.109.xx.xx) on Mon 19 Jun 2006 at 23:43
I wanted to use osd_cat for notifications like a simple "usb stick plugged in".

Does anyone know a tool like tenshi (http://dev.inversepath.com/trac/tenshim)
that can parse eg. logfiles, and then execute a command like osd_cat?

[ Parent ]

Re: Creating desktop notifications
Posted by deadcat (69.110.xx.xx) on Tue 20 Jun 2006 at 03:00
[ View Weblogs ]
i still use root-tail to display all my logs.

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (131.188.xx.xx) on Fri 23 Jun 2006 at 10:41
notify-send -u critical -t 2000 Debian Administration Rocks
see notify-send(1).

[ Parent ]

Re: Creating desktop notifications
Posted by Steve (62.30.xx.xx) on Fri 23 Jun 2006 at 10:45
[ View Weblogs ]

Cool command - but you'll need to install the libnotify-bin package to use it.

Steve

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (65.102.xx.xx) on Tue 15 Aug 2006 at 03:42
Very nice article! been fighting to just find some code like that somewhere! The second way you are using to use the notification messages, is this more a hack or are you using dbus directly?

[ Parent ]

Re: Creating desktop notifications
Posted by Steve (62.30.xx.xx) on Tue 15 Aug 2006 at 09:32
[ View Weblogs ]

The second way is valid enough, if you added error checking. It is using libnotify directly rather than DBUS.

Steve

[ Parent ]

Re: Creating desktop notifications
Posted by Anonymous (213.134.xx.xx) on Mon 25 Sep 2006 at 02:33
But what if you're using virtual screen (f.e. 1280x1024, but you can see only 800x600 part)? It would be handy to be able to place the alert message within that "current" 800x600 coordinates, and not use the "real ones" 1280x1024... you know, what I mean: the message can be on the part of the screen, which is not currently visible.

[ Parent ]