Merge branch 'master' into svn_merge
[framework/uifw/elementary.git] / src / lib / elm_notify.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Notify Notify
6  *
7  * Display a window in a particular region of the application (top,
8  * bottom, etc.  A timeout can be set to automatically close the
9  * window. This is so that, after an evas_object_show() on a notify
10  * object, if a timeout was set on it, it will <b>automatically</b>
11  * get hidden after that time.
12  *
13  * Signals that you can add callbacks for are:
14  *
15  * "timeout" - when timeout happens on notify and it's hidden
16  * "block,clicked" - when it's hidden by a click outside of the notify's view
17  */
18
19 typedef struct _Widget_Data Widget_Data;
20
21 struct _Widget_Data
22 {
23    Evas_Object *notify, *content, *parent;
24
25    Elm_Notify_Orient orient;
26    Eina_Bool repeat_events;
27    Evas_Object *block_events;
28
29    double timeout;
30    Ecore_Timer *timer;
31 };
32
33 static const char *widtype = NULL;
34 static void _del_hook(Evas_Object *obj);
35 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
36 static void _theme_hook(Evas_Object *obj);
37 static void _sizing_eval(Evas_Object *obj);
38 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
39 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
40 static void _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
41 static void _calc(Evas_Object *obj);
42 static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
43 static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
44 static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
45 static void _parent_del(void *data,  Evas *e, Evas_Object *obj, void *event_info);
46 static void _parent_hide(void *data,  Evas *e, Evas_Object *obj, void *event_info);
47
48 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
49 static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
50
51 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
52 static const char SIG_TIMEOUT[] = "timeout";
53 static const Evas_Smart_Cb_Description _signals[] = {
54        {SIG_BLOCK_CLICKED, ""},
55        {SIG_TIMEOUT, ""},
56        {NULL, NULL}
57 };
58
59 static void
60 _del_pre_hook(Evas_Object *obj)
61 {
62    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
63    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
64    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
65    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
66    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
67 }
68
69 static void
70 _del_hook(Evas_Object *obj)
71 {
72    Widget_Data *wd = elm_widget_data_get(obj);
73    if (!wd) return;
74    elm_notify_parent_set(obj, NULL);
75    elm_notify_repeat_events_set(obj, EINA_TRUE);
76    if (wd->timer)
77      {
78         ecore_timer_del(wd->timer);
79         wd->timer = NULL;
80      }
81    free(wd);
82 }
83
84 /**
85  * Return Notification orientation with RTL
86  *
87  * This function switches-sides of notification area when in RTL mode.
88  *
89  * @param obj notification object.
90  *
91  * @param orient Original notification orientation.
92  *
93  * @return notification orientation with respect to the object RTL mode.
94  *
95  * @internal
96  **/
97 static Elm_Notify_Orient
98 _notify_orientation_with_rtl(Evas_Object *obj, Elm_Notify_Orient orient)
99 {
100    if (elm_widget_mirrored_get(obj))
101      {
102         switch (orient)
103           {
104            case ELM_NOTIFY_ORIENT_LEFT:
105               orient = ELM_NOTIFY_ORIENT_RIGHT;
106               break;
107            case ELM_NOTIFY_ORIENT_RIGHT:
108               orient = ELM_NOTIFY_ORIENT_LEFT;
109               break;
110            case ELM_NOTIFY_ORIENT_TOP_LEFT:
111               orient = ELM_NOTIFY_ORIENT_TOP_RIGHT;
112               break;
113            case ELM_NOTIFY_ORIENT_TOP_RIGHT:
114               orient = ELM_NOTIFY_ORIENT_TOP_LEFT;
115               break;
116            case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
117               orient = ELM_NOTIFY_ORIENT_BOTTOM_RIGHT;
118               break;
119            case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
120               orient = ELM_NOTIFY_ORIENT_BOTTOM_LEFT;
121               break;
122            default:
123               break;
124           }
125      }
126
127    return orient;
128 }
129
130 static void
131 _notify_theme_apply(Evas_Object *obj)
132 {
133    Widget_Data *wd = elm_widget_data_get(obj);
134    const char *style = elm_widget_style_get(obj);
135
136    switch (wd->orient)
137      {
138       case ELM_NOTIFY_ORIENT_TOP:
139          _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
140          break;
141       case ELM_NOTIFY_ORIENT_CENTER:
142          _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
143          break;
144       case ELM_NOTIFY_ORIENT_BOTTOM:
145          _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
146          break;
147       case ELM_NOTIFY_ORIENT_LEFT:
148          _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
149          break;
150       case ELM_NOTIFY_ORIENT_RIGHT:
151          _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
152          break;
153       case ELM_NOTIFY_ORIENT_TOP_LEFT:
154          _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
155          break;
156       case ELM_NOTIFY_ORIENT_TOP_RIGHT:
157          _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
158          break;
159       case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
160          _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
161          break;
162       case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
163          _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
164          break;
165       case ELM_NOTIFY_ORIENT_LAST:
166          break;
167      }
168 }
169
170 /**
171  * Moves notification to orientation.
172  *
173  * This fucntion moves notification to orientation
174  * according to object RTL orientation.
175  *
176  * @param obj notification object.
177  *
178  * @param orient notification orientation.
179  *
180  * @internal
181  **/
182 static void
183 _notify_move_to_orientation(Evas_Object *obj)
184 {
185    Widget_Data *wd = elm_widget_data_get(obj);
186    int offx;
187    int offy;
188    Evas_Coord minw = -1, minh = -1;
189    Evas_Coord x, y, w, h;
190
191    if (!wd) return;
192    evas_object_geometry_get(obj, &x, &y, &w, &h);
193    edje_object_size_min_get(wd->notify, &minw, &minh);
194    edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
195    offx = (w - minw) / 2;
196    offy = (h - minh) / 2;
197
198    switch (_notify_orientation_with_rtl(obj, wd->orient))
199      {
200       case ELM_NOTIFY_ORIENT_TOP:
201          evas_object_move(wd->notify, x + offx, y);
202          break;
203       case ELM_NOTIFY_ORIENT_CENTER:
204          evas_object_move(wd->notify, x + offx, y + offy);
205          break;
206       case ELM_NOTIFY_ORIENT_BOTTOM:
207          evas_object_move(wd->notify, x + offx, y + h - minh);
208          break;
209       case ELM_NOTIFY_ORIENT_LEFT:
210          evas_object_move(wd->notify, x, y + offy);
211          break;
212       case ELM_NOTIFY_ORIENT_RIGHT:
213          evas_object_move(wd->notify, x + w - minw, y + offy);
214          break;
215       case ELM_NOTIFY_ORIENT_TOP_LEFT:
216          evas_object_move(wd->notify, x, y);
217          break;
218       case ELM_NOTIFY_ORIENT_TOP_RIGHT:
219          evas_object_move(wd->notify, x + w - minw, y);
220          break;
221       case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
222          evas_object_move(wd->notify, x, y + h - minh);
223          break;
224       case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
225          evas_object_move(wd->notify, x + w - minw, y + h - minh);
226          break;
227       case ELM_NOTIFY_ORIENT_LAST:
228          break;
229      }
230 }
231
232 static void
233 _block_events_theme_apply(Evas_Object *obj)
234 {
235    Widget_Data *wd = elm_widget_data_get(obj);
236    const char *style = elm_widget_style_get(obj);
237    _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
238 }
239
240 static void
241 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
242 {
243    Widget_Data *wd = elm_widget_data_get(obj);
244    if (!wd) return;
245    edje_object_mirrored_set(wd->notify, rtl);
246    _notify_move_to_orientation(obj);
247 }
248
249 static void
250 _theme_hook(Evas_Object *obj)
251 {
252    Widget_Data *wd = elm_widget_data_get(obj);
253    if (!wd) return;
254    _elm_widget_mirrored_reload(obj);
255    _mirrored_set(obj, elm_widget_mirrored_get(obj));
256    _notify_theme_apply(obj);
257    if (wd->block_events) _block_events_theme_apply(obj);
258    edje_object_scale_set(wd->notify, elm_widget_scale_get(obj) *
259                          _elm_config->scale);
260    _sizing_eval(obj);
261 }
262
263 static void
264 _sizing_eval(Evas_Object *obj)
265 {
266    Widget_Data *wd = elm_widget_data_get(obj);
267    Evas_Coord x,y,w,h;
268    if (!wd) return;
269    if (!wd->parent) return;
270    evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
271    evas_object_move(obj, x, y);
272    evas_object_resize(obj, w, h);
273 }
274
275 static void
276 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
277 {
278    _calc(data);
279 }
280
281 static void
282 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
283 {
284    Widget_Data *wd = elm_widget_data_get(obj);
285    Evas_Object *sub = event_info;
286    if (!wd) return;
287
288    if (sub == wd->content)
289      {
290         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
291                                             _changed_size_hints, obj);
292         evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
293                                             _content_resize, obj);
294         wd->content = NULL;
295      }
296 }
297
298 static void
299 _signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
300 {
301    Widget_Data *wd = elm_widget_data_get(data);
302    if (!wd) return;
303    evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
304 }
305
306 static void
307 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
308 {
309    Widget_Data *wd = elm_widget_data_get(obj);
310    if (!wd) return;
311    evas_object_layer_set(wd->notify,
312                          evas_object_layer_get(obj));
313 }
314
315 static void
316 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
317 {
318    _calc(obj);
319 }
320
321 static void
322 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
323 {
324    _calc(data);
325 }
326
327 static void
328 _calc(Evas_Object *obj)
329 {
330    Widget_Data *wd = elm_widget_data_get(obj);
331    Evas_Coord minw = -1, minh = -1;
332    Evas_Coord x, y, w, h;
333
334    if (!wd) return;
335    _sizing_eval(obj);
336
337    evas_object_geometry_get(obj, &x, &y, &w, &h);
338    edje_object_size_min_get(wd->notify, &minw, &minh);
339    edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
340
341    if (wd->content)
342      {
343         _notify_move_to_orientation(obj);
344         evas_object_resize(wd->notify, minw, minh);
345      }
346 }
347
348 static Eina_Bool
349 _timer_cb(void *data)
350 {
351    Evas_Object *obj = data;
352    Widget_Data *wd = elm_widget_data_get(obj);
353    if (!wd) return ECORE_CALLBACK_CANCEL;
354    wd->timer = NULL;
355    evas_object_hide(obj);
356    evas_object_smart_callback_call(obj, SIG_TIMEOUT, NULL);
357    return ECORE_CALLBACK_CANCEL;
358 }
359
360 static void
361 _timer_init(Evas_Object *obj, Widget_Data *wd)
362 {
363    if (wd->timer)
364      {
365         ecore_timer_del(wd->timer);
366         wd->timer = NULL;
367      }
368    if ((evas_object_visible_get(obj)) && (wd->timeout > 0.0))
369      wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
370 }
371
372 static void
373 _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
374 {
375    Widget_Data *wd = elm_widget_data_get(obj);
376    if (!wd) return;
377    evas_object_show(wd->notify);
378    if (!wd->repeat_events)
379      evas_object_show(wd->block_events);
380    _timer_init(obj, wd);
381    elm_object_focus(obj);
382 }
383
384 static void
385 _hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
386 {
387    Widget_Data *wd = elm_widget_data_get(obj);
388    if (!wd) return;
389    evas_object_hide(wd->notify);
390    if (!wd->repeat_events)
391      evas_object_hide(wd->block_events);
392    if (wd->timer)
393      {
394         ecore_timer_del(wd->timer);
395         wd->timer = NULL;
396      }
397 }
398
399 static void
400 _parent_del(void *data,  Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
401 {
402    Widget_Data *wd = elm_widget_data_get(data);
403    if (!wd) return;
404    wd->parent = NULL;
405    evas_object_hide(data);
406 }
407
408 static void
409 _parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
410 {
411    Widget_Data *wd = elm_widget_data_get(data);
412    if (!wd) return;
413    evas_object_hide(data);
414 }
415
416 static Eina_Bool
417 _elm_notify_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
418 {
419    Widget_Data *wd = elm_widget_data_get(obj);
420    Evas_Object *cur;
421
422    if ((!wd) || (!wd->content))
423      return EINA_FALSE;
424
425    cur = wd->content;
426
427    /* Try Focus cycle in subitem */
428    return elm_widget_focus_next_get(cur, dir, next);
429 }
430
431 /**
432  * Add a new notify to the parent
433  *
434  * @param parent The parent object
435  * @return The new object or NULL if it cannot be created
436  *
437  * @ingroup Notify
438  */
439 EAPI Evas_Object *
440 elm_notify_add(Evas_Object *parent)
441 {
442    Evas_Object *obj;
443    Evas *e;
444    Widget_Data *wd;
445
446    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
447
448    ELM_SET_WIDTYPE(widtype, "notify");
449    elm_widget_type_set(obj, "notify");
450    elm_widget_sub_object_add(parent, obj);
451    elm_widget_data_set(obj, wd);
452    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
453    elm_widget_del_hook_set(obj, _del_hook);
454    elm_widget_theme_hook_set(obj, _theme_hook);
455    elm_widget_can_focus_set(obj, EINA_FALSE);
456    elm_widget_focus_next_hook_set(obj, _elm_notify_focus_next_hook);
457
458    wd->repeat_events = EINA_TRUE;
459
460    wd->notify = edje_object_add(e);
461    wd->orient = -1;
462    elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
463
464    elm_notify_parent_set(obj, parent);
465
466    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
467    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
468    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
469    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
470    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
471    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
472    _mirrored_set(obj, elm_widget_mirrored_get(obj));
473    _sizing_eval(obj);
474
475    evas_object_smart_callbacks_descriptions_set(obj, _signals);
476    return obj;
477 }
478
479 /**
480  * Set the content of the notify widget
481  *
482  * Once the content object is set, a previously set one will be deleted.
483  * If you want to keep that old content object, use the
484  * elm_notify_content_unset() function.
485  *
486  * @param obj The notify object
487  * @param content The content will be filled in this notify object
488  *
489  * @ingroup Notify
490  */
491 EAPI void
492 elm_notify_content_set(Evas_Object *obj, Evas_Object *content)
493 {
494    ELM_CHECK_WIDTYPE(obj, widtype);
495    Widget_Data *wd = elm_widget_data_get(obj);
496    if (!wd) return;
497    if (wd->content == content) return;
498    if (wd->content) evas_object_del(wd->content);
499    wd->content = content;
500
501    if (content)
502      {
503         elm_widget_sub_object_add(obj, content);
504         evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
505                                        _changed_size_hints, obj);
506         evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
507                                        _content_resize, obj);
508         edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
509      }
510    _sizing_eval(obj);
511    _calc(obj);
512 }
513
514 /**
515  * Unset the content of the notify widget
516  *
517  * Unparent and return the content object which was set for this widget
518  *
519  * @param obj The notify object
520  * @return The content that was being used
521  *
522  * @ingroup Notify
523  */
524 EAPI Evas_Object *
525 elm_notify_content_unset(Evas_Object *obj)
526 {
527    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
528    Widget_Data *wd = elm_widget_data_get(obj);
529    Evas_Object *content;
530    if (!wd) return NULL;
531    if (!wd->content) return NULL;
532    content = wd->content;
533    elm_widget_sub_object_del(obj, wd->content);
534    edje_object_part_unswallow(wd->notify, wd->content);
535    wd->content = NULL;
536    return content;
537 }
538
539 /**
540  * Return the content of the notify widget
541  *
542  * @param obj The notify object
543  * @return The content that is being used
544  *
545  * @ingroup Notify
546  */
547 EAPI Evas_Object *
548 elm_notify_content_get(const Evas_Object *obj)
549 {
550    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
551    Widget_Data *wd = elm_widget_data_get(obj);
552
553    if (!wd) return NULL;
554    return wd->content;
555 }
556
557 /**
558  * Set the notify parent
559  *
560  * Once the parent object is set, a previously set one will be disconnected
561  * and replaced.
562  *
563  * @param obj The notify object
564  * @param content The new parent
565  *
566  * @ingroup Notify
567  */
568 EAPI void
569 elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
570 {
571    ELM_CHECK_WIDTYPE(obj, widtype);
572    Widget_Data *wd = elm_widget_data_get(obj);
573    if (!wd) return;
574    if (wd->parent)
575      {
576         evas_object_event_callback_del_full(wd->parent,
577                                             EVAS_CALLBACK_CHANGED_SIZE_HINTS,
578                                             _changed_size_hints, obj);
579         evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
580                                             _changed_size_hints, obj);
581         evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
582                                             _changed_size_hints, obj);
583         evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
584                                             _parent_del, obj);
585         evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
586                                             _parent_hide, obj);
587         wd->parent = NULL;
588      }
589
590    if (parent)
591      {
592         wd->parent = parent;
593         evas_object_event_callback_add(parent,
594                                        EVAS_CALLBACK_CHANGED_SIZE_HINTS,
595                                        _changed_size_hints, obj);
596         evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
597                                        _changed_size_hints, obj);
598         evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
599                                        _changed_size_hints, obj);
600         evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
601                                        _parent_del, obj);
602         evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
603                                        _parent_hide, obj);
604         edje_object_part_swallow(wd->notify, "elm.swallow.parent", parent);
605         _sizing_eval(obj);
606      }
607    _calc(obj);
608 }
609
610 /**
611  * Get the notify parent
612  *
613  * @param obj The notify object
614  * @return The parent
615  *
616  * @ingroup Notify
617  */
618 EAPI Evas_Object *
619 elm_notify_parent_get(const Evas_Object *obj)
620 {
621    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
622    Widget_Data *wd = elm_widget_data_get(obj);
623    if (!wd) return NULL;
624    return wd->parent;
625 }
626
627 /**
628  * Set the orientation
629  *
630  * @param obj The notify object
631  * @param orient The new orientation
632  *
633  * @ingroup Notify
634  */
635 EAPI void
636 elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
637 {
638    ELM_CHECK_WIDTYPE(obj, widtype);
639    Widget_Data *wd = elm_widget_data_get(obj);
640    if (!wd) return;
641    if (wd->orient == orient) return;
642    wd->orient = orient;
643    _notify_theme_apply(obj);
644    _resize(obj, NULL, obj, NULL);
645 }
646
647 /**
648  * Return the orientation
649  * @param obj the notify objects
650  */
651 EAPI Elm_Notify_Orient
652 elm_notify_orient_get(const Evas_Object *obj)
653 {
654    ELM_CHECK_WIDTYPE(obj, widtype) -1;
655    Widget_Data *wd = elm_widget_data_get(obj);
656    if (!wd) return -1;
657    return wd->orient;
658 }
659
660 /**
661  * Set the time interval after which the notify window is going to be
662  * hidden.
663  *
664  * @param obj The notify object
665  * @param time The new timeout
666  *
667  * As said previously, an evas_object_show() on a notify object which
668  * had a timeout set by this function will trigger a timer to
669  * automatically hide it again. So, any order one calls
670  * elm_notify_timeout_set() and evas_object_show() on the same object
671  * (at hidden state) will behave the same.
672  *
673  * @note Set a value <= 0.0 to disable a running timer.
674  *
675  * @note If the value > 0.0 and the notify is previously visible, the
676  * timer will be started with this value, canceling any running timer.
677  *
678  */
679 EAPI void
680 elm_notify_timeout_set(Evas_Object *obj, double timeout)
681 {
682    ELM_CHECK_WIDTYPE(obj, widtype);
683    Widget_Data *wd = elm_widget_data_get(obj);
684    if (!wd) return;
685    wd->timeout = timeout;
686    _timer_init(obj, wd);
687 }
688
689 /**
690  * Return the timeout value (in seconds)
691  * @param obj the notify object
692  */
693 EAPI double
694 elm_notify_timeout_get(const Evas_Object *obj)
695 {
696    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
697    Widget_Data *wd = elm_widget_data_get(obj);
698    if (!wd) return 0.0;
699    return wd->timeout;
700 }
701
702 /**
703  * When true if the user clicks outside the window the events will be
704  * catch by the others widgets, else the events are block and the signal
705  * dismiss will be sent when the user click outside the window.
706  *
707  * @note The default value is EINA_TRUE.
708  *
709  * @param obj The notify object
710  * @param repeats EINA_TRUE Events are repeats, else no
711  */
712 EAPI void
713 elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
714 {
715    ELM_CHECK_WIDTYPE(obj, widtype);
716    Widget_Data *wd = elm_widget_data_get(obj);
717    if (!wd) return;
718    if (repeat == wd->repeat_events) return;
719    wd->repeat_events = repeat;
720    if (!repeat)
721      {
722         wd->block_events = edje_object_add(evas_object_evas_get(obj));
723         _block_events_theme_apply(obj);
724         elm_widget_resize_object_set(obj, wd->block_events);
725         edje_object_signal_callback_add(wd->block_events, "elm,action,clicked",
726                                         "elm", _signal_block_clicked, obj);
727      }
728    else
729      evas_object_del(wd->block_events);
730 }
731
732 /**
733  * Return true if events are repeat below the notify object
734  * @param obj the notify object
735  */
736 EAPI Eina_Bool
737 elm_notify_repeat_events_get(const Evas_Object *obj)
738 {
739    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
740    Widget_Data *wd = elm_widget_data_get(obj);
741    if (!wd) return EINA_FALSE;
742    return wd->repeat_events;
743 }