From 6ad79e964fd16fbca1e6722074dc2b37d48f3db6 Mon Sep 17 00:00:00 2001 From: Christopher Michael Date: Mon, 30 Aug 2010 18:47:37 +0000 Subject: [PATCH] Add notifications for illume2. These are handled as quickpanels that automatically show/hide. NB - May need more "sexing up" ;) SVN revision: 51762 --- src/modules/illume-indicator/Makefile.am | 4 + .../e-module-illume-indicator.edc | 118 +++++++ src/modules/illume-indicator/e_mod_main.c | 41 +-- src/modules/illume-indicator/e_mod_notify.c | 329 ++++++++++++++++++ src/modules/illume-indicator/e_mod_notify.h | 22 ++ 5 files changed, 479 insertions(+), 35 deletions(-) create mode 100644 src/modules/illume-indicator/e_mod_notify.c create mode 100644 src/modules/illume-indicator/e_mod_notify.h diff --git a/src/modules/illume-indicator/Makefile.am b/src/modules/illume-indicator/Makefile.am index 4fec1f5a3..c4e66a0d6 100644 --- a/src/modules/illume-indicator/Makefile.am +++ b/src/modules/illume-indicator/Makefile.am @@ -37,6 +37,10 @@ module_la_SOURCES = \ e_mod_main.c \ e_mod_main.h +if HAVE_ENOTIFY +module_la_SOURCES += e_mod_notify.h e_mod_notify.c +endif + module_la_LIBADD = @e_libs@ @ENOTIFY_LIBS@ @dlopen_libs@ module_la_LDFLAGS = -module -avoid-version module_la_DEPENDENCIES = $(top_builddir)/config.h diff --git a/src/modules/illume-indicator/e-module-illume-indicator.edc b/src/modules/illume-indicator/e-module-illume-indicator.edc index 58fa0e15f..6f2513e03 100644 --- a/src/modules/illume-indicator/e-module-illume-indicator.edc +++ b/src/modules/illume-indicator/e-module-illume-indicator.edc @@ -1,3 +1,20 @@ +styles +{ + style + { + name: "notification_style"; + base: "font=Sans font_size=10 align=left style=soft_shadow shadow_color=#fff color=#000 wrap=word text_class=module_normal"; + tag: "subject" "+ text_class=module_large font_size=10"; + tag: "body" "+ text_class=module_normal font_size=10"; + tag: "br" "\n"; + tag: "b" "+ font=Sans:style=Bold text_class=module_bold"; + tag: "i" "+ font=Sans:style=Oblique text_class=module_bold"; + tag: "u" "+ underline=on"; + tag: "img" ""; /* images not supported */ + tag: "a" ""; /* links not supported */ + } +} + collections { group @@ -54,4 +71,105 @@ collections } } } + group + { + images.image: "base_bg.png" COMP; + name: "modules/illume-indicator/notify"; + parts + { + part + { + name: "base"; + type: IMAGE; + mouse_events: 0; + description + { + state: "default" 0.0; + color_class: "shelf_base"; + image.normal: "base_bg.png"; + image.border: 1 1 1 1; + fill.smooth: 0; + } + } + part + { + name: "e.swallow.icon"; + type: SWALLOW; + mouse_events: 0; + description + { + state: "default" 0.0; + align: 0.0 0.0; + aspect: 1 1; + aspect_preference: BOTH; + rel1.offset: 4 4; + rel2 + { + relative: 0.0 1.0; + offset: 52 -5; + } + } + } + part + { + name: "e.text.title"; + type: TEXT; + mouse_events: 0; + scale: 1; + effect: SOFT_SHADOW; + description + { + state: "default" 0.0; + fixed: 1 1; + align: 0.0 0.0; + rel1 + { + relative: 1.0 0.0; + offset: 3 4; + to_x: "e.swallow.icon"; + } + rel2 + { + relative: 1.0 0.0; + offset: -5 4; // 15 + } + color: 0 0 0 255; + color3: 224 224 224 64; + color_class: "menu_title_active"; + text + { + font: "Sans:style=Bold"; + size: 10; + align: 0.0 0.0; + min: 0 1; + fit: 1 1; + text_class: "menu_title"; + } + } + } + part + { + name: "e.text.message"; + type: TEXTBLOCK; + mouse_events: 0; + description + { + state: "default" 0.0; + align: 0.0 0.0; + rel1 + { + relative: 1.0 0.0; + offset: 4 22; + to_x: "e.swallow.icon"; + } + rel2.offset: -5 -5; + text + { + style: "notification_style"; +// min: 0 1; + } + } + } + } + } } diff --git a/src/modules/illume-indicator/e_mod_main.c b/src/modules/illume-indicator/e_mod_main.c index 8a98f9bc4..f79299702 100644 --- a/src/modules/illume-indicator/e_mod_main.c +++ b/src/modules/illume-indicator/e_mod_main.c @@ -3,16 +3,13 @@ #include "e_mod_config.h" #include "e_mod_ind_win.h" +#ifdef HAVE_ENOTIFY +# include "e_mod_notify.h" +#endif + /* local variables */ static Eina_List *iwins = NULL; -#ifdef HAVE_ENOTIFY -static int _cb_notify_add(E_Notification_Daemon *daemon __UNUSED__, E_Notification *n); -static void _cb_notify_del(E_Notification_Daemon *daemon __UNUSED__, unsigned int id); - -static E_Notification_Daemon *notify_daemon = NULL; -#endif - /* external variables */ const char *_ind_mod_dir = NULL; @@ -40,8 +37,7 @@ e_modapi_init(E_Module *m) } #ifdef HAVE_ENOTIFY - /* init notification subsystem */ - if (!e_notification_daemon_init()) + if (!(e_mod_notify_init())) { /* shutdown config */ il_ind_config_shutdown(); @@ -49,15 +45,8 @@ e_modapi_init(E_Module *m) /* clear module directory variable */ if (_ind_mod_dir) eina_stringshare_del(_ind_mod_dir); _ind_mod_dir = NULL; - return NULL; } - notify_daemon = e_notification_daemon_add("illume-indicator", - "Enlightenment"); -// e_notification_daemon_data_set(notify_daemon, NULL); - e_notification_daemon_callback_notify_set(notify_daemon, _cb_notify_add); - e_notification_daemon_callback_close_notification_set(notify_daemon, - _cb_notify_del); #endif /* loop through the managers (root windows) */ @@ -104,10 +93,7 @@ e_modapi_shutdown(E_Module *m __UNUSED__) 0, 0, 0, 0); #ifdef HAVE_ENOTIFY - if (notify_daemon) e_notification_daemon_free(notify_daemon); - - /* shutdown notification subsystem */ - e_notification_daemon_shutdown(); + e_mod_notify_shutdown(); #endif /* shutdown config */ @@ -125,18 +111,3 @@ e_modapi_save(E_Module *m __UNUSED__) { return il_ind_config_save(); } - -/* local function prototypes */ -#ifdef HAVE_ENOTIFY -static int -_cb_notify_add(E_Notification_Daemon *daemon __UNUSED__, E_Notification *n) -{ - return 1; -} - -static void -_cb_notify_del(E_Notification_Daemon *daemon __UNUSED__, unsigned int id) -{ - -} -#endif diff --git a/src/modules/illume-indicator/e_mod_notify.c b/src/modules/illume-indicator/e_mod_notify.c new file mode 100644 index 000000000..cdeadf4b3 --- /dev/null +++ b/src/modules/illume-indicator/e_mod_notify.c @@ -0,0 +1,329 @@ +#include "e.h" +#include "e_mod_main.h" +#include "e_mod_notify.h" + +/* local function prototypes */ +static int _e_mod_notify_cb_add(E_Notification_Daemon *daemon __UNUSED__, E_Notification *n); +static void _e_mod_notify_cb_del(E_Notification_Daemon *daemon __UNUSED__, unsigned int id); +static Ind_Notify_Win *_e_mod_notify_find(unsigned int id); +static void _e_mod_notify_refresh(Ind_Notify_Win *nwin); +static Ind_Notify_Win *_e_mod_notify_merge(E_Notification *n); +static Ind_Notify_Win *_e_mod_notify_new(E_Notification *n); +static Eina_Bool _e_mod_notify_cb_timeout(void *data); +static void _e_mod_notify_cb_free(Ind_Notify_Win *nwin); +static void _e_mod_notify_cb_resize(E_Win *win); + +/* local variables */ +static E_Notification_Daemon *_notify_daemon = NULL; +static Eina_List *_nwins = NULL; +static int _notify_id = 0; + +int +e_mod_notify_init(void) +{ + /* init notification subsystem */ + if (!e_notification_daemon_init()) return 0; + + _notify_daemon = + e_notification_daemon_add("illume-indicator", "Enlightenment"); + + e_notification_daemon_callback_notify_set(_notify_daemon, + _e_mod_notify_cb_add); + e_notification_daemon_callback_close_notification_set(_notify_daemon, + _e_mod_notify_cb_del); + + return 1; +} + +int +e_mod_notify_shutdown(void) +{ + Ind_Notify_Win *nwin; + + EINA_LIST_FREE(_nwins, nwin) + e_object_del(E_OBJECT(nwin)); + + if (_notify_daemon) e_notification_daemon_free(_notify_daemon); + + /* shutdown notification subsystem */ + e_notification_daemon_shutdown(); + + return 1; +} + +static int +_e_mod_notify_cb_add(E_Notification_Daemon *daemon __UNUSED__, E_Notification *n) +{ + Ind_Notify_Win *nwin; + unsigned int replace; + double timeout; + + replace = e_notification_replaces_id_get(n); + if (!replace) + { + _notify_id++; + e_notification_id_set(n, _notify_id); + } + else + e_notification_id_set(n, replace); + + if ((replace) && (nwin = _e_mod_notify_find(replace))) + { + e_notification_ref(n); + if (nwin->notify) e_notification_unref(nwin->notify); + nwin->notify = n; + } + else if (!replace) + nwin = _e_mod_notify_merge(n); + + if (!nwin) + { + if (!(nwin = _e_mod_notify_new(n))) + return _notify_id; + _nwins = eina_list_append(_nwins, nwin); + } + + if (nwin) + _e_mod_notify_refresh(nwin); + + /* show it */ + ecore_x_e_illume_quickpanel_state_send(nwin->zone->black_win, + ECORE_X_ILLUME_QUICKPANEL_STATE_ON); + + if (nwin->timer) ecore_timer_del(nwin->timer); + nwin->timer = NULL; + + timeout = e_notification_timeout_get(nwin->notify); + if (timeout < 0) timeout = 3000.0; + timeout = timeout / 1000.0; + + if (timeout > 0) + nwin->timer = ecore_timer_add(timeout, _e_mod_notify_cb_timeout, nwin); + + return _notify_id; +} + +static void +_e_mod_notify_cb_del(E_Notification_Daemon *daemon __UNUSED__, unsigned int id) +{ + const Eina_List *l; + Ind_Notify_Win *nwin; + + EINA_LIST_FOREACH(_nwins, l, nwin) + { + if (e_notification_id_get(nwin->notify) == id) + { + e_object_del(E_OBJECT(nwin)); + _nwins = eina_list_remove_list(_nwins, (Eina_List *)l); + } + } +} + +static +Ind_Notify_Win * +_e_mod_notify_find(unsigned int id) +{ + const Eina_List *l; + Ind_Notify_Win *nwin; + + EINA_LIST_FOREACH(_nwins, l, nwin) + if ((e_notification_id_get(nwin->notify) == id)) + return nwin; + return NULL; +} + +static void +_e_mod_notify_refresh(Ind_Notify_Win *nwin) +{ + const char *icon, *tmp; + Evas_Coord mw, mh; + int size; + + if (!nwin) return; + + if (nwin->o_icon) + { + edje_object_part_unswallow(nwin->o_base, nwin->o_icon); + evas_object_del(nwin->o_icon); + } + + size = (48 * e_scale); + if ((icon = e_notification_app_icon_get(nwin->notify))) + { + if (!strncmp(icon, "file://", 7)) + { + icon += 7; + nwin->o_icon = e_util_icon_add(icon, nwin->win->evas); + } + else + { + nwin->o_icon = + e_util_icon_theme_icon_add(icon, size, nwin->win->evas); + } + } + else + { + E_Notification_Image *img; + + if ((img = e_notification_hint_icon_data_get(nwin->notify))) + { + nwin->o_icon = + e_notification_image_evas_object_add(nwin->win->evas, img); + evas_object_image_fill_set(nwin->o_icon, 0, 0, size, size); + } + } + + if (nwin->o_icon) + { + evas_object_resize(nwin->o_icon, size, size); + edje_extern_object_min_size_set(nwin->o_icon, size, size); + edje_extern_object_max_size_set(nwin->o_icon, size, size); + edje_object_part_swallow(nwin->o_base, "e.swallow.icon", nwin->o_icon); + } + + tmp = e_notification_summary_get(nwin->notify); + edje_object_part_text_set(nwin->o_base, "e.text.title", tmp); + + tmp = e_notification_body_get(nwin->notify); + edje_object_part_text_set(nwin->o_base, "e.text.message", tmp); + + edje_object_calc_force(nwin->o_base); + edje_object_size_min_calc(nwin->o_base, &mw, &mh); + + e_win_size_min_set(nwin->win, nwin->zone->w, mh); +} + +static Ind_Notify_Win * +_e_mod_notify_merge(E_Notification *n) +{ + Ind_Notify_Win *nwin; + const Eina_List *l; + const char *appname, *bold, *bnew; + + if (!n) return NULL; + if (!(appname = e_notification_app_name_get(n))) return NULL; + EINA_LIST_FOREACH(_nwins, l, nwin) + { + const char *name; + + if (!nwin->notify) continue; + if (!(name = e_notification_app_name_get(nwin->notify))) continue; + if (!strcmp(appname, name)) break; + } + if (!nwin) return NULL; + + bold = e_notification_body_get(nwin->notify); + bnew = e_notification_body_get(n); + + /* if the bodies are the same, skip merging */ + if (!strcmp(bold, bnew)) return nwin; + + e_notification_body_set(n, bnew); + + e_notification_unref(nwin->notify); + nwin->notify = n; + e_notification_ref(nwin->notify); + + return nwin; +} + +static Ind_Notify_Win * +_e_mod_notify_new(E_Notification *n) +{ + Ind_Notify_Win *nwin; + Ecore_X_Window_State states[2]; + E_Zone *zone; + + nwin = E_OBJECT_ALLOC(Ind_Notify_Win, IND_NOTIFY_WIN_TYPE, + _e_mod_notify_cb_free); + if (!nwin) return NULL; + + e_notification_ref(n); + nwin->notify = n; + + zone = e_util_zone_current_get(e_manager_current_get()); + nwin->zone = zone; + + nwin->win = e_win_new(zone->container); + nwin->win->data = nwin; + + e_win_name_class_set(nwin->win, "Illume-Notify", "Illume-Notify"); + e_win_no_remember_set(nwin->win, EINA_TRUE); + e_win_resize_callback_set(nwin->win, _e_mod_notify_cb_resize); + + ecore_x_e_illume_quickpanel_set(nwin->win->evas_win, EINA_TRUE); + ecore_x_e_illume_quickpanel_priority_major_set(nwin->win->evas_win, + e_notification_hint_urgency_get(n)); + ecore_x_e_illume_quickpanel_zone_set(nwin->win->evas_win, zone->id); + + states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER; + ecore_x_netwm_window_state_set(nwin->win->evas_win, states, 2); + ecore_x_icccm_hints_set(nwin->win->evas_win, 0, 0, 0, 0, 0, 0, 0); + + nwin->o_base = edje_object_add(nwin->win->evas); + if (!e_theme_edje_object_set(nwin->o_base, + "base/theme/modules/illume-indicator", + "modules/illume-indicator/notify")) + { + char buff[PATH_MAX]; + + snprintf(buff, sizeof(buff), + "%s/e-module-illume-indicator.edj", _ind_mod_dir); + edje_object_file_set(nwin->o_base, buff, + "modules/illume-indicator/notify"); + } + evas_object_move(nwin->o_base, 0, 0); + evas_object_show(nwin->o_base); + + e_win_size_min_set(nwin->win, zone->w, 48); + e_win_show(nwin->win); + e_border_zone_set(nwin->win->border, zone); + nwin->win->border->user_skip_winlist = 1; + + return nwin; +} + +static Eina_Bool +_e_mod_notify_cb_timeout(void *data) +{ + Ind_Notify_Win *nwin; + + if (!(nwin = data)) return EINA_FALSE; + + /* hide it */ + ecore_x_e_illume_quickpanel_state_send(nwin->zone->black_win, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + + _nwins = eina_list_remove(_nwins, nwin); + e_object_del(E_OBJECT(nwin)); + return EINA_FALSE; +} + +static void +_e_mod_notify_cb_free(Ind_Notify_Win *nwin) +{ + if (nwin->timer) ecore_timer_del(nwin->timer); + nwin->timer = NULL; + if (nwin->o_icon) evas_object_del(nwin->o_icon); + nwin->o_icon = NULL; + if (nwin->o_base) evas_object_del(nwin->o_base); + nwin->o_base = NULL; + if (nwin->win) e_object_del(E_OBJECT(nwin->win)); + nwin->win = NULL; + e_notification_closed_set(nwin->notify, EINA_TRUE); + e_notification_daemon_signal_notification_closed(_notify_daemon, + e_notification_id_get(nwin->notify), + E_NOTIFICATION_CLOSED_REQUESTED); + e_notification_unref(nwin->notify); + E_FREE(nwin); +} + +static void +_e_mod_notify_cb_resize(E_Win *win) +{ + Ind_Notify_Win *nwin; + + if (!(nwin = win->data)) return; + if (nwin->o_base) evas_object_resize(nwin->o_base, win->w, win->h); +} diff --git a/src/modules/illume-indicator/e_mod_notify.h b/src/modules/illume-indicator/e_mod_notify.h new file mode 100644 index 000000000..0974e9cab --- /dev/null +++ b/src/modules/illume-indicator/e_mod_notify.h @@ -0,0 +1,22 @@ +#ifndef E_MOD_NOTIFY_H +# define E_MOD_NOTIFY_H + +# define IND_NOTIFY_WIN_TYPE 0xE1b0887 + +typedef struct _Ind_Notify_Win Ind_Notify_Win; +struct _Ind_Notify_Win +{ + E_Object e_obj_inherit; + + E_Notification *notify; + + E_Zone *zone; + E_Win *win; + Evas_Object *o_base, *o_icon; + Ecore_Timer *timer; +}; + +int e_mod_notify_init(void); +int e_mod_notify_shutdown(void); + +#endif