Love and Communication

For the Google Summer of Code, Vytas Liuolia wrote the (very much needed) guniqueapp library; just a small recap: libguniqueapp allows the creation of single instance applications, that is applications that gets instanced once and each subsequent instance just quits – or send a command to the currently running instance.

Libguniqueapp has two available backends: D-Bus, as default, and bacon (a Un*x socket living in /tmp and used to send and receive commands). After reading about guniqueapp on desktop-devel-list, I began hacking on it in order to add a new backend, using X itself as an IPC mechanism.

Single instance applications are used on the desktop (Gedit, Mozilla, Epiphany, Evince – the list goes on), but are very interesting for an embedded device because of the the memory and/or screen real estate limitations. On the Maemo platform, for instance, this issue has been solved by having each application behave as a D-Bus service: each time an application is launched a new object on the bus is created and subsequent instances just abort. Not every embedded platform uses (or can use) D-Bus, though, hence the need for anothe IPC mechanism – like the Xlibs-based backend.

In the process of adding this new backend I’ve accidentally broken the whole guniqueapp codebase; I know, I’m really sloppy at the times. Reassembling the pieces together using GTK+ coding style (which, even though it uses the evil 2-spaces indentation from hell, I actually prefer using when programming using GObject/GTK-based stuff) and clearly hiding the backend stuff under the carpet, something else came out of it – GtkUnique.

GtkUnique is pretty much similar to guniqueapp, except that:

  • the backend implementations have been more cleanly separated and hidden in helper libraries;
  • there’s an Xlibs-based backend, which is preferred right after the D-Bus backend;
  • the IPC channel is bidirectional; that is: the message sent from a second instance to the first instance of the application has a return code, in case the operation that has been requested failed;
  • the D-Bus backend has been changed: the name of the application is used as the object on the bus, so you don’t have awkward stuff like org.gnome.GUniqueApp.YourApp but something a bit more friendly like tld.your-company.YourApp;
  • also in the D-Bus backend, the SendMessage message has been changed: it now accepts a stringified command, which is the “nick” value of the GtkUniqueCommand enum object; this way you can send commands like activate or new instead of integers on the wire;
  • the GtkUniqueApp object keeps track of the top-level windows of the application;
  • I’ve added API documentation using gtk-doc;
  • Perl and Python bindings are in the works;

You may think of GtkUnique as a fork of guniqueapp; really, it’s more of an experiment I wrote to get more aquainted with Xlibs (for instance: now I learned the hard way that you must remember to use XSelectInput() on a window to get the PropertyNotify events) and D-Bus programming. I intend to use GtkUnique inside the next release of the Dictionary and inside another project of mine, so I’ll keep on working on it.

If you want to play with it, just pull the bazaar repository from here:

  main:  bzr branch http://o-hand.com/~ebassi/bzr/gtkunique
  perl bindings: bzr branch http://o-hand.com/~ebassi/bzr/gtkunique-perl

and there’s a tarball available here

Note on the library: the libbacon-like backend is broken at the moment, as I’m still playing with it.

Note on the bindings: I’ll add the branch for the python bindings as soon as I have them in a buildable state. The Perl bindings are very rough at the moment – the make test phase fails and while you can send a message from a Perl application to a C application sharing the same name, you can’t do the opposite.

6 Replies to “Love and Communication”

  1. gicmo: it can be done – I kept the code consistent with Gtk for future inclusion. I’ll see what the gtk-devel team thinks.

  2. While looking at the code, I noticed it’s not possible to inherit from GtkUniqueApp since the methods are implemented as child objects, and are incomplete types.

    Anyway the inheritance is desirable in two cases: additional properties or methods of the “app” object (I agree you could bypass this one using composition) and additional methods for the DBus service, for an interface custom to the app, or, say, to “org.world.AudioPlayer”. For this particular case, inheriting from a specific method is fine (such an app would probably only use DBus anyway)

    BTW maybe you could have a GtkApp and a GtkUniqueApp inheriting from it: many apps have a App object tracking windows. KDE has such a class too: KUniqueApplication inherits from KApplication.

  3. nud: lack of inheritance is a design choice: GtkUniqueApp is, effectively, a “public final” class because its implementation is decided at compile time. for instance: adding properties and/or methods would require a complete change of the bacon and xlibs backend, while it might come easier with the d-bus backend by using interface combination (via you patch, for instance :-)). so, no: I think that overriding GtkUniqueApp is a bad idea and providing a facility for doing so would be a bad design choice – hence the need for hiding the properties (name, startup-id and workspace) behind a private class and subclassing the implementation from that.

    KUniqueApplication allows subclassing because it only has one backend, and it can be exposed.

    maybe time will prove me wrong, and if I’ll implement GtkUniqueApp as part of GTK+ I could reconsider the subclassing – also because I do too would like a GtkApplication abstract class (to deprecate the GnomeProgram and GnomeApp classes, for instance).

  4. While looking at the code, I noticed it’s not possible to inherit from GtkUniqueApp since the methods are implemented as child objects, and are incomplete types.

    Anyway the inheritance is desirable in two cases: additional properties or methods of the “app” object (I agree you could bypass this one using composition) and additional methods for the DBus service, for an interface custom to the app, or, say, to “org.world.AudioPlayer”. info

Comments are closed.