cache systray items for each dbus session
authorMike Blumenkrantz <zmike@osg.samsung.com>
Wed, 14 Oct 2015 20:30:41 +0000 (16:30 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Wed, 14 Oct 2015 20:30:41 +0000 (16:30 -0400)
the current spec does not directly require any behavior from clients
when a systray host, leading to an issue where clients do not re-register
their items when a new host appears

when using an in-process systray watcher, as the current implementation does,
the best choice for maintaining consistency for systray items across restarts
is to cache them according to the current dbus session. the process of setting
up the item will validate it on subsequent restarts, and changes to the session
will clear the cache

fix T2786

src/modules/systray/e_mod_main.c
src/modules/systray/e_mod_main.h
src/modules/systray/e_mod_notifier_host_dbus.c
src/modules/systray/e_mod_notifier_watcher.c

index 3fceb47..dfe230e 100644 (file)
@@ -391,10 +391,19 @@ e_modapi_init(E_Module *m)
 
    ctx = calloc(1, sizeof(Systray_Context));
    ctx->conf_edd = E_CONFIG_DD_NEW("Systray_Config", Systray_Config);
+   ctx->notifier_item_edd = E_CONFIG_DD_NEW("Notifier_Item_Cache", Notifier_Item_Cache);
+   #undef T
+   #undef D
+   #define T Notifier_Item_Cache
+   #define D ctx->notifier_item_edd
+   E_CONFIG_VAL(D, T, path, STR);
    #undef T
    #undef D
    #define T Systray_Config
    #define D ctx->conf_edd
+   E_CONFIG_VAL(D, T, dbus, STR);
+   E_CONFIG_HASH(D, T, items, ctx->notifier_item_edd);
+
    ctx->config = e_config_domain_load(_name, ctx->conf_edd);
    if (!ctx->config)
      ctx->config = calloc(1, sizeof(Systray_Config));
@@ -415,6 +424,7 @@ e_modapi_shutdown(E_Module *m EINA_UNUSED)
    systray_notifier_host_shutdown();
 
    E_CONFIG_DD_FREE(ctx->conf_edd);
+   E_CONFIG_DD_FREE(ctx->notifier_item_edd);
    free(ctx->config);
    free(ctx);
    return 1;
index 4d83d24..189c884 100644 (file)
@@ -14,7 +14,7 @@ typedef struct _Context_Notifier_Host Context_Notifier_Host;
 typedef struct _Instance_Notifier_Host Instance_Notifier_Host;
 typedef struct _Notifier_Item Notifier_Item;
 typedef struct _Systray_Context Systray_Context;
-typedef struct _E_Config_Dialog_Data Systray_Config;
+typedef struct Systray_Config Systray_Config;
 
 struct _E_Config_Dialog_Data
 {
@@ -24,6 +24,7 @@ struct _Systray_Context
 {
    Systray_Config *config;
    E_Config_DD *conf_edd;
+   E_Config_DD *notifier_item_edd;
 };
 
 struct _Instance
@@ -41,6 +42,17 @@ struct _Instance
    } job;
 };
 
+typedef struct Notifier_Item_Cache
+{
+   Eina_Stringshare *path;
+} Notifier_Item_Cache;
+
+struct Systray_Config
+{
+   Eina_Stringshare *dbus;
+   Eina_Hash *items;
+};
+
 E_Gadcon_Orient systray_orient_get(const Instance *inst);
 const E_Gadcon *systray_gadcon_get(const Instance *inst);
 E_Gadcon_Client *systray_gadcon_client_get(const Instance *inst);
index 8eba2b1..7975bad 100644 (file)
@@ -340,6 +340,7 @@ static void
 notifier_item_add(const char *path, const char *bus_id, Context_Notifier_Host *ctx)
 {
    Eldbus_Proxy *proxy;
+   Notifier_Item_Cache *nic;
    Notifier_Item *item = calloc(1, sizeof(Notifier_Item));
    Eldbus_Signal_Handler *s;
    EINA_SAFETY_ON_NULL_RETURN(item);
@@ -368,6 +369,11 @@ notifier_item_add(const char *path, const char *bus_id, Context_Notifier_Host *c
    item->signals = eina_list_append(item->signals, s);
    s = eldbus_proxy_signal_handler_add(proxy, "NewTitle", new_title_cb, item);
    item->signals = eina_list_append(item->signals, s);
+   if (eina_hash_find(systray_ctx_get()->config->items, bus_id)) return;
+   nic = malloc(sizeof(Notifier_Item_Cache));
+   nic->path = eina_stringshare_ref(path);
+   eina_hash_add(systray_ctx_get()->config->items, bus_id, nic);
+   e_config_save_queue();
 }
 
 static void
index 3e9a47b..c091bb2 100644 (file)
@@ -27,16 +27,31 @@ static void
 item_name_monitor_cb(void *data, const char *bus, const char *old_id EINA_UNUSED, const char *new_id)
 {
    const char *svc, *service = data;
+   Eina_List *l;
 
+   l = eina_list_data_find_list(items, service);
    if (strcmp(new_id, ""))
-     return;
+     {
+        if (l) return;
+        items = eina_list_append(items, service);
+        svc = strchr(service, '/') + 1;
+        registered_cb(user_data, bus, svc);
+        return;
+     }
 
    svc = strchr(service, '/') + 1;
 
    eldbus_service_signal_emit(iface, ITEM_UNREGISTERED, svc);
-   items = eina_list_remove(items, service);
-   if (unregistered_cb)
-     unregistered_cb(user_data, bus, svc);
+   if (l)
+     {
+        items = eina_list_remove_list(items, l);
+        if (unregistered_cb)
+          unregistered_cb(user_data, bus, svc);
+     }
+   bus = eina_stringshare_add(bus);
+   if (eina_hash_del_by_key(systray_ctx_get()->config->items, bus))
+     e_config_save_queue();
+   eina_stringshare_del(bus);
    eldbus_name_owner_changed_callback_del(conn, bus, item_name_monitor_cb, service);
    eina_stringshare_del(service);
 }
@@ -152,9 +167,19 @@ static const Eldbus_Service_Interface_Desc iface_desc = {
    IFACE, methods, signals, properties, properties_get, NULL
 };
 
+
+static void
+systray_notifier_item_hash_del(Notifier_Item_Cache *item)
+{
+   eina_stringshare_del(item->path);
+   free(item);
+}
+
 void
 systray_notifier_dbus_watcher_start(Eldbus_Connection *connection, E_Notifier_Watcher_Item_Registered_Cb registered, E_Notifier_Watcher_Item_Unregistered_Cb unregistered, const void *data)
 {
+   const char *dbus;
+
    EINA_SAFETY_ON_TRUE_RETURN(!!conn);
    conn = connection;
    iface = eldbus_service_interface_register(conn, PATH, &iface_desc);
@@ -162,6 +187,37 @@ systray_notifier_dbus_watcher_start(Eldbus_Connection *connection, E_Notifier_Wa
    unregistered_cb = unregistered;
    user_data = (void *)data;
    host_service = eina_stringshare_add("internal");
+   dbus = getenv("DBUS_SESSION_BUS_ADDRESS");
+   if (systray_ctx_get()->config->items)
+     eina_hash_free_cb_set(systray_ctx_get()->config->items, (Eina_Free_Cb)systray_notifier_item_hash_del);
+   if (systray_ctx_get()->config->dbus && systray_ctx_get()->config->items)
+     {
+        if (!strcmp(systray_ctx_get()->config->dbus, dbus))
+          {
+             Eina_Iterator *it;
+             Eina_Hash_Tuple *t;
+
+             it = eina_hash_iterator_tuple_new(systray_ctx_get()->config->items);
+             EINA_ITERATOR_FOREACH(it, t)
+               {
+                  char buf[1024];
+                  Notifier_Item_Cache *nic = t->data;
+
+                  snprintf(buf, sizeof(buf), "%s/%s", (char*)t->key, nic->path);
+                  eldbus_name_owner_changed_callback_add(conn, t->key,
+                                      item_name_monitor_cb, eina_stringshare_add(buf),
+                                      EINA_TRUE);
+               }
+             eina_iterator_free(it);
+             return;
+          }
+     }
+   eina_stringshare_replace(&systray_ctx_get()->config->dbus, dbus);
+   if (systray_ctx_get()->config->items)
+     eina_hash_free_buckets(systray_ctx_get()->config->items);
+   else
+     systray_ctx_get()->config->items = eina_hash_stringshared_new((Eina_Free_Cb)systray_notifier_item_hash_del);
+   e_config_save_queue();
 }
 
 void