[Xfce4-commits] [panel-plugins/xfce4-statusnotifier-plugin] 01/02: Split watcher and host logic

noreply at xfce.org noreply at xfce.org
Sat Jul 22 02:43:30 CEST 2017


This is an automated email from the git hooks/post-receive script.

n   i   n   e   t   l   s       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository panel-plugins/xfce4-statusnotifier-plugin.

commit f017cfb5c466707ac9f30907193ff373aebaf811
Author: Viktor Odintsev <ninetls at xfce.org>
Date:   Sat Jul 22 03:26:48 2017 +0300

    Split watcher and host logic
    
    This change allows to use multiple instances of the plugin and even
    work with external watchers depending on how well they designed.
    
    One of the running plugins will be a "master" plugin which runs a
    watcher service while other plugins will use this service. One of
    these plugins will become a "master" plugin in the moment when
    previous "master" plugin was removed.
---
 panel-plugin/sn-backend.c              | 689 +++++++++++++++++++++++++--------
 panel-plugin/sn-item.c                 |  19 -
 panel-plugin/statusnotifier.desktop.in |   2 +-
 3 files changed, 530 insertions(+), 180 deletions(-)

diff --git a/panel-plugin/sn-backend.c b/panel-plugin/sn-backend.c
index 4148804..d42bf3a 100644
--- a/panel-plugin/sn-backend.c
+++ b/panel-plugin/sn-backend.c
@@ -35,22 +35,59 @@
 
 static void                  sn_backend_finalize                     (GObject                 *object);
 
-static void                  sn_backend_clear_items                  (SnBackend               *backend);
+static void                  sn_backend_watcher_bus_acquired         (GDBusConnection         *connection,
+                                                                      const gchar             *name,
+                                                                      gpointer                 user_data);
 
-static gboolean              sn_backend_register_item                (SnWatcher               *watcher,
+static void                  sn_backend_watcher_name_lost            (GDBusConnection         *connection,
+                                                                      const gchar             *name,
+                                                                      gpointer                 user_data);
+
+static gboolean              sn_backend_watcher_register_item        (SnWatcher               *watcher_skeleton,
                                                                       GDBusMethodInvocation   *invocation,
                                                                       const gchar             *service,
                                                                       SnBackend               *backend);
 
-static void                  sn_backend_unregister_item              (SnBackend               *backend,
-                                                                      SnItem                  *item,
-                                                                      gboolean                 remove_and_notify);
-
-static gboolean              sn_backend_register_host                (SnWatcher               *watcher,
+static gboolean              sn_backend_watcher_register_host        (SnWatcher               *watcher_skeleton,
                                                                       GDBusMethodInvocation   *invocation,
                                                                       const gchar             *service);
 
-static void                  sn_backend_update_registered_items      (SnBackend               *backend);
+static void                  sn_backend_watcher_update_items         (SnBackend               *backend);
+
+static void                  sn_backend_watcher_clear_items          (SnBackend               *backend);
+
+static void                  sn_backend_host_name_appeared           (GDBusConnection         *connection,
+                                                                      const gchar             *name,
+                                                                      const gchar             *name_owner,
+                                                                      gpointer                 user_data);
+
+static void                  sn_backend_host_name_vanished           (GDBusConnection        *connection,
+                                                                      const gchar            *name,
+                                                                      gpointer                user_data);
+
+static void                  sn_backend_host_item_registered         (SnWatcher               *host_proxy,
+                                                                      const gchar             *service,
+                                                                      SnBackend               *backend);
+
+static void                  sn_backend_host_item_unregistered       (SnWatcher               *host_proxy,
+                                                                      const gchar             *service,
+                                                                      SnBackend               *backend);
+
+static void                  sn_backend_host_items_changed           (GDBusProxy              *proxy,
+                                                                      GVariant                *changed_properties,
+                                                                      GStrv                    invalidated_properties,
+                                                                      gpointer                 user_data);
+
+static void                  sn_backend_host_add_item                (SnBackend               *backend,
+                                                                      const gchar             *service,
+                                                                      const gchar             *bus_name,
+                                                                      const gchar             *object_path);
+
+static void                  sn_backend_host_remove_item             (SnBackend               *backend,
+                                                                      SnItem                  *item,
+                                                                      gboolean                 remove_from_table);
+
+static void                  sn_backend_host_clear_items             (SnBackend               *backend);
 
 
 
@@ -63,10 +100,14 @@ struct _SnBackend
 {
   GObject              __parent__;
 
-  guint                bus_owner_id;
+  guint                watcher_bus_owner_id;
+  SnWatcher           *watcher_skeleton;
+  GHashTable          *watcher_items;
 
-  SnWatcher           *watcher;
-  GHashTable          *items;
+  guint                host_bus_watcher_id;
+  SnWatcher           *host_proxy;
+  GHashTable          *host_items;
+  GCancellable        *host_cancellable;
 };
 
 G_DEFINE_TYPE (SnBackend, sn_backend, G_TYPE_OBJECT)
@@ -92,6 +133,17 @@ static guint sn_backend_signals[LAST_SIGNAL] = { 0, };
 
 typedef struct
 {
+  const gchar         *key;
+  SnBackend           *backend;
+  GDBusConnection     *connection;
+  gulong               handler;
+}
+ItemConnectionContext;
+
+
+
+typedef struct
+{
   gint                 index;
   gchar              **out;
 }
@@ -99,6 +151,15 @@ CollectItemKeysContext;
 
 
 
+typedef struct
+{
+  SnBackend           *backend;
+  const gchar *const  *items;
+}
+RemoveComparingContext;
+
+
+
 static void
 sn_backend_class_init (SnBackendClass *klass)
 {
@@ -129,9 +190,14 @@ sn_backend_class_init (SnBackendClass *klass)
 static void
 sn_backend_init (SnBackend *backend)
 {
-  backend->bus_owner_id = 0;
-  backend->watcher = NULL;
-  backend->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  backend->watcher_bus_owner_id = 0;
+  backend->watcher_skeleton = NULL;
+  backend->watcher_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+  backend->host_bus_watcher_id = 0;
+  backend->host_proxy = NULL;
+  backend->host_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  backend->host_cancellable = g_cancellable_new ();
 }
 
 
@@ -141,132 +207,396 @@ sn_backend_finalize (GObject *object)
 {
   SnBackend *backend = XFCE_SN_BACKEND (object);
 
-  sn_backend_clear_items (backend);
-  g_hash_table_destroy (backend->items);
+  g_object_unref (backend->host_cancellable);
 
-  if (backend->watcher != NULL)
-    g_object_unref (backend->watcher);
+  sn_backend_host_clear_items (backend);
+  sn_backend_watcher_clear_items (backend);
+  g_hash_table_destroy (backend->host_items);
+  g_hash_table_destroy (backend->watcher_items);
 
-  if (backend->bus_owner_id != 0)
-    g_bus_unown_name (backend->bus_owner_id);
+  if (backend->host_proxy != NULL)
+    g_object_unref (backend->host_proxy);
+
+  if (backend->watcher_skeleton != NULL)
+    g_object_unref (backend->watcher_skeleton);
+
+  if (backend->host_bus_watcher_id != 0)
+    g_bus_unwatch_name (backend->host_bus_watcher_id);
+
+  if (backend->watcher_bus_owner_id != 0)
+    g_bus_unown_name (backend->watcher_bus_owner_id);
 
   G_OBJECT_CLASS (sn_backend_parent_class)->finalize (object);
 }
 
 
 
-static gboolean
-sn_backend_clear_item (gpointer key,
-                       gpointer value,
-                       gpointer user_data)
+SnBackend *
+sn_backend_new (void)
 {
-  SnBackend *backend = user_data;
-  SnItem    *item = value;
-
-  sn_backend_unregister_item (backend, item, FALSE);
-
-  return TRUE;
+  return g_object_new (XFCE_TYPE_SN_BACKEND, NULL);
 }
 
 
 
-static void
-sn_backend_clear_items (SnBackend *backend)
+void
+sn_backend_start (SnBackend *backend)
 {
-  g_hash_table_foreach_remove (backend->items, sn_backend_clear_item, backend);
+  g_return_if_fail (XFCE_IS_SN_BACKEND (backend));
+  g_return_if_fail (backend->watcher_bus_owner_id == 0);
+  g_return_if_fail (backend->host_bus_watcher_id == 0);
+
+  backend->watcher_bus_owner_id =
+    g_bus_own_name (G_BUS_TYPE_SESSION,
+                    "org.kde.StatusNotifierWatcher",
+                    G_BUS_NAME_OWNER_FLAGS_NONE,
+                    sn_backend_watcher_bus_acquired,
+                    NULL, sn_backend_watcher_name_lost,
+                    backend, NULL);
+
+  backend->host_bus_watcher_id =
+    g_bus_watch_name (G_BUS_TYPE_SESSION,
+                      "org.kde.StatusNotifierWatcher",
+                      G_BUS_NAME_WATCHER_FLAGS_NONE,
+                      sn_backend_host_name_appeared,
+                      sn_backend_host_name_vanished,
+                      backend, NULL);
 }
 
 
 
 static void
-sn_backend_bus_acquired (GDBusConnection *connection,
-                         const gchar     *name,
-                         gpointer         user_data)
+sn_backend_watcher_bus_acquired (GDBusConnection *connection,
+                                 const gchar     *name,
+                                 gpointer         user_data)
 {
   SnBackend *backend = user_data;
   GError    *error = NULL;
 
-  if (backend->watcher != NULL)
-    g_object_unref (backend->watcher);
+  if (backend->watcher_skeleton != NULL)
+    g_object_unref (backend->watcher_skeleton);
 
-  backend->watcher = sn_watcher_skeleton_new ();
+  backend->watcher_skeleton = sn_watcher_skeleton_new ();
 
-  sn_watcher_set_is_status_notifier_host_registered (backend->watcher, TRUE);
-  sn_watcher_set_registered_status_notifier_items (backend->watcher, NULL);
-  sn_watcher_set_protocol_version (backend->watcher, 0);
+  sn_watcher_set_is_status_notifier_host_registered (backend->watcher_skeleton, TRUE);
+  sn_watcher_set_registered_status_notifier_items (backend->watcher_skeleton, NULL);
+  sn_watcher_set_protocol_version (backend->watcher_skeleton, 0);
 
-  g_signal_connect (backend->watcher, "handle-register-status-notifier-item",
-                    G_CALLBACK (sn_backend_register_item), backend);
-  g_signal_connect (backend->watcher, "handle-register-status-notifier-host",
-                    G_CALLBACK (sn_backend_register_host), backend);
+  g_signal_connect (backend->watcher_skeleton, "handle-register-status-notifier-item",
+                    G_CALLBACK (sn_backend_watcher_register_item), backend);
+  g_signal_connect (backend->watcher_skeleton, "handle-register-status-notifier-host",
+                    G_CALLBACK (sn_backend_watcher_register_host), backend);
 
-  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (backend->watcher),
+  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (backend->watcher_skeleton),
                                     connection, "/StatusNotifierWatcher", &error);
 
   if (error != NULL)
     {
       g_error_free (error);
 
-      g_object_unref (backend->watcher);
-      backend->watcher = NULL;
+      g_object_unref (backend->watcher_skeleton);
+      backend->watcher_skeleton = NULL;
     }
 }
 
 
 
 static void
-sn_backend_name_acquired (GDBusConnection *connection,
-                          const gchar     *name,
-                          gpointer         user_data)
+sn_backend_watcher_name_lost (GDBusConnection *connection,
+                              const gchar     *name,
+                              gpointer         user_data)
 {
   SnBackend *backend = user_data;
 
-  if (backend->watcher != NULL)
-    sn_watcher_emit_status_notifier_host_registered (backend->watcher);
+  sn_backend_watcher_clear_items (backend);
+
+  if (backend->watcher_skeleton != NULL)
+    sn_watcher_set_registered_status_notifier_items (backend->watcher_skeleton, NULL);
 }
 
 
 
 static void
-sn_backend_name_lost (GDBusConnection *connection,
-                      const gchar     *name,
-                      gpointer         user_data)
+sn_backend_watcher_name_owner_changed (GDBusConnection *connection,
+                                       const gchar     *sender_name,
+                                       const gchar     *object_path,
+                                       const gchar     *interface_name,
+                                       const gchar     *signal_name,
+                                       GVariant        *parameters,
+                                       gpointer         user_data)
 {
-  SnBackend *backend = user_data;
+  ItemConnectionContext *context = user_data;
+  SnBackend             *backend = context->backend;
+  gchar                 *key;
+  gchar                 *new_owner;
 
-  sn_backend_clear_items (backend);
+  g_variant_get (parameters, "(sss)", NULL, NULL, &new_owner);
+  if (new_owner == NULL || strlen (new_owner) == 0)
+    {
+      key = g_strdup (context->key);
+      g_dbus_connection_signal_unsubscribe (context->connection, context->handler);
+      /* context and context->key will be freed after this call */
+      g_hash_table_remove (backend->watcher_items, key);
+      sn_backend_watcher_update_items (backend);
+      sn_watcher_emit_status_notifier_item_unregistered (backend->watcher_skeleton, key);
+      g_free (key);
+    }
 }
 
 
 
-SnBackend *
-sn_backend_new (void)
+static gboolean
+sn_backend_watcher_register_item (SnWatcher             *watcher_skeleton,
+                                  GDBusMethodInvocation *invocation,
+                                  const gchar           *service,
+                                  SnBackend             *backend)
 {
-  return g_object_new (XFCE_TYPE_SN_BACKEND, NULL);
+  const gchar           *bus_name;
+  const gchar           *object_path;
+  const gchar           *sender;
+  gchar                 *key;
+  GDBusConnection       *connection;
+  ItemConnectionContext *context;
+
+  sender = g_dbus_method_invocation_get_sender (invocation);
+
+  if (service[0] == '/')
+    {
+      /* /org/ayatana/NotificationItem */
+      bus_name = sender;
+      object_path = service;
+    }
+  else
+    {
+      /* org.kde.StatusNotifierItem */
+      bus_name = service;
+      object_path = "/StatusNotifierItem";
+    }
+
+  if (!g_dbus_is_name (bus_name))
+    {
+      g_dbus_method_invocation_return_error_literal (invocation,
+                                                     G_IO_ERROR,
+                                                     G_IO_ERROR_INVALID_ARGUMENT,
+                                                     "Invalid bus name");
+      return FALSE;
+    }
+
+  key = g_strdup_printf ("%s%s", bus_name, object_path);
+  connection = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (watcher_skeleton));
+
+  context = g_hash_table_lookup (backend->watcher_items, key);
+  if (context != NULL)
+    {
+      g_dbus_connection_signal_unsubscribe (connection, context->handler);
+      g_hash_table_remove (backend->watcher_items, key);
+    }
+
+  context = g_new0 (ItemConnectionContext, 1);
+  context->key = key;
+  context->backend = backend;
+  context->connection = connection;
+  context->handler =
+    g_dbus_connection_signal_subscribe (connection,
+                                        "org.freedesktop.DBus",
+                                        "org.freedesktop.DBus",
+                                        "NameOwnerChanged",
+                                        "/org/freedesktop/DBus",
+                                        bus_name,
+                                        G_DBUS_SIGNAL_FLAGS_NONE,
+                                        sn_backend_watcher_name_owner_changed,
+                                        context, NULL);
+
+  g_hash_table_insert (backend->watcher_items, key, context);
+
+  sn_backend_watcher_update_items (backend);
+
+  sn_watcher_complete_register_status_notifier_item (watcher_skeleton, invocation);
+
+  sn_watcher_emit_status_notifier_item_registered (watcher_skeleton, key);
+
+  return TRUE;
 }
 
 
 
-void
-sn_backend_start (SnBackend *backend)
+static gboolean
+sn_backend_watcher_register_host (SnWatcher             *watcher_skeleton,
+                                  GDBusMethodInvocation *invocation,
+                                  const gchar           *service)
 {
-  g_return_if_fail (XFCE_IS_SN_BACKEND (backend));
-  g_return_if_fail (backend->bus_owner_id == 0);
+  sn_watcher_complete_register_status_notifier_host (watcher_skeleton, invocation);
 
-  backend->bus_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
-                                          "org.kde.StatusNotifierWatcher",
-                                          G_BUS_NAME_OWNER_FLAGS_NONE,
-                                          sn_backend_bus_acquired,
-                                          sn_backend_name_acquired,
-                                          sn_backend_name_lost,
-                                          backend, NULL);
+  return TRUE;
 }
 
 
 
 static void
-sn_backend_item_expose (SnItem    *item,
-                        SnBackend *backend)
+sn_backend_watcher_collect_item_keys (gpointer key,
+                                      gpointer value,
+                                      gpointer user_data)
+{
+  CollectItemKeysContext *context = user_data;
+  context->out[context->index++] = key;
+}
+
+
+
+static void
+sn_backend_watcher_update_items (SnBackend *backend)
+{
+  CollectItemKeysContext context;
+
+  if (backend->watcher_skeleton != NULL)
+    {
+      context.index = 0;
+      context.out = g_new0 (gchar *, g_hash_table_size (backend->watcher_items) + 1);
+      g_hash_table_foreach (backend->watcher_items,
+                            sn_backend_watcher_collect_item_keys,
+                            &context);
+      sn_watcher_set_registered_status_notifier_items (backend->watcher_skeleton,
+                                                       (gpointer)context.out);
+      g_free (context.out);
+    }
+}
+
+
+
+static gboolean
+sn_backend_watcher_clear_item (gpointer key,
+                               gpointer value,
+                               gpointer user_data)
+{
+  ItemConnectionContext *context = value;
+
+  g_dbus_connection_signal_unsubscribe (context->connection, context->handler);
+
+  return TRUE;
+}
+
+
+
+static void
+sn_backend_watcher_clear_items (SnBackend *backend)
+{
+  g_hash_table_foreach_remove (backend->watcher_items, sn_backend_watcher_clear_item, NULL);
+}
+
+
+
+static gboolean
+sn_backend_host_parse_name_path (const gchar  *service,
+                                 gchar       **bus_name,
+                                 gchar       **object_path)
+{
+  const gchar *substring;
+  gchar       *bus_name_val;
+  gint         index;
+
+  substring = strstr (service, "/");
+
+  if (substring != NULL)
+    {
+      index = (gint) (substring - service);
+      bus_name_val = g_strndup (service, index);
+
+      if (!g_dbus_is_name (bus_name_val))
+        {
+          g_free (bus_name_val);
+          return FALSE;
+        }
+
+      *bus_name = bus_name_val;
+      *object_path = g_strdup (&service[index]);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+
+static void
+sn_backend_host_callback (GObject      *source_object,
+                          GAsyncResult *res,
+                          gpointer      user_data)
+{
+  SnBackend          *backend = user_data;
+  gchar              *bus_name;
+  gchar              *object_path;
+  const gchar *const *items;
+  gint                i;
+
+  backend->host_proxy = sn_watcher_proxy_new_finish (res, NULL);
+
+  if (backend->host_proxy != NULL)
+    {
+      g_signal_connect (backend->host_proxy, "status-notifier-item-registered",
+                        G_CALLBACK (sn_backend_host_item_registered), backend);
+      g_signal_connect (backend->host_proxy, "status-notifier-item-unregistered",
+                        G_CALLBACK (sn_backend_host_item_unregistered), backend);
+      g_signal_connect_after (backend->host_proxy, "g-properties-changed",
+                              G_CALLBACK (sn_backend_host_items_changed), backend);
+
+      items = sn_watcher_get_registered_status_notifier_items (backend->host_proxy);
+      if (items != NULL)
+        {
+          for (i = 0; items[i] != NULL; i++)
+            {
+              if (sn_backend_host_parse_name_path (items[i], &bus_name, &object_path))
+                {
+                  sn_backend_host_add_item (backend, items[i], bus_name, object_path);
+
+                  g_free (bus_name);
+                  g_free (object_path);
+                }
+            }
+        }
+    }
+}
+
+
+
+static void
+sn_backend_host_name_appeared (GDBusConnection *connection,
+                               const gchar     *name,
+                               const gchar     *name_owner,
+                               gpointer         user_data)
+{
+  SnBackend *backend = user_data;
+
+  sn_watcher_proxy_new (connection,
+                        G_DBUS_PROXY_FLAGS_NONE,
+                        name, "/StatusNotifierWatcher",
+                        backend->host_cancellable,
+                        sn_backend_host_callback,
+                        backend);
+}
+
+
+
+static void
+sn_backend_host_name_vanished (GDBusConnection *connection,
+                               const gchar     *name,
+                               gpointer         user_data)
+{
+  SnBackend *backend = user_data;
+
+  if (backend->host_proxy != NULL)
+    {
+      g_object_unref (backend->host_proxy);
+      backend->host_proxy = NULL;
+    }
+
+  sn_backend_host_clear_items (backend);
+}
+
+
+
+static void
+sn_backend_host_item_expose (SnItem    *item,
+                             SnBackend *backend)
 {
   g_signal_emit (G_OBJECT (backend), sn_backend_signals[ITEM_ADDED], 0, item);
 }
@@ -274,8 +604,8 @@ sn_backend_item_expose (SnItem    *item,
 
 
 static void
-sn_backend_item_seal (SnItem    *item,
-                      SnBackend *backend)
+sn_backend_host_item_seal (SnItem    *item,
+                           SnBackend *backend)
 {
   g_signal_emit (G_OBJECT (backend), sn_backend_signals[ITEM_REMOVED], 0, item);
 }
@@ -283,46 +613,126 @@ sn_backend_item_seal (SnItem    *item,
 
 
 static void
-sn_backend_item_finish (SnItem    *item,
-                        SnBackend *backend)
+sn_backend_host_item_finish (SnItem    *item,
+                             SnBackend *backend)
+{
+  sn_backend_host_remove_item (backend, item, TRUE);
+}
+
+
+
+static void
+sn_backend_host_item_registered (SnWatcher   *host_proxy,
+                                 const gchar *service,
+                                 SnBackend   *backend)
+{
+  gchar *bus_name;
+  gchar *object_path;
+
+  if (!sn_backend_host_parse_name_path (service, &bus_name, &object_path))
+    return;
+
+  sn_backend_host_add_item (backend, service, bus_name, object_path);
+
+  g_free (bus_name);
+  g_free (object_path);
+}
+
+
+
+static void
+sn_backend_host_item_unregistered (SnWatcher   *host_proxy,
+                                   const gchar *service,
+                                   SnBackend   *backend)
 {
-  sn_backend_unregister_item (backend, item, TRUE);
+  SnItem *item;
+
+  item = g_hash_table_lookup (backend->host_items, service);
+  if (item != NULL)
+    sn_backend_host_remove_item (backend, item, TRUE);
 }
 
 
 
 static gboolean
-sn_backend_register_item (SnWatcher             *watcher,
-                          GDBusMethodInvocation *invocation,
-                          const gchar           *service,
-                          SnBackend             *backend)
+sn_backend_host_items_changed_remove_item (gpointer key,
+                                           gpointer value,
+                                           gpointer user_data)
 {
-  const gchar *bus_name;
-  const gchar *object_path;
-  const gchar *sender;
-  gchar       *key;
-  SnItem      *item;
+  RemoveComparingContext *context = user_data;
+  SnItem                 *item = value;
+  gint                    i;
 
-  sender = g_dbus_method_invocation_get_sender (invocation);
+  for (i = 0; context->items[i] != NULL; i++)
+    {
+      if (!g_strcmp0 (key, context->items[i]))
+        return FALSE;
+    }
 
-  if (service[0] == '/')
+  sn_backend_host_remove_item (context->backend, item, FALSE);
+
+  return TRUE;
+}
+
+
+
+static void
+sn_backend_host_items_changed (GDBusProxy *proxy,
+                               GVariant   *changed_properties,
+                               GStrv       invalidated_properties,
+                               gpointer    user_data)
+{
+  SnBackend              *backend = user_data;
+  const gchar *const     *items;
+  gchar                  *bus_name;
+  gchar                  *object_path;
+  gint                    i;
+  RemoveComparingContext  context;
+
+  items = sn_watcher_get_registered_status_notifier_items (backend->host_proxy);
+  if (items != NULL)
     {
-      /* /org/ayatana/NotificationItem */
-      bus_name = sender;
-      object_path = service;
+      for (i = 0; items[i] != NULL; i++)
+        {
+          /* add new items */
+          if (!g_hash_table_contains (backend->host_items, items[i]))
+            {
+              if (sn_backend_host_parse_name_path (items[i], &bus_name, &object_path))
+                {
+                  sn_backend_host_add_item (backend, items[i], bus_name, object_path);
+
+                  g_free (bus_name);
+                  g_free (object_path);
+                }
+            }
+        }
+
+      /* remove old items */
+      context.backend = backend;
+      context.items = items;
+      g_hash_table_foreach_remove (backend->host_items,
+                                   sn_backend_host_items_changed_remove_item,
+                                   &context);
     }
   else
     {
-      /* org.kde.StatusNotifierItem */
-      bus_name = service;
-      object_path = "/StatusNotifierItem";
+      sn_backend_host_clear_items (backend);
     }
+}
 
-  key = g_strdup_printf ("%s%s", bus_name, object_path);
-  item = g_hash_table_lookup (backend->items, key);
+
+
+static void
+sn_backend_host_add_item (SnBackend   *backend,
+                          const gchar *service,
+                          const gchar *bus_name,
+                          const gchar *object_path)
+{
+  SnItem *item;
+
+  item = g_hash_table_lookup (backend->host_items, service);
   if (item != NULL)
     {
-      g_free (key);
       sn_item_invalidate (item);
     }
   else
@@ -330,41 +740,30 @@ sn_backend_register_item (SnWatcher             *watcher,
       item = g_object_new (XFCE_TYPE_SN_ITEM,
                            "bus-name", bus_name,
                            "object-path", object_path,
-                           "service", service,
-                           "key", key,
+                           "key", service,
                            NULL);
       g_signal_connect (item, "expose",
-                        G_CALLBACK (sn_backend_item_expose), backend);
+                        G_CALLBACK (sn_backend_host_item_expose), backend);
       g_signal_connect (item, "seal",
-                        G_CALLBACK (sn_backend_item_seal), backend);
+                        G_CALLBACK (sn_backend_host_item_seal), backend);
       g_signal_connect (item, "finish",
-                        G_CALLBACK (sn_backend_item_finish), backend);
+                        G_CALLBACK (sn_backend_host_item_finish), backend);
       sn_item_start (item);
-      g_hash_table_insert (backend->items, key, item);
+      g_hash_table_insert (backend->host_items, g_strdup (service), item);
     }
-
-  sn_backend_update_registered_items (backend);
-
-  sn_watcher_complete_register_status_notifier_item (watcher, invocation);
-
-  sn_watcher_emit_status_notifier_item_registered (watcher, service);
-
-  return TRUE;
 }
 
 
 
 static void
-sn_backend_unregister_item (SnBackend *backend,
-                            SnItem    *item,
-                            gboolean   remove_and_notify)
+sn_backend_host_remove_item (SnBackend *backend,
+                             SnItem    *item,
+                             gboolean   remove_from_table)
 {
-  gchar   *service;
   gchar   *key;
   gboolean exposed;
 
   g_object_get (item,
-                "service", &service,
                 "key", &key,
                 "exposed", &exposed,
                 NULL);
@@ -372,63 +771,33 @@ sn_backend_unregister_item (SnBackend *backend,
   if (exposed)
     g_signal_emit (G_OBJECT (backend), sn_backend_signals[ITEM_REMOVED], 0, item);
 
-  if (remove_and_notify)
-    g_hash_table_remove (backend->items, key);
+  if (remove_from_table)
+    g_hash_table_remove (backend->host_items, key);
 
   g_object_unref (item);
 
-  if (backend->watcher != NULL)
-    sn_watcher_emit_status_notifier_item_unregistered (backend->watcher, service);
-
-  g_free (service);
   g_free (key);
-
-  if (remove_and_notify)
-    sn_backend_update_registered_items (backend);
 }
 
 
 
 static gboolean
-sn_backend_register_host (SnWatcher             *watcher,
-                          GDBusMethodInvocation *invocation,
-                          const gchar           *service)
+sn_backend_host_clear_item (gpointer key,
+                            gpointer value,
+                            gpointer user_data)
 {
-  g_dbus_method_invocation_return_error_literal (invocation,
-                                                 G_IO_ERROR,
-                                                 G_IO_ERROR_EXISTS,
-                                                 "Multiple hosts are not supported");
-
-  return FALSE;
-}
-
+  SnBackend *backend = user_data;
+  SnItem    *item = value;
 
+  sn_backend_host_remove_item (backend, item, FALSE);
 
-static void
-sn_backend_collect_item_keys (gpointer key,
-                              gpointer value,
-                              gpointer user_data)
-{
-  CollectItemKeysContext *context = user_data;
-  context->out[context->index++] = key;
+  return TRUE;
 }
 
 
 
 static void
-sn_backend_update_registered_items (SnBackend *backend)
+sn_backend_host_clear_items (SnBackend *backend)
 {
-  CollectItemKeysContext context;
-
-  if (backend->watcher != NULL)
-    {
-      context.index = 0;
-      context.out = g_new0 (gchar *, g_hash_table_size (backend->items) + 1);
-      g_hash_table_foreach (backend->items,
-                            sn_backend_collect_item_keys,
-                            &context);
-      sn_watcher_set_registered_status_notifier_items (backend->watcher,
-                                                       (gpointer)context.out);
-      g_free (context.out);
-    }
+  g_hash_table_foreach_remove (backend->host_items, sn_backend_host_clear_item, backend);
 }
diff --git a/panel-plugin/sn-item.c b/panel-plugin/sn-item.c
index ff563a4..7f9d163 100644
--- a/panel-plugin/sn-item.c
+++ b/panel-plugin/sn-item.c
@@ -75,7 +75,6 @@ struct _SnItem
 
   gchar               *bus_name;
   gchar               *object_path;
-  gchar               *service;
   gchar               *key;
 
   gchar               *id;
@@ -107,7 +106,6 @@ enum
   PROP_0,
   PROP_BUS_NAME,
   PROP_OBJECT_PATH,
-  PROP_SERVICE,
   PROP_KEY,
   PROP_EXPOSED
 };
@@ -179,12 +177,6 @@ sn_item_class_init (SnItemClass *klass)
                                                         G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class,
-                                   PROP_SERVICE,
-                                   g_param_spec_string ("service", NULL, NULL, NULL,
-                                                        G_PARAM_READWRITE |
-                                                        G_PARAM_STATIC_STRINGS));
-
-  g_object_class_install_property (object_class,
                                    PROP_KEY,
                                    g_param_spec_string ("key", NULL, NULL, NULL,
                                                         G_PARAM_READWRITE |
@@ -260,7 +252,6 @@ sn_item_init (SnItem *item)
 
   item->bus_name = NULL;
   item->object_path = NULL;
-  item->service = NULL;
   item->key = NULL;
 
   item->id = NULL;
@@ -302,7 +293,6 @@ sn_item_finalize (GObject *object)
 
   g_free (item->bus_name);
   g_free (item->object_path);
-  g_free (item->service);
   g_free (item->key);
 
   g_free (item->id);
@@ -343,10 +333,6 @@ sn_item_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_SERVICE:
-      g_value_set_string (value, item->service);
-      break;
-
     case PROP_KEY:
       g_value_set_string (value, item->key);
       break;
@@ -383,11 +369,6 @@ sn_item_set_property (GObject      *object,
       item->object_path = g_value_dup_string (value);
       break;
 
-    case PROP_SERVICE:
-      g_free (item->service);
-      item->service = g_value_dup_string (value);
-      break;
-
     case PROP_KEY:
       g_free (item->key);
       item->key = g_value_dup_string (value);
diff --git a/panel-plugin/statusnotifier.desktop.in b/panel-plugin/statusnotifier.desktop.in
index 4d7e924..4557d7d 100644
--- a/panel-plugin/statusnotifier.desktop.in
+++ b/panel-plugin/statusnotifier.desktop.in
@@ -5,6 +5,6 @@ _Name=Status Notifier Plugin
 _Comment=Provides a panel area for status notifier items (application indicators)
 Icon=xfce4-statusnotifier-plugin
 X-XFCE-Module=statusnotifier
-X-XFCE-Unique=TRUE
+X-XFCE-Unique=FALSE
 X-XFCE-Internal=FALSE
 X-XFCE-API=2.0

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list