forked from enlightenment/enlightenment
e systray: Initial commit of dbus notifier host
Patch by: José Roberto de Souza <zehortigoza@profusion.mobi> SVN revision: 82111
This commit is contained in:
parent
3c6d7db5a3
commit
3014654d58
|
@ -17,14 +17,15 @@ group { name: "e/modules/systray/main";
|
||||||
part { name: "e.xembed.size"; type: RECT; mouse_events: 0;
|
part { name: "e.xembed.size"; type: RECT; mouse_events: 0;
|
||||||
description { state: "default" 0.0;
|
description { state: "default" 0.0;
|
||||||
visible: 0;
|
visible: 0;
|
||||||
rel1.offset: -1 0;
|
rel1.to: "e.xembed.box";
|
||||||
rel2.offset: 0 -1;
|
rel2.to: "e.xembed.box";
|
||||||
|
align: 0.0 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
part { name: "e.xembed.box"; type: BOX;
|
part { name: "e.xembed.box"; type: BOX;
|
||||||
description { state: "default" 0.0;
|
description { state: "default" 0.0;
|
||||||
rel1.to: "e.xembed.size";
|
rel2.relative: 0.0 1.0;
|
||||||
rel2.to: "e.xembed.size";
|
align: 0.0 0.5;
|
||||||
box {
|
box {
|
||||||
layout: "horizontal";
|
layout: "horizontal";
|
||||||
padding: 2 0;
|
padding: 2 0;
|
||||||
|
@ -40,78 +41,113 @@ group { name: "e/modules/systray/main";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
part { name: "e.dbus_notifier.box"; type: BOX;
|
||||||
|
description { state: "default" 0.0;
|
||||||
|
align: 1.0 0.5;
|
||||||
|
rel1 {
|
||||||
|
relative: 1.0 0.0;
|
||||||
|
to: "e.xembed.box";
|
||||||
|
}
|
||||||
|
box {
|
||||||
|
layout: "horizontal";
|
||||||
|
padding: 2 0;
|
||||||
|
align: 0.5 0.5;
|
||||||
|
min: 1 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
description { state: "vertical" 0.0;
|
||||||
|
inherit: "default" 0.0;
|
||||||
|
box {
|
||||||
|
layout: "vertical";
|
||||||
|
padding: 0 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
programs {
|
programs {
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,horiz"; source: "e";
|
signal: "e,action,orient,horiz"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,vert"; source: "e";
|
signal: "e,action,orient,vert"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,left"; source: "e";
|
signal: "e,action,orient,left"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,right"; source: "e";
|
signal: "e,action,orient,right"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,top"; source: "e";
|
signal: "e,action,orient,top"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,bottom"; source: "e";
|
signal: "e,action,orient,bottom"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_tl"; source: "e";
|
signal: "e,action,orient,corner_tl"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_tr"; source: "e";
|
signal: "e,action,orient,corner_tr"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_bl"; source: "e";
|
signal: "e,action,orient,corner_bl"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_br"; source: "e";
|
signal: "e,action,orient,corner_br"; source: "e";
|
||||||
action: STATE_SET "default" 0.0;
|
action: STATE_SET "default" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_lt"; source: "e";
|
signal: "e,action,orient,corner_lt"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_rt"; source: "e";
|
signal: "e,action,orient,corner_rt"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_lb"; source: "e";
|
signal: "e,action,orient,corner_lb"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
signal: "e,action,orient,corner_rb"; source: "e";
|
signal: "e,action,orient,corner_rb"; source: "e";
|
||||||
action: STATE_SET "vertical" 0.0;
|
action: STATE_SET "vertical" 0.0;
|
||||||
target: "e.xembed.box";
|
target: "e.xembed.box";
|
||||||
|
target: "e.dbus_notifier.box";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,10 @@ systraypkg_LTLIBRARIES = systray/module.la
|
||||||
|
|
||||||
systray_module_la_SOURCES = systray/e_mod_main.h \
|
systray_module_la_SOURCES = systray/e_mod_main.h \
|
||||||
systray/e_mod_main.c \
|
systray/e_mod_main.c \
|
||||||
systray/e_mod_xembed.c
|
systray/e_mod_xembed.c \
|
||||||
|
systray/e_mod_notifier_host_private.h \
|
||||||
|
systray/e_mod_notifier_host.c \
|
||||||
|
systray/e_mod_notifier_host_dbus.c
|
||||||
|
|
||||||
.PHONY: systray install-systray
|
.PHONY: systray install-systray
|
||||||
systray: $(systraypkg_LTLIBRARIES) $(systray_DATA)
|
systray: $(systraypkg_LTLIBRARIES) $(systray_DATA)
|
||||||
|
|
|
@ -6,6 +6,7 @@ struct _Instance
|
||||||
E_Container *con;
|
E_Container *con;
|
||||||
Evas *evas;
|
Evas *evas;
|
||||||
Instance_Xembed *xembed;
|
Instance_Xembed *xembed;
|
||||||
|
Instance_Notifier_Host *notifier;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Evas_Object *gadget;
|
Evas_Object *gadget;
|
||||||
|
@ -211,6 +212,7 @@ _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
|
||||||
_systray_cb_mouse_down, inst);
|
_systray_cb_mouse_down, inst);
|
||||||
|
|
||||||
inst->xembed = systray_xembed_new(inst);
|
inst->xembed = systray_xembed_new(inst);
|
||||||
|
inst->notifier = systray_notifier_host_new(inst, inst->gcc->gadcon);
|
||||||
|
|
||||||
instance = inst;
|
instance = inst;
|
||||||
return inst->gcc;
|
return inst->gcc;
|
||||||
|
@ -228,6 +230,7 @@ _gc_shutdown(E_Gadcon_Client *gcc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
systray_xembed_free(inst->xembed);
|
systray_xembed_free(inst->xembed);
|
||||||
|
systray_notifier_host_free(inst->notifier);
|
||||||
|
|
||||||
evas_object_del(inst->ui.gadget);
|
evas_object_del(inst->ui.gadget);
|
||||||
|
|
||||||
|
@ -449,6 +452,16 @@ systray_edje_box_append(const Instance *inst, const char *part,
|
||||||
edje_object_part_box_append(inst->ui.gadget, part, child);
|
edje_object_part_box_append(inst->ui.gadget, part, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_edje_box_remove(const Instance *inst, const char *part,
|
||||||
|
Evas_Object *child)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(inst);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(part);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(child);
|
||||||
|
edje_object_part_box_remove(inst->ui.gadget, part, child);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
systray_manager_number_get(const Instance *inst)
|
systray_manager_number_get(const Instance *inst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ EAPI int e_modapi_save(E_Module *m);
|
||||||
|
|
||||||
typedef struct _Instance Instance;
|
typedef struct _Instance Instance;
|
||||||
typedef struct _Instance_Xembed Instance_Xembed;
|
typedef struct _Instance_Xembed Instance_Xembed;
|
||||||
|
typedef struct _Instance_Notifier_Host Instance_Notifier_Host;
|
||||||
|
|
||||||
E_Gadcon_Orient systray_orient_get(const Instance *inst);
|
E_Gadcon_Orient systray_orient_get(const Instance *inst);
|
||||||
const E_Gadcon *systray_gadcon_get(const Instance *inst);
|
const E_Gadcon *systray_gadcon_get(const Instance *inst);
|
||||||
|
@ -21,6 +22,7 @@ Evas *systray_evas_get(const Instance *inst);
|
||||||
Evas_Object *systray_edje_get(const Instance *inst);
|
Evas_Object *systray_edje_get(const Instance *inst);
|
||||||
void systray_edje_emit(const Instance *inst, const char *sig);
|
void systray_edje_emit(const Instance *inst, const char *sig);
|
||||||
void systray_edje_box_append(const Instance *inst, const char *part, Evas_Object *child);
|
void systray_edje_box_append(const Instance *inst, const char *part, Evas_Object *child);
|
||||||
|
void systray_edje_box_remove(const Instance *inst, const char *part, Evas_Object *child);
|
||||||
|
|
||||||
int systray_manager_number_get(const Instance *inst);
|
int systray_manager_number_get(const Instance *inst);
|
||||||
Ecore_X_Window systray_root_get(const Instance *inst);
|
Ecore_X_Window systray_root_get(const Instance *inst);
|
||||||
|
@ -33,6 +35,9 @@ void systray_xembed_free(Instance_Xembed *xembed);
|
||||||
void systray_xembed_orient_set(Instance_Xembed *xembed, E_Gadcon_Orient orient);
|
void systray_xembed_orient_set(Instance_Xembed *xembed, E_Gadcon_Orient orient);
|
||||||
void systray_xembed_size_updated(Instance_Xembed *xembed);
|
void systray_xembed_size_updated(Instance_Xembed *xembed);
|
||||||
|
|
||||||
|
Instance_Notifier_Host *systray_notifier_host_new(Instance *inst, E_Gadcon *gadcon);
|
||||||
|
void systray_notifier_host_free(Instance_Notifier_Host *notifier);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup Optional_Gadgets
|
* @addtogroup Optional_Gadgets
|
||||||
* @{
|
* @{
|
||||||
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
#include "e_mod_notifier_host_private.h"
|
||||||
|
|
||||||
|
#define WATCHER_BUS "org.kde.StatusNotifierWatcher"
|
||||||
|
#define WATCHER_PATH "/StatusNotifierWatcher"
|
||||||
|
#define WATCHER_IFACE "org.kde.StatusNotifierWatcher"
|
||||||
|
|
||||||
|
#define ITEM_IFACE "org.kde.StatusNotifierItem"
|
||||||
|
|
||||||
|
const char *Category_Name[] = {
|
||||||
|
"unknown", "SystemServices"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *Status_Names[] = {
|
||||||
|
"unknown", "Active", "Passive", "NeedsAttention"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *box_part_name = "e.dbus_notifier.box";
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_notifier_item_free(Notifier_Item *item)
|
||||||
|
{
|
||||||
|
EDBus_Object *obj;
|
||||||
|
EDBus_Signal_Handler *sig;
|
||||||
|
evas_object_del(item->icon_object);
|
||||||
|
if (item->menu_path)
|
||||||
|
{
|
||||||
|
e_dbusmenu_unload(item->menu_data);
|
||||||
|
//TODO free evas_object of menu
|
||||||
|
}
|
||||||
|
eina_stringshare_del(item->bus_id);
|
||||||
|
eina_stringshare_del(item->path);
|
||||||
|
if (item->attention_icon_name)
|
||||||
|
eina_stringshare_del(item->attention_icon_name);
|
||||||
|
if (item->icon_name)
|
||||||
|
eina_stringshare_del(item->icon_name);
|
||||||
|
if (item->icon_path)
|
||||||
|
eina_stringshare_del(item->icon_path);
|
||||||
|
if (item->id)
|
||||||
|
eina_stringshare_del(item->id);
|
||||||
|
if (item->menu_path)
|
||||||
|
eina_stringshare_del(item->menu_path);
|
||||||
|
if (item->title)
|
||||||
|
eina_stringshare_del(item->title);
|
||||||
|
EINA_LIST_FREE(item->signals, sig)
|
||||||
|
edbus_signal_handler_del(sig);
|
||||||
|
obj = edbus_proxy_object_get(item->proxy);
|
||||||
|
edbus_proxy_unref(item->proxy);
|
||||||
|
edbus_object_unref(obj);
|
||||||
|
item->host_inst->items_list = eina_inlist_remove(item->host_inst->items_list,
|
||||||
|
EINA_INLIST_GET(item));
|
||||||
|
systray_size_updated(item->host_inst->inst);
|
||||||
|
free(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_load(const char *name, const char *path, Evas_Object *image)
|
||||||
|
{
|
||||||
|
if (path && strlen(path))
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
sprintf(buf, "%s/%s", path, name);
|
||||||
|
if (!e_icon_file_set(image, buf))
|
||||||
|
e_util_icon_theme_set(image, "dialog-error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!e_util_icon_theme_set(image, name))
|
||||||
|
e_util_icon_theme_set(image, "dialog-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_clicked_item_cb(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
Evas_Event_Mouse_Down *ev = event;
|
||||||
|
|
||||||
|
if (ev->button == 1)
|
||||||
|
{
|
||||||
|
DBG("left %s", item->id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
image_scale(Notifier_Item *item)
|
||||||
|
{
|
||||||
|
Evas_Coord sz;
|
||||||
|
switch (systray_gadcon_get(item->host_inst->inst)->orient)
|
||||||
|
{
|
||||||
|
case E_GADCON_ORIENT_HORIZ:
|
||||||
|
case E_GADCON_ORIENT_TOP:
|
||||||
|
case E_GADCON_ORIENT_BOTTOM:
|
||||||
|
case E_GADCON_ORIENT_CORNER_TL:
|
||||||
|
case E_GADCON_ORIENT_CORNER_TR:
|
||||||
|
case E_GADCON_ORIENT_CORNER_BL:
|
||||||
|
case E_GADCON_ORIENT_CORNER_BR:
|
||||||
|
sz = systray_gadcon_get(item->host_inst->inst)->shelf->h;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case E_GADCON_ORIENT_VERT:
|
||||||
|
case E_GADCON_ORIENT_LEFT:
|
||||||
|
case E_GADCON_ORIENT_RIGHT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_LT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_RT:
|
||||||
|
case E_GADCON_ORIENT_CORNER_LB:
|
||||||
|
case E_GADCON_ORIENT_CORNER_RB:
|
||||||
|
default:
|
||||||
|
sz = systray_gadcon_get(item->host_inst->inst)->shelf->w;
|
||||||
|
}
|
||||||
|
sz = sz - 5;
|
||||||
|
evas_object_resize(item->icon_object, sz, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_notifier_item_update(Notifier_Item *item)
|
||||||
|
{
|
||||||
|
if (!item->icon_object)
|
||||||
|
{
|
||||||
|
item->icon_object = e_icon_add(evas_object_evas_get(item->host_inst->edje));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(item->icon_object);
|
||||||
|
image_scale(item);
|
||||||
|
systray_size_updated(item->host_inst->inst);
|
||||||
|
evas_object_event_callback_add(item->icon_object, EVAS_CALLBACK_MOUSE_DOWN,
|
||||||
|
_clicked_item_cb, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (item->status)
|
||||||
|
{
|
||||||
|
case STATUS_ACTIVE:
|
||||||
|
{
|
||||||
|
image_load(item->icon_name, item->icon_path, item->icon_object);
|
||||||
|
if (!item->in_box)
|
||||||
|
{
|
||||||
|
systray_edje_box_append(item->host_inst->inst, box_part_name,
|
||||||
|
item->icon_object);
|
||||||
|
evas_object_show(item->icon_object);
|
||||||
|
}
|
||||||
|
item->in_box = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATUS_PASSIVE:
|
||||||
|
{
|
||||||
|
if (item->in_box)
|
||||||
|
{
|
||||||
|
systray_edje_box_remove(item->host_inst->inst, box_part_name,
|
||||||
|
item->icon_object);
|
||||||
|
evas_object_hide(item->icon_object);
|
||||||
|
}
|
||||||
|
item->in_box = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATUS_ATTENTION:
|
||||||
|
{
|
||||||
|
image_load(item->attention_icon_name, item->icon_path,
|
||||||
|
item->icon_object);
|
||||||
|
if (!item->in_box)
|
||||||
|
{
|
||||||
|
systray_edje_box_append(item->host_inst->inst, box_part_name,
|
||||||
|
item->icon_object);
|
||||||
|
evas_object_show(item->icon_object);
|
||||||
|
}
|
||||||
|
item->in_box = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ERR("Status unexpected.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
systray_size_updated(item->host_inst->inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance_Notifier_Host *
|
||||||
|
systray_notifier_host_new(Instance *inst, E_Gadcon *gadcon)
|
||||||
|
{
|
||||||
|
Instance_Notifier_Host *host_inst = NULL;
|
||||||
|
host_inst = calloc(1, sizeof(Instance_Notifier_Host));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(host_inst, NULL);
|
||||||
|
host_inst->inst = inst;
|
||||||
|
host_inst->edje = systray_edje_get(inst);
|
||||||
|
host_inst->gadcon = gadcon;
|
||||||
|
systray_notifier_dbus_init(host_inst);
|
||||||
|
|
||||||
|
return host_inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
systray_notifier_host_free(Instance_Notifier_Host *notifier)
|
||||||
|
{
|
||||||
|
systray_notifier_dbus_shutdown(notifier);
|
||||||
|
free(notifier);
|
||||||
|
}
|
|
@ -0,0 +1,429 @@
|
||||||
|
#include "e_mod_notifier_host_private.h"
|
||||||
|
|
||||||
|
#define WATCHER_BUS "org.kde.StatusNotifierWatcher"
|
||||||
|
#define WATCHER_PATH "/StatusNotifierWatcher"
|
||||||
|
#define WATCHER_IFACE "org.kde.StatusNotifierWatcher"
|
||||||
|
|
||||||
|
#define ITEM_IFACE "org.kde.StatusNotifierItem"
|
||||||
|
|
||||||
|
#define HOST_REGISTRER "/bla" //TODO check what watcher expect we send to him
|
||||||
|
|
||||||
|
extern const char *Category_Name[];
|
||||||
|
extern const char *Status_Names[];
|
||||||
|
|
||||||
|
typedef struct _Notifier_Host_Data {
|
||||||
|
Instance_Notifier_Host *host_inst;
|
||||||
|
void *data;
|
||||||
|
} Notifier_Host_Data;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
service_string_parse(const char *item, const char **path, const char **bus_id)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < strlen(item); i++)
|
||||||
|
{
|
||||||
|
if (item[i] != '/')
|
||||||
|
continue;
|
||||||
|
*path = eina_stringshare_add(item+i);
|
||||||
|
*bus_id = eina_stringshare_nprintf(i+1, "%s", item);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Notifier_Item *
|
||||||
|
notifier_item_find(const char *path, const char *bus_id, Instance_Notifier_Host *host_inst)
|
||||||
|
{
|
||||||
|
Notifier_Item *item;
|
||||||
|
EINA_INLIST_FOREACH(host_inst->items_list, item)
|
||||||
|
{
|
||||||
|
if (item->bus_id == bus_id && item->path == path)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
id_find(const char *text, const char *array_of_names[], unsigned max)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(text, array_of_names[i]))
|
||||||
|
continue;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
item_prop_get(void *data, const void *key, EDBus_Message_Iter *var)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
|
||||||
|
if (!strcmp(key, "Category"))
|
||||||
|
{
|
||||||
|
const char *category;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &category);
|
||||||
|
item->category = id_find(category, Category_Name, CATEGORY_LAST);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "IconName"))
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &name);
|
||||||
|
eina_stringshare_replace(&item->icon_name, name);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "AttentionIconName"))
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &name);
|
||||||
|
eina_stringshare_replace(&item->attention_icon_name, name);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "IconThemePath"))
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &path);
|
||||||
|
eina_stringshare_replace(&item->icon_path, path);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "Menu"))
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
edbus_message_iter_arguments_get(var, "o", &path);
|
||||||
|
eina_stringshare_replace(&item->menu_path, path);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "Status"))
|
||||||
|
{
|
||||||
|
const char *status;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &status);
|
||||||
|
item->status = id_find(status, Status_Names, STATUS_LAST);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "Id"))
|
||||||
|
{
|
||||||
|
const char *id;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &id);
|
||||||
|
eina_stringshare_replace(&item->id, id);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "Title"))
|
||||||
|
{
|
||||||
|
const char *title;
|
||||||
|
edbus_message_iter_arguments_get(var, "s", &title);
|
||||||
|
eina_stringshare_replace(&item->title, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//debug
|
||||||
|
static void
|
||||||
|
render_menu_itens(void *data, E_DBusMenu_Item *new_root_item)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
E_DBusMenu_Item *child;
|
||||||
|
//TODO create evas_object of menu
|
||||||
|
|
||||||
|
printf("icon = %s\n", item->id);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN(new_root_item->is_submenu);
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH(new_root_item->sub_items, child)
|
||||||
|
{
|
||||||
|
if (child->type == E_DBUSMENU_ITEM_TYPE_SEPARATOR)
|
||||||
|
printf("\tseparator\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\tLabel= %s | Icon name=%s | Toggle type=%d | Toggle state=%d | Visible = %d | Enabled = %d\n",
|
||||||
|
child->label, child->icon_name, child->toggle_type,
|
||||||
|
child->toggle_state, child->visible, child->enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
props_changed(void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *interface, *menu = item->menu_path;
|
||||||
|
EDBus_Message_Iter *changed, *invalidate;
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "sa{sv}as", &interface, &changed, &invalidate))
|
||||||
|
{
|
||||||
|
ERR("Error reading message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
edbus_message_iter_dict_iterate(changed, "sv", item_prop_get, item);
|
||||||
|
|
||||||
|
if (menu != item->menu_path)
|
||||||
|
{
|
||||||
|
EDBus_Connection *conn = edbus_object_connection_get(edbus_proxy_object_get(item->proxy));
|
||||||
|
e_dbusmenu_unload(item->menu_data);
|
||||||
|
item->menu_data = e_dbusmenu_load(conn, item->bus_id, item->menu_path, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
props_get_all_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
const char *error, *error_name;
|
||||||
|
EDBus_Message_Iter *dict;
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
EDBus_Connection *conn;
|
||||||
|
|
||||||
|
if (edbus_message_error_get(msg, &error, &error_name))
|
||||||
|
{
|
||||||
|
ERR("%s %s", error, error_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "a{sv}", &dict))
|
||||||
|
{
|
||||||
|
ERR("Error getting arguments.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
edbus_message_iter_dict_iterate(dict, "sv", item_prop_get, item);
|
||||||
|
|
||||||
|
if (!item->menu_path)
|
||||||
|
ERR("Notifier item %s dont have menu path.", item->menu_path);
|
||||||
|
|
||||||
|
conn = edbus_object_connection_get(edbus_proxy_object_get(item->proxy));
|
||||||
|
item->menu_data = e_dbusmenu_load(conn, item->bus_id, item->menu_path, item);
|
||||||
|
e_dbusmenu_update_cb_set(item->menu_data, render_menu_itens);
|
||||||
|
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
basic_prop_get(const char *propname, void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
EDBus_Message_Iter *var;
|
||||||
|
const char *error, *error_msg;
|
||||||
|
|
||||||
|
if (edbus_message_error_get(msg, &error, &error_msg))
|
||||||
|
{
|
||||||
|
ERR("%s %s", error, error_msg);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "v", &var))
|
||||||
|
{
|
||||||
|
ERR("Error reading message.");
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
item_prop_get(data, propname, var);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
attention_icon_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *propname = "AttentionIconName";
|
||||||
|
basic_prop_get(propname, item, msg);
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_attention_icon_cb(void *data, const EDBus_Message *msg EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
edbus_proxy_property_get(item->proxy, "AttentionIconName", attention_icon_get_cb, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
icon_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *propname = "IconName";
|
||||||
|
basic_prop_get(propname, item, msg);
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_icon_cb(void *data, const EDBus_Message *msg EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
edbus_proxy_property_get(item->proxy, "IconName", icon_get_cb, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
title_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *propname = "Title";
|
||||||
|
basic_prop_get(propname, item, msg);
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_title_cb(void *data, const EDBus_Message *msg EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
edbus_proxy_property_get(item->proxy, "Title", title_get_cb, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_icon_theme_path_cb(void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *path;
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &path))
|
||||||
|
{
|
||||||
|
ERR("Error reading message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eina_stringshare_replace(&item->icon_path, path);
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_status_cb(void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
Notifier_Item *item = data;
|
||||||
|
const char *status;
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &status))
|
||||||
|
{
|
||||||
|
ERR("Error reading message.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item->status = id_find(status, Status_Names, STATUS_LAST);
|
||||||
|
systray_notifier_item_update(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notifier_item_add(const char *path, const char *bus_id, Instance_Notifier_Host *host_inst)
|
||||||
|
{
|
||||||
|
EDBus_Proxy *proxy;
|
||||||
|
Notifier_Item *item = calloc(1, sizeof(Notifier_Item));
|
||||||
|
EDBus_Signal_Handler *s;
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(item);
|
||||||
|
|
||||||
|
item->path = path;
|
||||||
|
item->bus_id = bus_id;
|
||||||
|
host_inst->items_list = eina_inlist_append(host_inst->items_list,
|
||||||
|
EINA_INLIST_GET(item));
|
||||||
|
item->host_inst = host_inst;
|
||||||
|
|
||||||
|
proxy = edbus_proxy_get(edbus_object_get(host_inst->conn, bus_id, path),
|
||||||
|
ITEM_IFACE);
|
||||||
|
item->proxy = proxy;
|
||||||
|
edbus_proxy_property_get_all(proxy, props_get_all_cb, item);
|
||||||
|
s = edbus_proxy_properties_changed_callback_add(proxy, props_changed, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
s = edbus_proxy_signal_handler_add(proxy, "NewAttentionIcon",
|
||||||
|
new_attention_icon_cb, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
s = edbus_proxy_signal_handler_add(proxy, "NewIcon",
|
||||||
|
new_icon_cb, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
s = edbus_proxy_signal_handler_add(proxy, "NewIconThemePath",
|
||||||
|
new_icon_theme_path_cb, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
s = edbus_proxy_signal_handler_add(proxy, "NewStatus", new_status_cb, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
s = edbus_proxy_signal_handler_add(proxy, "NewTitle", new_title_cb, item);
|
||||||
|
item->signals = eina_list_append(item->signals, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notifier_item_add_cb(void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
const char *item, *bus, *path;
|
||||||
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &item))
|
||||||
|
{
|
||||||
|
ERR("Error getting arguments from msg.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBG("add %s", item);
|
||||||
|
if (service_string_parse(item, &path, &bus))
|
||||||
|
notifier_item_add(path, bus, host_inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
notifier_item_del_cb(void *data, const EDBus_Message *msg)
|
||||||
|
{
|
||||||
|
const char *service, *bus, *path;
|
||||||
|
Notifier_Item *item;
|
||||||
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "s", &service))
|
||||||
|
{
|
||||||
|
ERR("Error getting arguments from msg.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBG("service %s", service);
|
||||||
|
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
|
||||||
|
notifier_items_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EINA_UNUSED)
|
||||||
|
{
|
||||||
|
const char *item;
|
||||||
|
const char *error, *error_msg;
|
||||||
|
EDBus_Message_Iter *array, *variant;
|
||||||
|
Instance_Notifier_Host *host_inst = data;
|
||||||
|
|
||||||
|
if (edbus_message_error_get(msg, &error, &error_msg))
|
||||||
|
{
|
||||||
|
ERR("%s %s", error, error_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edbus_message_arguments_get(msg, "v", &variant))
|
||||||
|
{
|
||||||
|
ERR("Error getting arguments from msg.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edbus_message_iter_arguments_get(variant, "as", &array))
|
||||||
|
{
|
||||||
|
ERR("Error getting arguments from msg.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (edbus_message_iter_get_and_next(array, 's', &item))
|
||||||
|
{
|
||||||
|
const char *bus, *path;
|
||||||
|
if (service_string_parse(item, &path, &bus))
|
||||||
|
notifier_item_add(path, bus, host_inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst)
|
||||||
|
{
|
||||||
|
EDBus_Object *obj;
|
||||||
|
edbus_init();
|
||||||
|
|
||||||
|
host_inst->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
|
||||||
|
obj = edbus_object_get(host_inst->conn, WATCHER_BUS, WATCHER_PATH);
|
||||||
|
host_inst->watcher = edbus_proxy_get(obj, WATCHER_IFACE);
|
||||||
|
edbus_proxy_call(host_inst->watcher, "RegisterStatusNotifierHost", NULL, NULL, -1, "s",
|
||||||
|
HOST_REGISTRER);
|
||||||
|
edbus_proxy_property_get(host_inst->watcher, "RegisteredStatusNotifierItems",
|
||||||
|
notifier_items_get_cb, host_inst);
|
||||||
|
edbus_proxy_signal_handler_add(host_inst->watcher, "StatusNotifierItemRegistered",
|
||||||
|
notifier_item_add_cb, host_inst);
|
||||||
|
edbus_proxy_signal_handler_add(host_inst->watcher, "StatusNotifierItemUnregistered",
|
||||||
|
notifier_item_del_cb, host_inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst)
|
||||||
|
{
|
||||||
|
Eina_Inlist *safe_list;
|
||||||
|
Notifier_Item *item;
|
||||||
|
EDBus_Object *obj;
|
||||||
|
|
||||||
|
EINA_INLIST_FOREACH_SAFE(host_inst->items_list, safe_list, item)
|
||||||
|
systray_notifier_item_free(item);
|
||||||
|
|
||||||
|
obj = edbus_proxy_object_get(host_inst->watcher);
|
||||||
|
edbus_proxy_unref(host_inst->watcher);
|
||||||
|
edbus_object_unref(obj);
|
||||||
|
edbus_connection_unref(host_inst->conn);
|
||||||
|
edbus_shutdown();
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include "e_mod_main.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CATEGORY_UNKNOWN = 0,
|
||||||
|
CATEGORY_SYSTEM_SERVICES,
|
||||||
|
CATEGORY_LAST
|
||||||
|
} Category;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STATUS_UNKNOWN = 0,
|
||||||
|
STATUS_ACTIVE,
|
||||||
|
STATUS_PASSIVE,
|
||||||
|
STATUS_ATTENTION,
|
||||||
|
STATUS_LAST
|
||||||
|
} Status;
|
||||||
|
|
||||||
|
struct _Instance_Notifier_Host
|
||||||
|
{
|
||||||
|
Instance *inst;
|
||||||
|
Eina_Inlist *items_list;
|
||||||
|
const Evas_Object *box;
|
||||||
|
const Evas_Object *edje;
|
||||||
|
EDBus_Connection *conn;
|
||||||
|
EDBus_Proxy *watcher;
|
||||||
|
E_Gadcon *gadcon;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _Notifier_Item
|
||||||
|
{
|
||||||
|
EINA_INLIST;
|
||||||
|
const char *bus_id;
|
||||||
|
const char *path;
|
||||||
|
EDBus_Proxy *proxy;
|
||||||
|
Category category;
|
||||||
|
Status status;
|
||||||
|
const char *id;
|
||||||
|
const char *title;
|
||||||
|
const char *icon_name;
|
||||||
|
const char *attention_icon_name;
|
||||||
|
const char *icon_path;
|
||||||
|
Evas_Object *icon_object;
|
||||||
|
Instance_Notifier_Host *host_inst;
|
||||||
|
const char *menu_path;
|
||||||
|
E_DBusMenu_Ctx *menu_data;
|
||||||
|
Eina_List *signals;
|
||||||
|
Eina_Bool in_box;
|
||||||
|
} Notifier_Item;
|
||||||
|
|
||||||
|
|
||||||
|
void systray_notifier_item_update(Notifier_Item *item);
|
||||||
|
void systray_notifier_item_free(Notifier_Item *item);
|
||||||
|
|
||||||
|
void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst);
|
||||||
|
void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst);
|
Loading…
Reference in New Issue