Merge branch 'master' into svn_merge
[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->disabled) return;
1756         if (sd->focused) break;
1757         parent = o;
1758      }
1759    if (!elm_widget_parent_get(parent))
1760      elm_widget_focused_object_clear(parent);
1761    else
1762      {
1763         parent = elm_widget_parent_get(parent);
1764         sd = evas_object_smart_data_get(parent);
1765         if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
1766           elm_widget_focused_object_clear(sd->resize_obj);
1767         else
1768           {
1769              const Eina_List *l;
1770              Evas_Object *child;
1771              EINA_LIST_FOREACH(sd->subobjs, l, child)
1772                {
1773                   if (elm_widget_focus_get(child))
1774                     {
1775                        elm_widget_focused_object_clear(child);
1776                        break;
1777                     }
1778                }
1779           }
1780      }
1781    _parent_focus(obj);
1782    return;
1783 }
1784
1785 EAPI void
1786 elm_widget_activate(Evas_Object *obj)
1787 {
1788    API_ENTRY return;
1789    elm_widget_change(obj);
1790    if (sd->activate_func) sd->activate_func(obj);
1791 }
1792
1793 EAPI void
1794 elm_widget_change(Evas_Object *obj)
1795 {
1796    API_ENTRY return;
1797    elm_widget_change(elm_widget_parent_get(obj));
1798    if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
1799 }
1800
1801 EAPI void
1802 elm_widget_disabled_set(Evas_Object *obj,
1803                         Eina_Bool    disabled)
1804 {
1805    API_ENTRY return;
1806
1807    if (sd->disabled == disabled) return;
1808    sd->disabled = !!disabled;
1809    if (sd->focused)
1810      {
1811         Evas_Object *o, *parent;
1812         parent = obj;
1813         o = elm_widget_parent_get(parent);
1814         if (!o)
1815           elm_widget_focused_object_clear(parent);
1816         else
1817           {
1818              parent = o;
1819              for (;;)
1820                {
1821                   o = elm_widget_parent_get(parent);
1822                   if (!o) break;
1823                   parent = o;
1824                }
1825              elm_widget_focus_cycle(parent, ELM_FOCUS_NEXT);
1826           }
1827      }
1828    if (sd->disable_func) sd->disable_func(obj);
1829 }
1830
1831 EAPI Eina_Bool
1832 elm_widget_disabled_get(const Evas_Object *obj)
1833 {
1834    API_ENTRY return 0;
1835    return sd->disabled;
1836 }
1837
1838 EAPI void
1839 elm_widget_show_region_set(Evas_Object *obj,
1840                            Evas_Coord   x,
1841                            Evas_Coord   y,
1842                            Evas_Coord   w,
1843                            Evas_Coord   h,
1844                            Eina_Bool    forceshow)
1845 {
1846    Evas_Object *parent_obj, *child_obj;
1847    Evas_Coord px, py, cx, cy;
1848
1849    API_ENTRY return;
1850    if (!forceshow && (x == sd->rx) && (y == sd->ry)
1851             && (w == sd->rw) && (h == sd->rh)) return;
1852    sd->rx = x;
1853    sd->ry = y;
1854    sd->rw = w;
1855    sd->rh = h;
1856    if (sd->on_show_region_func)
1857      sd->on_show_region_func(sd->on_show_region_data, obj);
1858
1859    do
1860      {
1861         parent_obj = sd->parent_obj;
1862         child_obj = sd->obj;
1863         if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
1864         sd = evas_object_smart_data_get(parent_obj);
1865         if (!sd) break;
1866
1867         evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
1868         evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
1869
1870         x += (cx - px);
1871         y += (cy - py);
1872         sd->rx = x;
1873         sd->ry = y;
1874         sd->rw = w;
1875         sd->rh = h;
1876
1877         if (sd->on_show_region_func)
1878           {
1879              sd->on_show_region_func(sd->on_show_region_data, parent_obj);
1880           }
1881      }
1882    while (parent_obj);
1883 }
1884
1885 EAPI void
1886 elm_widget_show_region_get(const Evas_Object *obj,
1887                            Evas_Coord        *x,
1888                            Evas_Coord        *y,
1889                            Evas_Coord        *w,
1890                            Evas_Coord        *h)
1891 {
1892    API_ENTRY return;
1893    if (x) *x = sd->rx;
1894    if (y) *y = sd->ry;
1895    if (w) *w = sd->rw;
1896    if (h) *h = sd->rh;
1897 }
1898
1899 /**
1900  * @internal
1901  *
1902  * Get the focus region of the given widget.
1903  *
1904  * The focus region is the area of a widget that should brought into the
1905  * visible area when the widget is focused. Mostly used to show the part of
1906  * an entry where the cursor is, for example. The area returned is relative
1907  * to the object @p obj.
1908  * If the @p obj doesn't have the proper on_focus_region_hook set, this
1909  * function will return the full size of the object.
1910  *
1911  * @param obj The widget object
1912  * @param x Where to store the x coordinate of the area
1913  * @param y Where to store the y coordinate of the area
1914  * @param w Where to store the width of the area
1915  * @param h Where to store the height of the area
1916  *
1917  * @ingroup Widget
1918  */
1919 EAPI void
1920 elm_widget_focus_region_get(const Evas_Object *obj,
1921                             Evas_Coord        *x,
1922                             Evas_Coord        *y,
1923                             Evas_Coord        *w,
1924                             Evas_Coord        *h)
1925 {
1926    Smart_Data *sd;
1927
1928    if (!obj) return;
1929
1930    sd = evas_object_smart_data_get(obj);
1931    if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
1932      {
1933         evas_object_geometry_get(obj, NULL, NULL, w, h);
1934         if (x) *x = 0;
1935         if (y) *y = 0;
1936         return;
1937      }
1938    sd->on_focus_region_func(obj, x, y, w, h);
1939 }
1940
1941 EAPI void
1942 elm_widget_scroll_hold_push(Evas_Object *obj)
1943 {
1944    API_ENTRY return;
1945    sd->scroll_hold++;
1946    if (sd->scroll_hold == 1)
1947      evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
1948    if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
1949    // FIXME: on delete/reparent hold pop
1950 }
1951
1952 EAPI void
1953 elm_widget_scroll_hold_pop(Evas_Object *obj)
1954 {
1955    API_ENTRY return;
1956    sd->scroll_hold--;
1957    if (sd->scroll_hold < 0) sd->scroll_hold = 0;
1958    if (!sd->scroll_hold)
1959      evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
1960    if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
1961 }
1962
1963 EAPI int
1964 elm_widget_scroll_hold_get(const Evas_Object *obj)
1965 {
1966    API_ENTRY return 0;
1967    return sd->scroll_hold;
1968 }
1969
1970 EAPI void
1971 elm_widget_scroll_freeze_push(Evas_Object *obj)
1972 {
1973    API_ENTRY return;
1974    sd->scroll_freeze++;
1975    if (sd->scroll_freeze == 1)
1976      evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
1977    if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
1978    // FIXME: on delete/reparent freeze pop
1979 }
1980
1981 EAPI void
1982 elm_widget_scroll_freeze_pop(Evas_Object *obj)
1983 {
1984    API_ENTRY return;
1985    sd->scroll_freeze--;
1986    if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
1987    if (!sd->scroll_freeze)
1988      evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
1989    if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
1990 }
1991
1992 EAPI int
1993 elm_widget_scroll_freeze_get(const Evas_Object *obj)
1994 {
1995    API_ENTRY return 0;
1996    return sd->scroll_freeze;
1997 }
1998
1999 EAPI void
2000 elm_widget_scale_set(Evas_Object *obj,
2001                      double       scale)
2002 {
2003    API_ENTRY return;
2004    if (scale <= 0.0) scale = 0.0;
2005    if (sd->scale != scale)
2006      {
2007         sd->scale = scale;
2008         elm_widget_theme(obj);
2009      }
2010 }
2011
2012 EAPI double
2013 elm_widget_scale_get(const Evas_Object *obj)
2014 {
2015    API_ENTRY return 1.0;
2016    // FIXME: save walking up the tree by storing/caching parent scale
2017    if (sd->scale == 0.0)
2018      {
2019         if (sd->parent_obj)
2020           return elm_widget_scale_get(sd->parent_obj);
2021         else
2022           return 1.0;
2023      }
2024    return sd->scale;
2025 }
2026
2027 EAPI void
2028 elm_widget_theme_set(Evas_Object *obj,
2029                      Elm_Theme   *th)
2030 {
2031    API_ENTRY return;
2032    if (sd->theme != th)
2033      {
2034         if (sd->theme) elm_theme_free(sd->theme);
2035         sd->theme = th;
2036         if (th) th->ref++;
2037         elm_widget_theme(obj);
2038      }
2039 }
2040
2041 EAPI void
2042 elm_widget_text_part_set(Evas_Object *obj, const char *item, const char *label)
2043 {
2044    API_ENTRY return;
2045
2046    if (!sd->on_text_set_func)
2047      return;
2048
2049    sd->on_text_set_func(obj, item, label);
2050 }
2051
2052 EAPI const char *
2053 elm_widget_text_part_get(const Evas_Object *obj, const char *item)
2054 {
2055    API_ENTRY return NULL;
2056
2057    if (!sd->on_text_get_func)
2058      return NULL;
2059
2060    return sd->on_text_get_func(obj, item);
2061 }
2062
2063 EAPI Elm_Theme *
2064 elm_widget_theme_get(const Evas_Object *obj)
2065 {
2066    API_ENTRY return NULL;
2067    if (!sd->theme)
2068      {
2069         if (sd->parent_obj)
2070           return elm_widget_theme_get(sd->parent_obj);
2071         else
2072           return NULL;
2073      }
2074    return sd->theme;
2075 }
2076
2077 EAPI void
2078 elm_widget_style_set(Evas_Object *obj,
2079                      const char  *style)
2080 {
2081    API_ENTRY return;
2082
2083    if (eina_stringshare_replace(&sd->style, style))
2084      elm_widget_theme(obj);
2085 }
2086
2087 EAPI const char *
2088 elm_widget_style_get(const Evas_Object *obj)
2089 {
2090    API_ENTRY return NULL;
2091    if (sd->style) return sd->style;
2092    return "default";
2093 }
2094
2095 EAPI void
2096 elm_widget_type_set(Evas_Object *obj,
2097                     const char  *type)
2098 {
2099    API_ENTRY return;
2100    eina_stringshare_replace(&sd->type, type);
2101 }
2102
2103 EAPI const char *
2104 elm_widget_type_get(const Evas_Object *obj)
2105 {
2106    API_ENTRY return NULL;
2107    if (sd->type) return sd->type;
2108    return "";
2109 }
2110
2111 EAPI void
2112 elm_widget_tooltip_add(Evas_Object *obj,
2113                        Elm_Tooltip *tt)
2114 {
2115    API_ENTRY return;
2116    sd->tooltips = eina_list_append(sd->tooltips, tt);
2117 }
2118
2119 EAPI void
2120 elm_widget_tooltip_del(Evas_Object *obj,
2121                        Elm_Tooltip *tt)
2122 {
2123    API_ENTRY return;
2124    sd->tooltips = eina_list_remove(sd->tooltips, tt);
2125 }
2126
2127 EAPI void
2128 elm_widget_cursor_add(Evas_Object *obj,
2129                       Elm_Cursor  *cur)
2130 {
2131    API_ENTRY return;
2132    sd->cursors = eina_list_append(sd->cursors, cur);
2133 }
2134
2135 EAPI void
2136 elm_widget_cursor_del(Evas_Object *obj,
2137                       Elm_Cursor  *cur)
2138 {
2139    API_ENTRY return;
2140    sd->cursors = eina_list_remove(sd->cursors, cur);
2141 }
2142
2143 EAPI void
2144 elm_widget_drag_lock_x_set(Evas_Object *obj,
2145                            Eina_Bool    lock)
2146 {
2147    API_ENTRY return;
2148    if (sd->drag_x_locked == lock) return;
2149    sd->drag_x_locked = lock;
2150    if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2151    else _propagate_x_drag_lock(obj, -1);
2152 }
2153
2154 EAPI void
2155 elm_widget_drag_lock_y_set(Evas_Object *obj,
2156                            Eina_Bool    lock)
2157 {
2158    API_ENTRY return;
2159    if (sd->drag_y_locked == lock) return;
2160    sd->drag_y_locked = lock;
2161    if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2162    else _propagate_y_drag_lock(obj, -1);
2163 }
2164
2165 EAPI Eina_Bool
2166 elm_widget_drag_lock_x_get(const Evas_Object *obj)
2167 {
2168    API_ENTRY return EINA_FALSE;
2169    return sd->drag_x_locked;
2170 }
2171
2172 EAPI Eina_Bool
2173 elm_widget_drag_lock_y_get(const Evas_Object *obj)
2174 {
2175    API_ENTRY return EINA_FALSE;
2176    return sd->drag_y_locked;
2177 }
2178
2179 EAPI int
2180 elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2181 {
2182    API_ENTRY return 0;
2183    return sd->child_drag_x_locked;
2184 }
2185
2186 EAPI int
2187 elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2188 {
2189    API_ENTRY return 0;
2190    return sd->child_drag_y_locked;
2191 }
2192
2193 EAPI Eina_Bool
2194 elm_widget_theme_object_set(Evas_Object *obj,
2195                             Evas_Object *edj,
2196                             const char  *wname,
2197                             const char  *welement,
2198                             const char  *wstyle)
2199 {
2200    API_ENTRY return EINA_FALSE;
2201    return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2202 }
2203
2204 EAPI Eina_Bool
2205 elm_widget_type_check(const Evas_Object *obj,
2206                       const char        *type)
2207 {
2208    const char *provided, *expected = "(unknown)";
2209    static int abort_on_warn = -1;
2210    provided = elm_widget_type_get(obj);
2211    if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2212    if (type) expected = type;
2213    if ((!provided) || (!provided[0]))
2214      {
2215         provided = evas_object_type_get(obj);
2216         if ((!provided) || (!provided[0]))
2217           provided = "(unknown)";
2218      }
2219    ERR("Passing Object: %p, of type: '%s' when expecting type: '%s'", obj, provided, expected);
2220    if (abort_on_warn == -1)
2221      {
2222         if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2223         else abort_on_warn = 0;
2224      }
2225    if (abort_on_warn == 1) abort();
2226    return EINA_FALSE;
2227 }
2228
2229 /**
2230  * @internal
2231  *
2232  * Split string in words
2233  *
2234  * @param str Source string
2235  * @return List of const words
2236  *
2237  * @see elm_widget_stringlist_free()
2238  * @ingroup Widget
2239  */
2240 EAPI Eina_List *
2241 elm_widget_stringlist_get(const char *str)
2242 {
2243    Eina_List *list = NULL;
2244    const char *s, *b;
2245    if (!str) return NULL;
2246    for (b = s = str; 1; s++)
2247      {
2248         if ((*s == ' ') || (!*s))
2249           {
2250              char *t = malloc(s - b + 1);
2251              if (t)
2252                {
2253                   strncpy(t, b, s - b);
2254                   t[s - b] = 0;
2255                   list = eina_list_append(list, eina_stringshare_add(t));
2256                   free(t);
2257                }
2258              b = s + 1;
2259           }
2260         if (!*s) break;
2261      }
2262    return list;
2263 }
2264
2265 EAPI void
2266 elm_widget_stringlist_free(Eina_List *list)
2267 {
2268    const char *s;
2269    EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2270 }
2271
2272 EAPI void
2273 elm_widget_focus_hide_handle(Evas_Object *obj)
2274 {
2275    _if_focused_revert(obj, EINA_TRUE);
2276 }
2277
2278 EAPI void
2279 elm_widget_focus_mouse_down_handle(Evas_Object *obj)
2280 {
2281    Evas_Object *o = obj;
2282    do
2283      {
2284         if (_elm_widget_is(o)) break;
2285         o = evas_object_smart_parent_get(o);
2286      }
2287    while (o);
2288    if (!o) return;
2289    if (!_is_focusable(o)) return;
2290    elm_widget_focus_steal(o);
2291 }
2292
2293 /**
2294  * @internal
2295  *
2296  * Allocate a new Elm_Widget_Item-derived structure.
2297  *
2298  * The goal of this structure is to provide common ground for actions
2299  * that a widget item have, such as the owner widget, callback to
2300  * notify deletion, data pointer and maybe more.
2301  *
2302  * @param widget the owner widget that holds this item, must be an elm_widget!
2303  * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2304  *        be used to allocate memory.
2305  *
2306  * @return allocated memory that is already zeroed out, or NULL on errors.
2307  *
2308  * @see elm_widget_item_new() convenience macro.
2309  * @see elm_widget_item_del() to release memory.
2310  * @ingroup Widget
2311  */
2312 EAPI Elm_Widget_Item *
2313 _elm_widget_item_new(Evas_Object *widget,
2314                      size_t       alloc_size)
2315 {
2316    if (!_elm_widget_is(widget))
2317      return NULL;
2318
2319    Elm_Widget_Item *item;
2320
2321    EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2322    EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2323
2324    item = calloc(1, alloc_size);
2325    EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2326
2327    EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2328    item->widget = widget;
2329    return item;
2330 }
2331
2332 /**
2333  * @internal
2334  *
2335  * Releases widget item memory, calling back del_cb() if it exists.
2336  *
2337  * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2338  * to memory release. Note that elm_widget_item_pre_notify_del() calls
2339  * this function and then unset it, thus being useful for 2 step
2340  * cleanup whenever the del_cb may use any of the data that must be
2341  * deleted from item.
2342  *
2343  * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2344  * is presented!
2345  *
2346  * @param item a valid #Elm_Widget_Item to be deleted.
2347  * @see elm_widget_item_del() convenience macro.
2348  * @ingroup Widget
2349  */
2350 EAPI void
2351 _elm_widget_item_del(Elm_Widget_Item *item)
2352 {
2353    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2354
2355    if (item->del_cb)
2356      item->del_cb((void *)item->data, item->widget, item);
2357
2358    if (item->view)
2359      evas_object_del(item->view);
2360
2361    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2362    free(item);
2363 }
2364
2365 /**
2366  * @internal
2367  *
2368  * Notify object will be deleted without actually deleting it.
2369  *
2370  * This function will callback Elm_Widget_Item::del_cb if it is set
2371  * and then unset it so it is not called twice (ie: from
2372  * elm_widget_item_del()).
2373  *
2374  * @param item a valid #Elm_Widget_Item to be notified
2375  * @see elm_widget_item_pre_notify_del() convenience macro.
2376  * @ingroup Widget
2377  */
2378 EAPI void
2379 _elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2380 {
2381    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2382    if (!item->del_cb) return;
2383    item->del_cb((void *)item->data, item->widget, item);
2384    item->del_cb = NULL;
2385 }
2386
2387 /**
2388  * @internal
2389  *
2390  * Set the function to notify when item is being deleted.
2391  *
2392  * This function will complain if there was a callback set already,
2393  * however it will set the new one.
2394  *
2395  * The callback will be called from elm_widget_item_pre_notify_del()
2396  * or elm_widget_item_del() will be called with:
2397  *   - data: the Elm_Widget_Item::data value.
2398  *   - obj: the Elm_Widget_Item::widget evas object.
2399  *   - event_info: the item being deleted.
2400  *
2401  * @param item a valid #Elm_Widget_Item to be notified
2402  * @see elm_widget_item_del_cb_set() convenience macro.
2403  * @ingroup Widget
2404  */
2405 EAPI void
2406 _elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2407                             Evas_Smart_Cb    del_cb)
2408 {
2409    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2410
2411    if ((item->del_cb) && (item->del_cb != del_cb))
2412      WRN("You're replacing a previously set del_cb %p of item %p with %p",
2413          item->del_cb, item, del_cb);
2414
2415    item->del_cb = del_cb;
2416 }
2417
2418 /**
2419  * @internal
2420  *
2421  * Set user-data in this item.
2422  *
2423  * User data may be used to identify this item or just store any
2424  * application data. It is automatically given as the first parameter
2425  * of the deletion notify callback.
2426  *
2427  * @param item a valid #Elm_Widget_Item to store data in.
2428  * @param data user data to store.
2429  * @see elm_widget_item_del_cb_set() convenience macro.
2430  * @ingroup Widget
2431  */
2432 EAPI void
2433 _elm_widget_item_data_set(Elm_Widget_Item *item,
2434                           const void      *data)
2435 {
2436    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2437    if ((item->data) && (item->data != data))
2438      DBG("Replacing item %p data %p with %p", item, item->data, data);
2439    item->data = data;
2440 }
2441
2442 /**
2443  * @internal
2444  *
2445  * Retrieves user-data of this item.
2446  *
2447  * @param item a valid #Elm_Widget_Item to get data from.
2448  * @see elm_widget_item_data_set()
2449  * @ingroup Widget
2450  */
2451 EAPI void *
2452 _elm_widget_item_data_get(const Elm_Widget_Item *item)
2453 {
2454    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2455    return (void *)item->data;
2456 }
2457
2458 typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
2459
2460 struct _Elm_Widget_Item_Tooltip
2461 {
2462    Elm_Widget_Item            *item;
2463    Elm_Tooltip_Item_Content_Cb func;
2464    Evas_Smart_Cb               del_cb;
2465    const void                 *data;
2466 };
2467
2468 static Evas_Object *
2469 _elm_widget_item_tooltip_label_create(void        *data,
2470                                       Evas_Object *obj,
2471                                       void        *item __UNUSED__)
2472 {
2473    Evas_Object *label = elm_label_add(obj);
2474    if (!label)
2475      return NULL;
2476    elm_object_style_set(label, "tooltip");
2477    elm_object_text_set(label, data);
2478    return label;
2479 }
2480
2481 static void
2482 _elm_widget_item_tooltip_label_del_cb(void        *data,
2483                                       Evas_Object *obj __UNUSED__,
2484                                       void        *event_info __UNUSED__)
2485 {
2486    eina_stringshare_del(data);
2487 }
2488
2489 /**
2490  * @internal
2491  *
2492  * Set the text to be shown in the widget item.
2493  *
2494  * @param item Target item
2495  * @param text The text to set in the content
2496  *
2497  * Setup the text as tooltip to object. The item can have only one tooltip,
2498  * so any previous tooltip data is removed.
2499  *
2500  * @ingroup Widget
2501  */
2502 EAPI void
2503 _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
2504                                   const char      *text)
2505 {
2506    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2507    EINA_SAFETY_ON_NULL_RETURN(text);
2508
2509    text = eina_stringshare_add(text);
2510    _elm_widget_item_tooltip_content_cb_set
2511      (item, _elm_widget_item_tooltip_label_create, text,
2512      _elm_widget_item_tooltip_label_del_cb);
2513 }
2514
2515 static Evas_Object *
2516 _elm_widget_item_tooltip_create(void        *data,
2517                                 Evas_Object *obj)
2518 {
2519    Elm_Widget_Item_Tooltip *wit = data;
2520    return wit->func((void *)wit->data, obj, wit->item);
2521 }
2522
2523 static void
2524 _elm_widget_item_tooltip_del_cb(void        *data,
2525                                 Evas_Object *obj,
2526                                 void        *event_info __UNUSED__)
2527 {
2528    Elm_Widget_Item_Tooltip *wit = data;
2529    if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
2530    free(wit);
2531 }
2532
2533 /**
2534  * @internal
2535  *
2536  * Set the content to be shown in the tooltip item
2537  *
2538  * Setup the tooltip to item. The item can have only one tooltip,
2539  * so any previous tooltip data is removed. @p func(with @p data) will
2540  * be called every time that need show the tooltip and it should
2541  * return a valid Evas_Object. This object is then managed fully by
2542  * tooltip system and is deleted when the tooltip is gone.
2543  *
2544  * @param item the widget item being attached a tooltip.
2545  * @param func the function used to create the tooltip contents.
2546  * @param data what to provide to @a func as callback data/context.
2547  * @param del_cb called when data is not needed anymore, either when
2548  *        another callback replaces @func, the tooltip is unset with
2549  *        elm_widget_item_tooltip_unset() or the owner @a item
2550  *        dies. This callback receives as the first parameter the
2551  *        given @a data, and @c event_info is the item.
2552  *
2553  * @ingroup Widget
2554  */
2555 EAPI void
2556 _elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item            *item,
2557                                         Elm_Tooltip_Item_Content_Cb func,
2558                                         const void                 *data,
2559                                         Evas_Smart_Cb               del_cb)
2560 {
2561    Elm_Widget_Item_Tooltip *wit;
2562
2563    ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
2564
2565    if (!func)
2566      {
2567         _elm_widget_item_tooltip_unset(item);
2568         return;
2569      }
2570
2571    wit = ELM_NEW(Elm_Widget_Item_Tooltip);
2572    if (!wit) goto error;
2573    wit->item = item;
2574    wit->func = func;
2575    wit->data = data;
2576    wit->del_cb = del_cb;
2577
2578    elm_object_sub_tooltip_content_cb_set
2579      (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
2580      _elm_widget_item_tooltip_del_cb);
2581
2582    return;
2583
2584 error_noitem:
2585    if (del_cb) del_cb((void *)data, NULL, item);
2586    return;
2587 error:
2588    if (del_cb) del_cb((void *)data, item->widget, item);
2589 }
2590
2591 /**
2592  * @internal
2593  *
2594  * Unset tooltip from item
2595  *
2596  * @param item widget item to remove previously set tooltip.
2597  *
2598  * Remove tooltip from item. The callback provided as del_cb to
2599  * elm_widget_item_tooltip_content_cb_set() will be called to notify
2600  * it is not used anymore.
2601  *
2602  * @see elm_widget_item_tooltip_content_cb_set()
2603  *
2604  * @ingroup Widget
2605  */
2606 EAPI void
2607 _elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
2608 {
2609    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2610    elm_object_tooltip_unset(item->view);
2611 }
2612
2613 /**
2614  * @internal
2615  *
2616  * Sets a different style for this item tooltip.
2617  *
2618  * @note before you set a style you should define a tooltip with
2619  *       elm_widget_item_tooltip_content_cb_set() or
2620  *       elm_widget_item_tooltip_text_set()
2621  *
2622  * @param item widget item with tooltip already set.
2623  * @param style the theme style to use (default, transparent, ...)
2624  *
2625  * @ingroup Widget
2626  */
2627 EAPI void
2628 _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
2629                                    const char      *style)
2630 {
2631    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2632    elm_object_tooltip_style_set(item->view, style);
2633 }
2634
2635 /**
2636  * @internal
2637  *
2638  * Get the style for this item tooltip.
2639  *
2640  * @param item widget item with tooltip already set.
2641  * @return style the theme style in use, defaults to "default". If the
2642  *         object does not have a tooltip set, then NULL is returned.
2643  *
2644  * @ingroup Widget
2645  */
2646 EAPI const char *
2647 _elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
2648 {
2649    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2650    return elm_object_tooltip_style_get(item->view);
2651 }
2652
2653 EAPI void
2654 _elm_widget_item_cursor_set(Elm_Widget_Item *item,
2655                             const char      *cursor)
2656 {
2657    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2658    elm_object_sub_cursor_set(item->view, item->widget, cursor);
2659 }
2660
2661 EAPI const char *
2662 _elm_widget_item_cursor_get(const Elm_Widget_Item *item)
2663 {
2664    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2665    return elm_object_cursor_get(item->view);
2666 }
2667
2668 EAPI void
2669 _elm_widget_item_cursor_unset(Elm_Widget_Item *item)
2670 {
2671    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2672    elm_object_cursor_unset(item->view);
2673 }
2674
2675 /**
2676  * @internal
2677  *
2678  * Sets a different style for this item cursor.
2679  *
2680  * @note before you set a style you should define a cursor with
2681  *       elm_widget_item_cursor_set()
2682  *
2683  * @param item widget item with cursor already set.
2684  * @param style the theme style to use (default, transparent, ...)
2685  *
2686  * @ingroup Widget
2687  */
2688 EAPI void
2689 _elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
2690                                   const char      *style)
2691 {
2692    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2693    elm_object_cursor_style_set(item->view, style);
2694 }
2695
2696 /**
2697  * @internal
2698  *
2699  * Get the style for this item cursor.
2700  *
2701  * @param item widget item with cursor already set.
2702  * @return style the theme style in use, defaults to "default". If the
2703  *         object does not have a cursor set, then NULL is returned.
2704  *
2705  * @ingroup Widget
2706  */
2707 EAPI const char *
2708 _elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
2709 {
2710    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
2711    return elm_object_cursor_style_get(item->view);
2712 }
2713
2714 /**
2715  * @internal
2716  *
2717  * Set if the cursor set should be searched on the theme or should use
2718  * the provided by the engine, only.
2719  *
2720  * @note before you set if should look on theme you should define a cursor
2721  * with elm_object_cursor_set(). By default it will only look for cursors
2722  * provided by the engine.
2723  *
2724  * @param item widget item with cursor already set.
2725  * @param engine_only boolean to define it cursors should be looked only
2726  * between the provided by the engine or searched on widget's theme as well.
2727  *
2728  * @ingroup Widget
2729  */
2730 EAPI void
2731 _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
2732                                         Eina_Bool        engine_only)
2733 {
2734    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2735    elm_object_cursor_engine_only_set(item->view, engine_only);
2736 }
2737
2738 /**
2739  * @internal
2740  *
2741  * Get the cursor engine only usage for this item cursor.
2742  *
2743  * @param item widget item with cursor already set.
2744  * @return engine_only boolean to define it cursors should be looked only
2745  * between the provided by the engine or searched on widget's theme as well. If
2746  *         the object does not have a cursor set, then EINA_FALSE is returned.
2747  *
2748  * @ingroup Widget
2749  */
2750 EAPI Eina_Bool
2751 _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
2752 {
2753    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
2754    return elm_object_cursor_engine_only_get(item->view);
2755 }
2756
2757 // smart object funcs
2758 static void
2759 _smart_reconfigure(Smart_Data *sd)
2760 {
2761    if (sd->resize_obj)
2762      {
2763         evas_object_move(sd->resize_obj, sd->x, sd->y);
2764         evas_object_resize(sd->resize_obj, sd->w, sd->h);
2765      }
2766    if (sd->hover_obj)
2767      {
2768         evas_object_move(sd->hover_obj, sd->x, sd->y);
2769         evas_object_resize(sd->hover_obj, sd->w, sd->h);
2770      }
2771 }
2772
2773 static void
2774 _smart_add(Evas_Object *obj)
2775 {
2776    Smart_Data *sd;
2777
2778    sd = calloc(1, sizeof(Smart_Data));
2779    if (!sd) return;
2780    sd->obj = obj;
2781    sd->x = sd->y = sd->w = sd->h = 0;
2782    sd->can_focus = 1;
2783    sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
2784    evas_object_smart_data_set(obj, sd);
2785 }
2786
2787 static Evas_Object *
2788 _newest_focus_order_get(Evas_Object  *obj,
2789                         unsigned int *newest_focus_order,
2790                         Eina_Bool     can_focus_only)
2791 {
2792    const Eina_List *l;
2793    Evas_Object *child, *ret, *best;
2794
2795    API_ENTRY return NULL;
2796
2797    if ((!evas_object_visible_get(obj)) || (elm_widget_disabled_get(obj)))
2798      return NULL;
2799
2800    best = NULL;
2801    if (*newest_focus_order < sd->focus_order)
2802      {
2803         *newest_focus_order = sd->focus_order;
2804         best = obj;
2805      }
2806    EINA_LIST_FOREACH(sd->subobjs, l, child)
2807      {
2808         ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
2809         if (!ret) continue;
2810         best = ret;
2811      }
2812    if (can_focus_only)
2813      {
2814         if ((!best) || (!elm_widget_can_focus_get(best)))
2815           return NULL;
2816      }
2817    return best;
2818 }
2819
2820 static void
2821 _if_focused_revert(Evas_Object *obj,
2822                    Eina_Bool    can_focus_only)
2823 {
2824    Evas_Object *top;
2825    Evas_Object *newest = NULL;
2826    unsigned int newest_focus_order = 0;
2827
2828    INTERNAL_ENTRY
2829
2830    if (!sd->focused) return;
2831    if (!sd->parent_obj) return;
2832
2833    top = elm_widget_top_get(sd->parent_obj);
2834    if (top)
2835      {
2836         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
2837         if (newest)
2838           {
2839              elm_object_unfocus(newest);
2840              elm_object_focus(newest);
2841           }
2842      }
2843 }
2844
2845 static void
2846 _smart_del(Evas_Object *obj)
2847 {
2848    Evas_Object *sobj;
2849    Edje_Signal_Data *esd;
2850
2851    INTERNAL_ENTRY
2852
2853    if (sd->del_pre_func) sd->del_pre_func(obj);
2854    if (sd->resize_obj)
2855      {
2856         sobj = sd->resize_obj;
2857         sd->resize_obj = NULL;
2858         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2859         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2860         evas_object_del(sobj);
2861      }
2862    if (sd->hover_obj)
2863      {
2864         sobj = sd->hover_obj;
2865         sd->hover_obj = NULL;
2866         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2867         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2868         evas_object_del(sobj);
2869      }
2870    EINA_LIST_FREE(sd->subobjs, sobj)
2871      {
2872         evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
2873         evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
2874         evas_object_del(sobj);
2875      }
2876    eina_list_free(sd->tooltips); /* should be empty anyway */
2877    eina_list_free(sd->cursors); /* should be empty anyway */
2878    EINA_LIST_FREE(sd->edje_signals, esd)
2879      {
2880         eina_stringshare_del(esd->emission);
2881         eina_stringshare_del(esd->source);
2882         free(esd);
2883      }
2884    eina_list_free(sd->event_cb); /* should be empty anyway */
2885    if (sd->del_func) sd->del_func(obj);
2886    if (sd->style) eina_stringshare_del(sd->style);
2887    if (sd->type) eina_stringshare_del(sd->type);
2888    if (sd->theme) elm_theme_free(sd->theme);
2889    _if_focused_revert(obj, EINA_TRUE);
2890    free(sd);
2891 }
2892
2893 static void
2894 _smart_move(Evas_Object *obj,
2895             Evas_Coord   x,
2896             Evas_Coord   y)
2897 {
2898    INTERNAL_ENTRY
2899    sd->x = x;
2900    sd->y = y;
2901    _smart_reconfigure(sd);
2902 }
2903
2904 static void
2905 _smart_resize(Evas_Object *obj,
2906               Evas_Coord   w,
2907               Evas_Coord   h)
2908 {
2909    INTERNAL_ENTRY
2910    sd->w = w;
2911    sd->h = h;
2912    _smart_reconfigure(sd);
2913 }
2914
2915 static void
2916 _smart_show(Evas_Object *obj)
2917 {
2918    Eina_List *list;
2919    Evas_Object *o;
2920    INTERNAL_ENTRY
2921    if ((list = evas_object_smart_members_get(obj)))
2922      {
2923         EINA_LIST_FREE(list, o)
2924           {
2925              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2926              evas_object_show(o);
2927           }
2928      }
2929 }
2930
2931 static void
2932 _smart_hide(Evas_Object *obj)
2933 {
2934    Eina_List *list;
2935    Evas_Object *o;
2936    INTERNAL_ENTRY
2937
2938    list = evas_object_smart_members_get(obj);
2939    EINA_LIST_FREE(list, o)
2940      {
2941         if (evas_object_data_get(o, "_elm_leaveme")) continue;
2942         evas_object_hide(o);
2943      }
2944 }
2945
2946 static void
2947 _smart_color_set(Evas_Object *obj,
2948                  int          r,
2949                  int          g,
2950                  int          b,
2951                  int          a)
2952 {
2953    Eina_List *list;
2954    Evas_Object *o;
2955    INTERNAL_ENTRY
2956    if ((list = evas_object_smart_members_get(obj)))
2957      {
2958         EINA_LIST_FREE(list, o)
2959           {
2960              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2961              evas_object_color_set(o, r, g, b, a);
2962           }
2963      }
2964 }
2965
2966 static void
2967 _smart_clip_set(Evas_Object *obj,
2968                 Evas_Object *clip)
2969 {
2970    Eina_List *list;
2971    Evas_Object *o;
2972    INTERNAL_ENTRY
2973    if ((list = evas_object_smart_members_get(obj)))
2974      {
2975         EINA_LIST_FREE(list, o)
2976           {
2977              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2978              evas_object_clip_set(o, clip);
2979           }
2980      }
2981 }
2982
2983 static void
2984 _smart_clip_unset(Evas_Object *obj)
2985 {
2986    Eina_List *list;
2987    Evas_Object *o;
2988    INTERNAL_ENTRY
2989    if ((list = evas_object_smart_members_get(obj)))
2990      {
2991         EINA_LIST_FREE(list, o)
2992           {
2993              if (evas_object_data_get(o, "_elm_leaveme")) continue;
2994              evas_object_clip_unset(o);
2995           }
2996      }
2997 }
2998
2999 static void
3000 _smart_calculate(Evas_Object *obj)
3001 {
3002    INTERNAL_ENTRY
3003    if (sd->changed_func) sd->changed_func(obj);
3004 }
3005
3006 /* never need to touch this */
3007 static void
3008 _smart_init(void)
3009 {
3010    if (_e_smart) return;
3011    {
3012       static const Evas_Smart_Class sc =
3013       {
3014          SMART_NAME,
3015          EVAS_SMART_CLASS_VERSION,
3016          _smart_add,
3017          _smart_del,
3018          _smart_move,
3019          _smart_resize,
3020          _smart_show,
3021          _smart_hide,
3022          _smart_color_set,
3023          _smart_clip_set,
3024          _smart_clip_unset,
3025          _smart_calculate,
3026          NULL,
3027          NULL,
3028          NULL,
3029          NULL,
3030          NULL,
3031          NULL
3032       };
3033       _e_smart = evas_smart_class_new(&sc);
3034    }
3035 }
3036
3037 /* happy debug functions */
3038 #ifdef ELM_DEBUG
3039 static void
3040 _sub_obj_tree_dump(const Evas_Object *obj,
3041                    int                lvl)
3042 {
3043    int i;
3044
3045    for (i = 0; i < lvl * 3; i++)
3046      putchar(' ');
3047
3048    if (_elm_widget_is(obj))
3049      {
3050         Eina_List *l;
3051         INTERNAL_ENTRY
3052         printf("+ %s(%p)\n",
3053                sd->type,
3054                obj);
3055         if (sd->resize_obj)
3056           _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3057         EINA_LIST_FOREACH(sd->subobjs, l, obj)
3058           {
3059              if (obj != sd->resize_obj)
3060                _sub_obj_tree_dump(obj, lvl + 1);
3061           }
3062      }
3063    else
3064      printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3065 }
3066
3067 static void
3068 _sub_obj_tree_dot_dump(const Evas_Object *obj,
3069                        FILE              *output)
3070 {
3071    if (!_elm_widget_is(obj))
3072      return;
3073    INTERNAL_ENTRY
3074
3075    Eina_Bool visible = evas_object_visible_get(obj);
3076    Eina_Bool disabled = elm_widget_disabled_get(obj);
3077    Eina_Bool focused = elm_widget_focus_get(obj);
3078    Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3079
3080    if (sd->parent_obj)
3081      {
3082         fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3083
3084         if (focused)
3085           fprintf(output, ", style=bold");
3086
3087         if (!visible)
3088           fprintf(output, ", color=gray28");
3089
3090         fprintf(output, " ];\n");
3091      }
3092
3093    fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3094                    "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3095            evas_object_name_get(obj), visible, disabled, focused, can_focus,
3096            sd->focus_order);
3097
3098    if (focused)
3099      fprintf(output, ", style=bold");
3100
3101    if (!visible)
3102      fprintf(output, ", fontcolor=gray28");
3103
3104    if ((disabled) || (!visible))
3105      fprintf(output, ", color=gray");
3106
3107    fprintf(output, " ];\n");
3108
3109    Eina_List *l;
3110    Evas_Object *o;
3111    EINA_LIST_FOREACH(sd->subobjs, l, o)
3112      _sub_obj_tree_dot_dump(o, output);
3113 }
3114 #endif
3115
3116 EAPI void
3117 elm_widget_tree_dump(const Evas_Object *top)
3118 {
3119 #ifdef ELM_DEBUG
3120    _sub_obj_tree_dump(top, 0);
3121 #else
3122    return;
3123    (void)top;
3124 #endif
3125 }
3126
3127 EAPI void
3128 elm_widget_tree_dot_dump(const Evas_Object *top,
3129                          FILE              *output)
3130 {
3131 #ifdef ELM_DEBUG
3132    if (!_elm_widget_is(top))
3133      return;
3134    fprintf(output, "graph " " { node [shape=record];\n");
3135    _sub_obj_tree_dot_dump(top, output);
3136    fprintf(output, "}\n");
3137 #else
3138    return;
3139    (void)top;
3140    (void)output;
3141 #endif
3142 }