forked from enlightenment/enlightenment
e systray: Add notifier watcher
Patch by: José Roberto de Souza <zehortigoza@profusion.mobi> SVN revision: 82114
This commit is contained in:
parent
40d65f04ad
commit
c71d0fb539
|
@ -12,7 +12,8 @@ systray_module_la_SOURCES = systray/e_mod_main.h \
|
||||||
systray/e_mod_xembed.c \
|
systray/e_mod_xembed.c \
|
||||||
systray/e_mod_notifier_host_private.h \
|
systray/e_mod_notifier_host_private.h \
|
||||||
systray/e_mod_notifier_host.c \
|
systray/e_mod_notifier_host.c \
|
||||||
systray/e_mod_notifier_host_dbus.c
|
systray/e_mod_notifier_host_dbus.c \
|
||||||
|
systray/e_mod_notifier_watcher.c
|
||||||
|
|
||||||
.PHONY: systray install-systray
|
.PHONY: systray install-systray
|
||||||
systray: $(systraypkg_LTLIBRARIES) $(systray_DATA)
|
systray: $(systraypkg_LTLIBRARIES) $(systray_DATA)
|
||||||
|
|
|
@ -373,12 +373,60 @@ notifier_items_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pendi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst)
|
static void
|
||||||
|
item_registered_local_cb(void *data, const char *service)
|
||||||
{
|
{
|
||||||
EDBus_Object *obj;
|
const char *bus, *path;
|
||||||
edbus_init();
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
if (service_string_parse(service, &path, &bus))
|
||||||
|
notifier_item_add(path, bus, host_inst);
|
||||||
|
}
|
||||||
|
|
||||||
host_inst->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
|
static void
|
||||||
|
item_unregistered_local_cb(void *data, const char *service)
|
||||||
|
{
|
||||||
|
const char *bus, *path;
|
||||||
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
Notifier_Item *item;
|
||||||
|
|
||||||
|
if (!service_string_parse(service, &path, &bus))
|
||||||
|
return;
|
||||||
|
item = notifier_item_find(path, bus, host_inst);
|
||||||
|
if (item)
|
||||||
|
systray_notifier_item_free(item);
|
||||||
|
eina_stringshare_del(path);
|
||||||
|
eina_stringshare_del(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
name_request_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
const char *error, *error_msg;
|
||||||
|
unsigned flag;
|
||||||
|
EDBus_Object *obj;
|
||||||
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
|
||||||
|
if (edbus_message_error_get(msg, &error, &error_msg))
|
||||||
|
{
|
||||||
|
ERR("%s %s", error, error_msg);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "u", &flag))
|
||||||
|
{
|
||||||
|
ERR("Error reading message.");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == EDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER)
|
||||||
|
{
|
||||||
|
systray_notifier_dbus_watcher_start(host_inst->conn,
|
||||||
|
item_registered_local_cb,
|
||||||
|
item_unregistered_local_cb, host_inst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
WRN("Bus name: %s already in use, getting data via dbus.\n", WATCHER_BUS);
|
||||||
obj = edbus_object_get(host_inst->conn, WATCHER_BUS, WATCHER_PATH);
|
obj = edbus_object_get(host_inst->conn, WATCHER_BUS, WATCHER_PATH);
|
||||||
host_inst->watcher = edbus_proxy_get(obj, WATCHER_IFACE);
|
host_inst->watcher = edbus_proxy_get(obj, WATCHER_IFACE);
|
||||||
edbus_proxy_call(host_inst->watcher, "RegisterStatusNotifierHost", NULL, NULL, -1, "s",
|
edbus_proxy_call(host_inst->watcher, "RegisterStatusNotifierHost", NULL, NULL, -1, "s",
|
||||||
|
@ -391,18 +439,35 @@ void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst)
|
||||||
notifier_item_del_cb, host_inst);
|
notifier_item_del_cb, host_inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst)
|
||||||
|
{
|
||||||
|
edbus_init();
|
||||||
|
|
||||||
|
host_inst->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
|
||||||
|
|
||||||
|
edbus_name_request(host_inst->conn,
|
||||||
|
WATCHER_BUS, EDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING,
|
||||||
|
name_request_cb, host_inst);
|
||||||
|
}
|
||||||
|
|
||||||
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst)
|
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst)
|
||||||
{
|
{
|
||||||
Eina_Inlist *safe_list;
|
Eina_Inlist *safe_list;
|
||||||
Notifier_Item *item;
|
Notifier_Item *item;
|
||||||
EDBus_Object *obj;
|
|
||||||
|
|
||||||
EINA_INLIST_FOREACH_SAFE(host_inst->items_list, safe_list, item)
|
EINA_INLIST_FOREACH_SAFE(host_inst->items_list, safe_list, item)
|
||||||
systray_notifier_item_free(item);
|
systray_notifier_item_free(item);
|
||||||
|
|
||||||
obj = edbus_proxy_object_get(host_inst->watcher);
|
if (!host_inst->watcher)
|
||||||
edbus_proxy_unref(host_inst->watcher);
|
systray_notifier_dbus_watcher_stop();
|
||||||
edbus_object_unref(obj);
|
else
|
||||||
|
{
|
||||||
|
EDBus_Object *obj;
|
||||||
|
obj = edbus_proxy_object_get(host_inst->watcher);
|
||||||
|
edbus_proxy_unref(host_inst->watcher);
|
||||||
|
edbus_object_unref(obj);
|
||||||
|
host_inst->watcher = NULL;
|
||||||
|
}
|
||||||
edbus_connection_unref(host_inst->conn);
|
edbus_connection_unref(host_inst->conn);
|
||||||
edbus_shutdown();
|
edbus_shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,8 @@ typedef struct _Notifier_Item
|
||||||
Eina_Bool in_box;
|
Eina_Bool in_box;
|
||||||
} Notifier_Item;
|
} Notifier_Item;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
void systray_notifier_update_menu(void *data, E_DBusMenu_Item *new_root_item);
|
void systray_notifier_update_menu(void *data, E_DBusMenu_Item *new_root_item);
|
||||||
void systray_notifier_item_update(Notifier_Item *item);
|
void systray_notifier_item_update(Notifier_Item *item);
|
||||||
|
@ -54,3 +56,6 @@ void systray_notifier_item_free(Notifier_Item *item);
|
||||||
|
|
||||||
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst);
|
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst);
|
||||||
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst);
|
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst);
|
||||||
|
|
||||||
|
void systray_notifier_dbus_watcher_start(EDBus_Connection *connection, E_Notifier_Watcher_Item_Registered_Cb registered, E_Notifier_Watcher_Item_Unregistered_Cb unregistered, const void *data);
|
||||||
|
void systray_notifier_dbus_watcher_stop(void);
|
||||||
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
#include "e_mod_notifier_host_private.h"
|
||||||
|
|
||||||
|
#define PATH "/StatusNotifierWatcher"
|
||||||
|
#define IFACE "org.kde.StatusNotifierWatcher"
|
||||||
|
#define PROTOCOL_VERSION 1
|
||||||
|
|
||||||
|
#define ERROR_HOST_ALREADY_REGISTERED "org.kde.StatusNotifierWatcher.Host.AlreadyRegistered"
|
||||||
|
#define ERROR_ITEM_ALREADY_REGISTERED "org.kde.StatusNotifierWatcher.Item.AlreadyRegistered"
|
||||||
|
|
||||||
|
static EDBus_Connection *conn = NULL;
|
||||||
|
static EDBus_Service_Interface *iface = NULL;
|
||||||
|
static Eina_List *items;
|
||||||
|
static const char *host_service = NULL;
|
||||||
|
static E_Notifier_Watcher_Item_Registered_Cb registered_cb;
|
||||||
|
static E_Notifier_Watcher_Item_Unregistered_Cb unregistered_cb;
|
||||||
|
static void *user_data;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ITEM_REGISTERED = 0,
|
||||||
|
ITEM_UNREGISTERED,
|
||||||
|
HOST_REGISTERED,
|
||||||
|
HOST_UNREGISTERED
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
item_name_monitor_cb(void *data, const char *bus, const char *old_id EINA_UNUSED, const char *new_id)
|
||||||
|
{
|
||||||
|
const char *service = data;
|
||||||
|
|
||||||
|
if (strcmp(new_id, ""))
|
||||||
|
return;
|
||||||
|
|
||||||
|
edbus_service_signal_emit(iface, ITEM_UNREGISTERED, service);
|
||||||
|
items = eina_list_remove(items, service);
|
||||||
|
if (unregistered_cb)
|
||||||
|
unregistered_cb(user_data, service);
|
||||||
|
eina_stringshare_del(service);
|
||||||
|
edbus_name_owner_changed_callback_del(conn, bus, item_name_monitor_cb, service);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EDBus_Message *
|
||||||
|
register_item_cb(const EDBus_Service_Interface *s_iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
const char *service;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &service))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sprintf(buf, "%s%s", edbus_message_sender_get(msg), service);
|
||||||
|
service = eina_stringshare_add(buf);
|
||||||
|
if (eina_list_data_find(items, service))
|
||||||
|
{
|
||||||
|
eina_stringshare_del(service);
|
||||||
|
return edbus_message_error_new(msg, ERROR_ITEM_ALREADY_REGISTERED, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
items = eina_list_append(items, service);
|
||||||
|
edbus_service_signal_emit(s_iface, ITEM_REGISTERED, service);
|
||||||
|
edbus_name_owner_changed_callback_add(conn, edbus_message_sender_get(msg),
|
||||||
|
item_name_monitor_cb, service,
|
||||||
|
EINA_FALSE);
|
||||||
|
|
||||||
|
if (registered_cb)
|
||||||
|
registered_cb(user_data, service);
|
||||||
|
return edbus_message_method_return_new(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
host_name_monitor_cb(void *data EINA_UNUSED, const char *bus, const char *old_id EINA_UNUSED, const char *new_id)
|
||||||
|
{
|
||||||
|
if (strcmp(new_id, ""))
|
||||||
|
return;
|
||||||
|
|
||||||
|
edbus_service_signal_emit(iface, HOST_UNREGISTERED);
|
||||||
|
eina_stringshare_del(host_service);
|
||||||
|
host_service = NULL;
|
||||||
|
edbus_name_owner_changed_callback_del(conn, bus, host_name_monitor_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static EDBus_Message *
|
||||||
|
register_host_cb(const EDBus_Service_Interface *s_iface, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
if (host_service)
|
||||||
|
return edbus_message_error_new(msg, ERROR_HOST_ALREADY_REGISTERED, "");
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &host_service))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
host_service = eina_stringshare_add(host_service);
|
||||||
|
edbus_service_signal_emit(s_iface, HOST_REGISTERED);
|
||||||
|
edbus_name_owner_changed_callback_add(conn, edbus_message_sender_get(msg),
|
||||||
|
host_name_monitor_cb, NULL, EINA_FALSE);
|
||||||
|
return edbus_message_method_return_new(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
properties_get(const EDBus_Service_Interface *s_iface EINA_UNUSED, const char *propname, EDBus_Message_Iter *iter, const EDBus_Message *request_msg EINA_UNUSED, EDBus_Message **error EINA_UNUSED)
|
||||||
|
{
|
||||||
|
if (!strcmp(propname, "ProtocolVersion"))
|
||||||
|
edbus_message_iter_basic_append(iter, 'i', PROTOCOL_VERSION);
|
||||||
|
else if (!strcmp(propname, "RegisteredStatusNotifierItems"))
|
||||||
|
{
|
||||||
|
EDBus_Message_Iter *array;
|
||||||
|
Eina_List *l;
|
||||||
|
const char *service;
|
||||||
|
|
||||||
|
edbus_message_iter_arguments_append(iter, "as", &array);
|
||||||
|
EINA_LIST_FOREACH(items, l, service)
|
||||||
|
edbus_message_iter_arguments_append(array, "s", service);
|
||||||
|
edbus_message_iter_container_close(iter, array);
|
||||||
|
}
|
||||||
|
else if (!strcmp(propname, "IsStatusNotifierHostRegistered"))
|
||||||
|
edbus_message_iter_arguments_append(iter, "b", host_service ? EINA_TRUE : EINA_FALSE);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const EDBus_Property properties[] =
|
||||||
|
{
|
||||||
|
{ "RegisteredStatusNotifierItems", "as", NULL, NULL, 0 },
|
||||||
|
{ "IsStatusNotifierHostRegistered", "b", NULL, NULL, 0 },
|
||||||
|
{ "ProtocolVersion", "i", NULL, NULL, 0 },
|
||||||
|
{ NULL, NULL, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EDBus_Signal signals[] = {
|
||||||
|
{ "StatusNotifierItemRegistered", EDBUS_ARGS({"s", "service"}), 0 },
|
||||||
|
{ "StatusNotifierItemUnregistered", EDBUS_ARGS({"s", "service"}), 0 },
|
||||||
|
{ "StatusNotifierHostRegistered", NULL, 0 },
|
||||||
|
{ "StatusNotifierHostUnregistered", NULL, 0 },
|
||||||
|
{ NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EDBus_Method methods[] =
|
||||||
|
{
|
||||||
|
{"RegisterStatusNotifierItem", EDBUS_ARGS({"s", "service"}), NULL,
|
||||||
|
register_item_cb, 0 },
|
||||||
|
{"RegisterStatusNotifierHost", EDBUS_ARGS({"s", "service"}), NULL,
|
||||||
|
register_host_cb, 0 },
|
||||||
|
{ NULL, NULL, NULL, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EDBus_Service_Interface_Desc iface_desc = {
|
||||||
|
IFACE, methods, signals, properties, properties_get, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_notifier_dbus_watcher_start(EDBus_Connection *connection, E_Notifier_Watcher_Item_Registered_Cb registered, E_Notifier_Watcher_Item_Unregistered_Cb unregistered, const void *data)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(!!conn);
|
||||||
|
conn = connection;
|
||||||
|
iface = edbus_service_interface_register(conn, PATH, &iface_desc);
|
||||||
|
registered_cb = registered;
|
||||||
|
unregistered_cb = unregistered;
|
||||||
|
user_data = (void *)data;
|
||||||
|
host_service = eina_stringshare_add("internal");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_notifier_dbus_watcher_stop(void)
|
||||||
|
{
|
||||||
|
const char *txt;
|
||||||
|
|
||||||
|
edbus_service_interface_unregister(iface);
|
||||||
|
EINA_LIST_FREE(items, txt)
|
||||||
|
{
|
||||||
|
char *bus;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; txt[i] != '/'; i++);
|
||||||
|
i++;
|
||||||
|
bus = malloc(sizeof(char) * i);
|
||||||
|
snprintf(bus, i, "%s", txt);
|
||||||
|
edbus_name_owner_changed_callback_del(conn, bus, item_name_monitor_cb, txt);
|
||||||
|
free(bus);
|
||||||
|
eina_stringshare_del(txt);
|
||||||
|
}
|
||||||
|
if (host_service)
|
||||||
|
eina_stringshare_del(host_service);
|
||||||
|
conn = NULL;
|
||||||
|
}
|
Loading…
Reference in New Issue