forked from enlightenment/enlightenment
fix systray implementation of notifier watcher (StatusNotifierItem)
previously, this would throw dbus errors (or not) and then do nothing in many cases. now it manages bus/path names more effectively and falls back to binary image data when an icon path is not available fix T2626 and probably some others
This commit is contained in:
parent
c9c880ec59
commit
0978d22f8e
|
@ -42,6 +42,8 @@ systray_notifier_item_free(Notifier_Item *item)
|
|||
e_dbusmenu_unload(item->menu_data);
|
||||
eina_stringshare_del(item->bus_id);
|
||||
eina_stringshare_del(item->path);
|
||||
free(item->imgdata);
|
||||
free(item->attnimgdata);
|
||||
if (item->attention_icon_name)
|
||||
eina_stringshare_del(item->attention_icon_name);
|
||||
if (item->icon_name)
|
||||
|
@ -64,7 +66,7 @@ systray_notifier_item_free(Notifier_Item *item)
|
|||
}
|
||||
|
||||
static void
|
||||
image_load(const char *name, const char *path, Evas_Object *image)
|
||||
image_load(const char *name, const char *path, uint32_t *imgdata, int w, int h, Evas_Object *image)
|
||||
{
|
||||
const char **ext, *exts[] =
|
||||
{
|
||||
|
@ -96,7 +98,18 @@ image_load(const char *name, const char *path, Evas_Object *image)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!e_util_icon_theme_set(image, name))
|
||||
if (name && name[0] && e_util_icon_theme_set(image, name)) return;
|
||||
if (imgdata)
|
||||
{
|
||||
Evas_Object *o;
|
||||
|
||||
o = evas_object_image_filled_add(evas_object_evas_get(image));
|
||||
evas_object_image_alpha_set(o, 1);
|
||||
evas_object_image_size_set(o, w, h);
|
||||
evas_object_image_data_set(o, imgdata);
|
||||
e_icon_image_object_set(image, o);
|
||||
}
|
||||
else
|
||||
e_util_icon_theme_set(image, "dialog-error");
|
||||
}
|
||||
|
||||
|
@ -261,7 +274,7 @@ jump_search:
|
|||
{
|
||||
case STATUS_ACTIVE:
|
||||
{
|
||||
image_load(item->icon_name, item->icon_path, ii->icon);
|
||||
image_load(item->icon_name, item->icon_path, item->imgdata, item->imgw, item->imgh, ii->icon);
|
||||
if (!evas_object_visible_get(ii->icon))
|
||||
{
|
||||
systray_edje_box_append(host_inst->inst, ii->icon);
|
||||
|
@ -280,7 +293,7 @@ jump_search:
|
|||
}
|
||||
case STATUS_ATTENTION:
|
||||
{
|
||||
image_load(item->attention_icon_name, item->icon_path, ii->icon);
|
||||
image_load(item->attention_icon_name, item->icon_path, item->attnimgdata, item->attnimgw, item->attnimgh, ii->icon);
|
||||
if (!evas_object_visible_get(ii->icon))
|
||||
{
|
||||
systray_edje_box_append(host_inst->inst, ii->icon);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
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;
|
||||
|
@ -56,6 +58,36 @@ id_find(const char *s, const char *names[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
icon_pixmap_deserialize(Eldbus_Message_Iter *variant, uint32_t **data, int *w, int *h)
|
||||
{
|
||||
Eldbus_Message_Iter *iter, *struc;
|
||||
|
||||
*data = NULL;
|
||||
*w = *h = 0;
|
||||
eldbus_message_iter_arguments_get(variant, "a(iiay)", &iter);
|
||||
while (eldbus_message_iter_get_and_next(iter, 'r', &struc))
|
||||
{
|
||||
Eldbus_Message_Iter *imgdata;
|
||||
|
||||
if (eldbus_message_iter_arguments_get(struc, "iiay", w, h, &imgdata))
|
||||
{
|
||||
uint32_t *img;
|
||||
int len;
|
||||
|
||||
if (eldbus_message_iter_fixed_array_get(imgdata, 'y', &img, &len))
|
||||
{
|
||||
unsigned int pos;
|
||||
|
||||
*data = malloc(len * sizeof(int));
|
||||
for (pos = 0; pos < (unsigned int)len; pos++)
|
||||
(*data)[pos] = eina_swap32(img[pos]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
item_prop_get(void *data, const void *key, Eldbus_Message_Iter *var)
|
||||
{
|
||||
|
@ -73,6 +105,16 @@ item_prop_get(void *data, const void *key, Eldbus_Message_Iter *var)
|
|||
eldbus_message_iter_arguments_get(var, "s", &name);
|
||||
eina_stringshare_replace(&item->icon_name, name);
|
||||
}
|
||||
else if (!strcmp(key, "IconPixmap"))
|
||||
{
|
||||
free(item->imgdata);
|
||||
icon_pixmap_deserialize(var, &item->imgdata, &item->imgw, &item->imgh);
|
||||
}
|
||||
else if (!strcmp(key, "AttentionIconPixmap"))
|
||||
{
|
||||
free(item->attnimgdata);
|
||||
icon_pixmap_deserialize(var, &item->attnimgdata, &item->attnimgw, &item->attnimgh);
|
||||
}
|
||||
else if (!strcmp(key, "AttentionIconName"))
|
||||
{
|
||||
const char *name;
|
||||
|
@ -190,13 +232,28 @@ basic_prop_get(const char *propname, void *data, const Eldbus_Message *msg)
|
|||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
attention_icon_pixmap_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
|
||||
{
|
||||
Notifier_Item *item = data;
|
||||
Eldbus_Message_Iter *variant;
|
||||
|
||||
if (!eldbus_message_arguments_get(msg, "v", &variant)) return;
|
||||
free(item->attnimgdata);
|
||||
icon_pixmap_deserialize(variant, &item->attnimgdata, &item->attnimgw, &item->attnimgh);
|
||||
systray_notifier_item_update(item);
|
||||
}
|
||||
|
||||
static void
|
||||
attention_icon_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
|
||||
{
|
||||
Notifier_Item *item = data;
|
||||
const char *propname = "AttentionIconName";
|
||||
basic_prop_get(propname, item, msg);
|
||||
systray_notifier_item_update(item);
|
||||
if ((!item->attention_icon_name) || (!item->attention_icon_name[0]))
|
||||
eldbus_proxy_property_get(item->proxy, "AttentionIconPixmap", attention_icon_pixmap_get_cb, item);
|
||||
else
|
||||
systray_notifier_item_update(item);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -206,13 +263,28 @@ new_attention_icon_cb(void *data, const Eldbus_Message *msg EINA_UNUSED)
|
|||
eldbus_proxy_property_get(item->proxy, "AttentionIconName", attention_icon_get_cb, item);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_pixmap_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
|
||||
{
|
||||
Notifier_Item *item = data;
|
||||
Eldbus_Message_Iter *variant;
|
||||
|
||||
if (!eldbus_message_arguments_get(msg, "v", &variant)) return;
|
||||
free(item->imgdata);
|
||||
icon_pixmap_deserialize(variant, &item->imgdata, &item->imgw, &item->imgh);
|
||||
systray_notifier_item_update(item);
|
||||
}
|
||||
|
||||
static void
|
||||
icon_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
|
||||
{
|
||||
Notifier_Item *item = data;
|
||||
const char *propname = "IconName";
|
||||
basic_prop_get(propname, item, msg);
|
||||
systray_notifier_item_update(item);
|
||||
if ((!item->icon_name) || (!item->icon_name[0]))
|
||||
eldbus_proxy_property_get(item->proxy, "IconPixmap", icon_pixmap_get_cb, item);
|
||||
else
|
||||
systray_notifier_item_update(item);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -373,28 +445,24 @@ notifier_items_get_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pen
|
|||
}
|
||||
|
||||
static void
|
||||
item_registered_local_cb(void *data, const char *service)
|
||||
item_registered_local_cb(void *data, const char *bus)
|
||||
{
|
||||
const char *bus, *path;
|
||||
Context_Notifier_Host *ctx = data;
|
||||
if (service_string_parse(service, &path, &bus))
|
||||
notifier_item_add(path, bus, ctx);
|
||||
notifier_item_add(eina_stringshare_ref(DBUS_PATH), eina_stringshare_add(bus), ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
item_unregistered_local_cb(void *data, const char *service)
|
||||
item_unregistered_local_cb(void *data, const char *bus)
|
||||
{
|
||||
const char *bus, *path;
|
||||
Context_Notifier_Host *ctx = data;
|
||||
Notifier_Item *item;
|
||||
Eina_Stringshare *s;
|
||||
|
||||
if (!service_string_parse(service, &path, &bus))
|
||||
return;
|
||||
item = notifier_item_find(path, bus, ctx);
|
||||
s = eina_stringshare_add(bus);
|
||||
item = notifier_item_find(DBUS_PATH, s, ctx);
|
||||
if (item)
|
||||
systray_notifier_item_free(item);
|
||||
eina_stringshare_del(path);
|
||||
eina_stringshare_del(bus);
|
||||
eina_stringshare_del(s);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -447,6 +515,7 @@ 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);
|
||||
|
@ -473,6 +542,7 @@ 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();
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ struct _Notifier_Item
|
|||
const char *menu_path;
|
||||
E_DBusMenu_Ctx *menu_data;
|
||||
Eina_List *signals;
|
||||
uint32_t *imgdata;
|
||||
int imgw, imgh;
|
||||
uint32_t *attnimgdata;
|
||||
int attnimgw, attnimgh;
|
||||
};
|
||||
|
||||
typedef void (*E_Notifier_Watcher_Item_Registered_Cb)(void *data, const char *service);
|
||||
|
|
|
@ -26,29 +26,32 @@ enum
|
|||
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;
|
||||
const char *svc, *service = data;
|
||||
|
||||
if (strcmp(new_id, ""))
|
||||
return;
|
||||
|
||||
eldbus_service_signal_emit(iface, ITEM_UNREGISTERED, service);
|
||||
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, service);
|
||||
unregistered_cb(user_data, bus);
|
||||
eldbus_name_owner_changed_callback_del(conn, svc, item_name_monitor_cb, service);
|
||||
eina_stringshare_del(service);
|
||||
eldbus_name_owner_changed_callback_del(conn, bus, item_name_monitor_cb, service);
|
||||
}
|
||||
|
||||
static Eldbus_Message *
|
||||
register_item_cb(const Eldbus_Service_Interface *s_iface, const Eldbus_Message *msg)
|
||||
{
|
||||
const char *service;
|
||||
const char *service, *svc;
|
||||
char buf[1024];
|
||||
|
||||
if (!eldbus_message_arguments_get(msg, "s", &service))
|
||||
return NULL;
|
||||
svc = service;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s%s", eldbus_message_sender_get(msg), service);
|
||||
snprintf(buf, sizeof(buf), "%s/%s", eldbus_message_sender_get(msg), service);
|
||||
service = eina_stringshare_add(buf);
|
||||
if (eina_list_data_find(items, service))
|
||||
{
|
||||
|
@ -57,13 +60,13 @@ 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, service);
|
||||
eldbus_name_owner_changed_callback_add(conn, eldbus_message_sender_get(msg),
|
||||
eldbus_service_signal_emit(s_iface, ITEM_REGISTERED, svc);
|
||||
eldbus_name_owner_changed_callback_add(conn, svc,
|
||||
item_name_monitor_cb, service,
|
||||
EINA_FALSE);
|
||||
|
||||
if (registered_cb)
|
||||
registered_cb(user_data, service);
|
||||
registered_cb(user_data, svc);
|
||||
return eldbus_message_method_return_new(msg);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue