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