update for beta release
[framework/uifw/e17.git] / src / modules / notification / e_mod_box.c
1 #include "e_mod_main.h"
2
3 /* Notification box protos */
4 static Notification_Box *_notification_box_new(const char *id,
5                                                Evas       *evas);
6 static void              _notification_box_free(Notification_Box *b);
7 static void              _notification_box_evas_set(Notification_Box *b,
8                                                     Evas             *evas);
9 static void              _notification_box_empty(Notification_Box *b);
10 static void              _notification_box_resize_handle(Notification_Box *b);
11 static void              _notification_box_empty_handle(Notification_Box *b);
12 static Eina_List        *_notification_box_find(E_Notification_Urgency urgency);
13
14 /* Notification box icons protos */
15 static Notification_Box_Icon *_notification_box_icon_new(Notification_Box *b,
16                                                          E_Notification   *n,
17                                                          E_Border         *bd,
18                                                          unsigned int      id);
19 static void                   _notification_box_icon_free(Notification_Box_Icon *ic);
20 static void                   _notification_box_icon_fill(Notification_Box_Icon *ic,
21                                                           E_Notification        *n);
22 static void                   _notification_box_icon_fill_label(Notification_Box_Icon *ic);
23 static void                   _notification_box_icon_empty(Notification_Box_Icon *ic);
24 static Notification_Box_Icon *_notification_box_icon_find(Notification_Box *b,
25                                                           E_Border         *bd,
26                                                           unsigned int      n_id);
27 static void _notification_box_icon_signal_emit(Notification_Box_Icon *ic,
28                                                char                  *sig,
29                                                char                  *src);
30
31 /* Utils */
32 static E_Border *_notification_find_source_border(E_Notification *n);
33
34 /* Notification box callbacks */
35 static void _notification_box_cb_menu_post(void   *data,
36                                            E_Menu *m);
37
38 void
39 notification_box_notify(E_Notification *n,
40                         unsigned int    replaces_id,
41                         unsigned int    id)
42 {
43    Eina_List *n_box;
44    E_Border *bd;
45    Notification_Box *b;
46    Notification_Box_Icon *ic = NULL;
47
48    bd = _notification_find_source_border(n);
49
50    n_box = _notification_box_find(e_notification_hint_urgency_get(n));
51    EINA_LIST_FREE(n_box, b)
52      {
53         if (bd || replaces_id)
54           ic = _notification_box_icon_find(b, bd, replaces_id);
55         if (ic)
56           {
57              e_notification_unref(ic->notif);
58              e_notification_ref(n);
59              ic->notif = n;
60              ic->n_id = id;
61              _notification_box_icon_empty(ic);
62              _notification_box_icon_fill(ic, n);
63           }
64         else
65           {
66              ic = _notification_box_icon_new(b, n, bd, id);
67              if (!ic) continue;
68              b->icons = eina_list_append(b->icons, ic);
69              e_box_pack_end(b->o_box, ic->o_holder);
70           }
71         _notification_box_empty_handle(b);
72         _notification_box_resize_handle(b);
73         _gc_orient(b->inst->gcc, b->inst->gcc->gadcon->orient);
74      }
75 }
76
77 void
78 notification_box_shutdown(void)
79 {
80    Notification_Box *b;
81
82    EINA_LIST_FREE(notification_cfg->n_box, b)
83      {
84         if (b) _notification_box_free(b);
85      }
86 }
87
88 void
89 notification_box_del(const char *id)
90 {
91    Eina_List *l;
92    Notification_Box *b;
93
94    /* Find old config */
95    EINA_LIST_FOREACH(notification_cfg->n_box, l, b)
96      {
97         if (b->id == id)
98           {
99              _notification_box_free(b);
100              notification_cfg->n_box = eina_list_remove(notification_cfg->n_box, b);
101              return;
102           }
103      }
104 }
105
106 void
107 notification_box_visible_set(Notification_Box *b, Eina_Bool visible)
108 {
109    Eina_List *l;
110    Notification_Box_Icon *ic;
111    Ecore_Cb cb = (Ecore_Cb)(visible ? evas_object_show : evas_object_hide);
112
113    cb(b->o_box);
114    if (b->o_empty) cb(b->o_empty);
115    EINA_LIST_FOREACH(b->icons, l, ic)
116      {
117         if (!ic) continue;
118         cb(ic->o_holder);
119         cb(ic->o_holder2);
120         cb(ic->o_icon);
121         cb(ic->o_icon2);
122      }
123 }
124
125 Notification_Box *
126 notification_box_get(const char *id,
127                      Evas       *evas)
128 {
129    Eina_List *l;
130    Notification_Box *b;
131
132    /* Find old config */
133    EINA_LIST_FOREACH(notification_cfg->n_box, l, b)
134      {
135         if (b->id == id)
136           {
137              _notification_box_evas_set(b, evas);
138              notification_box_visible_set(b, EINA_TRUE);
139              return b;
140           }
141      }
142
143    b = _notification_box_new(id, evas);
144    notification_cfg->n_box = eina_list_append(notification_cfg->n_box, b);
145    return b;
146 }
147
148 Config_Item *
149 notification_box_config_item_get(const char *id)
150 {
151    Config_Item *ci;
152
153    GADCON_CLIENT_CONFIG_GET(Config_Item, notification_cfg->items, _gc_class, id);
154
155    ci = E_NEW(Config_Item, 1);
156    ci->id = eina_stringshare_ref(id);
157    ci->show_label = 1;
158    ci->show_popup = 1;
159    ci->focus_window = 1;
160    ci->store_low = 1;
161    ci->store_normal = 1;
162    ci->store_critical = 0;
163    notification_cfg->items = eina_list_append(notification_cfg->items, ci);
164
165    return ci;
166 }
167
168 void
169 notification_box_orient_set(Notification_Box *b,
170                             int               horizontal)
171 {
172    e_box_orientation_set(b->o_box, horizontal);
173    e_box_align_set(b->o_box, 0.5, 0.5);
174 }
175
176 void
177 notification_box_cb_obj_moveresize(void        *data,
178                                    Evas        *e __UNUSED__,
179                                    Evas_Object *obj __UNUSED__,
180                                    void        *event_info __UNUSED__)
181 {
182    Instance *inst;
183
184    inst = data;
185    _notification_box_resize_handle(inst->n_box);
186 }
187
188 Eina_Bool
189 notification_box_cb_border_remove(void *data __UNUSED__,
190                                   int   type __UNUSED__,
191                                   E_Event_Border_Remove *ev)
192 {
193    Notification_Box_Icon *ic;
194    Eina_List *l;
195    Instance *inst;
196
197    EINA_LIST_FOREACH(notification_cfg->instances, l, inst)
198      {
199         Notification_Box *b;
200
201         if (!inst) continue;
202         b = inst->n_box;
203
204         ic = _notification_box_icon_find(b, ev->border, 0);
205         if (!ic) continue;
206         b->icons = eina_list_remove(b->icons, ic);
207         _notification_box_icon_free(ic);
208         _notification_box_empty_handle(b);
209         _notification_box_resize_handle(b);
210         _gc_orient(inst->gcc, inst->gcc->gadcon->orient);
211      }
212    return ECORE_CALLBACK_RENEW;
213 }
214
215 static Notification_Box *
216 _notification_box_new(const char *id,
217                       Evas       *evas)
218 {
219    Notification_Box *b;
220
221    b = E_NEW(Notification_Box, 1);
222    b->id = eina_stringshare_ref(id);
223    b->o_box = e_box_add(evas);
224    e_box_homogenous_set(b->o_box, 1);
225    e_box_orientation_set(b->o_box, 1);
226    e_box_align_set(b->o_box, 0.5, 0.5);
227    _notification_box_empty(b);
228    return b;
229 }
230
231 static void
232 _notification_box_free(Notification_Box *b)
233 {
234    _notification_box_empty(b);
235    eina_stringshare_del(b->id);
236    evas_object_del(b->o_box);
237    if (b->o_empty) evas_object_del(b->o_empty);
238    b->o_empty = NULL;
239    free(b);
240 }
241
242 static void
243 _notification_box_evas_set(Notification_Box *b,
244                            Evas             *evas)
245 {
246    Eina_List *new_icons = NULL;
247    Notification_Box_Icon *ic, *new_ic;
248
249    evas_object_del(b->o_box);
250    if (b->o_empty) evas_object_del(b->o_empty);
251    b->o_empty = NULL;
252    b->o_box = e_box_add(evas);
253
254    e_box_homogenous_set(b->o_box, 1);
255    e_box_orientation_set(b->o_box, 1);
256    e_box_align_set(b->o_box, 0.5, 0.5);
257
258    EINA_LIST_FREE(b->icons, ic)
259      {
260         if (!ic) continue;
261
262         new_ic = _notification_box_icon_new(b, ic->notif, ic->border, ic->n_id);
263         _notification_box_icon_free(ic);
264         new_icons = eina_list_append(new_icons, new_ic);
265
266         e_box_pack_end(b->o_box, new_ic->o_holder);
267      }
268    b->icons = new_icons;
269    _notification_box_empty_handle(b);
270    _notification_box_resize_handle(b);
271 }
272
273 static void
274 _notification_box_empty(Notification_Box *b)
275 {
276    Notification_Box_Icon *ic;
277    EINA_LIST_FREE(b->icons, ic)
278      _notification_box_icon_free(b->icons->data);
279    _notification_box_empty_handle(b);
280 }
281
282 static void
283 _notification_box_resize_handle(Notification_Box *b)
284 {
285    Notification_Box_Icon *ic;
286    Evas_Coord w, h;
287
288    evas_object_geometry_get(b->o_box, NULL, NULL, &w, &h);
289    if (e_box_orientation_get(b->o_box))
290      w = h;
291    else
292      h = w;
293    e_box_freeze(b->o_box);
294    EINA_LIST_FREE(b->icons, ic)
295      e_box_pack_options_set(ic->o_holder, 1, 1, 0, 0, 0.5, 0.5, w, h, w, h);
296    e_box_thaw(b->o_box);
297 }
298
299 static Eina_List *
300 _notification_box_find(E_Notification_Urgency urgency)
301 {
302    Eina_List *l, *n_box = NULL;
303    Instance *inst;
304
305    EINA_LIST_FOREACH(notification_cfg->instances, l, inst)
306      {
307         if ((urgency == E_NOTIFICATION_URGENCY_LOW) && (!inst->ci->store_low))
308           continue;
309         if ((urgency == E_NOTIFICATION_URGENCY_NORMAL) && (!inst->ci->store_normal))
310           continue;
311         if ((urgency == E_NOTIFICATION_URGENCY_CRITICAL) && (!inst->ci->store_critical))
312           continue;
313         n_box = eina_list_append(n_box, inst->n_box);
314      }
315    return n_box;
316 }
317
318 static void
319 _notification_box_icon_free(Notification_Box_Icon *ic)
320 {
321    if (notification_cfg->menu)
322      {
323         e_menu_post_deactivate_callback_set(notification_cfg->menu, NULL, NULL);
324         e_object_del(E_OBJECT(notification_cfg->menu));
325         notification_cfg->menu = NULL;
326      }
327    _notification_box_icon_empty(ic);
328    evas_object_del(ic->o_holder);
329    evas_object_del(ic->o_holder2);
330    if (ic->border) e_object_unref(E_OBJECT(ic->border));
331    if (ic->notif) e_notification_unref(ic->notif);
332    free(ic);
333 }
334
335 static void
336 _notification_box_icon_fill(Notification_Box_Icon *ic,
337                             E_Notification        *n)
338 {
339    void *img;
340    const char *icon_path;
341    Evas_Object *app_icon;
342    Evas_Object *dummy = NULL;
343    int w, h = 0;
344
345    if ((icon_path = e_notification_app_icon_get(n)) && *icon_path)
346      {
347         if (!memcmp(icon_path, "file://", 7)) icon_path += 7;
348         app_icon = evas_object_image_add(evas_object_evas_get(ic->n_box->o_box));
349         evas_object_image_load_scale_down_set(app_icon, 1);
350         evas_object_image_load_size_set(app_icon, 80, 80);
351         evas_object_image_file_set(app_icon, icon_path, NULL);
352         evas_object_image_fill_set(app_icon, 0, 0, 80, 80);
353      }
354    else if ((img = e_notification_hint_icon_data_get(n)))
355      {
356         app_icon = e_notification_image_evas_object_add(evas_object_evas_get(ic->n_box->o_box), img);
357      }
358    else
359      {
360         char buf[PATH_MAX];
361
362         snprintf(buf, sizeof(buf), "%s/e-module-notification.edj", notification_mod->dir);
363         dummy = edje_object_add(evas_object_evas_get(ic->n_box->o_box));
364         if (!e_theme_edje_object_set(dummy, "base/theme/modules/notification",
365                                      "modules/notification/logo"))
366           edje_object_file_set(dummy, buf, "modules/notification/logo");
367         evas_object_resize(dummy, 80, 80);
368         app_icon = (Evas_Object*)edje_object_part_object_get(dummy, "image");
369      }
370    evas_object_image_size_get(app_icon, &w, &h);
371
372    ic->o_icon = e_icon_add(evas_object_evas_get(ic->n_box->o_box));
373    e_icon_alpha_set(ic->o_icon, 1);
374    e_icon_data_set(ic->o_icon, evas_object_image_data_get(app_icon, 0), w, h);
375    edje_object_part_swallow(ic->o_holder, "e.swallow.content", ic->o_icon);
376    evas_object_pass_events_set(ic->o_icon, 1);
377    evas_object_show(ic->o_icon);
378
379    ic->o_icon2 = e_icon_add(evas_object_evas_get(ic->n_box->o_box));
380    e_icon_alpha_set(ic->o_icon2, 1);
381    e_icon_data_set(ic->o_icon2, evas_object_image_data_get(app_icon, 0), w, h);
382    edje_object_part_swallow(ic->o_holder2, "e.swallow.content", ic->o_icon2);
383    evas_object_pass_events_set(ic->o_icon2, 1);
384    evas_object_show(ic->o_icon2);
385
386    if (dummy) evas_object_del(dummy);
387    evas_object_del(app_icon);
388    _notification_box_icon_fill_label(ic);
389 }
390
391 static void
392 _notification_box_icon_fill_label(Notification_Box_Icon *ic)
393 {
394    const char *label = NULL;
395
396    if (ic->border)
397      label = ic->border->client.netwm.name;
398
399    if (!label) label = e_notification_app_name_get(ic->notif);
400    edje_object_part_text_set(ic->o_holder, "e.text.label", label);
401    edje_object_part_text_set(ic->o_holder2, "e.text.label", label);
402 }
403
404 static void
405 _notification_box_icon_empty(Notification_Box_Icon *ic)
406 {
407    if (ic->o_icon) evas_object_del(ic->o_icon);
408    if (ic->o_icon2) evas_object_del(ic->o_icon2);
409    ic->o_icon2 = ic->o_icon = NULL;
410 }
411
412 static Notification_Box_Icon *
413 _notification_box_icon_find(Notification_Box *b,
414                             E_Border         *bd,
415                             unsigned int      n_id)
416 {
417    Eina_List *l;
418    Notification_Box_Icon *ic;
419
420    EINA_LIST_FOREACH(b->icons, l, ic)
421      {
422         if (!ic) continue;
423         if ((ic->border == bd) || (ic->n_id == n_id))
424           return ic;
425      }
426
427    return NULL;
428 }
429
430 static void
431 _notification_box_icon_signal_emit(Notification_Box_Icon *ic,
432                                    char                  *sig,
433                                    char                  *src)
434 {
435    if (ic->o_holder)
436      edje_object_signal_emit(ic->o_holder, sig, src);
437    if (ic->o_icon)
438      edje_object_signal_emit(ic->o_icon, sig, src);
439    if (ic->o_holder2)
440      edje_object_signal_emit(ic->o_holder2, sig, src);
441    if (ic->o_icon2)
442      edje_object_signal_emit(ic->o_icon2, sig, src);
443 }
444
445 static E_Border *
446 _notification_find_source_border(E_Notification *n)
447 {
448    const char *app_name;
449    Eina_List *l;
450    E_Border *bd;
451
452    if (!(app_name = e_notification_app_name_get(n))) return NULL;
453
454    EINA_LIST_FOREACH(e_border_client_list(), l, bd)
455      {
456         size_t app, test;
457
458         if ((!bd) || ((!bd->client.icccm.name) && (!bd->client.icccm.class))) continue;
459         /* We can't be sure that the app_name really match the application name.
460          * Some plugin put their name instead. But this search gives some good
461          * results.
462          */
463         app = strlen(app_name);
464         if (bd->client.icccm.name)
465           {
466              test = eina_strlen_bounded(bd->client.icccm.name, app + 1);
467              if (!strncasecmp(bd->client.icccm.name, app_name, (app < test) ? app : test))
468                return bd;
469           }
470         if (bd->client.icccm.class)
471           {
472              test = eina_strlen_bounded(bd->client.icccm.class, app + 1);
473              if (!strncasecmp(bd->client.icccm.class, app_name, (app < test) ? app : test))
474                return bd;
475           }
476      }
477    return NULL;
478 }
479
480 static void
481 _notification_box_cb_menu_post(void   *data __UNUSED__,
482                                E_Menu *m __UNUSED__)
483 {
484    if (!notification_cfg->menu) return;
485    e_object_del(E_OBJECT(notification_cfg->menu));
486    notification_cfg->menu = NULL;
487 }
488
489 static void
490 _notification_box_cb_menu_configuration(Notification_Box *b,
491                                         E_Menu      *m __UNUSED__,
492                                         E_Menu_Item *mi __UNUSED__)
493 {
494    Eina_List *l;
495    E_Config_Dialog *cfd;
496
497    EINA_LIST_FOREACH(notification_cfg->config_dialog, l, cfd)
498      {
499         if (cfd->data == b->inst->ci) return;
500      }
501    config_notification_box_module(b->inst->ci);
502 }
503
504 static void
505 _notification_box_cb_empty_mouse_down(Notification_Box *b,
506                                       Evas        *e __UNUSED__,
507                                       Evas_Object *obj __UNUSED__,
508                                       Evas_Event_Mouse_Down *ev)
509 {
510    E_Menu *m;
511    E_Menu_Item *mi;
512    int cx, cy, cw, ch;
513
514    if (notification_cfg->menu) return;
515    m = e_menu_new();
516    mi = e_menu_item_new(m);
517    e_menu_item_label_set(mi, _("Settings"));
518    e_util_menu_item_theme_icon_set(mi, "preferences-system");
519    e_menu_item_callback_set(mi, (E_Menu_Cb)_notification_box_cb_menu_configuration, b);
520
521    notification_cfg->menu = m = e_gadcon_client_util_menu_items_append(b->inst->gcc, m, 0);
522    e_menu_post_deactivate_callback_set(m, _notification_box_cb_menu_post, NULL);
523
524    e_gadcon_canvas_zone_geometry_get(b->inst->gcc->gadcon,
525                                      &cx, &cy, &cw, &ch);
526    e_menu_activate_mouse(m,
527                          e_util_zone_current_get(e_manager_current_get()),
528                          cx + ev->output.x, cy + ev->output.y, 1, 1,
529                          E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
530 }
531
532 static void
533 _notification_box_cb_icon_move(Notification_Box_Icon *ic,
534                                Evas        *e __UNUSED__,
535                                Evas_Object *obj __UNUSED__,
536                                void        *event_info __UNUSED__)
537 {
538    Evas_Coord x, y;
539
540    evas_object_geometry_get(ic->o_holder, &x, &y, NULL, NULL);
541    evas_object_move(ic->o_holder2, x, y);
542    evas_object_raise(ic->o_holder2);
543 }
544
545 static void
546 _notification_box_cb_icon_resize(Notification_Box_Icon *ic,
547                                  Evas        *e __UNUSED__,
548                                  Evas_Object *obj __UNUSED__,
549                                  void        *event_info __UNUSED__)
550 {
551    Evas_Coord w, h;
552
553    evas_object_geometry_get(ic->o_holder, NULL, NULL, &w, &h);
554    evas_object_resize(ic->o_holder2, w, h);
555    evas_object_raise(ic->o_holder2);
556 }
557
558
559 static Eina_Bool
560 _notification_box_cb_icon_mouse_still_in(Notification_Box_Icon *ic)
561 {
562    e_notification_timeout_set(ic->notif, 0);
563    e_notification_hint_urgency_set(ic->notif, 4);
564    ic->popup = notification_popup_notify(ic->notif,
565                                          e_notification_id_get(ic->notif),
566                                          e_notification_app_name_get(ic->notif));
567    ecore_timer_del(ic->mouse_in_timer);
568    ic->mouse_in_timer = NULL;
569    return EINA_FALSE;
570 }
571
572
573 static void
574 _notification_box_cb_icon_mouse_in(Notification_Box_Icon *ic,
575                                    Evas        *e __UNUSED__,
576                                    Evas_Object *obj __UNUSED__,
577                                    void        *event_info __UNUSED__)
578 {
579    Config_Item *ci;
580
581    if ((!ic) || !ic->n_box || !ic->n_box->inst) return;
582    if (!(ci = ic->n_box->inst->ci)) return;
583
584    _notification_box_icon_signal_emit(ic, "e,state,focused", "e");
585    if (ci->show_label)
586      {
587         _notification_box_icon_fill_label(ic);
588         _notification_box_icon_signal_emit(ic, "e,action,show,label", "e");
589      }
590    if (ci->show_popup && !ic->popup && !ic->mouse_in_timer)
591      ic->mouse_in_timer = ecore_timer_add(0.5, (Ecore_Task_Cb)_notification_box_cb_icon_mouse_still_in, ic);
592 }
593
594 static void
595 _notification_box_cb_icon_mouse_out(Notification_Box_Icon *ic,
596                                     Evas        *e __UNUSED__,
597                                     Evas_Object *obj __UNUSED__,
598                                     void        *event_info __UNUSED__)
599 {
600    _notification_box_icon_signal_emit(ic, "e,state,unfocused", "e");
601    if (ic->n_box->inst->ci->show_label)
602      _notification_box_icon_signal_emit(ic, "e,action,hide,label", "e");
603
604    if (ic->mouse_in_timer)
605      {
606         ecore_timer_del(ic->mouse_in_timer);
607         ic->mouse_in_timer = NULL;
608      }
609    if (ic->popup)
610      {
611         notification_popup_close(e_notification_id_get(ic->notif));
612         ic->popup = 0;
613      }
614 }
615
616 static void
617 _notification_box_cb_icon_mouse_up(Notification_Box_Icon *ic,
618                                    Evas        *e __UNUSED__,
619                                    Evas_Object *obj __UNUSED__,
620                                    Evas_Event_Mouse_Up *ev)
621 {
622    Notification_Box *b;
623
624    b = ic->n_box;
625    if (ev->button != 1) return;
626
627    if (b->inst->ci->focus_window && ic->border)
628      {
629         e_border_uniconify(ic->border);
630         e_desk_show(ic->border->desk);
631         e_border_show(ic->border);
632         e_border_raise(ic->border);
633         e_border_focus_set(ic->border, 1, 1);
634      }
635    b->icons = eina_list_remove(b->icons, ic);
636    _notification_box_icon_free(ic);
637    _notification_box_empty_handle(b);
638    _notification_box_resize_handle(b);
639    _gc_orient(b->inst->gcc, b->inst->gcc->gadcon->orient);
640 }
641
642 static void
643 _notification_box_cb_icon_mouse_down(Notification_Box_Icon *ic,
644                                      Evas        *e __UNUSED__,
645                                      Evas_Object *obj __UNUSED__,
646                                      Evas_Event_Mouse_Down *ev)
647 {
648    E_Menu *m;
649    E_Menu_Item *mi;
650    int cx, cy, cw, ch;
651
652    if (notification_cfg->menu || (ev->button != 3)) return;
653
654    m = e_menu_new();
655    mi = e_menu_item_new(m);
656    e_menu_item_label_set(mi, _("Settings"));
657    e_util_menu_item_theme_icon_set(mi, "preferences-system");
658    e_menu_item_callback_set(mi, (E_Menu_Cb)_notification_box_cb_menu_configuration, ic->n_box);
659
660    m = e_gadcon_client_util_menu_items_append(ic->n_box->inst->gcc, m, 0);
661    e_menu_post_deactivate_callback_set(m, _notification_box_cb_menu_post, NULL);
662    notification_cfg->menu = m;
663
664    e_gadcon_canvas_zone_geometry_get(ic->n_box->inst->gcc->gadcon,
665                                      &cx, &cy, &cw, &ch);
666    e_menu_activate_mouse(m,
667                          e_util_zone_current_get(e_manager_current_get()),
668                          cx + ev->output.x, cy + ev->output.y, 1, 1,
669                          E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
670 }
671
672 static void
673 _notification_box_empty_handle(Notification_Box *b)
674 {
675    if (!b->icons)
676      {
677         Evas_Coord w, h;
678         if (b->o_empty) return;
679
680         b->o_empty = evas_object_rectangle_add(evas_object_evas_get(b->o_box));
681         evas_object_event_callback_add(b->o_empty, EVAS_CALLBACK_MOUSE_DOWN,
682                                        (Evas_Object_Event_Cb)_notification_box_cb_empty_mouse_down, b);
683         evas_object_color_set(b->o_empty, 0, 0, 0, 0);
684         evas_object_show(b->o_empty);
685         e_box_pack_end(b->o_box, b->o_empty);
686         evas_object_geometry_get(b->o_box, NULL, NULL, &w, &h);
687         if (e_box_orientation_get(b->o_box))
688           w = h;
689         else
690           h = w;
691         e_box_pack_options_set(b->o_empty,
692                                1, 1, /* fill */
693                                1, 1, /* expand */
694                                0.5, 0.5, /* align */
695                                w, h, /* min */
696                                9999, 9999 /* max */
697                                );
698      }
699    else if (b->o_empty)
700      {
701         evas_object_del(b->o_empty);
702         b->o_empty = NULL;
703      }
704 }
705
706 static Notification_Box_Icon *
707 _notification_box_icon_new(Notification_Box *b,
708                            E_Notification   *n,
709                            E_Border         *bd,
710                            unsigned int      id)
711 {
712    Notification_Box_Icon *ic;
713
714    ic = E_NEW(Notification_Box_Icon, 1);
715    if (bd) e_object_ref(E_OBJECT(bd));
716    e_notification_ref(n);
717    ic->label = e_notification_app_name_get(n);
718    ic->n_box = b;
719    ic->n_id = id;
720    ic->border = bd;
721    ic->notif = n;
722    ic->o_holder = edje_object_add(evas_object_evas_get(b->o_box));
723    e_theme_edje_object_set(ic->o_holder, "base/theme/modules/ibox",
724                            "e/modules/ibox/icon");
725    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_MOUSE_IN,
726                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_mouse_in, ic);
727    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_MOUSE_OUT,
728                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_mouse_out, ic);
729    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_MOUSE_DOWN,
730                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_mouse_down, ic);
731    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_MOUSE_UP,
732                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_mouse_up, ic);
733    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_MOVE,
734                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_move, ic);
735    evas_object_event_callback_add(ic->o_holder, EVAS_CALLBACK_RESIZE,
736                                   (Evas_Object_Event_Cb)_notification_box_cb_icon_resize, ic);
737    evas_object_show(ic->o_holder);
738
739    ic->o_holder2 = edje_object_add(evas_object_evas_get(b->o_box));
740    e_theme_edje_object_set(ic->o_holder2, "base/theme/modules/ibox",
741                            "e/modules/ibox/icon_overlay");
742    evas_object_layer_set(ic->o_holder2, 9999);
743    evas_object_pass_events_set(ic->o_holder2, 1);
744    evas_object_show(ic->o_holder2);
745
746    _notification_box_icon_fill(ic, n);
747    return ic;
748 }