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