clean up some of this horrific function pointer debacle
[framework/uifw/elementary.git] / src / lib / elm_widget.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char SMART_NAME[] = "elm_widget";
5
6 #define API_ENTRY                                    \
7   Smart_Data * sd = evas_object_smart_data_get(obj); \
8   if ((!obj) || (!sd) || (!_elm_widget_is(obj)))
9 #define INTERNAL_ENTRY                               \
10   Smart_Data * sd = evas_object_smart_data_get(obj); \
11   if (!sd) return;
12
13 #undef elm_widget_text_set_hook_set
14 #undef elm_widget_text_get_hook_set
15 #undef elm_widget_content_set_hook_set
16 #undef elm_widget_content_get_hook_set
17 #undef elm_widget_content_unset_hook_set
18
19 typedef struct _Smart_Data        Smart_Data;
20 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
21 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22
23 struct _Smart_Data
24 {
25    Evas_Object *obj;
26    const char  *type;
27    Evas_Object *parent_obj;
28    Evas_Object *parent2;
29    Evas_Coord   x, y, w, h;
30    Eina_List   *subobjs;
31    Evas_Object *resize_obj;
32    Evas_Object *hover_obj;
33    Eina_List   *tooltips, *cursors;
34    void       (*del_func)(Evas_Object *obj);
35    void       (*del_pre_func)(Evas_Object *obj);
36    void       (*focus_func)(Evas_Object *obj);
37    void       (*activate_func)(Evas_Object *obj);
38    void       (*disable_func)(Evas_Object *obj);
39    void       (*theme_func)(Evas_Object *obj);
40    Eina_Bool  (*event_func)(Evas_Object       *obj,
41                             Evas_Object       *source,
42                             Evas_Callback_Type type,
43                             void              *event_info);
44    void       (*signal_func)(Evas_Object *obj,
45                              const char  *emission,
46                              const char  *source);
47    void       (*callback_add_func)(Evas_Object   *obj,
48                                    const char    *emission,
49                                    const char    *source,
50                                    Edje_Signal_Cb func,
51                                    void          *data);
52    void       (*callback_del_func)(Evas_Object   *obj,
53                                    const char    *emission,
54                                    const char    *source,
55                                    Edje_Signal_Cb func,
56                                    void          *data);
57    void       (*changed_func)(Evas_Object *obj);
58    Eina_Bool  (*focus_next_func)(const Evas_Object  *obj,
59                                  Elm_Focus_Direction dir,
60                                  Evas_Object       **next);
61    void       (*on_focus_func)(void        *data,
62                                Evas_Object *obj);
63    void        *on_focus_data;
64    void       (*on_change_func)(void        *data,
65                                 Evas_Object *obj);
66    void        *on_change_data;
67    void       (*on_show_region_func)(void        *data,
68                                      Evas_Object *obj);
69    void        *on_show_region_data;
70    void       (*focus_region_func)(Evas_Object *obj,
71                                    Evas_Coord   x,
72                                    Evas_Coord   y,
73                                    Evas_Coord   w,
74                                    Evas_Coord   h);
75    void       (*on_focus_region_func)(const Evas_Object *obj,
76                                       Evas_Coord        *x,
77                                       Evas_Coord        *y,
78                                       Evas_Coord        *w,
79                                       Evas_Coord        *h);
80    Elm_Widget_On_Text_Set_Cb on_text_set_func;
81    Elm_Widget_On_Text_Get_Cb on_text_get_func;
82    Elm_Widget_On_Content_Set_Cb on_content_set_func;
83    Elm_Widget_On_Content_Get_Cb on_content_get_func;
84    Elm_Widget_On_Content_Unset_Cb on_content_unset_func;
85    void        *data;
86    Evas_Coord   rx, ry, rw, rh;
87    int          scroll_hold;
88    int          scroll_freeze;
89    double       scale;
90    Elm_Theme   *theme;
91    const char  *style;
92    unsigned int focus_order;
93    Eina_Bool    focus_order_on_calc;
94
95    int          child_drag_x_locked;
96    int          child_drag_y_locked;
97
98    Eina_List   *edje_signals;
99
100    Eina_Bool    drag_x_locked : 1;
101    Eina_Bool    drag_y_locked : 1;
102
103    Eina_Bool    can_focus : 1;
104    Eina_Bool    child_can_focus : 1;
105    Eina_Bool    focused : 1;
106    Eina_Bool    tree_unfocusable : 1;
107    Eina_Bool    highlight_ignore : 1;
108    Eina_Bool    highlight_in_theme : 1;
109    Eina_Bool    disabled : 1;
110    Eina_Bool    is_mirrored : 1;
111    Eina_Bool    mirrored_auto_mode : 1;   /* This is TRUE by default */
112
113    Eina_List   *focus_chain;
114    Eina_List   *event_cb;
115 };
116
117 struct _Edje_Signal_Data
118 {
119    Evas_Object   *obj;
120    Edje_Signal_Cb func;
121    const char    *emission;
122    const char    *source;
123    void          *data;
124 };
125
126 struct _Elm_Event_Cb_Data
127 {
128    Elm_Event_Cb func;
129    const void  *data;
130 };
131
132 /* local subsystem functions */
133 static void _smart_reconfigure(Smart_Data *sd);
134 static void _smart_add(Evas_Object *obj);
135 static void _smart_del(Evas_Object *obj);
136 static void _smart_move(Evas_Object *obj,
137                         Evas_Coord   x,
138                         Evas_Coord   y);
139 static void _smart_resize(Evas_Object *obj,
140                           Evas_Coord   w,
141                           Evas_Coord   h);
142 static void _smart_show(Evas_Object *obj);
143 static void _smart_hide(Evas_Object *obj);
144 static void _smart_color_set(Evas_Object *obj,
145                              int          r,
146                              int          g,
147                              int          b,
148                              int          a);
149 static void _smart_clip_set(Evas_Object *obj,
150                             Evas_Object *clip);
151 static void _smart_clip_unset(Evas_Object *obj);
152 static void _smart_calculate(Evas_Object *obj);
153 static void _smart_init(void);
154
155 static void _if_focused_revert(Evas_Object *obj,
156                                Eina_Bool    can_focus_only);
157 static Evas_Object *_newest_focus_order_get(Evas_Object  *obj,
158                                             unsigned int *newest_focus_order,
159                                             Eina_Bool     can_focus_only);
160
161 /* local subsystem globals */
162 static Evas_Smart *_e_smart = NULL;
163 static Eina_List  *widtypes = NULL;
164
165 static unsigned int focus_order = 0;
166
167 // internal funcs
168 static inline Eina_Bool
169 _elm_widget_is(const Evas_Object *obj)
170 {
171    const char *type = evas_object_type_get(obj);
172    return type == SMART_NAME;
173 }
174
175 static inline Eina_Bool
176 _is_focusable(Evas_Object *obj)
177 {
178    API_ENTRY return EINA_FALSE;
179    return sd->can_focus || (sd->child_can_focus);
180 }
181
182 static void
183 _unfocus_parents(Evas_Object *obj)
184 {
185    for (; obj; obj = elm_widget_parent_get(obj))
186      {
187         INTERNAL_ENTRY
188         if (!sd->focused) return;
189         sd->focused = 0;
190      }
191 }
192
193 static void
194 _focus_parents(Evas_Object *obj)
195 {
196    for (; obj; obj = elm_widget_parent_get(obj))
197      {
198         INTERNAL_ENTRY
199         if (sd->focused) return;
200         sd->focused = 1;
201      }
202 }
203
204 static void
205 _sub_obj_del(void        *data,
206              Evas        *e __UNUSED__,
207              Evas_Object *obj,
208              void        *event_info __UNUSED__)
209 {
210    Smart_Data *sd = data;
211
212    if (_elm_widget_is(obj))
213      {
214         if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
215      }
216    if (obj == sd->resize_obj)
217      sd->resize_obj = NULL;
218    else if (obj == sd->hover_obj)
219      sd->hover_obj = NULL;
220    else
221      sd->subobjs = eina_list_remove(sd->subobjs, obj);
222    evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
223 }
224
225 static void
226 _sub_obj_hide(void        *data __UNUSED__,
227               Evas        *e __UNUSED__,
228               Evas_Object *obj,
229               void        *event_info __UNUSED__)
230 {
231    elm_widget_focus_hide_handle(obj);
232 }
233
234 static void
235 _sub_obj_mouse_up(void        *data __UNUSED__,
236                   Evas        *e __UNUSED__,
237                   Evas_Object *obj,
238                   void        *event_info)
239 {
240    Evas_Event_Mouse_Up *ev = event_info;
241    if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
242       elm_widget_focus_mouse_up_handle(obj);
243 }
244
245 static void
246 _propagate_x_drag_lock(Evas_Object *obj,
247                        int          dir)
248 {
249    INTERNAL_ENTRY
250    if (sd->parent_obj)
251      {
252         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
253         if (sd2)
254           {
255              sd2->child_drag_x_locked += dir;
256              _propagate_x_drag_lock(sd->parent_obj, dir);
257           }
258      }
259 }
260
261 static void
262 _propagate_y_drag_lock(Evas_Object *obj,
263                        int          dir)
264 {
265    INTERNAL_ENTRY
266    if (sd->parent_obj)
267      {
268         Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
269         if (sd2)
270           {
271              sd2->child_drag_y_locked += dir;
272              _propagate_y_drag_lock(sd->parent_obj, dir);
273           }
274      }
275 }
276
277 static void
278 _propagate_event(void        *data,
279                  Evas        *e __UNUSED__,
280                  Evas_Object *obj,
281                  void        *event_info)
282 {
283    INTERNAL_ENTRY
284    Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
285    Evas_Event_Flags *event_flags = NULL;
286
287    switch (type)
288      {
289       case EVAS_CALLBACK_KEY_DOWN:
290           {
291             Evas_Event_Key_Down *ev = event_info;
292             event_flags = &(ev->event_flags);
293           }
294         break;
295
296       case EVAS_CALLBACK_KEY_UP:
297           {
298              Evas_Event_Key_Up *ev = event_info;
299              event_flags = &(ev->event_flags);
300           }
301         break;
302
303       case EVAS_CALLBACK_MOUSE_WHEEL:
304           {
305             Evas_Event_Mouse_Wheel *ev = event_info;
306             event_flags = &(ev->event_flags);
307           }
308         break;
309
310       default:
311         break;
312      }
313
314    elm_widget_event_propagate(obj, type, event_info, event_flags);
315 }
316
317 static void
318 _parent_focus(Evas_Object *obj)
319 {
320    API_ENTRY return;
321    if (sd->focused) return;
322
323    Evas_Object *o = elm_widget_parent_get(obj);
324    sd->focus_order_on_calc = EINA_TRUE;
325
326    if (o) _parent_focus(o);
327
328    if (!sd->focus_order_on_calc)
329      return; /* we don't want to override it if by means of any of the
330                 callbacks below one gets to calculate our order
331                 first. */
332
333    focus_order++;
334    sd->focus_order = focus_order;
335    sd->focused = EINA_TRUE;
336    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
337    if (sd->focus_func) sd->focus_func(obj);
338
339    _elm_widget_focus_region_show(obj);
340
341    sd->focus_order_on_calc = EINA_FALSE;
342 }
343
344 static void
345 _elm_object_focus_chain_del_cb(void        *data,
346                                Evas        *e __UNUSED__,
347                                Evas_Object *obj,
348                                void        *event_info __UNUSED__)
349 {
350    Smart_Data *sd = data;
351
352    sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
353 }
354
355 // exposed util funcs to elm
356 void
357 _elm_widget_type_clear(void)
358 {
359    const char **ptr;
360
361    EINA_LIST_FREE(widtypes, ptr)
362      {
363         eina_stringshare_del(*ptr);
364         *ptr = NULL;
365      }
366 }
367
368 void
369 _elm_widget_focus_region_show(const Evas_Object *obj)
370 {
371    Evas_Coord x, y, w, h, ox, oy;
372    Smart_Data *sd2;
373    Evas_Object *o;
374
375    API_ENTRY return;
376
377    o = elm_widget_parent_get(obj);
378    if (!o) return;
379
380    elm_widget_focus_region_get(obj, &x, &y, &w, &h);
381    evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
382    while (o)
383      {
384         Evas_Coord px, py;
385         sd2 = evas_object_smart_data_get(o);
386         if (sd2->focus_region_func)
387           {
388              sd2->focus_region_func(o, x, y, w, h);
389              elm_widget_focus_region_get(o, &x, &y, &w, &h);
390           }
391         else
392           {
393              evas_object_geometry_get(o, &px, &py, NULL, NULL);
394              x += ox - px;
395              y += oy - py;
396              ox = px;
397              oy = py;
398           }
399         o = elm_widget_parent_get(o);
400      }
401 }
402
403 /**
404  * @defgroup Widget Widget
405  *
406  * @internal
407  * Exposed api for making widgets
408  */
409 EAPI void
410 elm_widget_type_register(const char **ptr)
411 {
412    widtypes = eina_list_append(widtypes, (void *)ptr);
413 }
414
415 /**
416  * @defgroup Widget Widget
417  *
418  * @internal
419  * Disposed api for making widgets
420  */
421 EAPI void
422 elm_widget_type_unregister(const char **ptr)
423 {
424    widtypes = eina_list_remove(widtypes, (void *)ptr);
425 }
426
427 EAPI Eina_Bool
428 elm_widget_api_check(int ver)
429 {
430    if (ver != ELM_INTERNAL_API_VERSION)
431      {
432         CRITICAL("Elementary widget api versions do not match");
433         return EINA_FALSE;
434      }
435    return EINA_TRUE;
436 }
437
438 EAPI Evas_Object *
439 elm_widget_add(Evas *evas)
440 {
441    Evas_Object *obj;
442    _smart_init();
443    obj = evas_object_smart_add(evas, _e_smart);
444    elm_widget_mirrored_set(obj, elm_mirrored_get());
445    return obj;
446 }
447
448 EAPI void
449 elm_widget_del_hook_set(Evas_Object *obj,
450                         void       (*func)(Evas_Object *obj))
451 {
452    API_ENTRY return;
453    sd->del_func = func;
454 }
455
456 EAPI void
457 elm_widget_del_pre_hook_set(Evas_Object *obj,
458                             void       (*func)(Evas_Object *obj))
459 {
460    API_ENTRY return;
461    sd->del_pre_func = func;
462 }
463
464 EAPI void
465 elm_widget_focus_hook_set(Evas_Object *obj,
466                           void       (*func)(Evas_Object *obj))
467 {
468    API_ENTRY return;
469    sd->focus_func = func;
470 }
471
472 EAPI void
473 elm_widget_activate_hook_set(Evas_Object *obj,
474                              void       (*func)(Evas_Object *obj))
475 {
476    API_ENTRY return;
477    sd->activate_func = func;
478 }
479
480 EAPI void
481 elm_widget_disable_hook_set(Evas_Object *obj,
482                             void       (*func)(Evas_Object *obj))
483 {
484    API_ENTRY return;
485    sd->disable_func = func;
486 }
487
488 EAPI void
489 elm_widget_theme_hook_set(Evas_Object *obj,
490                           void       (*func)(Evas_Object *obj))
491 {
492    API_ENTRY return;
493    sd->theme_func = func;
494 }
495
496 EAPI void
497 elm_widget_event_hook_set(Evas_Object *obj,
498                           Eina_Bool  (*func)(Evas_Object       *obj,
499                                              Evas_Object       *source,
500                                              Evas_Callback_Type type,
501                                              void              *event_info))
502 {
503    API_ENTRY return;
504    sd->event_func = func;
505 }
506
507 EAPI void
508 elm_widget_text_set_hook_set(Evas_Object *obj,
509                              Elm_Widget_On_Text_Set_Cb func)
510 {
511    API_ENTRY return;
512    sd->on_text_set_func = func;
513 }
514
515 EAPI void
516 elm_widget_text_get_hook_set(Evas_Object *obj,
517                              Elm_Widget_On_Text_Get_Cb func)
518 {
519    API_ENTRY return;
520    sd->on_text_get_func = func;
521 }
522
523 EAPI void
524 elm_widget_content_set_hook_set(Evas_Object *obj,
525                                 Elm_Widget_On_Content_Set_Cb func)
526 {
527    API_ENTRY return;
528    sd->on_content_set_func = func;
529 }
530
531 EAPI void
532 elm_widget_content_get_hook_set(Evas_Object *obj,
533                                 Elm_Widget_On_Content_Get_Cb func)
534 {
535    API_ENTRY return;
536    sd->on_content_get_func = func;
537 }
538
539 EAPI void
540 elm_widget_content_unset_hook_set(Evas_Object *obj,
541                                   Elm_Widget_On_Content_Unset_Cb func)
542 {
543    API_ENTRY return;
544    sd->on_content_unset_func = func;
545 }
546
547 EAPI void
548 elm_widget_changed_hook_set(Evas_Object *obj,
549                             void       (*func)(Evas_Object *obj))
550 {
551    API_ENTRY return;
552    sd->changed_func = func;
553 }
554
555 EAPI void
556 elm_widget_signal_emit_hook_set(Evas_Object *obj,
557                                 void       (*func)(Evas_Object *obj,
558                                                    const char *emission,
559                                                    const char *source))
560 {
561    API_ENTRY return;
562    sd->signal_func = func;
563 }
564
565 EAPI void
566 elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
567                                         void       (*func)(Evas_Object   *obj,
568                                                            const char    *emission,
569                                                            const char    *source,
570                                                            Edje_Signal_Cb func_cb,
571                                                            void          *data))
572 {
573    API_ENTRY return;
574    sd->callback_add_func = func;
575 }
576
577 EAPI void
578 elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
579                                         void       (*func)(Evas_Object   *obj,
580                                                            const char    *emission,
581                                                            const char    *source,
582                                                            Edje_Signal_Cb func_cb,
583                                                            void          *data))
584 {
585    API_ENTRY return;
586    sd->callback_del_func = func;
587 }
588
589 EAPI void
590 elm_widget_theme(Evas_Object *obj)
591 {
592    const Eina_List *l;
593    Evas_Object *child;
594    Elm_Tooltip *tt;
595    Elm_Cursor *cur;
596
597    API_ENTRY return;
598    EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_theme(child);
599    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
600    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
601    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
602    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
603    if (sd->theme_func) sd->theme_func(obj);
604 }
605
606 EAPI void
607 elm_widget_theme_specific(Evas_Object *obj,
608                           Elm_Theme   *th,
609                           Eina_Bool    force)
610 {
611    const Eina_List *l;
612    Evas_Object *child;
613    Elm_Tooltip *tt;
614    Elm_Cursor *cur;
615    Elm_Theme *th2, *thdef;
616
617    API_ENTRY return;
618    thdef = elm_theme_default_get();
619    if (!th) th = thdef;
620    if (!force)
621      {
622         th2 = sd->theme;
623         if (!th2) th2 = thdef;
624         while (th2)
625           {
626              if (th2 == th)
627                {
628                   force = EINA_TRUE;
629                   break;
630                }
631              if (th2 == thdef) break;
632              th2 = th2->ref_theme;
633              if (!th2) th2 = thdef;
634           }
635      }
636    if (!force) return;
637    EINA_LIST_FOREACH(sd->subobjs, l, child)
638      elm_widget_theme_specific(child, th, force);
639    if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
640    if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
641    EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
642    EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
643    if (sd->theme_func) sd->theme_func(obj);
644 }
645
646 /**
647  * @internal
648  *
649  * Set hook to get next object in object focus chain.
650  *
651  * @param obj The widget object.
652  * @param func The hook to be used with this widget.
653  *
654  * @ingroup Widget
655  */
656 EAPI void
657 elm_widget_focus_next_hook_set(Evas_Object *obj,
658                                Eina_Bool  (*func)(const Evas_Object   *obj,
659                                                    Elm_Focus_Direction dir,
660                                                    Evas_Object       **next))
661 {
662    API_ENTRY return;
663    sd->focus_next_func = func;
664 }
665
666 /**
667  * Returns the widget's mirrored mode.
668  *
669  * @param obj The widget.
670  * @return mirrored mode of the object.
671  *
672  **/
673 EAPI Eina_Bool
674 elm_widget_mirrored_get(const Evas_Object *obj)
675 {
676    API_ENTRY return EINA_FALSE;
677    return sd->is_mirrored;
678 }
679
680 /**
681  * Sets the widget's mirrored mode.
682  *
683  * @param obj The widget.
684  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
685  */
686 EAPI void
687 elm_widget_mirrored_set(Evas_Object *obj,
688                         Eina_Bool    mirrored)
689 {
690    API_ENTRY return;
691    if (sd->is_mirrored != mirrored)
692      {
693         sd->is_mirrored = mirrored;
694         elm_widget_theme(obj);
695      }
696 }
697
698 /**
699  * @internal
700  * Resets the mirrored mode from the system mirror mode for widgets that are in
701  * automatic mirroring mode. This function does not call elm_widget_theme.
702  *
703  * @param obj The widget.
704  * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
705  */
706 void
707 _elm_widget_mirrored_reload(Evas_Object *obj)
708 {
709    API_ENTRY return;
710    Eina_Bool mirrored = elm_mirrored_get();
711    if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
712      {
713         sd->is_mirrored = mirrored;
714      }
715 }
716
717 /**
718  * Returns the widget's mirrored mode setting.
719  *
720  * @param obj The widget.
721  * @return mirrored mode setting of the object.
722  *
723  **/
724 EAPI Eina_Bool
725 elm_widget_mirrored_automatic_get(const Evas_Object *obj)
726 {
727    API_ENTRY return EINA_FALSE;
728    return sd->mirrored_auto_mode;
729 }
730
731 /**
732  * Sets the widget's mirrored mode setting.
733  * When widget in automatic mode, it follows the system mirrored mode set by
734  * elm_mirrored_set().
735  * @param obj The widget.
736  * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
737  */
738 EAPI void
739 elm_widget_mirrored_automatic_set(Evas_Object *obj,
740                                   Eina_Bool    automatic)
741 {
742    API_ENTRY return;
743    if (sd->mirrored_auto_mode != automatic)
744      {
745         sd->mirrored_auto_mode = automatic;
746
747         if (automatic)
748           {
749              elm_widget_mirrored_set(obj, elm_mirrored_get());
750           }
751      }
752 }
753
754 EAPI void
755 elm_widget_on_focus_hook_set(Evas_Object *obj,
756                              void       (*func)(void *data,
757                                                 Evas_Object *obj),
758                              void        *data)
759 {
760    API_ENTRY return;
761    sd->on_focus_func = func;
762    sd->on_focus_data = data;
763 }
764
765 EAPI void
766 elm_widget_on_change_hook_set(Evas_Object *obj,
767                               void       (*func)(void *data,
768                                                  Evas_Object *obj),
769                               void        *data)
770 {
771    API_ENTRY return;
772    sd->on_change_func = func;
773    sd->on_change_data = data;
774 }
775
776 EAPI void
777 elm_widget_on_show_region_hook_set(Evas_Object *obj,
778                                    void       (*func)(void *data,
779                                                       Evas_Object *obj),
780                                    void        *data)
781 {
782    API_ENTRY return;
783    sd->on_show_region_func = func;
784    sd->on_show_region_data = data;
785 }
786
787 /**
788  * @internal
789  *
790  * Set the hook to use to show the focused region.
791  *
792  * Whenever a new widget gets focused or it's needed to show the focused
793  * area of the current one, this hook will be called on objects that may
794  * want to move their children into their visible area.
795  * The area given in the hook function is relative to the @p obj widget.
796  *
797  * @param obj The widget object
798  * @param func The function to call to show the specified area.
799  *
800  * @ingroup Widget
801  */
802 EAPI void
803 elm_widget_focus_region_hook_set(Evas_Object *obj,
804                                  void       (*func)(Evas_Object *obj,
805                                                     Evas_Coord x,
806                                                     Evas_Coord y,
807                                                     Evas_Coord w,
808                                                     Evas_Coord h))
809 {
810    API_ENTRY return;
811    sd->focus_region_func = func;
812 }
813
814 /**
815  * @internal
816  *
817  * Set the hook to retrieve the focused region of a widget.
818  *
819  * This hook will be called by elm_widget_focus_region_get() whenever
820  * it's needed to get the focused area of a widget. The area must be relative
821  * to the widget itself and if no hook is set, it will default to the entire
822  * object.
823  *
824  * @param obj The widget object
825  * @param func The function used to retrieve the focus region.
826  *
827  * @ingroup Widget
828  */
829 EAPI void
830 elm_widget_on_focus_region_hook_set(Evas_Object *obj,
831                                     void       (*func)(const Evas_Object *obj,
832                                                        Evas_Coord *x,
833                                                        Evas_Coord *y,
834                                                        Evas_Coord *w,
835                                                        Evas_Coord *h))
836 {
837    API_ENTRY return;
838    sd->on_focus_region_func = func;
839 }
840
841 EAPI void
842 elm_widget_data_set(Evas_Object *obj,
843                     void        *data)
844 {
845    API_ENTRY return;
846    sd->data = data;
847 }
848
849 EAPI void *
850 elm_widget_data_get(const Evas_Object *obj)
851 {
852    API_ENTRY return NULL;
853    return sd->data;
854 }
855
856 EAPI void
857 elm_widget_sub_object_add(Evas_Object *obj,
858                           Evas_Object *sobj)
859 {
860    API_ENTRY return;
861    double scale, pscale = elm_widget_scale_get(sobj);
862    Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
863    Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
864
865    if (_elm_widget_is(sobj))
866      {
867         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
868         if (sd2)
869           {
870              if (sd2->parent_obj == obj)
871                return;
872              if (sd2->parent_obj)
873                elm_widget_sub_object_del(sd2->parent_obj, sobj);
874              sd2->parent_obj = obj;
875              if (!sd->child_can_focus && (_is_focusable(sobj)))
876                sd->child_can_focus = EINA_TRUE;
877           }
878      }
879    else
880      {
881         void *data = evas_object_data_get(sobj, "elm-parent");
882         if (data)
883           {
884              if (data == obj) return;
885              evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
886                                             _sub_obj_del);
887           }
888      }
889
890    sd->subobjs = eina_list_append(sd->subobjs, sobj);
891    evas_object_data_set(sobj, "elm-parent", obj);
892    evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
893    if (_elm_widget_is(sobj))
894      evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
895    evas_object_smart_callback_call(obj, "sub-object-add", sobj);
896    scale = elm_widget_scale_get(sobj);
897    th = elm_widget_theme_get(sobj);
898    mirrored = elm_widget_mirrored_get(sobj);
899    if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
900    if (elm_widget_focus_get(sobj)) _focus_parents(obj);
901 }
902
903 EAPI void
904 elm_widget_sub_object_del(Evas_Object *obj,
905                           Evas_Object *sobj)
906 {
907    Evas_Object *sobj_parent;
908    API_ENTRY return;
909    if (!sobj) return;
910
911    sobj_parent = evas_object_data_del(sobj, "elm-parent");
912    if (sobj_parent != obj)
913      {
914         static int abort_on_warn = -1;
915         ERR("removing sub object %p from parent %p, "
916             "but elm-parent is different %p!",
917             sobj, obj, sobj_parent);
918         if (EINA_UNLIKELY(abort_on_warn == -1))
919           {
920              if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
921              else abort_on_warn = 0;
922           }
923         if (abort_on_warn == 1) abort();
924      }
925    if (_elm_widget_is(sobj))
926      {
927         Smart_Data *sd2 = evas_object_smart_data_get(sobj);
928         if (sd2)
929           {
930              sd2->parent_obj = NULL;
931              if (sd2->resize_obj == sobj)
932                sd2->resize_obj = NULL;
933              else
934                sd->subobjs = eina_list_remove(sd->subobjs, sobj);
935           }
936         else
937           sd->subobjs = eina_list_remove(sd->subobjs, sobj);
938         if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
939         if ((sd->child_can_focus) && (_is_focusable(sobj)))
940           {
941              Evas_Object *subobj;
942              const Eina_List *l;
943              sd->child_can_focus = EINA_FALSE;
944              EINA_LIST_FOREACH(sd->subobjs, l, subobj)
945                {
946                   if (_is_focusable(subobj))
947                     {
948                        sd->child_can_focus = EINA_TRUE;
949                        break;
950                     }
951                }
952           }
953      }
954    else
955      sd->subobjs = eina_list_remove(sd->subobjs, sobj);
956    evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
957                                        _sub_obj_del, sd);
958    if (_elm_widget_is(sobj))
959      evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
960                                          _sub_obj_hide, sd);
961    evas_object_smart_callback_call(obj, "sub-object-del", sobj);
962 }
963
964 EAPI void
965 elm_widget_resize_object_set(Evas_Object *obj,
966                              Evas_Object *sobj)
967 {
968    API_ENTRY return;
969    // orphan previous resize obj
970    if (sd->resize_obj)
971      {
972         evas_object_clip_unset(sd->resize_obj);
973         evas_object_data_del(sd->resize_obj, "elm-parent");
974         if (_elm_widget_is(sd->resize_obj))
975           {
976              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
977              if (sd2) sd2->parent_obj = NULL;
978              evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_HIDE,
979                                                  _sub_obj_hide, sd);
980           }
981         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
982                                             _sub_obj_del, sd);
983         evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_MOUSE_UP,
984                                             _sub_obj_mouse_up, sd);
985         evas_object_smart_member_del(sd->resize_obj);
986         if (_elm_widget_is(sd->resize_obj))
987           {
988              if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
989           }
990      }
991    // orphan new resize obj
992    if (sobj)
993      {
994         evas_object_data_del(sobj, "elm-parent");
995         if (_elm_widget_is(sobj))
996           {
997              Smart_Data *sd2 = evas_object_smart_data_get(sobj);
998              if (sd2) sd2->parent_obj = NULL;
999              evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1000                                                  _sub_obj_hide, sd);
1001           }
1002         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1003                                             _sub_obj_del, sd);
1004         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1005                                             _sub_obj_mouse_up, sd);
1006         evas_object_smart_member_del(sobj);
1007         if (_elm_widget_is(sobj))
1008           {
1009              if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1010           }
1011      }
1012    // set the resize obj up
1013    sd->resize_obj = sobj;
1014    if (sd->resize_obj)
1015      {
1016         if (_elm_widget_is(sd->resize_obj))
1017           {
1018              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1019              if (sd2) sd2->parent_obj = obj;
1020              evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1021                                             _sub_obj_hide, sd);
1022           }
1023         evas_object_clip_set(sobj, evas_object_clip_get(obj));
1024         evas_object_smart_member_add(sobj, obj);
1025         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1026                                        _sub_obj_del, sd);
1027         evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1028                                        _sub_obj_mouse_up, sd);
1029         _smart_reconfigure(sd);
1030         evas_object_data_set(sobj, "elm-parent", obj);
1031         evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1032         if (_elm_widget_is(sobj))
1033           {
1034              if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1035           }
1036      }
1037 }
1038
1039 EAPI void
1040 elm_widget_hover_object_set(Evas_Object *obj,
1041                             Evas_Object *sobj)
1042 {
1043    API_ENTRY return;
1044    if (sd->hover_obj)
1045      {
1046         evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1047                                             _sub_obj_del, sd);
1048      }
1049    sd->hover_obj = sobj;
1050    if (sd->hover_obj)
1051      {
1052         evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1053                                        _sub_obj_del, sd);
1054         _smart_reconfigure(sd);
1055      }
1056 }
1057
1058 EAPI void
1059 elm_widget_can_focus_set(Evas_Object *obj,
1060                          Eina_Bool    can_focus)
1061 {
1062    API_ENTRY return;
1063    sd->can_focus = can_focus;
1064    if (can_focus)
1065      {
1066         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1067                                        _propagate_event,
1068                                        (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1069         evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1070                                        _propagate_event,
1071                                        (void *)(long)EVAS_CALLBACK_KEY_UP);
1072         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1073                                        _propagate_event,
1074                                        (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1075      }
1076    else
1077      {
1078         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1079                                        _propagate_event);
1080         evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1081                                        _propagate_event);
1082         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1083                                        _propagate_event);
1084      }
1085 }
1086
1087 EAPI Eina_Bool
1088 elm_widget_can_focus_get(const Evas_Object *obj)
1089 {
1090    API_ENTRY return EINA_FALSE;
1091    return sd->can_focus;
1092 }
1093
1094 EAPI Eina_Bool
1095 elm_widget_child_can_focus_get(const Evas_Object *obj)
1096 {
1097    API_ENTRY return EINA_FALSE;
1098    return sd->child_can_focus;
1099 }
1100
1101 /**
1102  * @internal
1103  *
1104  * This API makes the widget object and its children to be unfocusable.
1105  *
1106  * This API can be helpful for an object to be deleted.
1107  * When an object will be deleted soon, it and its children may not
1108  * want to get focus (by focus reverting or by other focus controls).
1109  * Then, just use this API before deleting.
1110  *
1111  * @param obj The widget root of sub-tree
1112  * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1113  *
1114  * @ingroup Widget
1115  */
1116 EAPI void
1117 elm_widget_tree_unfocusable_set(Evas_Object *obj,
1118                                 Eina_Bool    tree_unfocusable)
1119 {
1120    API_ENTRY return;
1121
1122    if (sd->tree_unfocusable == tree_unfocusable) return;
1123    sd->tree_unfocusable = !!tree_unfocusable;
1124    elm_widget_focus_tree_unfocusable_handle(obj);
1125 }
1126
1127 /**
1128  * @internal
1129  *
1130  * This returns true, if the object sub-tree is unfocusable.
1131  *
1132  * @param obj The widget root of sub-tree
1133  * @return EINA_TRUE if the object sub-tree is unfocusable
1134  *
1135  * @ingroup Widget
1136  */
1137 EAPI Eina_Bool
1138 elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1139 {
1140    API_ENTRY return EINA_FALSE;
1141    return sd->tree_unfocusable;
1142 }
1143
1144 /**
1145  * @internal
1146  *
1147  * Get the list of focusable child objects.
1148  *
1149  * This function retruns list of child objects which can get focus.
1150  *
1151  * @param obj The parent widget
1152  * @retrun list of focusable child objects.
1153  *
1154  * @ingroup Widget
1155  */
1156 EAPI Eina_List *
1157 elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1158 {
1159    API_ENTRY return NULL;
1160
1161    const Eina_List *l;
1162    Eina_List *child_list = NULL;
1163    Evas_Object *child;
1164
1165    if (sd->subobjs)
1166      {
1167         EINA_LIST_FOREACH(sd->subobjs, l, child)
1168           {
1169              if ((elm_widget_can_focus_get(child)) &&
1170                  (evas_object_visible_get(child)) &&
1171                  (!elm_widget_disabled_get(child)))
1172                child_list = eina_list_append(child_list, child);
1173              else if (elm_widget_is(child))
1174                {
1175                   Eina_List *can_focus_list;
1176                   can_focus_list = elm_widget_can_focus_child_list_get(child);
1177                   if (can_focus_list)
1178                     child_list = eina_list_merge(child_list, can_focus_list);
1179                }
1180           }
1181      }
1182    return child_list;
1183 }
1184
1185 EAPI void
1186 elm_widget_highlight_ignore_set(Evas_Object *obj,
1187                                 Eina_Bool    ignore)
1188 {
1189    API_ENTRY return;
1190    sd->highlight_ignore = !!ignore;
1191 }
1192
1193 EAPI Eina_Bool
1194 elm_widget_highlight_ignore_get(const Evas_Object *obj)
1195 {
1196    API_ENTRY return EINA_FALSE;
1197    return sd->highlight_ignore;
1198 }
1199
1200 EAPI void
1201 elm_widget_highlight_in_theme_set(Evas_Object *obj,
1202                                   Eina_Bool    highlight)
1203 {
1204    API_ENTRY return;
1205    sd->highlight_in_theme = !!highlight;
1206    /* FIXME: if focused, it should switch from one mode to the other */
1207 }
1208
1209 EAPI Eina_Bool
1210 elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1211 {
1212    API_ENTRY return EINA_FALSE;
1213    return sd->highlight_in_theme;
1214 }
1215
1216 EAPI Eina_Bool
1217 elm_widget_focus_get(const Evas_Object *obj)
1218 {
1219    API_ENTRY return EINA_FALSE;
1220    return sd->focused;
1221 }
1222
1223 EAPI Evas_Object *
1224 elm_widget_focused_object_get(const Evas_Object *obj)
1225 {
1226    const Evas_Object *subobj;
1227    const Eina_List *l;
1228    API_ENTRY return NULL;
1229
1230    if (!sd->focused) return NULL;
1231    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1232      {
1233         Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1234         if (fobj) return fobj;
1235      }
1236    return (Evas_Object *)obj;
1237 }
1238
1239 EAPI Evas_Object *
1240 elm_widget_top_get(const Evas_Object *obj)
1241 {
1242    API_ENTRY return NULL;
1243    if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1244    return (Evas_Object *)obj;
1245 }
1246
1247 EAPI Eina_Bool
1248 elm_widget_is(const Evas_Object *obj)
1249 {
1250    return _elm_widget_is(obj);
1251 }
1252
1253 EAPI Evas_Object *
1254 elm_widget_parent_widget_get(const Evas_Object *obj)
1255 {
1256    Evas_Object *parent;
1257
1258    if (_elm_widget_is(obj))
1259      {
1260         Smart_Data *sd = evas_object_smart_data_get(obj);
1261         if (!sd) return NULL;
1262         parent = sd->parent_obj;
1263      }
1264    else
1265      {
1266         parent = evas_object_data_get(obj, "elm-parent");
1267         if (!parent) parent = evas_object_smart_parent_get(obj);
1268      }
1269
1270    while (parent)
1271      {
1272         Evas_Object *elm_parent;
1273         if (_elm_widget_is(parent)) break;
1274         elm_parent = evas_object_data_get(parent, "elm-parent");
1275         if (elm_parent) parent = elm_parent;
1276         else parent = evas_object_smart_parent_get(parent);
1277      }
1278    return parent;
1279 }
1280
1281 EAPI Evas_Object *
1282 elm_widget_parent2_get(const Evas_Object *obj)
1283 {
1284    if (_elm_widget_is(obj))
1285      {
1286         Smart_Data *sd = evas_object_smart_data_get(obj);
1287         if (sd) return sd->parent2;
1288      }
1289    return NULL;
1290 }
1291
1292 EAPI void
1293 elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1294 {
1295    API_ENTRY return;
1296    sd->parent2 = parent;
1297 }
1298
1299 EAPI void
1300 elm_widget_event_callback_add(Evas_Object *obj,
1301                               Elm_Event_Cb func,
1302                               const void  *data)
1303 {
1304    API_ENTRY return;
1305    EINA_SAFETY_ON_NULL_RETURN(func);
1306    Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1307    ecb->func = func;
1308    ecb->data = data;
1309    sd->event_cb = eina_list_append(sd->event_cb, ecb);
1310 }
1311
1312 EAPI void *
1313 elm_widget_event_callback_del(Evas_Object *obj,
1314                               Elm_Event_Cb func,
1315                               const void  *data)
1316 {
1317    API_ENTRY return NULL;
1318    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1319    Eina_List *l;
1320    Elm_Event_Cb_Data *ecd;
1321    EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1322      if ((ecd->func == func) && (ecd->data == data))
1323        {
1324           free(ecd);
1325           sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1326           return (void *)data;
1327        }
1328    return NULL;
1329 }
1330
1331 EAPI Eina_Bool
1332 elm_widget_event_propagate(Evas_Object       *obj,
1333                            Evas_Callback_Type type,
1334                            void              *event_info,
1335                            Evas_Event_Flags  *event_flags)
1336 {
1337    API_ENTRY return EINA_FALSE; //TODO reduce.
1338    if (!_elm_widget_is(obj)) return EINA_FALSE;
1339    Evas_Object *parent = obj;
1340    Elm_Event_Cb_Data *ecd;
1341    Eina_List *l, *l_prev;
1342
1343    while (parent &&
1344           (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1345      {
1346         sd = evas_object_smart_data_get(parent);
1347         if ((!sd) || (!_elm_widget_is(obj)))
1348           return EINA_FALSE; //Not Elm Widget
1349
1350         if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1351           return EINA_TRUE;
1352
1353         EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1354           {
1355              if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1356                  (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1357                return EINA_TRUE;
1358           }
1359         parent = sd->parent_obj;
1360      }
1361
1362    return EINA_FALSE;
1363 }
1364
1365 /**
1366  * @internal
1367  *
1368  * Set custom focus chain.
1369  *
1370  * This function i set one new and overwrite any previous custom focus chain
1371  * with the list of objects. The previous list will be deleted and this list
1372  * will be managed. After setted, don't modity it.
1373  *
1374  * @note On focus cycle, only will be evaluated children of this container.
1375  *
1376  * @param obj The container widget
1377  * @param objs Chain of objects to pass focus
1378  * @ingroup Widget
1379  */
1380 EAPI void
1381 elm_widget_focus_custom_chain_set(Evas_Object *obj,
1382                                   Eina_List   *objs)
1383 {
1384    API_ENTRY return;
1385    if (!sd->focus_next_func)
1386      return;
1387
1388    elm_widget_focus_custom_chain_unset(obj);
1389
1390    Eina_List *l;
1391    Evas_Object *o;
1392
1393    EINA_LIST_FOREACH(objs, l, o)
1394      {
1395         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1396                                        _elm_object_focus_chain_del_cb, sd);
1397      }
1398
1399    sd->focus_chain = objs;
1400 }
1401
1402 /**
1403  * @internal
1404  *
1405  * Get custom focus chain
1406  *
1407  * @param obj The container widget
1408  * @ingroup Widget
1409  */
1410 EAPI const Eina_List *
1411 elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1412 {
1413    API_ENTRY return NULL;
1414    return (const Eina_List *)sd->focus_chain;
1415 }
1416
1417 /**
1418  * @internal
1419  *
1420  * Unset custom focus chain
1421  *
1422  * @param obj The container widget
1423  * @ingroup Widget
1424  */
1425 EAPI void
1426 elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1427 {
1428    API_ENTRY return;
1429    Eina_List *l, *l_next;
1430    Evas_Object *o;
1431
1432    EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1433      {
1434         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1435                                             _elm_object_focus_chain_del_cb, sd);
1436         sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1437      }
1438 }
1439
1440 /**
1441  * @internal
1442  *
1443  * Append object to custom focus chain.
1444  *
1445  * @note If relative_child equal to NULL or not in custom chain, the object
1446  * will be added in end.
1447  *
1448  * @note On focus cycle, only will be evaluated children of this container.
1449  *
1450  * @param obj The container widget
1451  * @param child The child to be added in custom chain
1452  * @param relative_child The relative object to position the child
1453  * @ingroup Widget
1454  */
1455 EAPI void
1456 elm_widget_focus_custom_chain_append(Evas_Object *obj,
1457                                      Evas_Object *child,
1458                                      Evas_Object *relative_child)
1459 {
1460    API_ENTRY return;
1461    EINA_SAFETY_ON_NULL_RETURN(child);
1462    if (!sd->focus_next_func)
1463      return;
1464
1465    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1466                                        _elm_object_focus_chain_del_cb, sd);
1467
1468    if (!relative_child)
1469      {
1470         sd->focus_chain = eina_list_append(sd->focus_chain, child);
1471         return;
1472      }
1473
1474    sd->focus_chain = eina_list_append_relative(sd->focus_chain, child, relative_child);
1475    return;
1476 }
1477
1478 /**
1479  * @internal
1480  *
1481  * Prepend object to custom focus chain.
1482  *
1483  * @note If relative_child equal to NULL or not in custom chain, the object
1484  * will be added in begin.
1485  *
1486  * @note On focus cycle, only will be evaluated children of this container.
1487  *
1488  * @param obj The container widget
1489  * @param child The child to be added in custom chain
1490  * @param relative_child The relative object to position the child
1491  * @ingroup Widget
1492  */
1493 EAPI void
1494 elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1495                                       Evas_Object *child,
1496                                       Evas_Object *relative_child)
1497 {
1498    API_ENTRY return;
1499    EINA_SAFETY_ON_NULL_RETURN(child);
1500    if (!sd->focus_next_func)
1501      return;
1502
1503    evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1504                                        _elm_object_focus_chain_del_cb, sd);
1505
1506    if (!relative_child)
1507      {
1508         sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1509         return;
1510      }
1511
1512    sd->focus_chain = eina_list_prepend_relative(sd->focus_chain, child, relative_child);
1513    return;
1514 }
1515
1516 /**
1517  * @internal
1518  *
1519  * Give focus to next object in object tree.
1520  *
1521  * Give focus to next object in focus chain of one object sub-tree.
1522  * If the last object of chain already have focus, the focus will go to the
1523  * first object of chain.
1524  *
1525  * @param obj The widget root of sub-tree
1526  * @param dir Direction to cycle the focus
1527  *
1528  * @ingroup Widget
1529  */
1530 EAPI void
1531 elm_widget_focus_cycle(Evas_Object        *obj,
1532                        Elm_Focus_Direction dir)
1533 {
1534    Evas_Object *target = NULL;
1535    if (!_elm_widget_is(obj))
1536      return;
1537    elm_widget_focus_next_get(obj, dir, &target);
1538    if (target)
1539      elm_widget_focus_steal(target);
1540 }
1541
1542 /**
1543  * @internal
1544  *
1545  * Give focus to near object in one direction.
1546  *
1547  * Give focus to near object in direction of one object.
1548  * If none focusable object in given direction, the focus will not change.
1549  *
1550  * @param obj The reference widget
1551  * @param x Horizontal component of direction to focus
1552  * @param y Vertical component of direction to focus
1553  *
1554  * @ingroup Widget
1555  */
1556 EAPI void
1557 elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1558                               int          x __UNUSED__,
1559                               int          y __UNUSED__)
1560 {
1561    return; /* TODO */
1562 }
1563
1564 /**
1565  * @internal
1566  *
1567  * Get next object in focus chain of object tree.
1568  *
1569  * Get next object in focus chain of one object sub-tree.
1570  * Return the next object by reference. If don't have any candidate to receive
1571  * focus before chain end, the first candidate will be returned.
1572  *
1573  * @param obj The widget root of sub-tree
1574  * @param dir Direction os focus chain
1575  * @param next The next object in focus chain
1576  * @return EINA_TRUE if don't need focus chain restart/loop back
1577  *         to use 'next' obj.
1578  *
1579  * @ingroup Widget
1580  */
1581 EAPI Eina_Bool
1582 elm_widget_focus_next_get(const Evas_Object  *obj,
1583                           Elm_Focus_Direction dir,
1584                           Evas_Object       **next)
1585 {
1586    if (!next)
1587      return EINA_FALSE;
1588    *next = NULL;
1589
1590    API_ENTRY return EINA_FALSE;
1591
1592    /* Ignore if disabled */
1593    if ((!evas_object_visible_get(obj))
1594        || (elm_widget_disabled_get(obj))
1595        || (elm_widget_tree_unfocusable_get(obj)))
1596      return EINA_FALSE;
1597
1598    /* Try use hook */
1599    if (sd->focus_next_func)
1600      return sd->focus_next_func(obj, dir, next);
1601
1602    if (!elm_widget_can_focus_get(obj))
1603      return EINA_FALSE;
1604
1605    /* Return */
1606    *next = (Evas_Object *)obj;
1607    return !elm_widget_focus_get(obj);
1608 }
1609
1610 /**
1611  * @internal
1612  *
1613  * Get next object in focus chain of object tree in list.
1614  *
1615  * Get next object in focus chain of one object sub-tree ordered by one list.
1616  * Return the next object by reference. If don't have any candidate to receive
1617  * focus before list end, the first candidate will be returned.
1618  *
1619  * @param obj The widget root of sub-tree
1620  * @param dir Direction os focus chain
1621  * @param items list with ordered objects
1622  * @param list_data_get function to get the object from one item of list
1623  * @param next The next object in focus chain
1624  * @return EINA_TRUE if don't need focus chain restart/loop back
1625  *         to use 'next' obj.
1626  *
1627  * @ingroup Widget
1628  */
1629 EAPI Eina_Bool
1630 elm_widget_focus_list_next_get(const Evas_Object  *obj,
1631                                const Eina_List    *items,
1632                                void *(*list_data_get)(const Eina_List * list),
1633                                Elm_Focus_Direction dir,
1634                                Evas_Object       **next)
1635 {
1636    Eina_List *(*list_next)(const Eina_List * list) = NULL;
1637
1638    if (!next)
1639      return EINA_FALSE;
1640    *next = NULL;
1641
1642    if (!_elm_widget_is(obj))
1643      return EINA_FALSE;
1644
1645    if (!items)
1646      return EINA_FALSE;
1647
1648    /* Direction */
1649    if (dir == ELM_FOCUS_PREVIOUS)
1650      {
1651         items = eina_list_last(items);
1652         list_next = eina_list_prev;
1653      }
1654    else if (dir == ELM_FOCUS_NEXT)
1655      list_next = eina_list_next;
1656    else
1657      return EINA_FALSE;
1658
1659    const Eina_List *l = items;
1660
1661    /* Recovery last focused sub item */
1662    if (elm_widget_focus_get(obj))
1663      for (; l; l = list_next(l))
1664        {
1665           Evas_Object *cur = list_data_get(l);
1666           if (elm_widget_focus_get(cur)) break;
1667        }
1668
1669    const Eina_List *start = l;
1670    Evas_Object *to_focus = NULL;
1671
1672    /* Interate sub items */
1673    /* Go to end of list */
1674    for (; l; l = list_next(l))
1675      {
1676         Evas_Object *tmp = NULL;
1677         Evas_Object *cur = list_data_get(l);
1678
1679         if (elm_widget_parent_get(cur) != obj)
1680           continue;
1681
1682         /* Try Focus cycle in subitem */
1683         if (elm_widget_focus_next_get(cur, dir, &tmp))
1684           {
1685              *next = tmp;
1686              return EINA_TRUE;
1687           }
1688         else if ((tmp) && (!to_focus))
1689           to_focus = tmp;
1690      }
1691
1692    l = items;
1693
1694    /* Get First possible */
1695    for (; l != start; l = list_next(l))
1696      {
1697         Evas_Object *tmp = NULL;
1698         Evas_Object *cur = list_data_get(l);
1699
1700         if (elm_widget_parent_get(cur) != obj)
1701           continue;
1702
1703         /* Try Focus cycle in subitem */
1704         elm_widget_focus_next_get(cur, dir, &tmp);
1705         if (tmp)
1706           {
1707              *next = tmp;
1708              return EINA_FALSE;
1709           }
1710      }
1711
1712    *next = to_focus;
1713    return EINA_FALSE;
1714 }
1715
1716 EAPI void
1717 elm_widget_signal_emit(Evas_Object *obj,
1718                        const char  *emission,
1719                        const char  *source)
1720 {
1721    API_ENTRY return;
1722    if (!sd->signal_func) return;
1723    sd->signal_func(obj, emission, source);
1724 }
1725
1726 static void
1727 _edje_signal_callback(void        *data,
1728                       Evas_Object *obj __UNUSED__,
1729                       const char  *emission,
1730                       const char  *source)
1731 {
1732    Edje_Signal_Data *esd = data;
1733    esd->func(esd->data, esd->obj, emission, source);
1734 }
1735
1736 EAPI void
1737 elm_widget_signal_callback_add(Evas_Object   *obj,
1738                                const char    *emission,
1739                                const char    *source,
1740                                Edje_Signal_Cb func,
1741                                void          *data)
1742 {
1743    Edje_Signal_Data *esd;
1744    API_ENTRY return;
1745    if (!sd->callback_add_func) return;
1746    EINA_SAFETY_ON_NULL_RETURN(func);
1747
1748    esd = ELM_NEW(Edje_Signal_Data);
1749    if (!esd) return;
1750
1751    esd->obj = obj;
1752    esd->func = func;
1753    esd->emission = eina_stringshare_add(emission);
1754    esd->source = eina_stringshare_add(source);
1755    esd->data = data;
1756    sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1757    sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1758 }
1759
1760 EAPI void *
1761 elm_widget_signal_callback_del(Evas_Object   *obj,
1762                                const char    *emission,
1763                                const char    *source,
1764                                Edje_Signal_Cb func)
1765 {
1766    Edje_Signal_Data *esd;
1767    Eina_List *l;
1768    void *data = NULL;
1769    API_ENTRY return NULL;
1770    if (!sd->callback_del_func) return NULL;
1771
1772    EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1773      {
1774         if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1775             (!strcmp(esd->source, source)))
1776           {
1777              sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1778              eina_stringshare_del(esd->emission);
1779              eina_stringshare_del(esd->source);
1780              data = esd->data;
1781              free(esd);
1782              break;
1783           }
1784      }
1785    sd->callback_del_func(obj, emission, source, _edje_signal_callback, esd);
1786    return data;
1787 }
1788
1789 EAPI void
1790 elm_widget_focus_set(Evas_Object *obj,
1791                      int          first)
1792 {
1793    API_ENTRY return;
1794    if (!sd->focused)
1795      {
1796         focus_order++;
1797         sd->focus_order = focus_order;
1798         sd->focused = EINA_TRUE;
1799         if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1800      }
1801    if (sd->focus_func)
1802      {
1803         sd->focus_func(obj);
1804         return;
1805      }
1806    else
1807      {
1808         if (first)
1809           {
1810              if ((_is_focusable(sd->resize_obj)) &&
1811                  (!elm_widget_disabled_get(sd->resize_obj)))
1812                {
1813                   elm_widget_focus_set(sd->resize_obj, first);
1814                }
1815              else
1816                {
1817                   const Eina_List *l;
1818                   Evas_Object *child;
1819                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1820                     {
1821                        if ((_is_focusable(child)) &&
1822                            (!elm_widget_disabled_get(child)))
1823                          {
1824                             elm_widget_focus_set(child, first);
1825                             break;
1826                          }
1827                     }
1828                }
1829           }
1830         else
1831           {
1832              const Eina_List *l;
1833              Evas_Object *child;
1834              EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1835                {
1836                   if ((_is_focusable(child)) &&
1837                       (!elm_widget_disabled_get(child)))
1838                     {
1839                        elm_widget_focus_set(child, first);
1840                        break;
1841                     }
1842                }
1843              if (!l)
1844                {
1845                   if ((_is_focusable(sd->resize_obj)) &&
1846                       (!elm_widget_disabled_get(sd->resize_obj)))
1847                     {
1848                        elm_widget_focus_set(sd->resize_obj, first);
1849                     }
1850                }
1851           }
1852      }
1853 }
1854
1855 EAPI Evas_Object *
1856 elm_widget_parent_get(const Evas_Object *obj)
1857 {
1858    API_ENTRY return NULL;
1859    return sd->parent_obj;
1860 }
1861
1862 EAPI void
1863 elm_widget_focused_object_clear(Evas_Object *obj)
1864 {
1865    API_ENTRY return;
1866    if (!sd->focused) return;
1867    if (elm_widget_focus_get(sd->resize_obj))
1868      elm_widget_focused_object_clear(sd->resize_obj);
1869    else
1870      {
1871         const Eina_List *l;
1872         Evas_Object *child;
1873         EINA_LIST_FOREACH(sd->subobjs, l, child)
1874           {
1875              if (elm_widget_focus_get(child))
1876                {
1877                   elm_widget_focused_object_clear(child);
1878                   break;
1879                }
1880           }
1881      }
1882    sd->focused = EINA_FALSE;
1883    if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1884    if (sd->focus_func) sd->focus_func(obj);
1885 }
1886
1887 EAPI void
1888 elm_widget_focus_steal(Evas_Object *obj)
1889 {
1890    Evas_Object *parent, *parent2, *o;
1891    API_ENTRY return;
1892
1893    if (sd->focused) return;
1894    if (sd->disabled) return;
1895    if (!sd->can_focus) return;
1896    if (sd->tree_unfocusable) return;
1897    parent = obj;
1898    for (;;)
1899      {
1900         o = elm_widget_parent_get(parent);
1901         if (!o) break;
1902         sd = evas_object_smart_data_get(o);
1903         if (sd->disabled || sd->tree_unfocusable) return;
1904         if (sd->focused) break;
1905         parent = o;
1906      }
1907    if ((!elm_widget_parent_get(parent)) &&
1908        (!elm_widget_parent2_get(parent)))
1909       elm_widget_focused_object_clear(parent);
1910    else
1911      {
1912         parent2 = elm_widget_parent_get(parent);
1913         if (!parent2) parent2 = elm_widget_parent2_get(parent);
1914         parent = parent2;
1915         sd = evas_object_smart_data_get(parent);
1916         if (sd)
1917           {
1918              if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1919                 elm_widget_focused_object_clear(sd->resize_obj);
1920              else
1921                {
1922                   const Eina_List *l;
1923                   Evas_Object *child;
1924                   EINA_LIST_FOREACH(sd->subobjs, l, child)
1925                     {
1926                        if (elm_widget_focus_get(child))
1927                          {
1928                             elm_widget_focused_object_clear(child);
1929                             break;
1930                          }
1931                     }
1932                }
1933           }
1934      }
1935    _parent_focus(obj);
1936    return;
1937 }
1938
1939 EAPI void
1940 elm_widget_focus_restore(Evas_Object *obj)
1941 {
1942    Evas_Object *newest = NULL;
1943    unsigned int newest_focus_order = 0;
1944    API_ENTRY return;
1945
1946    newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
1947    if (newest)
1948      {
1949         elm_object_focus_set(newest, EINA_FALSE);
1950         elm_object_focus_set(newest, EINA_TRUE);
1951      }
1952 }
1953
1954 EAPI void
1955 elm_widget_activate(Evas_Object *obj)
1956 {
1957    API_ENTRY return;
1958    elm_widget_change(obj);
1959    if (sd->activate_func) sd->activate_func(obj);
1960 }
1961
1962 EAPI void
1963 elm_widget_change(Evas_Object *obj)
1964 {
1965    API_ENTRY return;
1966    elm_widget_change(elm_widget_parent_get(obj));
1967    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
1968 }
1969
1970 EAPI void
1971 elm_widget_disabled_set(Evas_Object *obj,
1972                         Eina_Bool    disabled)
1973 {
1974    API_ENTRY return;
1975
1976    if (sd->disabled == disabled) return;
1977    sd->disabled = !!disabled;
1978    elm_widget_focus_disabled_handle(obj);
1979    if (sd->disable_func) sd->disable_func(obj);
1980 }
1981
1982 EAPI Eina_Bool
1983 elm_widget_disabled_get(const Evas_Object *obj)
1984 {
1985    API_ENTRY return 0;
1986    return sd->disabled;
1987 }
1988
1989 EAPI void
1990 elm_widget_show_region_set(Evas_Object *obj,
1991                            Evas_Coord   x,
1992                            Evas_Coord   y,
1993                            Evas_Coord   w,
1994                            Evas_Coord   h,
1995                            Eina_Bool    forceshow)
1996 {
1997    Evas_Object *parent_obj, *child_obj;
1998    Evas_Coord px, py, cx, cy;
1999
2000    API_ENTRY return;
2001    if (!forceshow && (x == sd->rx) && (y == sd->ry)
2002             && (w == sd->rw) && (h == sd->rh)) return;
2003    sd->rx = x;
2004    sd->ry = y;
2005    sd->rw = w;
2006    sd->rh = h;
2007    if (sd->on_show_region_func)
2008      sd->on_show_region_func(sd->on_show_region_data, obj);
2009
2010    do
2011      {
2012         parent_obj = sd->parent_obj;
2013         child_obj = sd->obj;
2014         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2015         sd = evas_object_smart_data_get(parent_obj);
2016         if (!sd) break;
2017
2018         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2019         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2020
2021         x += (cx - px);
2022         y += (cy - py);
2023         sd->rx = x;
2024         sd->ry = y;
2025         sd->rw = w;
2026         sd->rh = h;
2027
2028         if (sd->on_show_region_func)
2029           {
2030              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2031           }
2032      }
2033    while (parent_obj);
2034 }
2035
2036 EAPI void
2037 elm_widget_show_region_get(const Evas_Object *obj,
2038                            Evas_Coord        *x,
2039                            Evas_Coord        *y,
2040                            Evas_Coord        *w,
2041                            Evas_Coord        *h)
2042 {
2043    API_ENTRY return;
2044    if (x) *x = sd->rx;
2045    if (y) *y = sd->ry;
2046    if (w) *w = sd->rw;
2047    if (h) *h = sd->rh;
2048 }
2049
2050 /**
2051  * @internal
2052  *
2053  * Get the focus region of the given widget.
2054  *
2055  * The focus region is the area of a widget that should brought into the
2056  * visible area when the widget is focused. Mostly used to show the part of
2057  * an entry where the cursor is, for example. The area returned is relative
2058  * to the object @p obj.
2059  * If the @p obj doesn't have the proper on_focus_region_hook set, this
2060  * function will return the full size of the object.
2061  *
2062  * @param obj The widget object
2063  * @param x Where to store the x coordinate of the area
2064  * @param y Where to store the y coordinate of the area
2065  * @param w Where to store the width of the area
2066  * @param h Where to store the height of the area
2067  *
2068  * @ingroup Widget
2069  */
2070 EAPI void
2071 elm_widget_focus_region_get(const Evas_Object *obj,
2072                             Evas_Coord        *x,
2073                             Evas_Coord        *y,
2074                             Evas_Coord        *w,
2075                             Evas_Coord        *h)
2076 {
2077    Smart_Data *sd;
2078
2079    if (!obj) return;
2080
2081    sd = evas_object_smart_data_get(obj);
2082    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2083      {
2084         evas_object_geometry_get(obj, NULL, NULL, w, h);
2085         if (x) *x = 0;
2086         if (y) *y = 0;
2087         return;
2088      }
2089    sd->on_focus_region_func(obj, x, y, w, h);
2090 }
2091
2092 EAPI void
2093 elm_widget_scroll_hold_push(Evas_Object *obj)
2094 {
2095    API_ENTRY return;
2096    sd->scroll_hold++;
2097    if (sd->scroll_hold == 1)
2098      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2099    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2100    // FIXME: on delete/reparent hold pop
2101 }
2102
2103 EAPI void
2104 elm_widget_scroll_hold_pop(Evas_Object *obj)
2105 {
2106    API_ENTRY return;
2107    sd->scroll_hold--;
2108    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2109    if (!sd->scroll_hold)
2110      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2111    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2112 }
2113
2114 EAPI int
2115 elm_widget_scroll_hold_get(const Evas_Object *obj)
2116 {
2117    API_ENTRY return 0;
2118    return sd->scroll_hold;
2119 }
2120
2121 EAPI void
2122 elm_widget_scroll_freeze_push(Evas_Object *obj)
2123 {
2124    API_ENTRY return;
2125    sd->scroll_freeze++;
2126    if (sd->scroll_freeze == 1)
2127      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2128    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2129    // FIXME: on delete/reparent freeze pop
2130 }
2131
2132 EAPI void
2133 elm_widget_scroll_freeze_pop(Evas_Object *obj)
2134 {
2135    API_ENTRY return;
2136    sd->scroll_freeze--;
2137    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2138    if (!sd->scroll_freeze)
2139      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2140    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2141 }
2142
2143 EAPI int
2144 elm_widget_scroll_freeze_get(const Evas_Object *obj)
2145 {
2146    API_ENTRY return 0;
2147    return sd->scroll_freeze;
2148 }
2149
2150 EAPI void
2151 elm_widget_scale_set(Evas_Object *obj,
2152                      double       scale)
2153 {
2154    API_ENTRY return;
2155    if (scale <= 0.0) scale = 0.0;
2156    if (sd->scale != scale)
2157      {
2158         sd->scale = scale;
2159         elm_widget_theme(obj);
2160      }
2161 }
2162
2163 EAPI double
2164 elm_widget_scale_get(const Evas_Object *obj)
2165 {
2166    API_ENTRY return 1.0;
2167    // FIXME: save walking up the tree by storing/caching parent scale
2168    if (sd->scale == 0.0)
2169      {
2170         if (sd->parent_obj)
2171           return elm_widget_scale_get(sd->parent_obj);
2172         else
2173           return 1.0;
2174      }
2175    return sd->scale;
2176 }
2177
2178 EAPI void
2179 elm_widget_theme_set(Evas_Object *obj,
2180                      Elm_Theme   *th)
2181 {
2182    API_ENTRY return;
2183    if (sd->theme != th)
2184      {
2185         if (sd->theme) elm_theme_free(sd->theme);
2186         sd->theme = th;
2187         if (th) th->ref++;
2188         elm_widget_theme(obj);
2189      }
2190 }
2191
2192 EAPI void
2193 elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2194 {
2195    API_ENTRY return;
2196
2197    if (!sd->on_text_set_func)
2198      return;
2199
2200    sd->on_text_set_func(obj, part, label);
2201 }
2202
2203 EAPI const char *
2204 elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2205 {
2206    API_ENTRY return NULL;
2207
2208    if (!sd->on_text_get_func)
2209      return NULL;
2210
2211    return sd->on_text_get_func(obj, part);
2212 }
2213
2214 EAPI void
2215 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2216 {
2217    API_ENTRY return;
2218
2219    if (!sd->on_content_set_func)  return;
2220    sd->on_content_set_func(obj, part, content);
2221 }
2222
2223 EAPI Evas_Object *
2224 elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2225 {
2226    API_ENTRY return NULL;
2227
2228    if (!sd->on_content_get_func) return NULL;
2229    return sd->on_content_get_func(obj, part);
2230 }
2231
2232 EAPI Evas_Object *
2233 elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2234 {
2235    API_ENTRY return NULL;
2236
2237    if (!sd->on_content_unset_func) return NULL;
2238    return sd->on_content_unset_func(obj, part);
2239 }
2240
2241 EAPI Elm_Theme *
2242 elm_widget_theme_get(const Evas_Object *obj)
2243 {
2244    API_ENTRY return NULL;
2245    if (!sd->theme)
2246      {
2247         if (sd->parent_obj)
2248           return elm_widget_theme_get(sd->parent_obj);
2249         else
2250           return NULL;
2251      }
2252    return sd->theme;
2253 }
2254
2255 EAPI void
2256 elm_widget_style_set(Evas_Object *obj,
2257                      const char  *style)
2258 {
2259    API_ENTRY return;
2260
2261    if (eina_stringshare_replace(&sd->style, style))
2262      elm_widget_theme(obj);
2263 }
2264
2265 EAPI const char *
2266 elm_widget_style_get(const Evas_Object *obj)
2267 {
2268    API_ENTRY return NULL;
2269    if (sd->style) return sd->style;
2270    return "default";
2271 }
2272
2273 EAPI void
2274 elm_widget_type_set(Evas_Object *obj,
2275                     const char  *type)
2276 {
2277    API_ENTRY return;
2278    eina_stringshare_replace(&sd->type, type);
2279 }
2280
2281 EAPI const char *
2282 elm_widget_type_get(const Evas_Object *obj)
2283 {
2284    API_ENTRY return NULL;
2285    if (sd->type) return sd->type;
2286    return "";
2287 }
2288
2289 EAPI void
2290 elm_widget_tooltip_add(Evas_Object *obj,
2291                        Elm_Tooltip *tt)
2292 {
2293    API_ENTRY return;
2294    sd->tooltips = eina_list_append(sd->tooltips, tt);
2295 }
2296
2297 EAPI void
2298 elm_widget_tooltip_del(Evas_Object *obj,
2299                        Elm_Tooltip *tt)
2300 {
2301    API_ENTRY return;
2302    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2303 }
2304
2305 EAPI void
2306 elm_widget_cursor_add(Evas_Object *obj,
2307                       Elm_Cursor  *cur)
2308 {
2309    API_ENTRY return;
2310    sd->cursors = eina_list_append(sd->cursors, cur);
2311 }
2312
2313 EAPI void
2314 elm_widget_cursor_del(Evas_Object *obj,
2315                       Elm_Cursor  *cur)
2316 {
2317    API_ENTRY return;
2318    sd->cursors = eina_list_remove(sd->cursors, cur);
2319 }
2320
2321 EAPI void
2322 elm_widget_drag_lock_x_set(Evas_Object *obj,
2323                            Eina_Bool    lock)
2324 {
2325    API_ENTRY return;
2326    if (sd->drag_x_locked == lock) return;
2327    sd->drag_x_locked = lock;
2328    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2329    else _propagate_x_drag_lock(obj, -1);
2330 }
2331
2332 EAPI void
2333 elm_widget_drag_lock_y_set(Evas_Object *obj,
2334                            Eina_Bool    lock)
2335 {
2336    API_ENTRY return;
2337    if (sd->drag_y_locked == lock) return;
2338    sd->drag_y_locked = lock;
2339    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2340    else _propagate_y_drag_lock(obj, -1);
2341 }
2342
2343 EAPI Eina_Bool
2344 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2345 {
2346    API_ENTRY return EINA_FALSE;
2347    return sd->drag_x_locked;
2348 }
2349
2350 EAPI Eina_Bool
2351 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2352 {
2353    API_ENTRY return EINA_FALSE;
2354    return sd->drag_y_locked;
2355 }
2356
2357 EAPI int
2358 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2359 {
2360    API_ENTRY return 0;
2361    return sd->child_drag_x_locked;
2362 }
2363
2364 EAPI int
2365 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2366 {
2367    API_ENTRY return 0;
2368    return sd->child_drag_y_locked;
2369 }
2370
2371 EAPI Eina_Bool
2372 elm_widget_theme_object_set(Evas_Object *obj,
2373                             Evas_Object *edj,
2374                             const char  *wname,
2375                             const char  *welement,
2376                             const char  *wstyle)
2377 {
2378    API_ENTRY return EINA_FALSE;
2379    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2380 }
2381
2382 EAPI Eina_Bool
2383 elm_widget_type_check(const Evas_Object *obj,
2384                       const char        *type)
2385 {
2386    const char *provided, *expected = "(unknown)";
2387    static int abort_on_warn = -1;
2388    provided = elm_widget_type_get(obj);
2389    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2390    if (type) expected = type;
2391    if ((!provided) || (!provided[0]))
2392      {
2393         provided = evas_object_type_get(obj);
2394         if ((!provided) || (!provided[0]))
2395           provided = "(unknown)";
2396      }
2397    ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
2398    if (abort_on_warn == -1)
2399      {
2400         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2401         else abort_on_warn = 0;
2402      }
2403    if (abort_on_warn == 1) abort();
2404    return EINA_FALSE;
2405 }
2406
2407 /**
2408  * @internal
2409  *
2410  * Split string in words
2411  *
2412  * @param str Source string
2413  * @return List of const words
2414  *
2415  * @see elm_widget_stringlist_free()
2416  * @ingroup Widget
2417  */
2418 EAPI Eina_List *
2419 elm_widget_stringlist_get(const char *str)
2420 {
2421    Eina_List *list = NULL;
2422    const char *s, *b;
2423    if (!str) return NULL;
2424    for (b = s = str; 1; s++)
2425      {
2426         if ((*s == ' ') || (!*s))
2427           {
2428              char *t = malloc(s - b + 1);
2429              if (t)
2430                {
2431                   strncpy(t, b, s - b);
2432                   t[s - b] = 0;
2433                   list = eina_list_append(list, eina_stringshare_add(t));
2434                   free(t);
2435                }
2436              b = s + 1;
2437           }
2438         if (!*s) break;
2439      }
2440    return list;
2441 }
2442
2443 EAPI void
2444 elm_widget_stringlist_free(Eina_List *list)
2445 {
2446    const char *s;
2447    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2448 }
2449
2450 EAPI void
2451 elm_widget_focus_hide_handle(Evas_Object *obj)
2452 {
2453    _if_focused_revert(obj, EINA_TRUE);
2454 }
2455
2456 EAPI void
2457 elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2458 {
2459    Evas_Object *o = obj;
2460    do
2461      {
2462         if (_elm_widget_is(o)) break;
2463         o = evas_object_smart_parent_get(o);
2464      }
2465    while (o);
2466    if (!o) return;
2467    if (!_is_focusable(o)) return;
2468    elm_widget_focus_steal(o);
2469 }
2470
2471 EAPI void
2472 elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2473 {
2474    API_ENTRY return;
2475
2476    if (!elm_widget_parent_get(obj))
2477      elm_widget_focused_object_clear(obj);
2478    else
2479      _if_focused_revert(obj, EINA_TRUE);
2480 }
2481
2482 EAPI void
2483 elm_widget_focus_disabled_handle(Evas_Object *obj)
2484 {
2485    API_ENTRY return;
2486
2487    elm_widget_focus_tree_unfocusable_handle(obj);
2488 }
2489
2490 /**
2491  * @internal
2492  *
2493  * Allocate a new Elm_Widget_Item-derived structure.
2494  *
2495  * The goal of this structure is to provide common ground for actions
2496  * that a widget item have, such as the owner widget, callback to
2497  * notify deletion, data pointer and maybe more.
2498  *
2499  * @param widget the owner widget that holds this item, must be an elm_widget!
2500  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2501  *        be used to allocate memory.
2502  *
2503  * @return allocated memory that is already zeroed out, or NULL on errors.
2504  *
2505  * @see elm_widget_item_new() convenience macro.
2506  * @see elm_widget_item_del() to release memory.
2507  * @ingroup Widget
2508  */
2509 EAPI Elm_Widget_Item *
2510 _elm_widget_item_new(Evas_Object *widget,
2511                      size_t       alloc_size)
2512 {
2513    if (!_elm_widget_is(widget))
2514      return NULL;
2515
2516    Elm_Widget_Item *item;
2517
2518    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2519    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2520
2521    item = calloc(1, alloc_size);
2522    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2523
2524    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2525    item->widget = widget;
2526    return item;
2527 }
2528
2529 /**
2530  * @internal
2531  *
2532  * Releases widget item memory, calling back del_cb() if it exists.
2533  *
2534  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2535  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2536  * this function and then unset it, thus being useful for 2 step
2537  * cleanup whenever the del_cb may use any of the data that must be
2538  * deleted from item.
2539  *
2540  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2541  * is presented!
2542  *
2543  * @param item a valid #Elm_Widget_Item to be deleted.
2544  * @see elm_widget_item_del() convenience macro.
2545  * @ingroup Widget
2546  */
2547 EAPI void
2548 _elm_widget_item_del(Elm_Widget_Item *item)
2549 {
2550    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2551
2552    if (item->del_cb)
2553      item->del_cb((void *)item->data, item->widget, item);
2554
2555    if (item->view)
2556      evas_object_del(item->view);
2557
2558    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2559    free(item);
2560 }
2561
2562 /**
2563  * @internal
2564  *
2565  * Notify object will be deleted without actually deleting it.
2566  *
2567  * This function will callback Elm_Widget_Item::del_cb if it is set
2568  * and then unset it so it is not called twice (ie: from
2569  * elm_widget_item_del()).
2570  *
2571  * @param item a valid #Elm_Widget_Item to be notified
2572  * @see elm_widget_item_pre_notify_del() convenience macro.
2573  * @ingroup Widget
2574  */
2575 EAPI void
2576 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2577 {
2578    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2579    if (!item->del_cb) return;
2580    item->del_cb((void *)item->data, item->widget, item);
2581    item->del_cb = NULL;
2582 }
2583
2584 /**
2585  * @internal
2586  *
2587  * Set the function to notify when item is being deleted.
2588  *
2589  * This function will complain if there was a callback set already,
2590  * however it will set the new one.
2591  *
2592  * The callback will be called from elm_widget_item_pre_notify_del()
2593  * or elm_widget_item_del() will be called with:
2594  *   - data: the Elm_Widget_Item::data value.
2595  *   - obj: the Elm_Widget_Item::widget evas object.
2596  *   - event_info: the item being deleted.
2597  *
2598  * @param item a valid #Elm_Widget_Item to be notified
2599  * @see elm_widget_item_del_cb_set() convenience macro.
2600  * @ingroup Widget
2601  */
2602 EAPI void
2603 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2604                             Evas_Smart_Cb    del_cb)
2605 {
2606    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2607
2608    if ((item->del_cb) && (item->del_cb != del_cb))
2609      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2610          item->del_cb, item, del_cb);
2611
2612    item->del_cb = del_cb;
2613 }
2614
2615 /**
2616  * @internal
2617  *
2618  * Set user-data in this item.
2619  *
2620  * User data may be used to identify this item or just store any
2621  * application data. It is automatically given as the first parameter
2622  * of the deletion notify callback.
2623  *
2624  * @param item a valid #Elm_Widget_Item to store data in.
2625  * @param data user data to store.
2626  * @see elm_widget_item_del_cb_set() convenience macro.
2627  * @ingroup Widget
2628  */
2629 EAPI void
2630 _elm_widget_item_data_set(Elm_Widget_Item *item,
2631                           const void      *data)
2632 {
2633    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2634    if ((item->data) && (item->data != data))
2635      DBG("Replacing item %p data %p with %p", item, item->data, data);
2636    item->data = data;
2637 }
2638
2639 /**
2640  * @internal
2641  *
2642  * Retrieves user-data of this item.
2643  *
2644  * @param item a valid #Elm_Widget_Item to get data from.
2645  * @see elm_widget_item_data_set()
2646  * @ingroup Widget
2647  */
2648 EAPI void *
2649 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2650 {
2651    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2652    return (void *)item->data;
2653 }
2654
2655 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2656
2657 struct _Elm_Widget_Item_Tooltip
2658 {
2659    Elm_Widget_Item            *item;
2660    Elm_Tooltip_Item_Content_Cb func;
2661    Evas_Smart_Cb               del_cb;
2662    const void                 *data;
2663 };
2664
2665 static Evas_Object *
2666 _elm_widget_item_tooltip_label_create(void        *data,
2667                                       Evas_Object *obj __UNUSED__,
2668                                       Evas_Object *tooltip,
2669                                       void        *item __UNUSED__)
2670 {
2671    Evas_Object *label = elm_label_add(tooltip);
2672    if (!label)
2673      return NULL;
2674    elm_object_style_set(label, "tooltip");
2675    elm_object_text_set(label, data);
2676    return label;
2677 }
2678
2679 static void
2680 _elm_widget_item_tooltip_label_del_cb(void        *data,
2681                                       Evas_Object *obj __UNUSED__,
2682                                       void        *event_info __UNUSED__)
2683 {
2684    eina_stringshare_del(data);
2685 }
2686
2687 /**
2688  * @internal
2689  *
2690  * Set the text to be shown in the widget item.
2691  *
2692  * @param item Target item
2693  * @param text The text to set in the content
2694  *
2695  * Setup the text as tooltip to object. The item can have only one tooltip,
2696  * so any previous tooltip data is removed.
2697  *
2698  * @ingroup Widget
2699  */
2700 EAPI void
2701 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2702                                   const char      *text)
2703 {
2704    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2705    EINA_SAFETY_ON_NULL_RETURN(text);
2706
2707    text = eina_stringshare_add(text);
2708    _elm_widget_item_tooltip_content_cb_set
2709      (item, _elm_widget_item_tooltip_label_create, text,
2710      _elm_widget_item_tooltip_label_del_cb);
2711 }
2712
2713 static Evas_Object *
2714 _elm_widget_item_tooltip_create(void        *data,
2715                                 Evas_Object *obj,
2716                                 Evas_Object *tooltip)
2717 {
2718    Elm_Widget_Item_Tooltip *wit = data;
2719    return wit->func((void *)wit->data, obj, tooltip, wit->item);
2720 }
2721
2722 static void
2723 _elm_widget_item_tooltip_del_cb(void        *data,
2724                                 Evas_Object *obj,
2725                                 void        *event_info __UNUSED__)
2726 {
2727    Elm_Widget_Item_Tooltip *wit = data;
2728    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
2729    free(wit);
2730 }
2731
2732 /**
2733  * @internal
2734  *
2735  * Set the content to be shown in the tooltip item
2736  *
2737  * Setup the tooltip to item. The item can have only one tooltip,
2738  * so any previous tooltip data is removed. @p func(with @p data) will
2739  * be called every time that need show the tooltip and it should
2740  * return a valid Evas_Object. This object is then managed fully by
2741  * tooltip system and is deleted when the tooltip is gone.
2742  *
2743  * @param item the widget item being attached a tooltip.
2744  * @param func the function used to create the tooltip contents.
2745  * @param data what to provide to @a func as callback data/context.
2746  * @param del_cb called when data is not needed anymore, either when
2747  *        another callback replaces @func, the tooltip is unset with
2748  *        elm_widget_item_tooltip_unset() or the owner @a item
2749  *        dies. This callback receives as the first parameter the
2750  *        given @a data, and @c event_info is the item.
2751  *
2752  * @ingroup Widget
2753  */
2754 EAPI void
2755 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
2756                                         Elm_Tooltip_Item_Content_Cb func,
2757                                         const void                 *data,
2758                                         Evas_Smart_Cb               del_cb)
2759 {
2760    Elm_Widget_Item_Tooltip *wit;
2761
2762    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
2763
2764    if (!func)
2765      {
2766         _elm_widget_item_tooltip_unset(item);
2767         return;
2768      }
2769
2770    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
2771    if (!wit) goto error;
2772    wit->item = item;
2773    wit->func = func;
2774    wit->data = data;
2775    wit->del_cb = del_cb;
2776
2777    elm_object_sub_tooltip_content_cb_set
2778      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
2779      _elm_widget_item_tooltip_del_cb);
2780
2781    return;
2782
2783 error_noitem:
2784    if (del_cb) del_cb((void *)data, NULL, item);
2785    return;
2786 error:
2787    if (del_cb) del_cb((void *)data, item->widget, item);
2788 }
2789
2790 /**
2791  * @internal
2792  *
2793  * Unset tooltip from item
2794  *
2795  * @param item widget item to remove previously set tooltip.
2796  *
2797  * Remove tooltip from item. The callback provided as del_cb to
2798  * elm_widget_item_tooltip_content_cb_set() will be called to notify
2799  * it is not used anymore.
2800  *
2801  * @see elm_widget_item_tooltip_content_cb_set()
2802  *
2803  * @ingroup Widget
2804  */
2805 EAPI void
2806 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
2807 {
2808    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2809    elm_object_tooltip_unset(item->view);
2810 }
2811
2812 /**
2813  * @internal
2814  *
2815  * Sets a different style for this item tooltip.
2816  *
2817  * @note before you set a style you should define a tooltip with
2818  *       elm_widget_item_tooltip_content_cb_set() or
2819  *       elm_widget_item_tooltip_text_set()
2820  *
2821  * @param item widget item with tooltip already set.
2822  * @param style the theme style to use (default, transparent, ...)
2823  *
2824  * @ingroup Widget
2825  */
2826 EAPI void
2827 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
2828                                    const char      *style)
2829 {
2830    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2831    elm_object_tooltip_style_set(item->view, style);
2832 }
2833
2834 EAPI Eina_Bool
2835 _elm_widget_item_tooltip_size_restrict_disable(Elm_Widget_Item *item, Eina_Bool disable)
2836 {
2837    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2838    return elm_tooltip_size_restrict_disable(item->view, disable);
2839 }
2840
2841 EAPI Eina_Bool
2842 _elm_widget_item_tooltip_size_restrict_disabled_get(const Elm_Widget_Item *item)
2843 {
2844    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2845    return elm_tooltip_size_restrict_disabled_get(item->view);
2846 }
2847
2848 /**
2849  * @internal
2850  *
2851  * Get the style for this item tooltip.
2852  *
2853  * @param item widget item with tooltip already set.
2854  * @return style the theme style in use, defaults to "default". If the
2855  *         object does not have a tooltip set, then NULL is returned.
2856  *
2857  * @ingroup Widget
2858  */
2859 EAPI const char *
2860 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
2861 {
2862    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2863    return elm_object_tooltip_style_get(item->view);
2864 }
2865
2866 EAPI void
2867 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
2868                             const char      *cursor)
2869 {
2870    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2871    elm_object_sub_cursor_set(item->view, item->widget, cursor);
2872 }
2873
2874 EAPI const char *
2875 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
2876 {
2877    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2878    return elm_object_cursor_get(item->view);
2879 }
2880
2881 EAPI void
2882 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
2883 {
2884    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2885    elm_object_cursor_unset(item->view);
2886 }
2887
2888 /**
2889  * @internal
2890  *
2891  * Sets a different style for this item cursor.
2892  *
2893  * @note before you set a style you should define a cursor with
2894  *       elm_widget_item_cursor_set()
2895  *
2896  * @param item widget item with cursor already set.
2897  * @param style the theme style to use (default, transparent, ...)
2898  *
2899  * @ingroup Widget
2900  */
2901 EAPI void
2902 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
2903                                   const char      *style)
2904 {
2905    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2906    elm_object_cursor_style_set(item->view, style);
2907 }
2908
2909 /**
2910  * @internal
2911  *
2912  * Get the style for this item cursor.
2913  *
2914  * @param item widget item with cursor already set.
2915  * @return style the theme style in use, defaults to "default". If the
2916  *         object does not have a cursor set, then NULL is returned.
2917  *
2918  * @ingroup Widget
2919  */
2920 EAPI const char *
2921 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
2922 {
2923    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2924    return elm_object_cursor_style_get(item->view);
2925 }
2926
2927 /**
2928  * @internal
2929  *
2930  * Set if the cursor set should be searched on the theme or should use
2931  * the provided by the engine, only.
2932  *
2933  * @note before you set if should look on theme you should define a cursor
2934  * with elm_object_cursor_set(). By default it will only look for cursors
2935  * provided by the engine.
2936  *
2937  * @param item widget item with cursor already set.
2938  * @param engine_only boolean to define it cursors should be looked only
2939  * between the provided by the engine or searched on widget's theme as well.
2940  *
2941  * @ingroup Widget
2942  */
2943 EAPI void
2944 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
2945                                         Eina_Bool        engine_only)
2946 {
2947    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2948    elm_object_cursor_engine_only_set(item->view, engine_only);
2949 }
2950
2951 /**
2952  * @internal
2953  *
2954  * Get the cursor engine only usage for this item cursor.
2955  *
2956  * @param item widget item with cursor already set.
2957  * @return engine_only boolean to define it cursors should be looked only
2958  * between the provided by the engine or searched on widget's theme as well. If
2959  *         the object does not have a cursor set, then EINA_FALSE is returned.
2960  *
2961  * @ingroup Widget
2962  */
2963 EAPI Eina_Bool
2964 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
2965 {
2966    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2967    return elm_object_cursor_engine_only_get(item->view);
2968 }
2969
2970 // smart object funcs
2971 static void
2972 _smart_reconfigure(Smart_Data *sd)
2973 {
2974    if (sd->resize_obj)
2975      {
2976         evas_object_move(sd->resize_obj, sd->x, sd->y);
2977         evas_object_resize(sd->resize_obj, sd->w, sd->h);
2978      }
2979    if (sd->hover_obj)
2980      {
2981         evas_object_move(sd->hover_obj, sd->x, sd->y);
2982         evas_object_resize(sd->hover_obj, sd->w, sd->h);
2983      }
2984 }
2985
2986 EAPI void
2987 _elm_widget_item_content_part_set(Elm_Widget_Item *item,
2988                                  const char *part,
2989                                  Evas_Object *content)
2990 {
2991    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2992    if (!item->on_content_set_func) return;
2993    item->on_content_set_func((Elm_Object_Item *) item, part, content);
2994 }
2995
2996 EAPI Evas_Object *
2997 _elm_widget_item_content_part_get(const Elm_Widget_Item *item,
2998                                   const char *part)
2999 {
3000    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3001    if (!item->on_content_get_func) return NULL;
3002    return item->on_content_get_func((Elm_Object_Item *) item, part);
3003 }
3004
3005 EAPI Evas_Object *
3006 _elm_widget_item_content_part_unset(Elm_Widget_Item *item,
3007                                     const char *part)
3008 {
3009    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3010    if (!item->on_content_unset_func) return NULL;
3011    return item->on_content_unset_func((Elm_Object_Item *) item, part);
3012 }
3013
3014 EAPI void
3015 _elm_widget_item_text_part_set(Elm_Widget_Item *item,
3016                               const char *part,
3017                               const char *label)
3018 {
3019    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3020    if (!item->on_text_set_func) return;
3021    item->on_text_set_func((Elm_Object_Item *) item, part, label);
3022 }
3023
3024 EAPI const char *
3025 _elm_widget_item_text_part_get(const Elm_Widget_Item *item,
3026                                const char *part)
3027 {
3028    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3029    if (!item->on_text_get_func) return NULL;
3030    return item->on_text_get_func((Elm_Object_Item *) item, part);
3031 }
3032
3033 EAPI void
3034 _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3035                                       Elm_Widget_On_Content_Set_Cb func)
3036 {
3037    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3038    item->on_content_set_func = func;
3039 }
3040
3041 EAPI void
3042 _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3043                                       Elm_Widget_On_Content_Get_Cb func)
3044 {
3045    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3046    item->on_content_get_func = func;
3047 }
3048
3049 EAPI void
3050 _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3051                                         Elm_Widget_On_Content_Unset_Cb func)
3052 {
3053    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3054    item->on_content_unset_func = func;
3055 }
3056
3057 EAPI void
3058 _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3059                                    Elm_Widget_On_Text_Set_Cb func)
3060 {
3061    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3062    item->on_text_set_func = func;
3063 }
3064
3065 EAPI void
3066 _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3067                                    Elm_Widget_On_Text_Get_Cb func)
3068 {
3069    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3070    item->on_text_get_func = func;
3071 }
3072
3073 static void
3074 _smart_add(Evas_Object *obj)
3075 {
3076    Smart_Data *sd;
3077
3078    sd = calloc(1, sizeof(Smart_Data));
3079    if (!sd) return;
3080    sd->obj = obj;
3081    sd->x = sd->y = sd->w = sd->h = 0;
3082    sd->can_focus = 1;
3083    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3084    evas_object_smart_data_set(obj, sd);
3085 }
3086
3087 static Evas_Object *
3088 _newest_focus_order_get(Evas_Object  *obj,
3089                         unsigned int *newest_focus_order,
3090                         Eina_Bool     can_focus_only)
3091 {
3092    const Eina_List *l;
3093    Evas_Object *child, *ret, *best;
3094
3095    API_ENTRY return NULL;
3096
3097    if (!evas_object_visible_get(obj)
3098        || (elm_widget_disabled_get(obj))
3099        || (elm_widget_tree_unfocusable_get(obj)))
3100      return NULL;
3101
3102    best = NULL;
3103    if (*newest_focus_order < sd->focus_order)
3104      {
3105         *newest_focus_order = sd->focus_order;
3106         best = obj;
3107      }
3108    EINA_LIST_FOREACH(sd->subobjs, l, child)
3109      {
3110         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3111         if (!ret) continue;
3112         best = ret;
3113      }
3114    if (can_focus_only)
3115      {
3116         if ((!best) || (!elm_widget_can_focus_get(best)))
3117           return NULL;
3118      }
3119    return best;
3120 }
3121
3122 static void
3123 _if_focused_revert(Evas_Object *obj,
3124                    Eina_Bool    can_focus_only)
3125 {
3126    Evas_Object *top;
3127    Evas_Object *newest = NULL;
3128    unsigned int newest_focus_order = 0;
3129
3130    INTERNAL_ENTRY
3131
3132    if (!sd->focused) return;
3133    if (!sd->parent_obj) return;
3134
3135    top = elm_widget_top_get(sd->parent_obj);
3136    if (top)
3137      {
3138         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3139         if (newest)
3140           {
3141              elm_object_focus_set(newest, EINA_FALSE);
3142              elm_object_focus_set(newest, EINA_TRUE);
3143           }
3144      }
3145 }
3146
3147 static void
3148 _smart_del(Evas_Object *obj)
3149 {
3150    Evas_Object *sobj;
3151    Edje_Signal_Data *esd;
3152
3153    INTERNAL_ENTRY
3154
3155    if (sd->del_pre_func) sd->del_pre_func(obj);
3156    if (sd->resize_obj)
3157      {
3158         sobj = sd->resize_obj;
3159         sd->resize_obj = NULL;
3160         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3161         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3162         evas_object_del(sobj);
3163      }
3164    if (sd->hover_obj)
3165      {
3166         sobj = sd->hover_obj;
3167         sd->hover_obj = NULL;
3168         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3169         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3170         evas_object_del(sobj);
3171      }
3172    EINA_LIST_FREE(sd->subobjs, sobj)
3173      {
3174         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3175         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3176         evas_object_del(sobj);
3177      }
3178    eina_list_free(sd->tooltips); /* should be empty anyway */
3179    eina_list_free(sd->cursors); /* should be empty anyway */
3180    EINA_LIST_FREE(sd->edje_signals, esd)
3181      {
3182         eina_stringshare_del(esd->emission);
3183         eina_stringshare_del(esd->source);
3184         free(esd);
3185      }
3186    eina_list_free(sd->event_cb); /* should be empty anyway */
3187    if (sd->del_func) sd->del_func(obj);
3188    if (sd->style) eina_stringshare_del(sd->style);
3189    if (sd->type) eina_stringshare_del(sd->type);
3190    if (sd->theme) elm_theme_free(sd->theme);
3191    _if_focused_revert(obj, EINA_TRUE);
3192    free(sd);
3193 }
3194
3195 static void
3196 _smart_move(Evas_Object *obj,
3197             Evas_Coord   x,
3198             Evas_Coord   y)
3199 {
3200    INTERNAL_ENTRY
3201    sd->x = x;
3202    sd->y = y;
3203    _smart_reconfigure(sd);
3204 }
3205
3206 static void
3207 _smart_resize(Evas_Object *obj,
3208               Evas_Coord   w,
3209               Evas_Coord   h)
3210 {
3211    INTERNAL_ENTRY
3212    sd->w = w;
3213    sd->h = h;
3214    _smart_reconfigure(sd);
3215 }
3216
3217 static void
3218 _smart_show(Evas_Object *obj)
3219 {
3220    Eina_List *list;
3221    Evas_Object *o;
3222    INTERNAL_ENTRY
3223    if ((list = evas_object_smart_members_get(obj)))
3224      {
3225         EINA_LIST_FREE(list, o)
3226           {
3227              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3228              evas_object_show(o);
3229           }
3230      }
3231 }
3232
3233 static void
3234 _smart_hide(Evas_Object *obj)
3235 {
3236    Eina_List *list;
3237    Evas_Object *o;
3238    INTERNAL_ENTRY
3239
3240    list = evas_object_smart_members_get(obj);
3241    EINA_LIST_FREE(list, o)
3242      {
3243         if (evas_object_data_get(o, "_elm_leaveme")) continue;
3244         evas_object_hide(o);
3245      }
3246 }
3247
3248 static void
3249 _smart_color_set(Evas_Object *obj,
3250                  int          r,
3251                  int          g,
3252                  int          b,
3253                  int          a)
3254 {
3255    Eina_List *list;
3256    Evas_Object *o;
3257    INTERNAL_ENTRY
3258    if ((list = evas_object_smart_members_get(obj)))
3259      {
3260         EINA_LIST_FREE(list, o)
3261           {
3262              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3263              evas_object_color_set(o, r, g, b, a);
3264           }
3265      }
3266 }
3267
3268 static void
3269 _smart_clip_set(Evas_Object *obj,
3270                 Evas_Object *clip)
3271 {
3272    Eina_List *list;
3273    Evas_Object *o;
3274    INTERNAL_ENTRY
3275    if ((list = evas_object_smart_members_get(obj)))
3276      {
3277         EINA_LIST_FREE(list, o)
3278           {
3279              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3280              evas_object_clip_set(o, clip);
3281           }
3282      }
3283 }
3284
3285 static void
3286 _smart_clip_unset(Evas_Object *obj)
3287 {
3288    Eina_List *list;
3289    Evas_Object *o;
3290    INTERNAL_ENTRY
3291    if ((list = evas_object_smart_members_get(obj)))
3292      {
3293         EINA_LIST_FREE(list, o)
3294           {
3295              if (evas_object_data_get(o, "_elm_leaveme")) continue;
3296              evas_object_clip_unset(o);
3297           }
3298      }
3299 }
3300
3301 static void
3302 _smart_calculate(Evas_Object *obj)
3303 {
3304    INTERNAL_ENTRY
3305    if (sd->changed_func) sd->changed_func(obj);
3306 }
3307
3308 /* never need to touch this */
3309 static void
3310 _smart_init(void)
3311 {
3312    if (_e_smart) return;
3313    {
3314       static const Evas_Smart_Class sc =
3315       {
3316          SMART_NAME,
3317          EVAS_SMART_CLASS_VERSION,
3318          _smart_add,
3319          _smart_del,
3320          _smart_move,
3321          _smart_resize,
3322          _smart_show,
3323          _smart_hide,
3324          _smart_color_set,
3325          _smart_clip_set,
3326          _smart_clip_unset,
3327          _smart_calculate,
3328          NULL,
3329          NULL,
3330          NULL,
3331          NULL,
3332          NULL,
3333          NULL
3334       };
3335       _e_smart = evas_smart_class_new(&sc);
3336    }
3337 }
3338
3339 /* happy debug functions */
3340 #ifdef ELM_DEBUG
3341 static void
3342 _sub_obj_tree_dump(const Evas_Object *obj,
3343                    int                lvl)
3344 {
3345    int i;
3346
3347    for (i = 0; i < lvl * 3; i++)
3348      putchar(' ');
3349
3350    if (_elm_widget_is(obj))
3351      {
3352         Eina_List *l;
3353         INTERNAL_ENTRY
3354         printf("+ %s(%p)\n",
3355                sd->type,
3356                obj);
3357         if (sd->resize_obj)
3358           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3359         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3360           {
3361              if (obj != sd->resize_obj)
3362                _sub_obj_tree_dump(obj, lvl + 1);
3363           }
3364      }
3365    else
3366      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3367 }
3368
3369 static void
3370 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3371                        FILE              *output)
3372 {
3373    if (!_elm_widget_is(obj))
3374      return;
3375    INTERNAL_ENTRY
3376
3377    Eina_Bool visible = evas_object_visible_get(obj);
3378    Eina_Bool disabled = elm_widget_disabled_get(obj);
3379    Eina_Bool focused = elm_widget_focus_get(obj);
3380    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3381
3382    if (sd->parent_obj)
3383      {
3384         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3385
3386         if (focused)
3387           fprintf(output, ", style=bold");
3388
3389         if (!visible)
3390           fprintf(output, ", color=gray28");
3391
3392         fprintf(output, " ];\n");
3393      }
3394
3395    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3396                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3397            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3398            sd->focus_order);
3399
3400    if (focused)
3401      fprintf(output, ", style=bold");
3402
3403    if (!visible)
3404      fprintf(output, ", fontcolor=gray28");
3405
3406    if ((disabled) || (!visible))
3407      fprintf(output, ", color=gray");
3408
3409    fprintf(output, " ];\n");
3410
3411    Eina_List *l;
3412    Evas_Object *o;
3413    EINA_LIST_FOREACH(sd->subobjs, l, o)
3414      _sub_obj_tree_dot_dump(o, output);
3415 }
3416 #endif
3417
3418 EAPI void
3419 elm_widget_tree_dump(const Evas_Object *top)
3420 {
3421 #ifdef ELM_DEBUG
3422    _sub_obj_tree_dump(top, 0);
3423 #else
3424    return;
3425    (void)top;
3426 #endif
3427 }
3428
3429 EAPI void
3430 elm_widget_tree_dot_dump(const Evas_Object *top,
3431                          FILE              *output)
3432 {
3433 #ifdef ELM_DEBUG
3434    if (!_elm_widget_is(top))
3435      return;
3436    fprintf(output, "graph " " { node [shape=record];\n");
3437    _sub_obj_tree_dot_dump(top, output);
3438    fprintf(output, "}\n");
3439 #else
3440    return;
3441    (void)top;
3442    (void)output;
3443 #endif
3444 }