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