[gnome-flashback] libstatus-notifier: add code from old library



commit b01985c73683152193024a29bd98a1c576e6d0bc
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat Nov 5 21:43:00 2016 +0200

    libstatus-notifier: add code from old library

 libstatus-notifier/Makefile.am              |   28 +
 libstatus-notifier/sn-dbus-item-server-v0.c |  899 +++++++++++++++++
 libstatus-notifier/sn-dbus-item-server-v0.h |   31 +
 libstatus-notifier/sn-dbus-item-server.c    |  227 +++++
 libstatus-notifier/sn-dbus-item-server.h    |   73 ++
 libstatus-notifier/sn-dbus-item.c           |  451 +++++++++
 libstatus-notifier/sn-dbus-item.h           |  204 ++++
 libstatus-notifier/sn-dbus-menu-server.c    |  143 +++
 libstatus-notifier/sn-dbus-menu-server.h    |   34 +
 libstatus-notifier/sn-enum-types.c.in       |   37 +
 libstatus-notifier/sn-enum-types.h.in       |   21 +
 libstatus-notifier/sn-item-private.h        |   34 +
 libstatus-notifier/sn-item.c                | 1406 +++++++++++++++++++++++++++
 libstatus-notifier/sn-item.h                |  241 +++++
 libstatus-notifier/sn-watcher-private.h     |   33 +
 15 files changed, 3862 insertions(+), 0 deletions(-)
---
diff --git a/libstatus-notifier/Makefile.am b/libstatus-notifier/Makefile.am
index ee071cb..7f54901 100644
--- a/libstatus-notifier/Makefile.am
+++ b/libstatus-notifier/Makefile.am
@@ -3,6 +3,18 @@ NULL =
 noinst_LTLIBRARIES = libstatus-notifier.la
 
 libstatus_notifier_la_SOURCES = \
+       sn-item.c \
+       sn-item.h \
+       sn-dbus-item.c \
+       sn-dbus-item.h \
+       sn-dbus-item-server.c \
+       sn-dbus-item-server.h \
+       sn-dbus-item-server-v0.c \
+       sn-dbus-item-server-v0.h \
+       sn-dbus-menu-server.c \
+       sn-dbus-menu-server.h \
+       sn-item-private.h \
+       sn-watcher-private.h \
        $(BUILT_SOURCES) \
        $(NULL)
 
@@ -28,6 +40,18 @@ libstatus_notifier_la_LIBADD = \
        $(LIBSTATUS_NOTIFIER_LIBS) \
        $(NULL)
 
+ENUM_TYPES = \
+       $(srcdir)/sn-item.h \
+       $(NULL)
+
+sn-enum-types.c: sn-enum-types.c.in sn-enum-types.h $(ENUM_TYPES)
+       $(AM_V_GEN) $(GLIB_MKENUMS) --template $(srcdir)/sn-enum-types.c.in $(ENUM_TYPES) > \
+               sn-enum-types.c.tmp && mv sn-enum-types.c.tmp sn-enum-types.c
+
+sn-enum-types.h: sn-enum-types.h.in $(ENUM_TYPES)
+       $(AM_V_GEN) $(GLIB_MKENUMS) --template $(srcdir)/sn-enum-types.h.in $(ENUM_TYPES) > \
+               sn-enum-types.h.tmp && mv sn-enum-types.h.tmp sn-enum-types.h
+
 sn-dbus-menu-gen.h:
 sn-dbus-menu-gen.c: com.canonical.dbusmenu.xml
        $(AM_V_GEN) $(GDBUS_CODEGEN) --c-namespace Sn \
@@ -53,12 +77,16 @@ BUILT_SOURCES = \
        sn-item-v0-gen.h \
        sn-watcher-v0-gen.c \
        sn-watcher-v0-gen.h \
+       sn-enum-types.c \
+       sn-enum-types.h \
        $(NULL)
 
 EXTRA_DIST = \
        com.canonical.dbusmenu.xml \
        org.kde.StatusNotifierItem.xml \
        org.kde.StatusNotifierWatcher.xml \
+       sn-enum-types.c.in \
+       sn-enum-types.h.in \
        $(NULL)
 
 -include $(top_srcdir)/git.mk
diff --git a/libstatus-notifier/sn-dbus-item-server-v0.c b/libstatus-notifier/sn-dbus-item-server-v0.c
new file mode 100644
index 0000000..307c177
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item-server-v0.c
@@ -0,0 +1,899 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sn-dbus-item-server-v0.h"
+#include "sn-item-v0-gen.h"
+#include "sn-dbus-menu-server.h"
+#include "sn-watcher-v0-gen.h"
+#include "sn-item-private.h"
+#include "sn-watcher-private.h"
+
+struct _SnDBusItemServerV0
+{
+  SnDBusItemServer  parent;
+
+  guint             id;
+  SnItemV0Gen      *dbus_item;
+
+  guint             name_id;
+  guint             watcher_id;
+
+  GCancellable     *watcher_cancellable;
+  SnWatcherV0Gen   *watcher;
+
+  gboolean          is_item_ready;
+  gboolean          registered;
+
+  GtkMenu          *menu;
+  SnDBusMenuServer *dbus_menu;
+};
+
+G_DEFINE_TYPE (SnDBusItemServerV0, sn_dbus_item_server_v0,
+               SN_TYPE_DBUS_ITEM_SERVER)
+
+static gboolean
+handle_context_menu (SnItemV0Gen           *item_v0_gen,
+                     GDBusMethodInvocation *invocation,
+                     gint                   x,
+                     gint                   y,
+                     SnDBusItemServerV0    *server_v0)
+{
+  sn_item_v0_gen_complete_context_menu (item_v0_gen, invocation);
+  sn_dbus_item_server_emit_context_menu (SN_DBUS_ITEM_SERVER (server_v0),
+                                         x, y);
+
+  return TRUE;
+}
+
+static gboolean
+handle_activate (SnItemV0Gen           *item_v0_gen,
+                 GDBusMethodInvocation *invocation,
+                 gint                   x,
+                 gint                   y,
+                 SnDBusItemServerV0    *server_v0)
+{
+  sn_item_v0_gen_complete_activate (item_v0_gen, invocation);
+  sn_dbus_item_server_emit_activate (SN_DBUS_ITEM_SERVER (server_v0), x, y);
+
+  return TRUE;
+}
+
+static gboolean
+handle_secondary_activate (SnItemV0Gen           *item_v0_gen,
+                           GDBusMethodInvocation *invocation,
+                           gint                   x,
+                           gint                   y,
+                           SnDBusItemServerV0    *server_v0)
+{
+  sn_item_v0_gen_complete_secondary_activate (item_v0_gen, invocation);
+  sn_dbus_item_server_emit_secondary_activate (SN_DBUS_ITEM_SERVER (server_v0),
+                                               x, y);
+
+  return TRUE;
+}
+
+static gboolean
+handle_scroll (SnItemV0Gen           *item_v0_gen,
+               GDBusMethodInvocation *invocation,
+               gint                   delta,
+               SnItemOrientation      orientation,
+               SnDBusItemServerV0    *server_v0)
+{
+  switch (orientation)
+    {
+      case SN_ITEM_ORIENTATION_VERTICAL:
+      case SN_ITEM_ORIENTATION_HORIZONTAL:
+        break;
+
+      default:
+        orientation = SN_ITEM_ORIENTATION_HORIZONTAL;
+        break;
+    }
+
+  sn_item_v0_gen_complete_scroll (item_v0_gen, invocation);
+  sn_dbus_item_server_emit_scroll (SN_DBUS_ITEM_SERVER (server_v0),
+                                   delta, orientation);
+
+  return TRUE;
+}
+
+static void
+host_registered_cb (SnWatcherV0Gen     *watcher_v0_gen,
+                    SnDBusItemServerV0 *server_v0)
+{
+  gboolean registered;
+
+  registered = sn_watcher_v0_gen_get_is_host_registered (watcher_v0_gen);
+
+  sn_dbus_item_server_emit_hosts_changed (SN_DBUS_ITEM_SERVER (server_v0),
+                                          registered);
+}
+
+static void
+register_item_cb (GObject      *source_object,
+                  GAsyncResult *res,
+                  gpointer      user_data)
+{
+  SnDBusItemServerV0 *server;
+  GError *error;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (user_data);
+  error = NULL;
+
+  sn_watcher_v0_gen_call_register_item_finish (server->watcher, res, &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        sn_dbus_item_emit_error (SN_DBUS_ITEM (server), error);
+      g_error_free (error);
+
+      return;
+    }
+
+  server->registered = TRUE;
+}
+
+static void
+register_with_watcher (SnDBusItemServerV0 *server)
+{
+  SnDBusItem *impl;
+  const gchar *bus_name;
+
+  if (!server->watcher || !server->is_item_ready || server->registered)
+    return;
+
+  impl = SN_DBUS_ITEM (server);
+  bus_name = sn_dbus_item_get_bus_name (impl);
+
+  sn_watcher_v0_gen_call_register_item (server->watcher, bus_name, NULL,
+                                        register_item_cb, server);
+}
+
+static void
+proxy_ready_cb (GObject      *source_object,
+                GAsyncResult *res,
+                gpointer      user_data)
+{
+  SnDBusItemServerV0 *server;
+  GError *error;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (user_data);
+  error = NULL;
+
+  server->watcher = sn_watcher_v0_gen_proxy_new_finish (res, &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        sn_dbus_item_emit_error (SN_DBUS_ITEM (server), error);
+      g_error_free (error);
+
+      return;
+    }
+
+  g_signal_connect (server->watcher, "host-registered",
+                    G_CALLBACK (host_registered_cb), server);
+
+  register_with_watcher (server);
+}
+
+static void
+name_appeared_cb (GDBusConnection *connection,
+                  const gchar     *name,
+                  const gchar     *name_owner,
+                  gpointer         user_data)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (user_data);
+
+  server->watcher_cancellable = g_cancellable_new ();
+  sn_watcher_v0_gen_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
+                               SN_WATCHER_V0_BUS_NAME,
+                               SN_WATCHER_V0_OBJECT_PATH,
+                               server->watcher_cancellable,
+                               proxy_ready_cb, server);
+}
+
+static void
+name_vanished_cb (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (user_data);
+
+  if (server->watcher_cancellable)
+    {
+      g_cancellable_cancel (server->watcher_cancellable);
+      g_clear_object (&server->watcher_cancellable);
+    }
+
+  g_clear_object (&server->watcher);
+
+  server->registered = FALSE;
+}
+
+static void
+sn_dbus_item_server_v0_dispose (GObject *object)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (object);
+
+  if (server->registered)
+    {
+      SnDBusItem *impl;
+
+      impl = SN_DBUS_ITEM (server);
+
+      SN_DBUS_ITEM_GET_CLASS (impl)->unregister (impl);
+    }
+
+  if (server->watcher_cancellable)
+    {
+      g_cancellable_cancel (server->watcher_cancellable);
+      g_clear_object (&server->watcher_cancellable);
+    }
+
+  if (server->name_id > 0)
+    {
+      g_bus_unown_name (server->name_id);
+      server->name_id = 0;
+    }
+
+  if (server->watcher_id > 0)
+    {
+      g_bus_unwatch_name (server->watcher_id);
+      server->watcher_id = 0;
+    }
+
+  g_clear_object (&server->watcher);
+  g_clear_object (&server->dbus_item);
+
+  g_clear_object (&server->menu);
+  g_clear_object (&server->dbus_menu);
+
+  G_OBJECT_CLASS (sn_dbus_item_server_v0_parent_class)->dispose (object);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_attention_icon_name (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_attention_icon_name (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_attention_icon_name (SnDBusItem  *impl,
+                                                const gchar *attention_icon_name)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_attention_icon_name (server->dbus_item,
+                                          attention_icon_name);
+  sn_item_v0_gen_emit_new_attention_icon (server->dbus_item);
+}
+
+static GVariant *
+sn_dbus_item_server_v0_get_attention_icon_pixmap (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_attention_icon_pixmap (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_attention_icon_pixmap (SnDBusItem *impl,
+                                                  GVariant   *attention_icon_pixmap)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_attention_icon_pixmap (server->dbus_item,
+                                            attention_icon_pixmap);
+  sn_item_v0_gen_emit_new_attention_icon (server->dbus_item);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_attention_movie_name (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_attention_movie_name (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_attention_movie_name (SnDBusItem  *impl,
+                                                 const gchar *attention_movie_name)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_attention_movie_name (server->dbus_item,
+                                           attention_movie_name);
+}
+
+static SnItemCategory
+sn_dbus_item_server_v0_get_category (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+  const gchar *string;
+  SnItemCategory category;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+  string = sn_item_v0_gen_get_category (server->dbus_item);
+
+  if (g_strcmp0 (string, "ApplicationStatus") == 0)
+    category = SN_ITEM_CATEGORY_APPLICATION_STATUS;
+  else if (g_strcmp0 (string, "Hardware") == 0)
+    category = SN_ITEM_CATEGORY_HARDWARE;
+  else if (g_strcmp0 (string, "SystemServices") == 0)
+    category = SN_ITEM_CATEGORY_SYSTEM_SERVICES;
+  else if (g_strcmp0 (string, "Communications") == 0)
+    category = SN_ITEM_CATEGORY_COMMUNICATIONS;
+  else
+    category = SN_ITEM_CATEGORY_APPLICATION_STATUS;
+
+  return category;
+}
+
+static void
+sn_dbus_item_server_v0_set_category (SnDBusItem     *impl,
+                                     SnItemCategory  category)
+{
+  SnDBusItemServerV0 *server;
+  const gchar *string;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  switch (category)
+    {
+      case SN_ITEM_CATEGORY_APPLICATION_STATUS:
+        string = "ApplicationStatus";
+        break;
+
+      case SN_ITEM_CATEGORY_COMMUNICATIONS:
+        string = "Communications";
+        break;
+
+      case SN_ITEM_CATEGORY_SYSTEM_SERVICES:
+        string = "SystemServices";
+        break;
+
+      case SN_ITEM_CATEGORY_HARDWARE:
+        string = "Hardware";
+        break;
+
+      default:
+        string = "ApplicationStatus";
+        break;
+    }
+
+  sn_item_v0_gen_set_category (server->dbus_item, string);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_id (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_id (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_id (SnDBusItem  *impl,
+                               const gchar *id)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_id (server->dbus_item, id);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_icon_name (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_icon_name (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_icon_name (SnDBusItem  *impl,
+                                      const gchar *icon_name)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_icon_name (server->dbus_item, icon_name);
+  sn_item_v0_gen_emit_new_icon (server->dbus_item);
+}
+
+static GVariant *
+sn_dbus_item_server_v0_get_icon_pixmap (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_icon_pixmap (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_icon_pixmap (SnDBusItem *impl,
+                                        GVariant   *icon_pixmap)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_icon_pixmap (server->dbus_item, icon_pixmap);
+  sn_item_v0_gen_emit_new_icon (server->dbus_item);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_icon_theme_path (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_icon_theme_path (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_icon_theme_path (SnDBusItem  *impl,
+                                            const gchar *icon_theme_path)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_icon_theme_path (server->dbus_item, icon_theme_path);
+  sn_item_v0_gen_emit_new_icon_theme_path (server->dbus_item, icon_theme_path);
+}
+
+static gboolean
+sn_dbus_item_server_v0_get_item_is_menu (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_item_is_menu (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_item_is_menu (SnDBusItem *impl,
+                                         gboolean    item_is_menu)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_item_is_menu (server->dbus_item, item_is_menu);
+}
+
+static GtkMenu *
+sn_dbus_item_server_v0_get_menu (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return server->menu;
+}
+
+static void
+sn_dbus_item_server_v0_set_menu (SnDBusItem *impl,
+                                 GtkMenu    *menu)
+{
+  SnDBusItemServerV0 *server;
+  const gchar *object_path;
+  gchar *menu_path;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  g_clear_object (&server->menu);
+  g_clear_object (&server->dbus_menu);
+
+  if (menu == NULL)
+    {
+      sn_item_v0_gen_set_menu (server->dbus_item, "/");
+      return;
+    }
+
+  object_path = sn_dbus_item_get_object_path (impl);
+  menu_path = g_strdup_printf ("%s/Menu", object_path);
+
+  server->menu = g_object_ref_sink (menu);
+  server->dbus_menu = sn_dbus_menu_server_new (menu, menu_path);
+
+  sn_item_v0_gen_set_menu (server->dbus_item, menu_path);
+  g_free (menu_path);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_overlay_icon_name (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_overlay_icon_name (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_overlay_icon_name (SnDBusItem  *impl,
+                                              const gchar *overlay_icon_name)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_overlay_icon_name (server->dbus_item, overlay_icon_name);
+  sn_item_v0_gen_emit_new_overlay_icon (server->dbus_item);
+}
+
+static GVariant *
+sn_dbus_item_server_v0_get_overlay_icon_pixmap (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_overlay_icon_pixmap (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_overlay_icon_pixmap (SnDBusItem *impl,
+                                                GVariant   *overlay_icon_pixmap)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_overlay_icon_pixmap (server->dbus_item,
+                                          overlay_icon_pixmap);
+  sn_item_v0_gen_emit_new_overlay_icon (server->dbus_item);
+}
+
+static SnItemStatus
+sn_dbus_item_server_v0_get_status (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+  const gchar *string;
+  SnItemStatus status;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+  string = sn_item_v0_gen_get_status (server->dbus_item);
+
+  if (g_strcmp0 (string, "Passive") == 0)
+    status = SN_ITEM_STATUS_PASSIVE;
+  else if (g_strcmp0 (string, "Active") == 0)
+    status = SN_ITEM_STATUS_ACTIVE;
+  else if (g_strcmp0 (string, "NeedsAttention") == 0)
+    status = SN_ITEM_STATUS_NEEDS_ATTENTION;
+  else
+    status = SN_ITEM_STATUS_PASSIVE;
+
+  return status;
+}
+
+static void
+sn_dbus_item_server_v0_set_status (SnDBusItem   *impl,
+                                   SnItemStatus  status)
+{
+  SnDBusItemServerV0 *server;
+  const gchar *string;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  switch (status)
+    {
+      case SN_ITEM_STATUS_PASSIVE:
+        string = "Passive";
+        break;
+
+      case SN_ITEM_STATUS_ACTIVE:
+        string = "Active";
+        break;
+
+      case SN_ITEM_STATUS_NEEDS_ATTENTION:
+        string = "NeedsAttention";
+        break;
+
+      default:
+        string = "Passive";
+        break;
+    }
+
+  sn_item_v0_gen_set_status (server->dbus_item, string);
+  sn_item_v0_gen_emit_new_status (server->dbus_item, string);
+}
+
+static const gchar *
+sn_dbus_item_server_v0_get_title (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_title (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_title (SnDBusItem  *impl,
+                                  const gchar *title)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_title (server->dbus_item, title);
+  sn_item_v0_gen_emit_new_title (server->dbus_item);
+}
+
+static GVariant *
+sn_dbus_item_server_v0_get_tooltip (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_tool_tip (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_tooltip (SnDBusItem *impl,
+                                    GVariant   *tooltip)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_tool_tip (server->dbus_item, tooltip);
+  sn_item_v0_gen_emit_new_tool_tip (server->dbus_item);
+}
+
+static gint
+sn_dbus_item_server_v0_get_window_id (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  return sn_item_v0_gen_get_window_id (server->dbus_item);
+}
+
+static void
+sn_dbus_item_server_v0_set_window_id (SnDBusItem *impl,
+                                      gint        window_id)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+
+  sn_item_v0_gen_set_window_id (server->dbus_item, window_id);
+}
+
+static void
+sn_dbus_item_server_v0_context_menu (SnDBusItem *impl,
+                                     gint        x,
+                                     gint        y)
+{
+  g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_v0_activate (SnDBusItem *impl,
+                                 gint        x,
+                                 gint        y)
+{
+  g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_v0_secondary_activate (SnDBusItem *impl,
+                                           gint        x,
+                                           gint        y)
+{
+  g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_v0_scroll (SnDBusItem        *impl,
+                               gint               delta,
+                               SnItemOrientation  orientation)
+{
+  g_assert_not_reached ();
+}
+
+static void
+bus_acquired_cb (GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  SnDBusItemServerV0 *server;
+  GDBusInterfaceSkeleton *skeleton;
+  gchar *object_path;
+  GError *error;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (user_data);
+
+  skeleton = G_DBUS_INTERFACE_SKELETON (server->dbus_item);
+  object_path = g_strdup_printf ("%s", SN_ITEM_V0_OBJECT_PATH);
+  error = NULL;
+
+  g_signal_connect (server->dbus_item, "handle-context-menu",
+                    G_CALLBACK (handle_context_menu), server);
+  g_signal_connect (server->dbus_item, "handle-activate",
+                    G_CALLBACK (handle_activate), server);
+  g_signal_connect (server->dbus_item, "handle-secondary-activate",
+                    G_CALLBACK (handle_secondary_activate), server);
+  g_signal_connect (server->dbus_item, "handle-scroll",
+                    G_CALLBACK (handle_scroll), server);
+
+  if (!g_dbus_interface_skeleton_export (skeleton, connection,
+                                         object_path, &error))
+    {
+      sn_dbus_item_emit_error (SN_DBUS_ITEM (server), error);
+      g_error_free (error);
+
+      g_free (object_path);
+
+      return;
+    }
+
+  g_object_set (server, "bus-name", name, "object-path", object_path, NULL);
+  g_free (object_path);
+
+  register_with_watcher (server);
+}
+
+static void
+sn_dbus_item_server_v0_register (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+  gchar *bus_name;
+  GBusNameOwnerFlags flags;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+  server->is_item_ready = TRUE;
+
+  if (server->name_id > 0)
+    return;
+
+  bus_name = g_strdup_printf ("%s-%d-%d", SN_ITEM_V0_BUS_NAME,
+                              getpid (), server->id);
+  flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+          G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+  server->name_id = g_bus_own_name (G_BUS_TYPE_SESSION, bus_name, flags,
+                                    bus_acquired_cb, NULL, NULL,
+                                    server, NULL);
+
+  g_free (bus_name);
+}
+
+static void
+sn_dbus_item_server_v0_unregister (SnDBusItem *impl)
+{
+  SnDBusItemServerV0 *server;
+
+  server = SN_DBUS_ITEM_SERVER_V0 (impl);
+  server->is_item_ready = FALSE;
+
+  if (server->name_id > 0)
+    {
+      g_bus_unown_name (server->name_id);
+      server->name_id = 0;
+    }
+
+  server->registered = FALSE;
+}
+
+static void
+sn_dbus_item_server_v0_class_init (SnDBusItemServerV0Class *server_class)
+{
+  GObjectClass *object_class;
+  SnDBusItemClass *impl_class;
+
+  object_class = G_OBJECT_CLASS (server_class);
+  impl_class = SN_DBUS_ITEM_CLASS (server_class);
+
+  object_class->dispose = sn_dbus_item_server_v0_dispose;
+
+  impl_class->get_attention_icon_name = sn_dbus_item_server_v0_get_attention_icon_name;
+  impl_class->set_attention_icon_name = sn_dbus_item_server_v0_set_attention_icon_name;
+  impl_class->get_attention_icon_pixmap = sn_dbus_item_server_v0_get_attention_icon_pixmap;
+  impl_class->set_attention_icon_pixmap = sn_dbus_item_server_v0_set_attention_icon_pixmap;
+  impl_class->get_attention_movie_name = sn_dbus_item_server_v0_get_attention_movie_name;
+  impl_class->set_attention_movie_name = sn_dbus_item_server_v0_set_attention_movie_name;
+  impl_class->get_category = sn_dbus_item_server_v0_get_category;
+  impl_class->set_category = sn_dbus_item_server_v0_set_category;
+  impl_class->get_id = sn_dbus_item_server_v0_get_id;
+  impl_class->set_id = sn_dbus_item_server_v0_set_id;
+  impl_class->get_icon_name = sn_dbus_item_server_v0_get_icon_name;
+  impl_class->set_icon_name = sn_dbus_item_server_v0_set_icon_name;
+  impl_class->get_icon_pixmap = sn_dbus_item_server_v0_get_icon_pixmap;
+  impl_class->set_icon_pixmap = sn_dbus_item_server_v0_set_icon_pixmap;
+  impl_class->get_icon_theme_path = sn_dbus_item_server_v0_get_icon_theme_path;
+  impl_class->set_icon_theme_path = sn_dbus_item_server_v0_set_icon_theme_path;
+  impl_class->get_item_is_menu = sn_dbus_item_server_v0_get_item_is_menu;
+  impl_class->set_item_is_menu = sn_dbus_item_server_v0_set_item_is_menu;
+  impl_class->get_menu = sn_dbus_item_server_v0_get_menu;
+  impl_class->set_menu = sn_dbus_item_server_v0_set_menu;
+  impl_class->get_overlay_icon_name = sn_dbus_item_server_v0_get_overlay_icon_name;
+  impl_class->set_overlay_icon_name = sn_dbus_item_server_v0_set_overlay_icon_name;
+  impl_class->get_overlay_icon_pixmap = sn_dbus_item_server_v0_get_overlay_icon_pixmap;
+  impl_class->set_overlay_icon_pixmap = sn_dbus_item_server_v0_set_overlay_icon_pixmap;
+  impl_class->get_status = sn_dbus_item_server_v0_get_status;
+  impl_class->set_status = sn_dbus_item_server_v0_set_status;
+  impl_class->get_title = sn_dbus_item_server_v0_get_title;
+  impl_class->set_title = sn_dbus_item_server_v0_set_title;
+  impl_class->get_tooltip = sn_dbus_item_server_v0_get_tooltip;
+  impl_class->set_tooltip = sn_dbus_item_server_v0_set_tooltip;
+  impl_class->get_window_id = sn_dbus_item_server_v0_get_window_id;
+  impl_class->set_window_id = sn_dbus_item_server_v0_set_window_id;
+
+  impl_class->context_menu = sn_dbus_item_server_v0_context_menu;
+  impl_class->activate = sn_dbus_item_server_v0_activate;
+  impl_class->secondary_activate = sn_dbus_item_server_v0_secondary_activate;
+  impl_class->scroll = sn_dbus_item_server_v0_scroll;
+
+  impl_class->register_ = sn_dbus_item_server_v0_register;
+  impl_class->unregister = sn_dbus_item_server_v0_unregister;
+}
+
+static void
+sn_dbus_item_server_v0_init (SnDBusItemServerV0 *server)
+{
+  static guint next_id;
+  GBusNameWatcherFlags flags;
+
+  server->id = ++next_id;
+  server->dbus_item = sn_item_v0_gen_skeleton_new ();
+
+  flags = G_BUS_NAME_WATCHER_FLAGS_NONE;
+  server->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                         SN_WATCHER_V0_BUS_NAME, flags,
+                                         name_appeared_cb, name_vanished_cb,
+                                         server, NULL);
+}
diff --git a/libstatus-notifier/sn-dbus-item-server-v0.h b/libstatus-notifier/sn-dbus-item-server-v0.h
new file mode 100644
index 0000000..b28e8ef
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item-server-v0.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_DBUS_ITEM_SERVER_V0_H
+#define SN_DBUS_ITEM_SERVER_V0_H
+
+#include "sn-dbus-item-server.h"
+
+G_BEGIN_DECLS
+
+#define SN_TYPE_DBUS_ITEM_SERVER_V0 sn_dbus_item_server_v0_get_type ()
+G_DECLARE_FINAL_TYPE (SnDBusItemServerV0, sn_dbus_item_server_v0,
+                      SN, DBUS_ITEM_SERVER_V0, SnDBusItemServer)
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-dbus-item-server.c b/libstatus-notifier/sn-dbus-item-server.c
new file mode 100644
index 0000000..56ce1d9
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item-server.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sn-dbus-item-server.h"
+#include "sn-enum-types.h"
+
+typedef struct
+{
+  gboolean well_known;
+} SnDBusItemServerPrivate;
+
+enum
+{
+  PROP_0,
+
+  PROP_WELL_KNOWN,
+
+  LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+enum
+{
+  CONTEXT_MENU,
+  ACTIVATE,
+  SECONDARY_ACTIVATE,
+  SCROLL,
+
+  HOSTS_CHANGED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SnDBusItemServer, sn_dbus_item_server,
+                                     SN_TYPE_DBUS_ITEM)
+
+static void
+sn_dbus_item_server_set_property (GObject      *object,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  SnDBusItemServer *server;
+  SnDBusItemServerPrivate *priv;
+
+  server = SN_DBUS_ITEM_SERVER (object);
+  priv = sn_dbus_item_server_get_instance_private (server);
+
+  switch (property_id)
+    {
+      case PROP_WELL_KNOWN:
+        priv->well_known = g_value_get_boolean (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_dbus_item_server_context_menu (SnDBusItemServer *server,
+                                  gint              x,
+                                  gint              y)
+{
+  if (!g_signal_has_handler_pending (server, signals[CONTEXT_MENU], 0, TRUE))
+    g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_activate (SnDBusItemServer *server,
+                              gint              x,
+                              gint              y)
+{
+  if (!g_signal_has_handler_pending (server, signals[ACTIVATE], 0, TRUE))
+    g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_secondary_activate (SnDBusItemServer *server,
+                                        gint              x,
+                                        gint              y)
+{
+  if (!g_signal_has_handler_pending (server, signals[SECONDARY_ACTIVATE],
+                                     0, TRUE))
+    {
+      g_assert_not_reached ();
+    }
+}
+
+static void
+sn_dbus_item_server_scroll (SnDBusItemServer  *server,
+                            gint               delta,
+                            SnItemOrientation  orientation)
+{
+  if (!g_signal_has_handler_pending (server, signals[SCROLL], 0, TRUE))
+    g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_hosts_changed (SnDBusItemServer *server,
+                                   gboolean          registered)
+{
+  if (!g_signal_has_handler_pending (server, signals[HOSTS_CHANGED], 0, TRUE))
+    g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_server_class_init (SnDBusItemServerClass *server_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (server_class);
+
+  object_class->set_property = sn_dbus_item_server_set_property;
+
+  server_class->context_menu = sn_dbus_item_server_context_menu;
+  server_class->activate = sn_dbus_item_server_activate;
+  server_class->secondary_activate = sn_dbus_item_server_secondary_activate;
+  server_class->scroll = sn_dbus_item_server_scroll;
+  server_class->hosts_changed = sn_dbus_item_server_hosts_changed;
+
+  properties[PROP_WELL_KNOWN] =
+    g_param_spec_boolean ("well-known", "well-known", "well-known", FALSE,
+                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                          G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+  signals[CONTEXT_MENU] =
+    g_signal_new ("context-menu", SN_TYPE_DBUS_ITEM_SERVER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  2, G_TYPE_INT, G_TYPE_INT);
+
+  signals[ACTIVATE] =
+    g_signal_new ("activate", SN_TYPE_DBUS_ITEM_SERVER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  2, G_TYPE_INT, G_TYPE_INT);
+
+  signals[SECONDARY_ACTIVATE] =
+    g_signal_new ("secondary-activate", SN_TYPE_DBUS_ITEM_SERVER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  2, G_TYPE_INT, G_TYPE_INT);
+
+  signals[SCROLL] =
+    g_signal_new ("scroll", SN_TYPE_DBUS_ITEM_SERVER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  2, G_TYPE_INT, SN_TYPE_ITEM_ORIENTATION);
+
+  signals[HOSTS_CHANGED] =
+    g_signal_new ("hosts-changed", SN_TYPE_DBUS_ITEM_SERVER,
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  1, G_TYPE_BOOLEAN);
+}
+
+static void
+sn_dbus_item_server_init (SnDBusItemServer *server)
+{
+}
+
+gboolean
+sn_dbus_item_server_get_well_known (SnDBusItemServer *server)
+{
+  SnDBusItemServerPrivate *priv;
+
+  priv = sn_dbus_item_server_get_instance_private (server);
+
+  return priv->well_known;
+}
+
+void
+sn_dbus_item_server_emit_context_menu (SnDBusItemServer *server,
+                                       gint              x,
+                                       gint              y)
+{
+  g_signal_emit (server, signals[CONTEXT_MENU], 0, x, y);
+}
+
+void
+sn_dbus_item_server_emit_activate (SnDBusItemServer *server,
+                                   gint              x,
+                                   gint              y)
+{
+  g_signal_emit (server, signals[ACTIVATE], 0, x, y);
+}
+
+void
+sn_dbus_item_server_emit_secondary_activate (SnDBusItemServer *server,
+                                             gint              x,
+                                             gint              y)
+{
+  g_signal_emit (server, signals[SECONDARY_ACTIVATE], 0, x, y);
+}
+
+void
+sn_dbus_item_server_emit_scroll (SnDBusItemServer  *server,
+                                 gint               delta,
+                                 SnItemOrientation  orientation)
+{
+  g_signal_emit (server, signals[SCROLL], 0, delta, orientation);
+}
+
+void
+sn_dbus_item_server_emit_hosts_changed (SnDBusItemServer *server,
+                                        gboolean          registered)
+{
+  g_signal_emit (server, signals[HOSTS_CHANGED], 0, registered);
+}
diff --git a/libstatus-notifier/sn-dbus-item-server.h b/libstatus-notifier/sn-dbus-item-server.h
new file mode 100644
index 0000000..270a3eb
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item-server.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_DBUS_ITEM_SERVER_H
+#define SN_DBUS_ITEM_SERVER_H
+
+#include "sn-dbus-item.h"
+
+G_BEGIN_DECLS
+
+#define SN_TYPE_DBUS_ITEM_SERVER sn_dbus_item_server_get_type ()
+G_DECLARE_DERIVABLE_TYPE (SnDBusItemServer, sn_dbus_item_server,
+                          SN, DBUS_ITEM_SERVER, SnDBusItem)
+
+struct _SnDBusItemServerClass
+{
+  SnDBusItemClass parent_class;
+
+  void (* context_menu)       (SnDBusItemServer  *server,
+                               gint               x,
+                               gint               y);
+  void (* activate)           (SnDBusItemServer  *server,
+                               gint               x,
+                               gint               y);
+  void (* secondary_activate) (SnDBusItemServer  *server,
+                               gint               x,
+                               gint               y);
+  void (* scroll)             (SnDBusItemServer  *server,
+                               gint               delta,
+                               SnItemOrientation  orientation);
+
+  void (* hosts_changed)      (SnDBusItemServer  *server,
+                               gboolean           registered);
+};
+
+gboolean sn_dbus_item_server_get_well_known          (SnDBusItemServer  *server);
+
+void     sn_dbus_item_server_emit_context_menu       (SnDBusItemServer  *server,
+                                                      gint               x,
+                                                      gint               y);
+
+void     sn_dbus_item_server_emit_activate           (SnDBusItemServer  *server,
+                                                      gint               x,
+                                                      gint               y);
+
+void     sn_dbus_item_server_emit_secondary_activate (SnDBusItemServer  *server,
+                                                      gint               x,
+                                                      gint               y);
+
+void     sn_dbus_item_server_emit_scroll             (SnDBusItemServer  *server,
+                                                      gint               delta,
+                                                      SnItemOrientation  orientation);
+
+void     sn_dbus_item_server_emit_hosts_changed      (SnDBusItemServer  *server,
+                                                      gboolean           registered);
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-dbus-item.c b/libstatus-notifier/sn-dbus-item.c
new file mode 100644
index 0000000..f6ce152
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sn-dbus-item-server-v0.h"
+#include "sn-dbus-item.h"
+
+typedef struct _SnDBusItemPrivate
+{
+  gchar *bus_name;
+  gchar *object_path;
+} SnDBusItemPrivate;
+
+enum
+{
+  PROP_0,
+
+  PROP_BUS_NAME,
+  PROP_OBJECT_PATH,
+
+  LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+enum
+{
+  ERROR,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SnDBusItem, sn_dbus_item, G_TYPE_OBJECT)
+
+static void
+sn_dbus_item_finalize (GObject *object)
+{
+  SnDBusItem *impl;
+  SnDBusItemPrivate *priv;
+
+  impl = SN_DBUS_ITEM (object);
+  priv = sn_dbus_item_get_instance_private (impl);
+
+  g_free (priv->bus_name);
+  g_free (priv->object_path);
+
+  G_OBJECT_CLASS (sn_dbus_item_parent_class)->finalize (object);
+}
+
+static void
+sn_dbus_item_get_property (GObject    *object,
+                           guint       property_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  SnDBusItem *impl;
+  SnDBusItemPrivate *priv;
+
+  impl = SN_DBUS_ITEM (object);
+  priv = sn_dbus_item_get_instance_private (impl);
+
+  switch (property_id)
+    {
+      case PROP_BUS_NAME:
+        g_value_set_string (value, priv->bus_name);
+        break;
+
+      case PROP_OBJECT_PATH:
+        g_value_set_string (value, priv->object_path);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_dbus_item_set_property (GObject      *object,
+                           guint         property_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  SnDBusItem *impl;
+  SnDBusItemPrivate *priv;
+
+  impl = SN_DBUS_ITEM (object);
+  priv = sn_dbus_item_get_instance_private (impl);
+
+  switch (property_id)
+    {
+      case PROP_BUS_NAME:
+        g_assert (priv->bus_name == NULL);
+        priv->bus_name = g_value_dup_string (value);
+        break;
+
+      case PROP_OBJECT_PATH:
+        g_assert (priv->object_path == NULL);
+        priv->object_path = g_value_dup_string (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_dbus_item_error (SnDBusItem   *item,
+                    const GError *error)
+{
+  if (!g_signal_has_handler_pending (item, signals[ERROR], 0, TRUE))
+    g_assert_not_reached ();
+}
+
+static void
+sn_dbus_item_class_init (SnDBusItemClass *impl_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (impl_class);
+
+  object_class->finalize = sn_dbus_item_finalize;
+  object_class->get_property = sn_dbus_item_get_property;
+  object_class->set_property = sn_dbus_item_set_property;
+
+  impl_class->error = sn_dbus_item_error;
+
+  properties[PROP_BUS_NAME] =
+    g_param_spec_string ("bus-name", "bus-name", "bus-name", NULL,
+                         G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_OBJECT_PATH] =
+    g_param_spec_string ("object-path", "object-path", "object-path", NULL,
+                         G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+  signals[ERROR] =
+    g_signal_new ("error", SN_TYPE_DBUS_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnDBusItemClass, error),
+                  NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR);
+}
+
+static void
+sn_dbus_item_init (SnDBusItem *impl)
+{
+}
+
+const gchar *
+sn_dbus_item_get_attention_icon_name (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_attention_icon_name (impl);
+}
+
+void
+sn_dbus_item_set_attention_icon_name (SnDBusItem  *impl,
+                                      const gchar *attention_icon_name)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_attention_icon_name (impl,
+                                                          attention_icon_name);
+}
+
+GVariant *
+sn_dbus_item_get_attention_icon_pixmap (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_attention_icon_pixmap (impl);
+}
+
+void
+sn_dbus_item_set_attention_icon_pixmap (SnDBusItem *impl,
+                                        GVariant   *attention_icon_pixmap)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_attention_icon_pixmap (impl,
+                                                            attention_icon_pixmap);
+}
+
+const gchar *
+sn_dbus_item_get_attention_movie_name (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_attention_movie_name (impl);
+}
+
+void
+sn_dbus_item_set_attention_movie_name (SnDBusItem  *impl,
+                                       const gchar *attention_movie_name)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_attention_movie_name (impl,
+                                                           attention_movie_name);
+}
+
+SnItemCategory
+sn_dbus_item_get_category (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_category (impl);
+}
+
+void
+sn_dbus_item_set_category (SnDBusItem     *impl,
+                           SnItemCategory  category)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_category (impl, category);
+}
+
+const gchar *
+sn_dbus_item_get_id (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_id (impl);
+}
+
+void
+sn_dbus_item_set_id (SnDBusItem  *impl,
+                     const gchar *id)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_id (impl, id);
+}
+
+const gchar *
+sn_dbus_item_get_icon_name (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_icon_name (impl);
+}
+
+void
+sn_dbus_item_set_icon_name (SnDBusItem  *impl,
+                            const gchar *icon_name)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_icon_name (impl, icon_name);
+}
+
+GVariant *
+sn_dbus_item_get_icon_pixmap (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_icon_pixmap (impl);
+}
+
+void
+sn_dbus_item_set_icon_pixmap (SnDBusItem *impl,
+                              GVariant   *icon_pixmap)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_icon_pixmap (impl, icon_pixmap);
+}
+
+const gchar *
+sn_dbus_item_get_icon_theme_path (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_icon_theme_path (impl);
+}
+
+void
+sn_dbus_item_set_icon_theme_path (SnDBusItem  *impl,
+                                  const gchar *icon_theme_path)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_icon_theme_path (impl, icon_theme_path);
+}
+
+gboolean
+sn_dbus_item_get_item_is_menu (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_item_is_menu (impl);
+}
+
+void
+sn_dbus_item_set_item_is_menu (SnDBusItem *impl,
+                               gboolean    item_is_menu)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_item_is_menu (impl, item_is_menu);
+}
+
+GtkMenu *
+sn_dbus_item_get_menu (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_menu (impl);
+}
+
+void
+sn_dbus_item_set_menu (SnDBusItem *impl,
+                       GtkMenu    *menu)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_menu (impl, menu);
+}
+
+const gchar *
+sn_dbus_item_get_overlay_icon_name (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_overlay_icon_name (impl);
+}
+
+void
+sn_dbus_item_set_overlay_icon_name (SnDBusItem  *impl,
+                                    const gchar *overlay_icon_name)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_overlay_icon_name (impl,
+                                                        overlay_icon_name);
+}
+
+GVariant *
+sn_dbus_item_get_overlay_icon_pixmap (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_overlay_icon_pixmap (impl);
+}
+
+void
+sn_dbus_item_set_overlay_icon_pixmap (SnDBusItem *impl,
+                                      GVariant   *overlay_icon_pixmap)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_overlay_icon_pixmap (impl,
+                                                          overlay_icon_pixmap);
+}
+
+SnItemStatus
+sn_dbus_item_get_status (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_status (impl);
+}
+
+void
+sn_dbus_item_set_status (SnDBusItem   *impl,
+                         SnItemStatus  status)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_status (impl, status);
+}
+
+const gchar *
+sn_dbus_item_get_title (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_title (impl);
+}
+
+void
+sn_dbus_item_set_title (SnDBusItem  *impl,
+                        const gchar *title)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_title (impl, title);
+}
+
+GVariant *
+sn_dbus_item_get_tooltip (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_tooltip (impl);
+}
+
+void
+sn_dbus_item_set_tooltip (SnDBusItem *impl,
+                          GVariant   *tooltip)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_tooltip (impl, tooltip);
+}
+
+gint
+sn_dbus_item_get_window_id (SnDBusItem *impl)
+{
+  return SN_DBUS_ITEM_GET_CLASS (impl)->get_window_id (impl);
+}
+
+void
+sn_dbus_item_set_window_id (SnDBusItem *impl,
+                            gint        window_id)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->set_window_id (impl, window_id);
+}
+
+void
+sn_dbus_item_context_menu (SnDBusItem *impl,
+                           gint        x,
+                           gint        y)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->context_menu (impl, x, y);
+}
+
+void
+sn_dbus_item_activate (SnDBusItem *impl,
+                       gint        x,
+                       gint        y)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->activate (impl, x, y);
+}
+
+void
+sn_dbus_item_secondary_activate (SnDBusItem *impl,
+                                 gint        x,
+                                 gint        y)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->secondary_activate (impl, x, y);
+}
+
+void
+sn_dbus_item_scroll (SnDBusItem        *impl,
+                     gint               delta,
+                     SnItemOrientation  orientation)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->scroll (impl, delta, orientation);
+}
+
+void
+sn_dbus_item_register (SnDBusItem *impl)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->register_ (impl);
+}
+
+void
+sn_dbus_item_unregister (SnDBusItem *impl)
+{
+  SN_DBUS_ITEM_GET_CLASS (impl)->unregister (impl);
+}
+
+const gchar *
+sn_dbus_item_get_bus_name (SnDBusItem *impl)
+{
+  SnDBusItemPrivate *priv;
+
+  priv = sn_dbus_item_get_instance_private (impl);
+
+  return priv->bus_name;
+}
+
+const gchar *
+sn_dbus_item_get_object_path (SnDBusItem *impl)
+{
+  SnDBusItemPrivate *priv;
+
+  priv = sn_dbus_item_get_instance_private (impl);
+
+  return priv->object_path;
+}
+
+void
+sn_dbus_item_emit_error (SnDBusItem   *impl,
+                         const GError *error)
+{
+  g_signal_emit (impl, signals[ERROR], 0, error);
+}
diff --git a/libstatus-notifier/sn-dbus-item.h b/libstatus-notifier/sn-dbus-item.h
new file mode 100644
index 0000000..462d595
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-item.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_DBUS_ITEM_H
+#define SN_DBUS_ITEM_H
+
+#include "sn-item.h"
+
+G_BEGIN_DECLS
+
+#define SN_TYPE_DBUS_ITEM sn_dbus_item_get_type ()
+G_DECLARE_DERIVABLE_TYPE (SnDBusItem, sn_dbus_item, SN, DBUS_ITEM, GObject)
+
+struct _SnDBusItemClass
+{
+  GObjectClass parent_class;
+
+  const gchar *  (* get_attention_icon_name)   (SnDBusItem        *impl);
+  void           (* set_attention_icon_name)   (SnDBusItem        *impl,
+                                                const gchar       *attention_icon_name);
+
+  GVariant *     (* get_attention_icon_pixmap) (SnDBusItem        *impl);
+  void           (* set_attention_icon_pixmap) (SnDBusItem        *impl,
+                                                GVariant          *attention_icon_pixmap);
+
+  const gchar *  (* get_attention_movie_name)  (SnDBusItem        *impl);
+  void           (* set_attention_movie_name)  (SnDBusItem        *impl,
+                                                const gchar       *attention_movie_name);
+
+  SnItemCategory (* get_category)              (SnDBusItem        *impl);
+  void           (* set_category)              (SnDBusItem        *impl,
+                                                SnItemCategory     category);
+
+  const gchar *  (* get_id)                    (SnDBusItem        *impl);
+  void           (* set_id)                    (SnDBusItem        *impl,
+                                                const gchar       *id);
+
+  const gchar *  (* get_icon_name)             (SnDBusItem        *impl);
+  void           (* set_icon_name)             (SnDBusItem        *impl,
+                                                const gchar       *icon_name);
+
+  GVariant *     (* get_icon_pixmap)           (SnDBusItem        *impl);
+  void           (* set_icon_pixmap)           (SnDBusItem        *impl,
+                                                GVariant          *icon_pixmap);
+
+  const gchar *  (* get_icon_theme_path)       (SnDBusItem        *impl);
+  void           (* set_icon_theme_path)       (SnDBusItem        *impl,
+                                                const gchar       *icon_theme_path);
+
+  gboolean       (* get_item_is_menu)          (SnDBusItem        *impl);
+  void           (* set_item_is_menu)          (SnDBusItem        *impl,
+                                                gboolean           item_is_menu);
+
+  GtkMenu *      (* get_menu)                  (SnDBusItem        *impl);
+  void           (* set_menu)                  (SnDBusItem        *impl,
+                                                GtkMenu           *menu);
+
+  const gchar *  (* get_overlay_icon_name)     (SnDBusItem        *impl);
+  void           (* set_overlay_icon_name)     (SnDBusItem        *impl,
+                                                const gchar       *overlay_icon_name);
+
+  GVariant *     (* get_overlay_icon_pixmap)   (SnDBusItem        *impl);
+  void           (* set_overlay_icon_pixmap)   (SnDBusItem        *impl,
+                                                GVariant          *overlay_icon_pixmap);
+
+  SnItemStatus   (* get_status)                (SnDBusItem        *impl);
+  void           (* set_status)                (SnDBusItem        *impl,
+                                                SnItemStatus       status);
+
+  const gchar *  (* get_title)                 (SnDBusItem        *impl);
+  void           (* set_title)                 (SnDBusItem        *impl,
+                                                const gchar       *title);
+
+  GVariant *     (* get_tooltip)               (SnDBusItem        *impl);
+  void           (* set_tooltip)               (SnDBusItem        *impl,
+                                                GVariant          *tooltip);
+
+  gint           (* get_window_id)             (SnDBusItem        *impl);
+  void           (* set_window_id)             (SnDBusItem        *impl,
+                                                gint               window_id);
+
+  void           (* context_menu)              (SnDBusItem        *impl,
+                                                gint               x,
+                                                gint               y);
+  void           (* activate)                  (SnDBusItem        *impl,
+                                                gint               x,
+                                                gint               y);
+  void           (* secondary_activate)        (SnDBusItem        *impl,
+                                                gint               x,
+                                                gint               y);
+  void           (* scroll)                    (SnDBusItem        *impl,
+                                                gint               delta,
+                                                SnItemOrientation  orientation);
+
+  void           (* register_)                 (SnDBusItem        *impl);
+  void           (* unregister)                (SnDBusItem        *impl);
+
+  void           (* error)                     (SnDBusItem        *impl,
+                                                const GError      *error);
+};
+
+const gchar    *sn_dbus_item_get_attention_icon_name   (SnDBusItem        *impl);
+void            sn_dbus_item_set_attention_icon_name   (SnDBusItem        *impl,
+                                                        const gchar       *attention_icon_name);
+
+GVariant       *sn_dbus_item_get_attention_icon_pixmap (SnDBusItem        *impl);
+void            sn_dbus_item_set_attention_icon_pixmap (SnDBusItem        *impl,
+                                                        GVariant          *attention_icon_pixmap);
+
+const gchar    *sn_dbus_item_get_attention_movie_name  (SnDBusItem        *impl);
+void            sn_dbus_item_set_attention_movie_name  (SnDBusItem        *impl,
+                                                        const gchar       *attention_movie_name);
+
+SnItemCategory  sn_dbus_item_get_category              (SnDBusItem        *impl);
+void            sn_dbus_item_set_category              (SnDBusItem        *impl,
+                                                        SnItemCategory     category);
+
+const gchar    *sn_dbus_item_get_id                    (SnDBusItem        *impl);
+void            sn_dbus_item_set_id                    (SnDBusItem        *impl,
+                                                        const gchar       *id);
+
+const gchar    *sn_dbus_item_get_icon_name             (SnDBusItem        *impl);
+void            sn_dbus_item_set_icon_name             (SnDBusItem        *impl,
+                                                        const gchar       *icon_name);
+
+GVariant       *sn_dbus_item_get_icon_pixmap           (SnDBusItem        *impl);
+void            sn_dbus_item_set_icon_pixmap           (SnDBusItem        *impl,
+                                                        GVariant          *icon_pixmap);
+
+const gchar    *sn_dbus_item_get_icon_theme_path       (SnDBusItem        *impl);
+void            sn_dbus_item_set_icon_theme_path       (SnDBusItem        *impl,
+                                                        const gchar       *icon_theme_path);
+
+gboolean        sn_dbus_item_get_item_is_menu          (SnDBusItem        *impl);
+void            sn_dbus_item_set_item_is_menu          (SnDBusItem        *impl,
+                                                        gboolean           item_is_menu);
+
+GtkMenu        *sn_dbus_item_get_menu                  (SnDBusItem        *impl);
+void            sn_dbus_item_set_menu                  (SnDBusItem        *impl,
+                                                        GtkMenu           *menu);
+
+const gchar    *sn_dbus_item_get_overlay_icon_name     (SnDBusItem        *impl);
+void            sn_dbus_item_set_overlay_icon_name     (SnDBusItem        *impl,
+                                                        const gchar       *overlay_icon_name);
+
+GVariant       *sn_dbus_item_get_overlay_icon_pixmap   (SnDBusItem        *impl);
+void            sn_dbus_item_set_overlay_icon_pixmap   (SnDBusItem        *impl,
+                                                        GVariant          *overlay_icon_pixmap);
+
+SnItemStatus    sn_dbus_item_get_status                (SnDBusItem        *impl);
+void            sn_dbus_item_set_status                (SnDBusItem        *impl,
+                                                        SnItemStatus       status);
+
+const gchar    *sn_dbus_item_get_title                 (SnDBusItem        *impl);
+void            sn_dbus_item_set_title                 (SnDBusItem        *impl,
+                                                        const gchar       *title);
+
+GVariant       *sn_dbus_item_get_tooltip               (SnDBusItem        *impl);
+void            sn_dbus_item_set_tooltip               (SnDBusItem        *impl,
+                                                        GVariant          *tooltip);
+
+gint            sn_dbus_item_get_window_id             (SnDBusItem        *impl);
+void            sn_dbus_item_set_window_id             (SnDBusItem        *impl,
+                                                        gint               window_id);
+
+void            sn_dbus_item_context_menu              (SnDBusItem        *impl,
+                                                        gint               x,
+                                                        gint               y);
+void            sn_dbus_item_activate                  (SnDBusItem        *impl,
+                                                        gint               x,
+                                                        gint               y);
+void            sn_dbus_item_secondary_activate        (SnDBusItem        *impl,
+                                                        gint               x,
+                                                        gint               y);
+void            sn_dbus_item_scroll                    (SnDBusItem        *impl,
+                                                        gint               delta,
+                                                        SnItemOrientation  orientation);
+
+void            sn_dbus_item_register                  (SnDBusItem        *impl);
+void            sn_dbus_item_unregister                (SnDBusItem        *impl);
+
+const gchar    *sn_dbus_item_get_bus_name              (SnDBusItem        *impl);
+const gchar    *sn_dbus_item_get_object_path           (SnDBusItem        *impl);
+
+void            sn_dbus_item_emit_error                (SnDBusItem        *impl,
+                                                        const GError      *error);
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-dbus-menu-server.c b/libstatus-notifier/sn-dbus-menu-server.c
new file mode 100644
index 0000000..b730b52
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-menu-server.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sn-dbus-menu-server.h"
+#include "sn-dbus-menu-gen.h"
+
+struct _SnDBusMenuServer
+{
+  GObject  parent;
+
+  GtkMenu *menu;
+  gchar   *object_path;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_MENU,
+  PROP_OBJECT_PATH,
+
+  LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+G_DEFINE_TYPE (SnDBusMenuServer, sn_dbus_menu_server, G_TYPE_OBJECT)
+
+static void
+sn_dbus_menu_server_constructed (GObject *object)
+{
+  G_OBJECT_CLASS (sn_dbus_menu_server_parent_class)->constructed (object);
+}
+
+static void
+sn_dbus_menu_server_dispose (GObject *object)
+{
+  SnDBusMenuServer *server;
+
+  server = SN_DBUS_MENU_SERVER (object);
+
+  if (server->menu != NULL)
+    {
+      gtk_widget_destroy (GTK_WIDGET (server->menu));
+      server->menu = NULL;
+    }
+
+  G_OBJECT_CLASS (sn_dbus_menu_server_parent_class)->dispose (object);
+}
+
+static void
+sn_dbus_menu_server_finalize (GObject *object)
+{
+  SnDBusMenuServer *server;
+
+  server = SN_DBUS_MENU_SERVER (object);
+
+  g_free (server->object_path);
+
+  G_OBJECT_CLASS (sn_dbus_menu_server_parent_class)->finalize (object);
+}
+
+static void
+sn_dbus_menu_server_set_property (GObject      *object,
+                                  guint         property_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  SnDBusMenuServer *server;
+
+  server = SN_DBUS_MENU_SERVER (object);
+
+  switch (property_id)
+    {
+      case PROP_MENU:
+        server->menu = g_value_dup_object (value);
+        break;
+
+      case PROP_OBJECT_PATH:
+        server->object_path = g_value_dup_string (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_dbus_menu_server_class_init (SnDBusMenuServerClass *server_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (server_class);
+
+  object_class->constructed = sn_dbus_menu_server_constructed;
+  object_class->dispose = sn_dbus_menu_server_dispose;
+  object_class->finalize = sn_dbus_menu_server_finalize;
+  object_class->set_property = sn_dbus_menu_server_set_property;
+
+  properties[PROP_MENU] =
+    g_param_spec_object ("menu", "menu", "menu", GTK_TYPE_MENU,
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                         G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_OBJECT_PATH] =
+    g_param_spec_string ("object-path", "object-path", "object-path", NULL,
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                         G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+sn_dbus_menu_server_init (SnDBusMenuServer *server)
+{
+}
+
+SnDBusMenuServer *
+sn_dbus_menu_server_new (GtkMenu     *menu,
+                         const gchar *object_path)
+{
+  return g_object_new (SN_TYPE_DBUS_MENU_SERVER,
+                       "menu", menu,
+                       "object-path", object_path,
+                       NULL);
+}
diff --git a/libstatus-notifier/sn-dbus-menu-server.h b/libstatus-notifier/sn-dbus-menu-server.h
new file mode 100644
index 0000000..2367364
--- /dev/null
+++ b/libstatus-notifier/sn-dbus-menu-server.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_DBUS_MENU_SERVER_H
+#define SN_DBUS_MENU_SERVER_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define SN_TYPE_DBUS_MENU_SERVER sn_dbus_menu_server_get_type ()
+G_DECLARE_FINAL_TYPE (SnDBusMenuServer, sn_dbus_menu_server,
+                      SN, DBUS_MENU_SERVER, GObject)
+
+SnDBusMenuServer *sn_dbus_menu_server_new (GtkMenu     *menu,
+                                           const gchar *object_path);
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-enum-types.c.in b/libstatus-notifier/sn-enum-types.c.in
new file mode 100644
index 0000000..f8457f7
--- /dev/null
+++ b/libstatus-notifier/sn-enum-types.c.in
@@ -0,0 +1,37 @@
+/*** BEGIN file-header ***/
+#include "sn-enum-types.h"
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@filename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+
+GType
+@enum_name@_get_type (void)
+{
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+        { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+/*** END value-tail ***/
diff --git a/libstatus-notifier/sn-enum-types.h.in b/libstatus-notifier/sn-enum-types.h.in
new file mode 100644
index 0000000..5bf3eda
--- /dev/null
+++ b/libstatus-notifier/sn-enum-types.h.in
@@ -0,0 +1,21 @@
+/*** BEGIN file-header ***/
+#ifndef SN_ENUM_TYPES_H
+#define SN_ENUM_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define SN_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif
+/*** END file-tail ***/
diff --git a/libstatus-notifier/sn-item-private.h b/libstatus-notifier/sn-item-private.h
new file mode 100644
index 0000000..96836cf
--- /dev/null
+++ b/libstatus-notifier/sn-item-private.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_ITEM_PRIVATE_H
+#define SN_ITEM_PRIVATE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define SN_ITEM_V0_BUS_NAME "org.kde.StatusNotifierItem"
+#define SN_ITEM_V0_OBJECT_PATH "/StatusNotifierItem"
+#define SN_ITEM_V0_INTERFACE "org.kde.StatusNotifierItem"
+
+#define SN_ITEM_V1_BUS_NAME "org.freedesktop.StatusNotifier1.Item"
+#define SN_ITEM_V1_OBJECT_PATH "/org/freedesktop/StatusNotifier1/Item"
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-item.c b/libstatus-notifier/sn-item.c
new file mode 100644
index 0000000..62bec4f
--- /dev/null
+++ b/libstatus-notifier/sn-item.c
@@ -0,0 +1,1406 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION: sn-item
+ * @title: SnItem
+ * @short_description: A Status Notifier Item
+ *
+ * A Status Notifier Item
+ */
+
+/**
+ * SnItem:
+ *
+ * #SnItem is an opaque data structure and can only be accessed using the
+ * following functions.
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "sn-dbus-item-server-v0.h"
+#include "sn-dbus-item.h"
+#include "sn-enum-types.h"
+#include "sn-item.h"
+
+typedef struct _SnItemPrivate SnItemPrivate;
+struct _SnItemPrivate
+{
+  guint            version;
+
+  SnItemCategory   category;
+  gchar           *id;
+
+  SnDBusItem      *impl;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_VERSION,
+
+  PROP_CATEGORY,
+  PROP_ID,
+  PROP_TITLE,
+  PROP_STATUS,
+
+  LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+enum
+{
+  CONTEXT_MENU,
+  ACTIVATE,
+  SECONDARY_ACTIVATE,
+  SCROLL,
+
+  ERROR,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_PRIVATE (SnItem, sn_item, G_TYPE_OBJECT)
+
+static GdkPixbuf **
+gvariant_to_gdk_pixbufs (GVariant *variant)
+{
+  GVariantIter iter;
+  gsize n_pixbufs;
+  GdkPixbuf **pixbufs;
+  guint i;
+  gint width;
+  gint height;
+  GVariant *value;
+
+  n_pixbufs = g_variant_iter_init (&iter, variant);
+  if (n_pixbufs == 0)
+    return NULL;
+
+  pixbufs = g_new0 (GdkPixbuf *, n_pixbufs + 1);
+  i = 0;
+
+  while (g_variant_iter_next (&iter, "(ii@ay)", &width, &height, &value))
+    {
+      GBytes *bytes;
+      gint rowstride;
+
+      bytes = g_variant_get_data_as_bytes (value);
+      rowstride = g_bytes_get_size (bytes) / height;
+
+      pixbufs[i++] = gdk_pixbuf_new_from_bytes (bytes, GDK_COLORSPACE_RGB,
+                                                TRUE, 8, width, height,
+                                                rowstride);
+
+      g_bytes_unref (bytes);
+      g_variant_unref (value);
+    }
+
+  pixbufs[i] = NULL;
+
+  return pixbufs;
+}
+
+static GVariantBuilder *
+gdk_pixbufs_to_gvariant_builder (GdkPixbuf **pixbufs)
+{
+  GVariantBuilder *builder;
+  guint i;
+
+  builder = g_variant_builder_new (G_VARIANT_TYPE ("a(iiay)"));
+
+  if (pixbufs == NULL)
+    return builder;
+
+  for (i = 0; pixbufs[i] != NULL; i++)
+    {
+      gint width;
+      gint height;
+      GBytes *bytes;
+      GVariant *variant;
+
+      width = gdk_pixbuf_get_width (pixbufs[i]);
+      height = gdk_pixbuf_get_height (pixbufs[i]);
+      bytes = gdk_pixbuf_read_pixel_bytes (pixbufs[i]);
+
+      variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), bytes, TRUE);
+      g_bytes_unref (bytes);
+
+      g_variant_builder_open (builder, G_VARIANT_TYPE ("(iiay)"));
+      g_variant_builder_add (builder, "i", width);
+      g_variant_builder_add (builder, "i", height);
+      g_variant_builder_add_value (builder, variant);
+      g_variant_builder_close (builder);
+    }
+
+  return builder;
+}
+
+static void
+context_menu_cb (SnDBusItemServer *server,
+                 gint              x,
+                 gint              y,
+                 SnItem           *item)
+{
+  g_signal_emit (item, signals[CONTEXT_MENU], 0, x, y);
+}
+
+static void
+activate_cb (SnDBusItemServer *server,
+             gint              x,
+             gint              y,
+             SnItem           *item)
+{
+  g_signal_emit (item, signals[ACTIVATE], 0, x, y);
+}
+
+static void
+secondary_activate_cb (SnDBusItemServer *server,
+                       gint              x,
+                       gint              y,
+                       SnItem           *item)
+{
+  g_signal_emit (item, signals[SECONDARY_ACTIVATE], 0, x, y);
+}
+
+static void
+scroll_cb (SnDBusItemServer  *server,
+           gint               delta,
+           SnItemOrientation  orientation,
+           SnItem            *item)
+{
+  g_signal_emit (item, signals[SCROLL], 0, delta, orientation);
+}
+
+static void
+hosts_changed_cb (SnDBusItemServer *server,
+                  gboolean          is_host_registered,
+                  SnItem           *item)
+{
+}
+
+static void
+error_cb (SnDBusItem   *dbus_item,
+          const GError *error,
+          SnItem       *item)
+{
+  g_signal_emit (item, signals[ERROR], 0, error);
+}
+
+static void
+sn_item_constructed (GObject *object)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+  GType type;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  G_OBJECT_CLASS (sn_item_parent_class)->constructed (object);
+
+    {
+#if 0
+      if (priv->version == 1)
+        type = SN_TYPE_DBUS_ITEM_SERVER_V1;
+      else
+        type = SN_TYPE_DBUS_ITEM_SERVER_V0;
+#endif
+
+      type = SN_TYPE_DBUS_ITEM_SERVER_V0;
+      priv->impl = g_object_new (type,
+                                 "well-known", FALSE,
+                                 NULL);
+
+      g_signal_connect (priv->impl, "context-menu",
+                        G_CALLBACK (context_menu_cb), item);
+      g_signal_connect (priv->impl, "activate",
+                        G_CALLBACK (activate_cb), item);
+      g_signal_connect (priv->impl, "secondary-activate",
+                        G_CALLBACK (secondary_activate_cb), item);
+      g_signal_connect (priv->impl, "scroll",
+                        G_CALLBACK (scroll_cb), item);
+      g_signal_connect (priv->impl, "hosts-changed",
+                        G_CALLBACK (hosts_changed_cb), item);
+
+      sn_dbus_item_set_category (priv->impl, priv->category);
+      sn_dbus_item_set_id (priv->impl, priv->id);
+    }
+
+  g_signal_connect (priv->impl, "error", G_CALLBACK (error_cb), item);
+}
+
+static void
+sn_item_dispose (GObject *object)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  g_clear_object (&priv->impl);
+
+  G_OBJECT_CLASS (sn_item_parent_class)->dispose (object);
+}
+
+static void
+sn_item_finalize (GObject *object)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  g_free (priv->id);
+
+  G_OBJECT_CLASS (sn_item_parent_class)->finalize (object);
+}
+
+static void
+sn_item_get_property (GObject    *object,
+                      guint       property_id,
+                      GValue     *value,
+                      GParamSpec *pspec)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  switch (property_id)
+    {
+      case PROP_VERSION:
+        g_value_set_uint (value, priv->version);
+        break;
+
+      case PROP_CATEGORY:
+        g_value_set_enum (value, priv->category);
+        break;
+
+      case PROP_ID:
+        g_value_set_string (value, priv->id);
+        break;
+
+      case PROP_TITLE:
+        g_value_set_string (value, sn_item_get_title (item));
+        break;
+
+      case PROP_STATUS:
+        g_value_set_enum (value, sn_item_get_status (item));
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_item_set_property (GObject      *object,
+                      guint         property_id,
+                      const GValue *value,
+                      GParamSpec   *pspec)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  switch (property_id)
+    {
+      case PROP_VERSION:
+        priv->version = g_value_get_uint (value);
+        break;
+
+      case PROP_CATEGORY:
+        priv->category = g_value_get_enum (value);
+        break;
+
+      case PROP_ID:
+        priv->id = g_value_dup_string (value);
+        break;
+
+      case PROP_TITLE:
+        sn_item_set_title (item, g_value_get_string (value));
+        break;
+
+      case PROP_STATUS:
+        sn_item_set_status (item, g_value_get_enum (value));
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+sn_item_error (SnItem       *item,
+               const GError *error)
+{
+  if (!g_signal_has_handler_pending (item, signals[ERROR], 0, TRUE))
+    g_warning ("SnItem error: %s", error->message);
+}
+
+static void
+sn_item_class_init (SnItemClass *item_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (item_class);
+
+  object_class->constructed = sn_item_constructed;
+  object_class->dispose = sn_item_dispose;
+  object_class->finalize = sn_item_finalize;
+  object_class->get_property = sn_item_get_property;
+  object_class->set_property = sn_item_set_property;
+
+  item_class->error = sn_item_error;
+
+  properties[PROP_VERSION] =
+    g_param_spec_uint ("version", "version", "version", 0, G_MAXUINT, 0,
+                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS);
+
+  /**
+   * SnItem:category:
+   *
+   * Describes the category of this item.
+   */
+  properties[PROP_CATEGORY] =
+    g_param_spec_enum ("category",
+                       "Category",
+                       "Describes the category of this item.",
+                       SN_TYPE_ITEM_CATEGORY,
+                       SN_ITEM_CATEGORY_APPLICATION_STATUS,
+                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS);
+
+  /**
+   * SnItem:id:
+   *
+   * It's a name that should be unique for this application and consistent
+   * between sessions, such as the application name itself.
+   */
+  properties[PROP_ID] =
+    g_param_spec_string ("id",
+                         "Id",
+                         "Unique application identifier",
+                         NULL,
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS);
+
+  /**
+   * SnItem:title:
+   *
+   * It's a name that describes the application, it can be more descriptive
+   * than Id.
+   */
+  properties[PROP_TITLE] =
+    g_param_spec_string ("title",
+                         "Title",
+                         "It's a name that describes the application",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * SnItem:status:
+   *
+   * Describes the status of this item or of the associated application.
+   */
+  properties[PROP_STATUS] =
+    g_param_spec_enum ("status",
+                       "Status",
+                       "Status of the item",
+                       SN_TYPE_ITEM_STATUS,
+                       SN_ITEM_STATUS_PASSIVE,
+                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+
+  /**
+   * SnItem::context-menu:
+   * @item: the object on which the signal is emitted
+   * @x: the x coordinate on screen
+   * @y: the y coordinate on screen
+   *
+   * Asks the status notifier item to show a context menu, this is
+   * typically a consequence of user input, such as mouse right click over
+   * the graphical representation of the item.
+   *
+   * The x and y parameters are in screen coordinates and is to be
+   * considered an hint to the item about where to show the context menu.
+   */
+  signals[CONTEXT_MENU] =
+    g_signal_new ("context-menu", SN_TYPE_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, context_menu),
+                  NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
+  /**
+   * SnItem::activate:
+   * @item: the object on which the signal is emitted
+   * @x: the x coordinate on screen
+   * @y: the y coordinate on screen
+   *
+   * Asks the status notifier item for activation, this is typically a
+   * consequence of user input, such as mouse left click over the graphical
+   * representation of the item. The application will perform any task is
+   * considered appropriate as an activation request.
+   *
+   * The x and y parameters are in screen coordinates and is to be
+   * considered an hint to the item where to show eventual windows (if any).
+   */
+  signals[ACTIVATE] =
+    g_signal_new ("activate", SN_TYPE_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, activate),
+                  NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
+  /**
+   * SnItem::secondary-activate:
+   * @item: the object on which the signal is emitted
+   * @x: the x coordinate on screen
+   * @y: the y coordinate on screen
+   *
+   * Is to be considered a secondary and less important form of activation
+   * compared to Activate. This is typically a consequence of user input,
+   * such as mouse middle click over the graphical representation of the
+   * item. The application will perform any task is considered appropriate
+   * as an activation request.
+   *
+   * The x and y parameters are in screen coordinates and is to be
+   * considered an hint to the item where to show eventual windows (if any).
+   */
+  signals[SECONDARY_ACTIVATE] =
+    g_signal_new ("secondary-activate", SN_TYPE_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, secondary_activate),
+                  NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
+  /**
+   * SnItem::scroll:
+   * @item: the object on which the signal is emitted
+   * @delta: the amount of scroll
+   * @orientation: orientation of the scroll request
+   *
+   * The user asked for a scroll action. This is caused from input such as
+   * mouse wheel over the graphical representation of the item.
+   *
+   * The delta parameter represent the amount of scroll, the orientation
+   * parameter represent the horizontal or vertical orientation of the
+   * scroll request and its legal values are horizontal and vertical.
+   */
+  signals[SCROLL] =
+    g_signal_new ("scroll", SN_TYPE_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, scroll), NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, G_TYPE_INT, SN_TYPE_ITEM_ORIENTATION);
+
+  /**
+   * SnItem::error:
+   * @item: the object on which the signal is emitted
+   * @error: the #GError
+   *
+   * The ::error signal is emitted when error has occurred.
+   */
+  signals[ERROR] =
+    g_signal_new ("error", SN_TYPE_ITEM, G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, error), NULL,
+                  NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR);
+}
+
+static void
+sn_item_init (SnItem *item)
+{
+}
+
+/**
+ * sn_item_new_v0:
+ * @category: the category of this item.
+ * @id: unique application identifier
+ *
+ * Creates a new #SnItem.
+ *
+ * Returns: (transfer full): a newly created #SnItem.
+ */
+SnItem *
+sn_item_new_v0 (SnItemCategory  category,
+                const gchar    *id)
+{
+  return g_object_new (SN_TYPE_ITEM,
+                       "version", 0,
+                       "category", category,
+                       "id", id,
+                       NULL);
+}
+
+/**
+ * sn_item_new_v1:
+ * @category: the category of this item.
+ * @id: unique application identifier
+ *
+ * Creates a new #SnItem.
+ *
+ * Returns: (transfer full): a newly created #SnItem.
+ */
+SnItem *
+sn_item_new_v1 (SnItemCategory  category,
+                const gchar    *id)
+{
+  return g_object_new (SN_TYPE_ITEM,
+                       "version", 1,
+                       "category", category,
+                       "id", id,
+                       NULL);
+}
+
+/**
+ * sn_item_get_attention_icon_name:
+ * @item: a #SnItem
+ *
+ * Returns the attention icon name.
+ *
+ * Returns: the attention icon name.
+ */
+const gchar *
+sn_item_get_attention_icon_name (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_attention_icon_name (priv->impl);
+}
+
+/**
+ * sn_item_set_attention_icon_name:
+ * @item: a #SnItem
+ * @attention_icon_name: the attention icon pixmap
+ *
+ * Set the attention icon pixmap.
+ */
+void
+sn_item_set_attention_icon_name (SnItem      *item,
+                                 const gchar *attention_icon_name)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_attention_icon_name (priv->impl, attention_icon_name);
+}
+
+/**
+ * sn_item_get_attention_icon_pixbufs:
+ * @item: a #SnItem
+ *
+ * Returns the attention icon pixbufs.
+ *
+ * Returns: (transfer full): the attention icon pixbufs.
+ */
+GdkPixbuf **
+sn_item_get_attention_icon_pixbufs (SnItem *item)
+{
+  SnItemPrivate *priv;
+  GVariant *variant;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  variant = sn_dbus_item_get_attention_icon_pixmap (priv->impl);
+
+  return gvariant_to_gdk_pixbufs (variant);
+}
+
+/**
+ * sn_item_set_attention_icon_pixbufs:
+ * @item: a #SnItem
+ * @attention_icon_pixbufs: the attention icon pixbufs
+ *
+ * Set the attention icon pixbufs.
+ */
+void
+sn_item_set_attention_icon_pixbufs (SnItem     *item,
+                                    GdkPixbuf **attention_icon_pixbufs)
+{
+  SnItemPrivate *priv;
+  GVariantBuilder *builder;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  builder = gdk_pixbufs_to_gvariant_builder (attention_icon_pixbufs);
+
+  sn_dbus_item_set_attention_icon_pixmap (priv->impl,
+                                          g_variant_builder_end (builder));
+  g_variant_builder_unref (builder);
+}
+
+/**
+ * sn_item_get_attention_movie_name:
+ * @item: a #SnItem
+ *
+ * Returns the attention movie name.
+ *
+ * Returns: the attention movie name.
+ */
+const gchar *
+sn_item_get_attention_movie_name (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_attention_movie_name (priv->impl);
+}
+
+/**
+ * sn_item_set_attention_movie_name:
+ * @item: a #SnItem
+ * @attention_movie_name: the attention movie name
+ *
+ * Set the attention movie name.
+ */
+void
+sn_item_set_attention_movie_name (SnItem      *item,
+                                  const gchar *attention_movie_name)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_attention_movie_name (priv->impl, attention_movie_name);
+}
+
+/**
+ * sn_item_get_category:
+ * @item: a #SnItem
+ *
+ * Returns the category of @item.
+ *
+ * Returns: the #SnItemCategory of @item.
+ */
+SnItemCategory
+sn_item_get_category (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), SN_ITEM_CATEGORY_APPLICATION_STATUS);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_category (priv->impl);
+}
+
+/**
+ * sn_item_get_id:
+ * @item: a #SnItem
+ *
+ * Returns the id of @item.
+ *
+ * Returns: the id of @item.
+ */
+const gchar *
+sn_item_get_id (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_id (priv->impl);
+}
+
+/**
+ * sn_item_get_icon_name:
+ * @item: a #SnItem
+ *
+ * Returns the icon name.
+ *
+ * Returns: the icon name.
+ */
+const gchar *
+sn_item_get_icon_name (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_icon_name (priv->impl);
+}
+
+/**
+ * sn_item_set_icon_name:
+ * @item: a #SnItem
+ * @icon_name: the icon name
+ *
+ * Set the icon name.
+ */
+void
+sn_item_set_icon_name (SnItem      *item,
+                       const gchar *icon_name)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_icon_name (priv->impl, icon_name);
+}
+
+/**
+ * sn_item_get_icon_pixbufs:
+ * @item: a #SnItem
+ *
+ * Returns the icon pixbufs.
+ *
+ * Returns: (transfer full): the icon pixbufs
+ */
+GdkPixbuf **
+sn_item_get_icon_pixbufs (SnItem *item)
+{
+  SnItemPrivate *priv;
+  GVariant *variant;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  variant = sn_dbus_item_get_icon_pixmap (priv->impl);
+
+  return gvariant_to_gdk_pixbufs (variant);
+}
+
+/**
+ * sn_item_set_icon_pixbufs:
+ * @item: a #SnItem
+ * @icon_pixbufs: the icon pixbufs
+ *
+ * Set the icon pixbufs.
+ */
+void
+sn_item_set_icon_pixbufs (SnItem     *item,
+                          GdkPixbuf **icon_pixbufs)
+{
+  SnItemPrivate *priv;
+  GVariantBuilder *builder;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  builder = gdk_pixbufs_to_gvariant_builder (icon_pixbufs);
+
+  sn_dbus_item_set_icon_pixmap (priv->impl, g_variant_builder_end (builder));
+  g_variant_builder_unref (builder);
+}
+
+/**
+ * sn_item_get_icon_theme_path:
+ * @item: a #SnItem
+ *
+ * Returns the icon theme path.
+ *
+ * Returns: the icon theme path.
+ */
+const gchar *
+sn_item_get_icon_theme_path (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_icon_theme_path (priv->impl);
+}
+
+/**
+ * sn_item_set_icon_theme_path:
+ * @item: a #SnItem
+ * @icon_theme_path: the icon theme path
+ *
+ * Set the icon theme path.
+ */
+void
+sn_item_set_icon_theme_path (SnItem      *item,
+                             const gchar *icon_theme_path)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_icon_theme_path (priv->impl, icon_theme_path);
+}
+
+/**
+ * sn_item_get_item_is_menu:
+ * @item: a #SnItem
+ *
+ * Returns if item is menu.
+ *
+ * Returns: %TRUE if @item is menu, %FALSE otherwise.
+ */
+gboolean
+sn_item_get_item_is_menu (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), FALSE);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_item_is_menu (priv->impl);
+}
+
+/**
+ * sn_item_set_item_is_menu:
+ * @item: a #SnItem
+ * @item_is_menu: %TRUE if @item is menu
+ *
+ * Set if this @item is menu. Default is %FALSE.
+ */
+void
+sn_item_set_item_is_menu (SnItem   *item,
+                          gboolean  item_is_menu)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_item_is_menu (priv->impl, item_is_menu);
+}
+
+/**
+ * sn_item_get_menu:
+ * @item: a #SnItem
+ *
+ * Returns the menu.
+ *
+ * Returns: (transfer none): the menu.
+ */
+GtkMenu *
+sn_item_get_menu (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_menu (priv->impl);
+}
+
+/**
+ * sn_item_set_menu:
+ * @item: a #SnItem
+ * @menu: the menu
+ *
+ * Set the menu.
+ */
+void
+sn_item_set_menu (SnItem  *item,
+                  GtkMenu *menu)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_menu (priv->impl, menu);
+}
+
+/**
+ * sn_item_get_overlay_icon_name:
+ * @item: a #SnItem
+ *
+ * Returns the overlay icon name.
+ *
+ * Returns: the overlay icon name.
+ */
+const gchar *
+sn_item_get_overlay_icon_name (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_overlay_icon_name (priv->impl);
+}
+
+/**
+ * sn_item_set_overlay_icon_name:
+ * @item: a #SnItem
+ * @overlay_icon_name: the overlay icon name
+ *
+ * Set the overlay icon name.
+ */
+void
+sn_item_set_overlay_icon_name (SnItem      *item,
+                               const gchar *overlay_icon_name)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_overlay_icon_name (priv->impl, overlay_icon_name);
+}
+
+/**
+ * sn_item_get_overlay_icon_pixbufs:
+ * @item: a #SnItem
+ *
+ * Returns the overlay icon pixbufs.
+ *
+ * Returns: (transfer full): the overlay icon pixbufs.
+ */
+GdkPixbuf **
+sn_item_get_overlay_icon_pixbufs (SnItem *item)
+{
+  SnItemPrivate *priv;
+  GVariant *variant;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  variant = sn_dbus_item_get_overlay_icon_pixmap (priv->impl);
+
+  return gvariant_to_gdk_pixbufs (variant);
+}
+
+/**
+ * sn_item_set_overlay_icon_pixbufs:
+ * @item: a #SnItem
+ * @overlay_icon_pixbufs: the overlay icon pixbufs
+ *
+ * Set the overlay icon pixbufs.
+ */
+void
+sn_item_set_overlay_icon_pixbufs (SnItem     *item,
+                                  GdkPixbuf **overlay_icon_pixbufs)
+{
+  SnItemPrivate *priv;
+  GVariantBuilder *builder;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  builder = gdk_pixbufs_to_gvariant_builder (overlay_icon_pixbufs);
+
+  sn_dbus_item_set_overlay_icon_pixmap (priv->impl,
+                                        g_variant_builder_end (builder));
+  g_variant_builder_unref (builder);
+}
+
+/**
+ * sn_item_get_status:
+ * @item: a #SnItem
+ *
+ * Returns the status of @item.
+ *
+ * Returns: the #SnItemStatus of @item.
+ */
+SnItemStatus
+sn_item_get_status (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), SN_ITEM_STATUS_PASSIVE);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_status (priv->impl);
+}
+
+/**
+ * sn_item_set_status:
+ * @item: a #SnItem
+ * @status: the #SnItemStatus
+ *
+ * Set the status of this @item.
+ */
+void
+sn_item_set_status (SnItem       *item,
+                    SnItemStatus  status)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_status (priv->impl, status);
+}
+
+/**
+ * sn_item_get_title:
+ * @item: a #SnItem
+ *
+ * Returns the title of @item.
+ *
+ * Returns: the title of @item.
+ */
+const gchar *
+sn_item_get_title (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), NULL);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_title (priv->impl);
+}
+
+/**
+ * sn_item_set_title:
+ * @item: a #SnItem
+ * @title: the title.
+ *
+ * Set the title of this @item.
+ */
+void
+sn_item_set_title (SnItem      *item,
+                   const gchar *title)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_title (priv->impl, title);
+}
+
+/**
+ * sn_item_get_tooltip:
+ * @item: a #SnItem
+ * @icon_name: (out) (allow-none) (transfer none): location to store the
+ *     icon name, or %NULL
+ * @icon_pixbufs: (out) (allow-none) (transfer full): location to store the
+ *     icon pixbufs, or %NULL
+ * @title: (out) (allow-none) (transfer none): location to store the title,
+ *     or %NULL
+ * @text: (out) (allow-none) (transfer none): location to store the text, or
+ *     %NULL
+ *
+ * Get the tooltip.
+ *
+ * Returns: %TRUE if the tooltop exists, %FALSE otherwise.
+ */
+gboolean
+sn_item_get_tooltip (SnItem        *item,
+                     const gchar  **icon_name,
+                     GdkPixbuf   ***icon_pixbufs,
+                     const gchar  **title,
+                     const gchar  **text)
+{
+  SnItemPrivate *priv;
+  GVariant *tooltip;
+  const gchar *tmp_icon_name;
+  GVariant *variant;
+  const gchar *tmp_title;
+  const gchar *tmp_text;
+
+  if (icon_name)
+    *icon_name = NULL;
+
+  if (icon_pixbufs)
+    g_assert (*icon_pixbufs == NULL);
+
+  if (title)
+    *title = NULL;
+
+  if (text)
+    *text = NULL;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), FALSE);
+
+  priv = sn_item_get_instance_private (item);
+  tooltip = sn_dbus_item_get_tooltip (priv->impl);
+
+  if (tooltip == NULL)
+    return FALSE;
+
+  g_variant_get (tooltip, "(&sa(iiay)&s&s)", &tmp_icon_name,
+                 &variant, &tmp_title, &tmp_text);
+
+  if (icon_name && *tmp_icon_name != '\0')
+    *icon_name = tmp_icon_name;
+
+  if (icon_pixbufs)
+    *icon_pixbufs = gvariant_to_gdk_pixbufs (variant);
+
+  if (title && *tmp_title != '\0')
+    *title = tmp_title;
+
+  if (text && *tmp_text != '\0')
+    *text = tmp_text;
+
+  return TRUE;
+}
+
+/**
+ * sn_item_set_tooltip:
+ * @item: a #SnItem
+ * @icon_name: the icon name
+ * @icon_pixbufs: the icon pixbufs
+ * @title: the title
+ * @text: the text
+ *
+ * Set the tooltip.
+ */
+void
+sn_item_set_tooltip (SnItem       *item,
+                     const gchar  *icon_name,
+                     GdkPixbuf   **icon_pixbufs,
+                     const gchar  *title,
+                     const gchar  *text)
+{
+  SnItemPrivate *priv;
+  GVariantBuilder *builder;
+  GVariant *tooltip;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  builder = gdk_pixbufs_to_gvariant_builder (icon_pixbufs);
+  tooltip = g_variant_new ("(sa(iiay)ss)", icon_name ? icon_name : "",
+                           builder, title ? title : "", text ? text : "");
+
+  sn_dbus_item_set_tooltip (priv->impl, tooltip);
+}
+
+/**
+ * sn_item_get_window_id:
+ * @item: a #SnItem
+ *
+ * Returns the window id.
+ *
+ * Returns: the window id.
+ */
+gint
+sn_item_get_window_id (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_val_if_fail (SN_IS_ITEM (item), 0);
+
+  priv = sn_item_get_instance_private (item);
+
+  return sn_dbus_item_get_window_id (priv->impl);
+}
+
+/**
+ * sn_item_set_window_id:
+ * @item: a #SnItem
+ * @window_id: the window id
+ *
+ * Set the window id for this @item.
+ */
+void
+sn_item_set_window_id (SnItem *item,
+                       gint    window_id)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_set_window_id (priv->impl, window_id);
+}
+
+/**
+ * sn_item_context_menu:
+ * @item: a #SnItem
+ * @x: the x coordinate on screen
+ * @y: the y coordinate on screen
+ *
+ * Asks the status notifier item to show a context menu, this is typically
+ * a consequence of user input, such as mouse right click over the graphical
+ * representation of the item.
+ *
+ * The x and y parameters are in screen coordinates and is to be considered
+ * an hint to the item about where to show the context menu.
+ */
+void
+sn_item_context_menu (SnItem *item,
+                      gint    x,
+                      gint    y)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_context_menu (priv->impl, x, y);
+}
+
+/**
+ * sn_item_activate:
+ * @item: a #SnItem
+ * @x: the x coordinate on screen
+ * @y: the y coordinate on screen
+ *
+ * Asks the status notifier item for activation, this is typically a
+ * consequence of user input, such as mouse left click over the graphical
+ * representation of the item. The application will perform any task is
+ * considered appropriate as an activation request.
+ *
+ * The x and y parameters are in screen coordinates and is to be considered
+ * an hint to the item where to show eventual windows (if any).
+ */
+void
+sn_item_activate (SnItem *item,
+                  gint    x,
+                  gint    y)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_activate (priv->impl, x, y);
+}
+
+/**
+ * sn_item_secondary_activate:
+ * @item: a #SnItem
+ * @x: the x coordinate on screen
+ * @y: the y coordinate on screen
+ *
+ * Is to be considered a secondary and less important form of activation
+ * compared to Activate. This is typically a consequence of user input, such
+ * as mouse middle click over the graphical representation of the item. The
+ * application will perform any task is considered appropriate as an
+ * activation request.
+ *
+ * The x and y parameters are in screen coordinates and is to be considered
+ * an hint to the item where to show eventual windows (if any).
+ */
+void
+sn_item_secondary_activate (SnItem *item,
+                            gint    x,
+                            gint    y)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_secondary_activate (priv->impl, x, y);
+}
+
+/**
+ * sn_item_scroll:
+ * @item: a #SnItem
+ * @delta: the amount of scroll
+ * @orientation: orientation of the scroll request
+ *
+ * The user asked for a scroll action. This is caused from input such as
+ * mouse wheel over the graphical representation of the item.
+ *
+ * The delta parameter represent the amount of scroll, the orientation
+ * parameter represent the horizontal or vertical orientation of the scroll
+ * request and its legal values are horizontal and vertical.
+ */
+void
+sn_item_scroll (SnItem            *item,
+                gint               delta,
+                SnItemOrientation  orientation)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_scroll (priv->impl, delta, orientation);
+}
+
+/**
+ * sn_item_register:
+ * @item: a #SnItem
+ *
+ * Register @item with Status Notifier Watcher.
+ */
+void
+sn_item_register (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_register (priv->impl);
+}
+
+/**
+ * sn_item_unregister:
+ * @item: a #SnItem
+ *
+ * Unregister @item from Status Notifier Watcher.
+ */
+void
+sn_item_unregister (SnItem *item)
+{
+  SnItemPrivate *priv;
+
+  g_return_if_fail (SN_IS_ITEM (item));
+
+  priv = sn_item_get_instance_private (item);
+
+  sn_dbus_item_unregister (priv->impl);
+}
diff --git a/libstatus-notifier/sn-item.h b/libstatus-notifier/sn-item.h
new file mode 100644
index 0000000..4af3919
--- /dev/null
+++ b/libstatus-notifier/sn-item.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_ITEM_H
+#define SN_ITEM_H
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/**
+ * SN_TYPE_ITEM:
+ *
+ * The type for SnItem.
+ */
+#define SN_TYPE_ITEM sn_item_get_type ()
+G_DECLARE_DERIVABLE_TYPE (SnItem, sn_item, SN, ITEM, GObject)
+
+/**
+ * SnItemCategory:
+ * @SN_ITEM_CATEGORY_APPLICATION_STATUS: The item describes the status
+ *     of a generic application, for instance the current state of a media
+ *     player. In the case where the category of the item can not be known,
+ *     such as when the item is being proxied from another incompatible or
+ *     emulated system, ApplicationStatus can be used a sensible default
+ *     fallback.
+ * @SN_ITEM_CATEGORY_COMMUNICATIONS: The item describes the status of
+ *     communication oriented applications, like an instant messenger or
+ *     an email client.
+ * @SN_ITEM_CATEGORY_SYSTEM_SERVICES: The item describes services of the
+ *     system not seen as a stand alone application by the user, such as an
+ *     indicator for the activity of a disk indexing service.
+ * @SN_ITEM_CATEGORY_HARDWARE: The item describes the state and control of
+ *     a particular hardware, such as an indicator of the battery charge or
+ *     sound card volume control.
+ *
+ * Describes the category of this item.
+ */
+typedef enum
+{
+  SN_ITEM_CATEGORY_APPLICATION_STATUS,
+  SN_ITEM_CATEGORY_COMMUNICATIONS,
+  SN_ITEM_CATEGORY_SYSTEM_SERVICES,
+  SN_ITEM_CATEGORY_HARDWARE
+} SnItemCategory;
+
+/**
+ * SnItemStatus:
+ * @SN_ITEM_STATUS_PASSIVE: The item doesn't convey important information
+ *     to the user, it can be considered an "idle" status and is likely
+ *     that visualizations will chose to hide it.
+ * @SN_ITEM_STATUS_ACTIVE: The item is active, is more important that the
+ *     item will be shown in some way to the user.
+ * @SN_ITEM_STATUS_NEEDS_ATTENTION: The item carries really important
+ *     information for the user, such as battery charge running out and
+ *     is wants to incentive the direct user intervention. Visualizations
+ *     should emphasize in some way the items with NeedsAttention status.
+ *
+ * Describes the status of this item or of the associated application.
+ */
+typedef enum
+{
+  SN_ITEM_STATUS_PASSIVE,
+  SN_ITEM_STATUS_ACTIVE,
+  SN_ITEM_STATUS_NEEDS_ATTENTION,
+} SnItemStatus;
+
+/**
+ * SnItemOrientation:
+ * @SN_ITEM_ORIENTATION_HORIZONTAL: Horizontal orientation.
+ * @SN_ITEM_ORIENTATION_VERTICAL: Vertical orientation.
+ *
+ * The orientation of a scroll request performed on the representation of
+ * the item in the visualization.
+ */
+typedef enum
+{
+  SN_ITEM_ORIENTATION_HORIZONTAL,
+  SN_ITEM_ORIENTATION_VERTICAL
+} SnItemOrientation;
+
+/**
+ * SnItemClass:
+ * @parent_class: The parent class.
+ * @context_menu: Asks the status notifier item to show a context menu, this
+ *     is typically a consequence of user input, such as mouse right click
+ *     over the graphical representation of the item.
+ * @activate: Asks the status notifier item for activation, this is typically
+ *     a consequence of user input, such as mouse left click over the
+ *     graphical representation of the item. The application will perform any
+ *     task is considered appropriate as an activation request.
+ * @secondary_activate: Is to be considered a secondary and less important
+ *     form of activation compared to Activate. This is typically a
+ *     consequence of user input, such as mouse middle click over the
+ *     graphical representation of the item. The application will perform any
+ *     task is considered appropriate as an activation request.
+ * @scroll: The user asked for a scroll action. This is caused from input
+ *     such as mouse wheel over the graphical representation of the item.
+ * @changed: Signal is emitted when @item properties has changed.
+ * @ready: Signal is emitted when @item is ready to be used by hosts.
+ * @error: Signal is emitted when error has occurred.
+ *
+ * The class structure for the #SnItem class.
+ */
+struct _SnItemClass
+{
+  GObjectClass parent_class;
+
+  void (* context_menu)       (SnItem            *item,
+                               gint               x,
+                               gint               y);
+  void (* activate)           (SnItem            *item,
+                               gint               x,
+                               gint               y);
+  void (* secondary_activate) (SnItem            *item,
+                               gint               x,
+                               gint               y);
+  void (* scroll)             (SnItem            *item,
+                               gint               delta,
+                               SnItemOrientation  orientation);
+
+  void (* changed)            (SnItem            *item);
+  void (* ready)              (SnItem            *item);
+
+  void (* error)              (SnItem            *item,
+                               const GError      *error);
+
+  /*< private >*/
+  gpointer padding[10];
+};
+
+SnItem          *sn_item_new_v0                     (SnItemCategory       category,
+                                                     const gchar         *id);
+
+SnItem          *sn_item_new_v1                     (SnItemCategory       category,
+                                                     const gchar         *id);
+
+const gchar     *sn_item_get_attention_icon_name    (SnItem              *item);
+void             sn_item_set_attention_icon_name    (SnItem              *item,
+                                                     const gchar         *attention_icon_name);
+
+GdkPixbuf      **sn_item_get_attention_icon_pixbufs (SnItem              *item);
+void             sn_item_set_attention_icon_pixbufs (SnItem              *item,
+                                                     GdkPixbuf          **attention_icon_pixbufs);
+
+const gchar     *sn_item_get_attention_movie_name   (SnItem              *item);
+void             sn_item_set_attention_movie_name   (SnItem              *item,
+                                                     const gchar         *attention_movie_name);
+
+SnItemCategory   sn_item_get_category               (SnItem              *item);
+
+const gchar     *sn_item_get_id                     (SnItem              *item);
+
+const gchar     *sn_item_get_icon_name              (SnItem              *item);
+void             sn_item_set_icon_name              (SnItem              *item,
+                                                     const gchar         *icon_name);
+
+GdkPixbuf      **sn_item_get_icon_pixbufs           (SnItem              *item);
+void             sn_item_set_icon_pixbufs           (SnItem              *item,
+                                                     GdkPixbuf          **icon_pixbufs);
+
+const gchar     *sn_item_get_icon_theme_path        (SnItem              *item);
+void             sn_item_set_icon_theme_path        (SnItem              *item,
+                                                     const gchar         *icon_theme_path);
+
+gboolean         sn_item_get_item_is_menu           (SnItem              *item);
+void             sn_item_set_item_is_menu           (SnItem              *item,
+                                                     gboolean             item_is_menu);
+
+GtkMenu         *sn_item_get_menu                   (SnItem              *item);
+void             sn_item_set_menu                   (SnItem              *item,
+                                                     GtkMenu             *menu);
+
+const gchar     *sn_item_get_overlay_icon_name      (SnItem              *item);
+void             sn_item_set_overlay_icon_name      (SnItem              *item,
+                                                     const gchar         *overlay_icon_name);
+
+GdkPixbuf      **sn_item_get_overlay_icon_pixbufs   (SnItem              *item);
+void             sn_item_set_overlay_icon_pixbufs   (SnItem              *item,
+                                                     GdkPixbuf          **overlay_icon_pixbufs);
+
+SnItemStatus     sn_item_get_status                 (SnItem              *item);
+void             sn_item_set_status                 (SnItem              *item,
+                                                     SnItemStatus         status);
+
+const gchar     *sn_item_get_title                  (SnItem              *item);
+void             sn_item_set_title                  (SnItem              *item,
+                                                     const gchar         *title);
+
+gboolean         sn_item_get_tooltip                (SnItem              *item,
+                                                     const gchar        **icon_name,
+                                                     GdkPixbuf         ***icon_pixbufs,
+                                                     const gchar        **title,
+                                                     const gchar        **text);
+void             sn_item_set_tooltip                (SnItem              *item,
+                                                     const gchar         *icon_name,
+                                                     GdkPixbuf          **icon_pixbufs,
+                                                     const gchar         *title,
+                                                     const gchar         *text);
+
+gint             sn_item_get_window_id              (SnItem              *item);
+void             sn_item_set_window_id              (SnItem              *item,
+                                                     gint                 window_id);
+
+void             sn_item_context_menu               (SnItem              *item,
+                                                     gint                 x,
+                                                     gint                 y);
+void             sn_item_activate                   (SnItem              *item,
+                                                     gint                 x,
+                                                     gint                 y);
+void             sn_item_secondary_activate         (SnItem              *item,
+                                                     gint                 x,
+                                                     gint                 y);
+void             sn_item_scroll                     (SnItem              *item,
+                                                     gint                 delta,
+                                                     SnItemOrientation    orientation);
+
+void             sn_item_register                   (SnItem              *item);
+void             sn_item_unregister                 (SnItem              *item);
+
+const gchar     *sn_item_get_bus_name               (SnItem              *item);
+const gchar     *sn_item_get_object_path            (SnItem              *item);
+
+G_END_DECLS
+
+#endif
diff --git a/libstatus-notifier/sn-watcher-private.h b/libstatus-notifier/sn-watcher-private.h
new file mode 100644
index 0000000..bffbef5
--- /dev/null
+++ b/libstatus-notifier/sn-watcher-private.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_WATCHER_PRIVATE_H
+#define SN_WATCHER_PRIVATE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define SN_WATCHER_V0_BUS_NAME "org.kde.StatusNotifierWatcher"
+#define SN_WATCHER_V0_OBJECT_PATH "/StatusNotifierWatcher"
+
+#define SN_WATCHER_V1_BUS_NAME "org.freedesktop.StatusNotifier1.Watcher"
+#define SN_WATCHER_V1_OBJECT_PATH "/org/freedesktop/StatusNotifier1/Watcher"
+
+G_END_DECLS
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]