From 6ff98d8a397a496bdfbdc9cf61533b82de3f206e Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sun, 4 Oct 2015 08:41:07 -0400 Subject: [PATCH] fix systray to work with spec-breaking apps, eg. steam according to the StatusNotifierItem specification, applications register "service org.freedesktop.StatusNotifierItem-PID-ID" on the session bus, and then "must register the unique instance name to the StatusNotifierWatcher". some applications, such as steam, instead register the path that they will run on (/org/ayatana/NotificationItem/steam) and then expect the watcher to register the method call's send id bus: this is totally bogus. to catch this, when registering the new item the enlightenment watcher must first determine if the item is spec-conforming. if yes, proceed as normal. if no, pretend the application knows what it's doing and try to make things work as expected anyway for more details, read the full spec here http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem fix T2763 --- src/modules/systray/e_mod_notifier_host_dbus.c | 16 +++++++--------- .../systray/e_mod_notifier_host_private.h | 4 ++-- src/modules/systray/e_mod_notifier_watcher.c | 14 +++++++++----- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/modules/systray/e_mod_notifier_host_dbus.c b/src/modules/systray/e_mod_notifier_host_dbus.c index 77ae5b543..8eba2b19d 100644 --- a/src/modules/systray/e_mod_notifier_host_dbus.c +++ b/src/modules/systray/e_mod_notifier_host_dbus.c @@ -14,8 +14,6 @@ extern const char *Category_Names[]; extern const char *Status_Names[]; -static Eina_Stringshare *DBUS_PATH; - typedef struct _Notifier_Host_Data { Instance_Notifier_Host *host_inst; void *data; @@ -445,24 +443,26 @@ notifier_items_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pen } static void -item_registered_local_cb(void *data, const char *bus) +item_registered_local_cb(void *data, const char *bus, const char *path) { Context_Notifier_Host *ctx = data; - notifier_item_add(eina_stringshare_ref(DBUS_PATH), eina_stringshare_add(bus), ctx); + notifier_item_add(eina_stringshare_add(path), eina_stringshare_add(bus), ctx); } static void -item_unregistered_local_cb(void *data, const char *bus) +item_unregistered_local_cb(void *data, const char *bus, const char *path) { Context_Notifier_Host *ctx = data; Notifier_Item *item; - Eina_Stringshare *s; + Eina_Stringshare *s, *p; s = eina_stringshare_add(bus); - item = notifier_item_find(DBUS_PATH, s, ctx); + p = eina_stringshare_add(path); + item = notifier_item_find(p, s, ctx); if (item) systray_notifier_item_free(item); eina_stringshare_del(s); + eina_stringshare_del(p); } static void @@ -515,7 +515,6 @@ systray_notifier_dbus_init(Context_Notifier_Host *ctx) eldbus_init(); ctx->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION); if (!ctx->conn) return; - DBUS_PATH = eina_stringshare_add("/StatusNotifierItem"); p = eldbus_name_request(ctx->conn, WATCHER_BUS, ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, name_request_cb, ctx); @@ -542,7 +541,6 @@ void systray_notifier_dbus_shutdown(Context_Notifier_Host *ctx) eldbus_object_unref(obj); ctx->watcher = NULL; } - eina_stringshare_replace(&DBUS_PATH, NULL); eldbus_connection_unref(ctx->conn); eldbus_shutdown(); } diff --git a/src/modules/systray/e_mod_notifier_host_private.h b/src/modules/systray/e_mod_notifier_host_private.h index ad3bcd677..a7e2ea8d8 100644 --- a/src/modules/systray/e_mod_notifier_host_private.h +++ b/src/modules/systray/e_mod_notifier_host_private.h @@ -63,8 +63,8 @@ struct _Notifier_Item int attnimgw, attnimgh; }; -typedef void (*E_Notifier_Watcher_Item_Registered_Cb)(void *data, const char *service); -typedef void (*E_Notifier_Watcher_Item_Unregistered_Cb)(void *data, const char *service); +typedef void (*E_Notifier_Watcher_Item_Registered_Cb)(void *data, const char *service, const char *path); +typedef void (*E_Notifier_Watcher_Item_Unregistered_Cb)(void *data, const char *service, const char *path); void systray_notifier_update_menu(void *data, E_DBusMenu_Item *new_root_item); void systray_notifier_item_update(Notifier_Item *item); diff --git a/src/modules/systray/e_mod_notifier_watcher.c b/src/modules/systray/e_mod_notifier_watcher.c index 666a5b41f..3e9a47bd5 100644 --- a/src/modules/systray/e_mod_notifier_watcher.c +++ b/src/modules/systray/e_mod_notifier_watcher.c @@ -36,8 +36,8 @@ item_name_monitor_cb(void *data, const char *bus, const char *old_id EINA_UNUSED eldbus_service_signal_emit(iface, ITEM_UNREGISTERED, svc); items = eina_list_remove(items, service); if (unregistered_cb) - unregistered_cb(user_data, bus); - eldbus_name_owner_changed_callback_del(conn, svc, item_name_monitor_cb, service); + unregistered_cb(user_data, bus, svc); + eldbus_name_owner_changed_callback_del(conn, bus, item_name_monitor_cb, service); eina_stringshare_del(service); } @@ -46,12 +46,16 @@ register_item_cb(const Eldbus_Service_Interface *s_iface, const Eldbus_Message * { const char *service, *svc; char buf[1024]; + Eina_Bool stupid; if (!eldbus_message_arguments_get(msg, "s", &service)) return NULL; svc = service; + /* if stupid, this app does not conform to http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/ + * and is expecting to have its send id watched as it is not providing a real bus name here */ + stupid = !!strncmp(svc, "org.", 4); - snprintf(buf, sizeof(buf), "%s/%s", eldbus_message_sender_get(msg), service); + snprintf(buf, sizeof(buf), "%s/%s", stupid ? eldbus_message_sender_get(msg) : svc, stupid ? svc : "/StatusNotifierItem"); service = eina_stringshare_add(buf); if (eina_list_data_find(items, service)) { @@ -61,12 +65,12 @@ register_item_cb(const Eldbus_Service_Interface *s_iface, const Eldbus_Message * items = eina_list_append(items, service); eldbus_service_signal_emit(s_iface, ITEM_REGISTERED, svc); - eldbus_name_owner_changed_callback_add(conn, svc, + eldbus_name_owner_changed_callback_add(conn, stupid ? eldbus_message_sender_get(msg) : svc, item_name_monitor_cb, service, EINA_FALSE); if (registered_cb) - registered_cb(user_data, svc); + registered_cb(user_data, stupid ? eldbus_message_sender_get(msg) : svc, stupid ? svc : "/StatusNotifierItem"); return eldbus_message_method_return_new(msg); }