From a913411beba73188b690550b01378c5ba3c07412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 9 Jan 2013 22:38:21 +0000 Subject: [PATCH] e systray: Move dbus stuff out of gadcon instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix a bug that was empty dbus notification when shelf is moved and also allow multiple instance if some day we drop xembed support. Patch by: José Roberto de Souza SVN revision: 82492 --- src/modules/systray/e_mod_main.c | 2 + src/modules/systray/e_mod_main.h | 4 + src/modules/systray/e_mod_notifier_host.c | 154 +++++++++++++----- .../systray/e_mod_notifier_host_dbus.c | 84 +++++----- .../systray/e_mod_notifier_host_private.h | 30 +++- 5 files changed, 179 insertions(+), 95 deletions(-) diff --git a/src/modules/systray/e_mod_main.c b/src/modules/systray/e_mod_main.c index 894d33281..abb6ff3d8 100644 --- a/src/modules/systray/e_mod_main.c +++ b/src/modules/systray/e_mod_main.c @@ -367,6 +367,7 @@ e_modapi_init(E_Module *m) e_gadcon_provider_register(&_gc_class); systray_xembed_init(); + systray_notifier_host_init(); return m; } @@ -378,6 +379,7 @@ e_modapi_shutdown(E_Module *m __UNUSED__) systray_mod = NULL; systray_xembed_shutdown(); + systray_notifier_host_shutdown(); return 1; } diff --git a/src/modules/systray/e_mod_main.h b/src/modules/systray/e_mod_main.h index 3ba409adb..79e26d180 100644 --- a/src/modules/systray/e_mod_main.h +++ b/src/modules/systray/e_mod_main.h @@ -11,7 +11,9 @@ EAPI int e_modapi_save(E_Module *m); typedef struct _Instance Instance; typedef struct _Instance_Xembed Instance_Xembed; +typedef struct _Context_Notifier_Host Context_Notifier_Host; typedef struct _Instance_Notifier_Host Instance_Notifier_Host; +typedef struct _Notifier_Item Notifier_Item; E_Gadcon_Orient systray_orient_get(const Instance *inst); const E_Gadcon *systray_gadcon_get(const Instance *inst); @@ -37,6 +39,8 @@ 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); +void systray_notifier_host_init(void); +void systray_notifier_host_shutdown(void); /** * @addtogroup Optional_Gadgets diff --git a/src/modules/systray/e_mod_notifier_host.c b/src/modules/systray/e_mod_notifier_host.c index 7b62baad5..e50047f8c 100644 --- a/src/modules/systray/e_mod_notifier_host.c +++ b/src/modules/systray/e_mod_notifier_host.c @@ -15,13 +15,30 @@ const char *Status_Names[] = { }; static const char *box_part_name = "e.dbus_notifier.box"; +static Context_Notifier_Host *ctx = NULL; void systray_notifier_item_free(Notifier_Item *item) { EDBus_Object *obj; EDBus_Signal_Handler *sig; - evas_object_del(item->icon_object); + Instance_Notifier_Host *host_inst; + EINA_INLIST_FOREACH(ctx->instances, host_inst) + { + Notifier_Item_Icon *ii; + EINA_INLIST_FOREACH(host_inst->ii_list, ii) + { + if (ii->item == item) + break; + } + if (!ii) + continue; + host_inst->ii_list = eina_inlist_remove(host_inst->ii_list, + EINA_INLIST_GET(ii)); + evas_object_del(ii->icon); + free(ii); + systray_size_updated(host_inst->inst); + } if (item->menu_path) e_dbusmenu_unload(item->menu_data); eina_stringshare_del(item->bus_id); @@ -43,9 +60,7 @@ systray_notifier_item_free(Notifier_Item *item) 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); + ctx->item_list = eina_inlist_remove(ctx->item_list, EINA_INLIST_GET(item)); free(item); } @@ -126,16 +141,16 @@ _item_submenu_new(E_DBusMenu_Item *item, E_Menu_Item *mi) } static void -_item_menu_new(Notifier_Item *item) +_item_menu_new(Notifier_Item_Icon *ii) { E_DBusMenu_Item *root_item; E_Menu *m; E_Zone *zone; int x, y; - E_Gadcon *gadcon = item->host_inst->gadcon; - - if (!item->dbus_item) return; - root_item = item->dbus_item; + E_Gadcon *gadcon = evas_object_data_get(ii->icon, "gadcon"); + EINA_SAFETY_ON_NULL_RETURN(gadcon); + if (!ii->item->dbus_item) return; + root_item = ii->item->dbus_item; EINA_SAFETY_ON_FALSE_RETURN(root_item->is_submenu); m = _item_submenu_new(root_item, NULL); @@ -151,11 +166,11 @@ _item_menu_new(Notifier_Item *item) void _clicked_item_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event) { - Notifier_Item *item = data; + Notifier_Item_Icon *ii = data; Evas_Event_Mouse_Down *ev = event; if (ev->button != 1) return; - _item_menu_new(item); + _item_menu_new(ii); } void @@ -166,10 +181,10 @@ systray_notifier_update_menu(void *data, E_DBusMenu_Item *new_root_item) } static void -image_scale(Notifier_Item *item) +image_scale(Instance_Notifier_Host *notifier_inst, Notifier_Item_Icon *ii) { Evas_Coord sz; - switch (systray_gadcon_get(item->host_inst->inst)->orient) + switch (systray_gadcon_get(notifier_inst->inst)->orient) { case E_GADCON_ORIENT_HORIZ: case E_GADCON_ORIENT_TOP: @@ -178,7 +193,7 @@ image_scale(Notifier_Item *item) 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; + sz = systray_gadcon_get(notifier_inst->inst)->shelf->h; break; case E_GADCON_ORIENT_VERT: @@ -189,79 +204,107 @@ image_scale(Notifier_Item *item) case E_GADCON_ORIENT_CORNER_LB: case E_GADCON_ORIENT_CORNER_RB: default: - sz = systray_gadcon_get(item->host_inst->inst)->shelf->w; + sz = systray_gadcon_get(notifier_inst->inst)->shelf->w; + break; } sz = sz - 5; - evas_object_resize(item->icon_object, sz, sz); + evas_object_resize(ii->icon, sz, sz); } -void -systray_notifier_item_update(Notifier_Item *item) +static void +_systray_notifier_inst_item_update(Instance_Notifier_Host *host_inst, Notifier_Item *item, Eina_Bool search) { - if (!item->icon_object) + Notifier_Item_Icon *ii = NULL; + if (!search) + goto jump_search; + EINA_INLIST_FOREACH(host_inst->ii_list, ii) { - 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); + if (ii->item == item) + break; + } +jump_search: + if (!ii) + { + ii = calloc(1, sizeof(Notifier_Item_Icon)); + ii->item = item; + host_inst->ii_list = eina_inlist_append(host_inst->ii_list, + EINA_INLIST_GET(ii)); } + if (!ii->icon) + { + ii->icon = e_icon_add(evas_object_evas_get(host_inst->edje)); + EINA_SAFETY_ON_NULL_RETURN(ii->icon); + image_scale(host_inst, ii); + evas_object_data_set(ii->icon, "gadcon", host_inst->gadcon); + evas_object_event_callback_add(ii->icon, EVAS_CALLBACK_MOUSE_DOWN, + _clicked_item_cb, ii); + } switch (item->status) { case STATUS_ACTIVE: { - image_load(item->icon_name, item->icon_path, item->icon_object); - if (!evas_object_visible_get(item->icon_object)) + image_load(item->icon_name, item->icon_path, ii->icon); + if (!evas_object_visible_get(ii->icon)) { - systray_edje_box_append(item->host_inst->inst, box_part_name, - item->icon_object); - evas_object_show(item->icon_object); + systray_edje_box_append(host_inst->inst, box_part_name, + ii->icon); + evas_object_show(ii->icon); } break; } case STATUS_PASSIVE: { - if (evas_object_visible_get(item->icon_object)) + if (evas_object_visible_get(ii->icon)) { - systray_edje_box_remove(item->host_inst->inst, box_part_name, - item->icon_object); - evas_object_hide(item->icon_object); + systray_edje_box_remove(host_inst->inst, box_part_name, + ii->icon); + evas_object_hide(ii->icon); } break; } case STATUS_ATTENTION: { - image_load(item->attention_icon_name, item->icon_path, - item->icon_object); - if (!evas_object_visible_get(item->icon_object)) + image_load(item->attention_icon_name, item->icon_path, ii->icon); + if (!evas_object_visible_get(ii->icon)) { - systray_edje_box_append(item->host_inst->inst, box_part_name, - item->icon_object); - evas_object_show(item->icon_object); + systray_edje_box_append(host_inst->inst, box_part_name, + ii->icon); + evas_object_show(ii->icon); } break; } default: { - ERR("Status unexpected."); + WRN("unhandled status"); break; } } - systray_size_updated(item->host_inst->inst); + systray_size_updated(host_inst->inst); +} + +void +systray_notifier_item_update(Notifier_Item *item) +{ + Instance_Notifier_Host *inst; + EINA_INLIST_FOREACH(ctx->instances, inst) + _systray_notifier_inst_item_update(inst, item, EINA_TRUE); } Instance_Notifier_Host * systray_notifier_host_new(Instance *inst, E_Gadcon *gadcon) { Instance_Notifier_Host *host_inst = NULL; + Notifier_Item *item; 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); + ctx->instances = eina_inlist_append(ctx->instances, EINA_INLIST_GET(host_inst)); + + EINA_INLIST_FOREACH(ctx->item_list, item) + _systray_notifier_inst_item_update(host_inst, item, EINA_FALSE); return host_inst; } @@ -269,6 +312,29 @@ systray_notifier_host_new(Instance *inst, E_Gadcon *gadcon) void systray_notifier_host_free(Instance_Notifier_Host *notifier) { - systray_notifier_dbus_shutdown(notifier); + while (notifier->ii_list) + { + Notifier_Item_Icon *ii = EINA_INLIST_CONTAINER_GET(notifier->ii_list, Notifier_Item_Icon); + notifier->ii_list = eina_inlist_remove(notifier->ii_list, + notifier->ii_list); + free(ii); + } + ctx->instances = eina_inlist_remove(ctx->instances, EINA_INLIST_GET(notifier)); free(notifier); } + +void +systray_notifier_host_init(void) +{ + ctx = calloc(1, sizeof(Context_Notifier_Host)); + EINA_SAFETY_ON_NULL_RETURN(ctx); + systray_notifier_dbus_init(ctx); +} + +void +systray_notifier_host_shutdown(void) +{ + systray_notifier_dbus_shutdown(ctx); + free(ctx); + ctx = NULL; +} diff --git a/src/modules/systray/e_mod_notifier_host_dbus.c b/src/modules/systray/e_mod_notifier_host_dbus.c index 9f1183a73..fc6e683f6 100644 --- a/src/modules/systray/e_mod_notifier_host_dbus.c +++ b/src/modules/systray/e_mod_notifier_host_dbus.c @@ -32,10 +32,10 @@ service_string_parse(const char *item, const char **path, const char **bus_id) } static Notifier_Item * -notifier_item_find(const char *path, const char *bus_id, Instance_Notifier_Host *host_inst) +notifier_item_find(const char *path, const char *bus_id, Context_Notifier_Host *ctx) { Notifier_Item *item; - EINA_INLIST_FOREACH(host_inst->items_list, item) + EINA_INLIST_FOREACH(ctx->item_list, item) { if (item->bus_id == bus_id && item->path == path) return item; @@ -267,7 +267,7 @@ new_status_cb(void *data, const EDBus_Message *msg) } static void -notifier_item_add(const char *path, const char *bus_id, Instance_Notifier_Host *host_inst) +notifier_item_add(const char *path, const char *bus_id, Context_Notifier_Host *ctx) { EDBus_Proxy *proxy; Notifier_Item *item = calloc(1, sizeof(Notifier_Item)); @@ -276,11 +276,10 @@ notifier_item_add(const char *path, const char *bus_id, Instance_Notifier_Host * 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; + ctx->item_list = eina_inlist_append(ctx->item_list, + EINA_INLIST_GET(item)); - proxy = edbus_proxy_get(edbus_object_get(host_inst->conn, bus_id, path), + proxy = edbus_proxy_get(edbus_object_get(ctx->conn, bus_id, path), ITEM_IFACE); item->proxy = proxy; edbus_proxy_property_get_all(proxy, props_get_all_cb, item); @@ -305,7 +304,7 @@ static void notifier_item_add_cb(void *data, const EDBus_Message *msg) { const char *item, *bus, *path; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; if (!edbus_message_arguments_get(msg, "s", &item)) { @@ -314,7 +313,7 @@ notifier_item_add_cb(void *data, const EDBus_Message *msg) } DBG("add %s", item); if (service_string_parse(item, &path, &bus)) - notifier_item_add(path, bus, host_inst); + notifier_item_add(path, bus, ctx); } static void @@ -322,7 +321,7 @@ notifier_item_del_cb(void *data, const EDBus_Message *msg) { const char *service, *bus, *path; Notifier_Item *item; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; if (!edbus_message_arguments_get(msg, "s", &service)) { @@ -332,7 +331,7 @@ notifier_item_del_cb(void *data, const EDBus_Message *msg) DBG("service %s", service); if (!service_string_parse(service, &path, &bus)) return; - item = notifier_item_find(path, bus, host_inst); + item = notifier_item_find(path, bus, ctx); if (item) systray_notifier_item_free(item); eina_stringshare_del(path); @@ -345,7 +344,7 @@ notifier_items_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pendi const char *item; const char *error, *error_msg; EDBus_Message_Iter *array, *variant; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; if (edbus_message_error_get(msg, &error, &error_msg)) { @@ -369,7 +368,7 @@ notifier_items_get_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pendi { const char *bus, *path; if (service_string_parse(item, &path, &bus)) - notifier_item_add(path, bus, host_inst); + notifier_item_add(path, bus, ctx); } } @@ -377,21 +376,21 @@ static void item_registered_local_cb(void *data, const char *service) { const char *bus, *path; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; if (service_string_parse(service, &path, &bus)) - notifier_item_add(path, bus, host_inst); + notifier_item_add(path, bus, ctx); } static void item_unregistered_local_cb(void *data, const char *service) { const char *bus, *path; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; Notifier_Item *item; if (!service_string_parse(service, &path, &bus)) return; - item = notifier_item_find(path, bus, host_inst); + item = notifier_item_find(path, bus, ctx); if (item) systray_notifier_item_free(item); eina_stringshare_del(path); @@ -404,7 +403,7 @@ name_request_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EIN const char *error, *error_msg; unsigned flag; EDBus_Object *obj; - Instance_Notifier_Host *host_inst = data; + Context_Notifier_Host *ctx = data; if (edbus_message_error_get(msg, &error, &error_msg)) { @@ -420,54 +419,55 @@ name_request_cb(void *data, const EDBus_Message *msg, EDBus_Pending *pending EIN if (flag == EDBUS_NAME_REQUEST_REPLY_PRIMARY_OWNER) { - systray_notifier_dbus_watcher_start(host_inst->conn, + systray_notifier_dbus_watcher_start(ctx->conn, item_registered_local_cb, - item_unregistered_local_cb, host_inst); + item_unregistered_local_cb, ctx); 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); - host_inst->watcher = edbus_proxy_get(obj, WATCHER_IFACE); - edbus_proxy_call(host_inst->watcher, "RegisterStatusNotifierHost", NULL, NULL, -1, "s", + obj = edbus_object_get(ctx->conn, WATCHER_BUS, WATCHER_PATH); + ctx->watcher = edbus_proxy_get(obj, WATCHER_IFACE); + edbus_proxy_call(ctx->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); + edbus_proxy_property_get(ctx->watcher, "RegisteredStatusNotifierItems", + notifier_items_get_cb, ctx); + edbus_proxy_signal_handler_add(ctx->watcher, "StatusNotifierItemRegistered", + notifier_item_add_cb, ctx); + edbus_proxy_signal_handler_add(ctx->watcher, "StatusNotifierItemUnregistered", + notifier_item_del_cb, ctx); } -void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst) +void +systray_notifier_dbus_init(Context_Notifier_Host *ctx) { edbus_init(); - - host_inst->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION); - - edbus_name_request(host_inst->conn, + ctx->conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION); + edbus_name_request(ctx->conn, WATCHER_BUS, EDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, - name_request_cb, host_inst); + name_request_cb, ctx); } -void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst) +void systray_notifier_dbus_shutdown(Context_Notifier_Host *ctx) { Eina_Inlist *safe_list; Notifier_Item *item; - EINA_INLIST_FOREACH_SAFE(host_inst->items_list, safe_list, item) + ERR("systray_notifier_dbus_shutdown"); + + EINA_INLIST_FOREACH_SAFE(ctx->item_list, safe_list, item) systray_notifier_item_free(item); - if (!host_inst->watcher) + if (!ctx->watcher) systray_notifier_dbus_watcher_stop(); else { EDBus_Object *obj; - obj = edbus_proxy_object_get(host_inst->watcher); - edbus_proxy_unref(host_inst->watcher); + obj = edbus_proxy_object_get(ctx->watcher); + edbus_proxy_unref(ctx->watcher); edbus_object_unref(obj); - host_inst->watcher = NULL; + ctx->watcher = NULL; } - edbus_connection_unref(host_inst->conn); + edbus_connection_unref(ctx->conn); edbus_shutdown(); } diff --git a/src/modules/systray/e_mod_notifier_host_private.h b/src/modules/systray/e_mod_notifier_host_private.h index 0c3972b9d..3608ca070 100644 --- a/src/modules/systray/e_mod_notifier_host_private.h +++ b/src/modules/systray/e_mod_notifier_host_private.h @@ -14,18 +14,32 @@ typedef enum { STATUS_LAST } Status; +typedef struct _Notifier_Data +{ + EINA_INLIST; + Notifier_Item *item; + Evas_Object *icon; +} Notifier_Item_Icon; + struct _Instance_Notifier_Host { + EINA_INLIST; Instance *inst; - Eina_Inlist *items_list; const Evas_Object *box; const Evas_Object *edje; - EDBus_Connection *conn; - EDBus_Proxy *watcher; + Eina_Inlist *ii_list; E_Gadcon *gadcon; }; -typedef struct _Notifier_Item +struct _Context_Notifier_Host +{ + EDBus_Connection *conn; + EDBus_Proxy *watcher; + Eina_Inlist *item_list; + Eina_Inlist *instances; +}; + +struct _Notifier_Item { EINA_INLIST; const char *bus_id; @@ -39,12 +53,10 @@ typedef struct _Notifier_Item 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; -} 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); @@ -53,8 +65,8 @@ 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_free(Notifier_Item *item); -void systray_notifier_dbus_init(Instance_Notifier_Host *host_inst); -void systray_notifier_dbus_shutdown(Instance_Notifier_Host *host_inst); +void systray_notifier_dbus_init(Context_Notifier_Host *ctx); +void systray_notifier_dbus_shutdown(Context_Notifier_Host *ctx); 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);