tizen 2.4 release
[framework/uifw/elementary.git] / src / lib / elm_hover.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
7 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
8
9 #include <Elementary.h>
10
11 #include "elm_priv.h"
12 #include "elm_widget_hover.h"
13
14 #define MY_CLASS ELM_HOVER_CLASS
15
16 #define MY_CLASS_NAME "Elm_Hover"
17 #define MY_CLASS_NAME_LEGACY "elm_hover"
18
19 #define ELM_HOVER_PARTS_FOREACH unsigned int i; \
20   for (i = 0; i < sizeof(sd->subs) / sizeof(sd->subs[0]); i++)
21
22 #define _HOV_LEFT               (&(sd->subs[0]))
23 #define _HOV_TOP_LEFT           (&(sd->subs[1]))
24 #define _HOV_TOP                (&(sd->subs[2]))
25 #define _HOV_TOP_RIGHT          (&(sd->subs[2]))
26 #define _HOV_RIGHT              (&(sd->subs[4]))
27 #define _HOV_BOTTOM_RIGHT       (&(sd->subs[5]))
28 #define _HOV_BOTTOM             (&(sd->subs[6]))
29 #define _HOV_BOTTOM_LEFT        (&(sd->subs[7]))
30 #define _HOV_MIDDLE             (&(sd->subs[8]))
31
32 const Elm_Layout_Part_Alias_Description _content_aliases[] =
33 {
34    {"left", "elm.swallow.slot.left"},
35    {"top-left", "elm.swallow.slot.top-left"},
36    {"top", "elm.swallow.slot.top"},
37    {"top-right", "elm.swallow.slot.top-right"},
38    {"right", "elm.swallow.slot.right"},
39    {"bottom-right", "elm.swallow.slot.bottom-right"},
40    {"bottom", "elm.swallow.slot.bottom"},
41    {"bottom-left", "elm.swallow.slot.bottom-left"},
42    {"middle", "elm.swallow.slot.middle"},
43    {NULL, NULL}
44 };
45
46 #define ELM_PRIV_HOVER_SIGNALS(cmd) \
47    cmd(SIG_CLICKED, "clicked", "") \
48    cmd(SIG_DISMISSED, "dismissed", "") \
49    cmd(SIG_SMART_LOCATION_CHANGED, "smart,changed", "")
50
51 ELM_PRIV_HOVER_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
52
53 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
54    ELM_PRIV_HOVER_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
55    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
56    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
57    {NULL, NULL}
58 };
59 #undef ELM_PRIV_HOVER_SIGNALS
60
61 static void
62 _parent_move_cb(void *data,
63                 Evas *e EINA_UNUSED,
64                 Evas_Object *obj EINA_UNUSED,
65                 void *event_info EINA_UNUSED)
66 {
67    elm_layout_sizing_eval(data);
68 }
69
70 static void
71 _parent_resize_cb(void *data,
72                   Evas *e EINA_UNUSED,
73                   Evas_Object *obj EINA_UNUSED,
74                   void *event_info EINA_UNUSED)
75 {
76    elm_layout_sizing_eval(data);
77 }
78
79 static void
80 _parent_show_cb(void *data EINA_UNUSED,
81                 Evas *e EINA_UNUSED,
82                 Evas_Object *obj EINA_UNUSED,
83                 void *event_info EINA_UNUSED)
84 {
85 }
86
87 static void
88 _parent_hide_cb(void *data,
89                 Evas *e EINA_UNUSED,
90                 Evas_Object *obj EINA_UNUSED,
91                 void *event_info EINA_UNUSED)
92 {
93    evas_object_hide(data);
94 }
95
96 static void
97 _parent_del_cb(void *data,
98                Evas *e EINA_UNUSED,
99                Evas_Object *obj EINA_UNUSED,
100                void *event_info EINA_UNUSED)
101 {
102    elm_hover_parent_set(data, NULL);
103    elm_layout_sizing_eval(data);
104 }
105
106 static void
107 _elm_hover_parent_detach(Evas_Object *obj)
108 {
109    ELM_HOVER_DATA_GET(obj, sd);
110
111    if (sd->parent)
112      {
113         evas_object_event_callback_del_full
114           (sd->parent, EVAS_CALLBACK_MOVE, _parent_move_cb, obj);
115         evas_object_event_callback_del_full
116           (sd->parent, EVAS_CALLBACK_RESIZE, _parent_resize_cb, obj);
117         evas_object_event_callback_del_full
118           (sd->parent, EVAS_CALLBACK_SHOW, _parent_show_cb, obj);
119         evas_object_event_callback_del_full
120           (sd->parent, EVAS_CALLBACK_HIDE, _parent_hide_cb, obj);
121         evas_object_event_callback_del_full
122           (sd->parent, EVAS_CALLBACK_DEL, _parent_del_cb, obj);
123      }
124 }
125
126 static void
127 _elm_hover_left_space_calc(Elm_Hover_Data *sd,
128                            Evas_Coord *spc_l,
129                            Evas_Coord *spc_t,
130                            Evas_Coord *spc_r,
131                            Evas_Coord *spc_b)
132 {
133    Evas_Coord x = 0, y = 0, w = 0, h = 0, x2 = 0, y2 = 0, w2 = 0, h2 = 0;
134
135    if (sd->parent)
136      {
137         evas_object_geometry_get(sd->parent, &x, &y, &w, &h);
138         if (eo_isa(sd->parent, ELM_WIN_CLASS))
139           {
140              x = 0;
141              y = 0;
142           }
143      }
144    if (sd->target) evas_object_geometry_get(sd->target, &x2, &y2, &w2, &h2);
145
146    *spc_l = x2 - x;
147    *spc_r = (x + w) - (x2 + w2);
148    if (*spc_l < 0) *spc_l = 0;
149    if (*spc_r < 0) *spc_r = 0;
150
151    *spc_t = y2 - y;
152    *spc_b = (y + h) - (y2 + h2);
153    if (*spc_t < 0) *spc_t = 0;
154    if (*spc_b < 0) *spc_b = 0;
155 }
156
157 static Content_Info *
158 _elm_hover_smart_content_location_get(Elm_Hover_Data *sd,
159                                       Evas_Coord spc_l,
160                                       Evas_Coord spc_t,
161                                       Evas_Coord spc_r,
162                                       Evas_Coord spc_b)
163 {
164    Evas_Coord c_w = 0, c_h = 0, mid_w, mid_h;
165    int max;
166
167    evas_object_size_hint_min_get(sd->smt_sub->obj, &c_w, &c_h);
168    mid_w = c_w / 2;
169    mid_h = c_h / 2;
170
171    if (spc_l > spc_r) goto left;
172
173    max = MAX(spc_t, spc_r);
174    max = MAX(max, spc_b);
175
176    if (max == spc_t)
177      {
178         if (mid_w > spc_l) return _HOV_TOP_RIGHT;
179
180         return _HOV_TOP;
181      }
182
183    if (max == spc_r)
184      {
185         if (mid_h > spc_t) return _HOV_BOTTOM_RIGHT;
186         else if (mid_h > spc_b)
187           return _HOV_TOP_RIGHT;
188
189         return _HOV_RIGHT;
190      }
191
192    if (mid_h > spc_l)
193      return _HOV_BOTTOM_RIGHT;
194
195    return _HOV_BOTTOM;
196
197 left:
198    max = MAX(spc_t, spc_l);
199    max = MAX(max, spc_b);
200
201    if (max == spc_t)
202      {
203         if (mid_w > spc_r) return _HOV_TOP_LEFT;
204
205         return _HOV_TOP;
206      }
207
208    if (max == spc_l)
209      {
210         if (mid_h > spc_t) return _HOV_BOTTOM_LEFT;
211         else if (mid_h > spc_b)
212           return _HOV_TOP_LEFT;
213
214         return _HOV_LEFT;
215      }
216
217    if (mid_h > spc_r) return _HOV_BOTTOM_LEFT;
218
219    return _HOV_BOTTOM;
220 }
221
222 static void
223 _elm_hover_smt_sub_re_eval(Evas_Object *obj)
224 {
225    Evas_Coord spc_l, spc_r, spc_t, spc_b;
226    Content_Info *prev;
227    Evas_Object *sub;
228    char buf[1024];
229
230    ELM_HOVER_DATA_GET(obj, sd);
231
232    if (!sd->smt_sub) return;
233    prev = sd->smt_sub;
234
235    _elm_hover_left_space_calc(sd, &spc_l, &spc_t, &spc_r, &spc_b);
236    elm_layout_content_unset(obj, sd->smt_sub->swallow);
237
238    sub = sd->smt_sub->obj;
239
240    sd->smt_sub->obj = NULL;
241
242    sd->smt_sub =
243      _elm_hover_smart_content_location_get(sd, spc_l, spc_t, spc_r, spc_b);
244
245    sd->smt_sub->obj = sub;
246
247    if (sd->smt_sub != prev)
248      evas_object_smart_callback_call
249        (obj, SIG_SMART_LOCATION_CHANGED, (void *)sd->smt_sub->swallow);
250
251    if (elm_widget_mirrored_get(obj))
252      {
253         if (sd->smt_sub == _HOV_BOTTOM_LEFT) sd->smt_sub = _HOV_BOTTOM_RIGHT;
254         else if (sd->smt_sub == _HOV_BOTTOM_RIGHT)
255           sd->smt_sub = _HOV_BOTTOM_LEFT;
256         else if (sd->smt_sub == _HOV_RIGHT)
257           sd->smt_sub = _HOV_LEFT;
258         else if (sd->smt_sub == _HOV_LEFT)
259           sd->smt_sub = _HOV_RIGHT;
260         else if (sd->smt_sub == _HOV_TOP_RIGHT)
261           sd->smt_sub = _HOV_TOP_LEFT;
262         else if (sd->smt_sub == _HOV_TOP_LEFT)
263           sd->smt_sub = _HOV_TOP_RIGHT;
264      }
265
266    snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", sd->smt_sub->swallow);
267    elm_layout_content_set(obj, buf, sd->smt_sub->obj);
268 }
269
270 static void
271 _hov_show_do(Evas_Object *obj)
272 {
273    ELM_HOVER_DATA_GET(obj, sd);
274
275    elm_layout_signal_emit(obj, "elm,action,show", "elm");
276
277    ELM_HOVER_PARTS_FOREACH
278    {
279       char buf[1024];
280
281       if (sd->subs[i].obj)
282         {
283            snprintf
284              (buf, sizeof(buf), "elm,action,slot,%s,show",
285              sd->subs[i].swallow);
286
287            elm_layout_signal_emit(obj, buf, "elm");
288         }
289    }
290 }
291
292 EOLIAN static Eina_Bool
293 _elm_hover_elm_widget_theme_apply(Eo *obj, Elm_Hover_Data *sd)
294 {
295    Eina_Bool int_ret = EINA_FALSE;
296    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
297    if (!int_ret) return EINA_FALSE;
298
299    if (sd->smt_sub) _elm_hover_smt_sub_re_eval(obj);
300
301    elm_layout_sizing_eval(obj);
302
303    if (evas_object_visible_get(obj)) _hov_show_do(obj);
304
305    return EINA_TRUE;
306 }
307
308 EOLIAN static void
309 _elm_hover_elm_layout_sizing_eval(Eo *obj, Elm_Hover_Data *sd)
310 {
311    Evas_Coord ofs_x, x = 0, y = 0, w = 0, h = 0, x2 = 0,
312               y2 = 0, w2 = 0, h2 = 0;
313
314
315    if (sd->on_del) return;
316
317    if (sd->parent)
318      {
319         evas_object_geometry_get(sd->parent, &x, &y, &w, &h);
320         if (eo_isa(sd->parent, ELM_WIN_CLASS))
321           {
322              x = 0;
323              y = 0;
324           }
325      }
326    evas_object_geometry_get(obj, &x2, &y2, &w2, &h2);
327
328    if (elm_widget_mirrored_get(obj)) ofs_x = w - (x2 - x) - w2;
329    else ofs_x = x2 - x;
330
331    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
332    evas_object_move(wd->resize_obj, x, y);
333    evas_object_resize(wd->resize_obj, w, h);
334    evas_object_size_hint_min_set(sd->offset, ofs_x, y2 - y);
335    evas_object_size_hint_min_set(sd->size, w2, h2);
336 }
337
338 static void
339 _on_smt_sub_changed(void *data,
340                     Evas *e EINA_UNUSED,
341                     Evas_Object *obj EINA_UNUSED,
342                     void *event_info EINA_UNUSED)
343 {
344    _elm_hover_smt_sub_re_eval(data);
345 }
346
347 EOLIAN static Eina_Bool
348 _elm_hover_elm_widget_sub_object_add(Eo *obj, Elm_Hover_Data *sd, Evas_Object *sobj)
349 {
350    Eina_Bool int_ret = EINA_FALSE;
351
352    if (evas_object_data_get(sobj, "elm-parent") == obj) return EINA_TRUE;
353
354    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_add(sobj));
355    if (!int_ret) return EINA_FALSE;
356
357    if (sd->smt_sub && sd->smt_sub->obj == sobj)
358      evas_object_event_callback_add
359        (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_smt_sub_changed, obj);
360
361    return EINA_TRUE;
362 }
363
364 EOLIAN static Eina_Bool
365 _elm_hover_elm_widget_sub_object_del(Eo *obj, Elm_Hover_Data *sd, Evas_Object *sobj)
366 {
367    Eina_Bool int_ret = EINA_FALSE;
368
369    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_del(sobj));
370    if (!int_ret) return EINA_FALSE;
371
372    if (sd->smt_sub && sd->smt_sub->obj == sobj)
373      {
374         evas_object_event_callback_del_full
375           (sd->smt_sub->obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
376           _on_smt_sub_changed, obj);
377
378         sd->smt_sub->obj = NULL;
379         sd->smt_sub = NULL;
380      }
381    else
382      {
383         ELM_HOVER_PARTS_FOREACH
384         {
385            if (sd->subs[i].obj == sobj)
386              {
387                 sd->subs[i].obj = NULL;
388                 break;
389              }
390         }
391      }
392
393    return EINA_TRUE;
394 }
395
396 static void
397 _elm_hover_subs_del(Elm_Hover_Data *sd)
398 {
399    ELM_HOVER_PARTS_FOREACH
400      ELM_SAFE_FREE(sd->subs[i].obj, evas_object_del);
401 }
402
403 EOLIAN static Eina_Bool
404 _elm_hover_elm_container_content_set(Eo *obj, Elm_Hover_Data *sd, const char *swallow, Evas_Object *content)
405 {
406    Eina_Bool int_ret;
407
408    if (!swallow) return EINA_FALSE;
409
410    if (!strcmp(swallow, "smart"))
411      {
412         if (sd->smt_sub)     /* already under 'smart' mode */
413           {
414              if (sd->smt_sub->obj != content)
415                {
416                   evas_object_del(sd->smt_sub->obj);
417                   sd->smt_sub = _HOV_LEFT;
418                   sd->smt_sub->obj = content;
419                }
420
421              if (!content)
422                {
423                   sd->smt_sub->obj = NULL;
424                   sd->smt_sub = NULL;
425                }
426              else _elm_hover_smt_sub_re_eval(obj);
427
428              goto end;
429           }
430         else     /* switch from pristine spots to 'smart' */
431           {
432              _elm_hover_subs_del(sd);
433              sd->smt_sub = _HOV_LEFT;
434              sd->smt_sub->obj = content;
435
436              _elm_hover_smt_sub_re_eval(obj);
437
438              goto end;
439           }
440      }
441
442    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_container_content_set(swallow, content));
443    if (!int_ret) return EINA_FALSE;
444
445    if (strstr(swallow, "elm.swallow.slot."))
446      swallow += sizeof("elm.swallow.slot.");
447
448    ELM_HOVER_PARTS_FOREACH
449    {
450       if (!strcmp(swallow, sd->subs[i].swallow))
451         {
452            sd->subs[i].obj = content;
453            break;
454         }
455    }
456
457 end:
458    elm_layout_sizing_eval(obj);
459    return EINA_TRUE;
460 }
461
462 EOLIAN static Evas_Object*
463 _elm_hover_elm_container_content_get(Eo *obj, Elm_Hover_Data *sd, const char *swallow)
464 {
465    Evas_Object *ret;
466    ret = NULL;
467
468    if (!swallow) return ret;
469
470    if (!strcmp(swallow, "smart"))
471       eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(sd->smt_sub->swallow));
472    else
473       eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(swallow));
474
475    return ret;
476 }
477
478 EOLIAN static Evas_Object*
479 _elm_hover_elm_container_content_unset(Eo *obj, Elm_Hover_Data *sd, const char *swallow)
480 {
481    Evas_Object *ret = NULL;
482
483    if (!swallow) return NULL;
484
485    if (!strcmp(swallow, "smart"))
486       eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_unset
487             (sd->smt_sub->swallow));
488    else
489       eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_unset
490             (swallow));
491    return ret;
492 }
493
494 static void
495 _target_del_cb(void *data,
496                Evas *e EINA_UNUSED,
497                Evas_Object *obj EINA_UNUSED,
498                void *event_info EINA_UNUSED)
499 {
500    ELM_HOVER_DATA_GET(data, sd);
501
502    sd->target = NULL;
503 }
504
505 static void
506 _target_move_cb(void *data,
507                 Evas *e EINA_UNUSED,
508                 Evas_Object *obj EINA_UNUSED,
509                 void *event_info EINA_UNUSED)
510 {
511    elm_layout_sizing_eval(data);
512    _elm_hover_smt_sub_re_eval(data);
513 }
514
515 /// TIZEN_ONLY(20150917): Delay hover dismiss while handling edje signal
516 static void
517 _hov_hide_cb(void *data,
518                 Evas_Object *obj EINA_UNUSED,
519                 const char *emission EINA_UNUSED,
520                 const char *source EINA_UNUSED)
521 {
522    evas_object_hide(data);
523    evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
524 }
525 ///
526
527 static void
528 _hov_dismiss_cb(void *data,
529                 Evas_Object *obj EINA_UNUSED,
530                 const char *emission EINA_UNUSED,
531                 const char *source EINA_UNUSED)
532 {
533 /// TIZEN_ONLY(20150917): Delay hover dismiss while handling edje signal
534 /*
535    evas_object_hide(data);
536    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
537    evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
538 */
539    ELM_HOVER_DATA_GET(obj, sd);
540
541    elm_layout_signal_emit(obj, "elm,action,hide", "elm");
542
543    ELM_HOVER_PARTS_FOREACH
544      {
545         char buf[1024];
546
547         if (sd->subs[i].obj)
548           {
549              snprintf(buf, sizeof(buf), "elm,action,slot,%s,hide",
550                       sd->subs[i].swallow);
551              elm_layout_signal_emit(obj, buf, "elm");
552           }
553      }
554    evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
555 }
556
557 EOLIAN static void
558 _elm_hover_evas_object_smart_add(Eo *obj, Elm_Hover_Data *priv)
559 {
560    unsigned int i;
561
562    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
563    elm_widget_sub_object_parent_add(obj);
564
565    for (i = 0; i < sizeof(priv->subs) / sizeof(priv->subs[0]); i++)
566      priv->subs[i].swallow = _content_aliases[i].alias;
567
568    if (!elm_layout_theme_set(obj, "hover", "base", elm_widget_style_get(obj)))
569      ERR("Failed to set layout!");
570
571    elm_layout_signal_callback_add
572      (obj, "elm,action,dismiss", "*", _hov_dismiss_cb, obj);
573 /// TIZEN_ONLY(20150917): Delay hover dismiss while handling edje signal
574    elm_layout_signal_callback_add
575      (obj, "elm,action,hide,finished", "elm", _hov_hide_cb, obj);
576 ///
577
578    priv->offset = evas_object_rectangle_add(evas_object_evas_get(obj));
579    evas_object_pass_events_set(priv->offset, EINA_TRUE);
580    evas_object_color_set(priv->offset, 0, 0, 0, 0);
581
582    priv->size = evas_object_rectangle_add(evas_object_evas_get(obj));
583    evas_object_pass_events_set(priv->size, EINA_TRUE);
584    evas_object_color_set(priv->size, 0, 0, 0, 0);
585
586    elm_layout_content_set(obj, "elm.swallow.offset", priv->offset);
587    elm_layout_content_set(obj, "elm.swallow.size", priv->size);
588
589    elm_widget_can_focus_set(obj, EINA_FALSE);
590 }
591
592 EOLIAN static void
593 _elm_hover_evas_object_smart_del(Eo *obj, Elm_Hover_Data *sd)
594 {
595
596    sd->on_del = EINA_TRUE;
597
598    if (evas_object_visible_get(obj))
599      {
600         evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
601         evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL);
602      }
603
604    elm_hover_target_set(obj, NULL);
605
606    _elm_hover_parent_detach(obj);
607    sd->parent = NULL;
608
609    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
610 }
611
612 EOLIAN static void
613 _elm_hover_evas_object_smart_move(Eo *obj, Elm_Hover_Data *_pd EINA_UNUSED, Evas_Coord x, Evas_Coord y)
614 {
615    eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
616
617    elm_layout_sizing_eval(obj);
618 }
619
620 EOLIAN static void
621 _elm_hover_evas_object_smart_resize(Eo *obj, Elm_Hover_Data *_pd EINA_UNUSED, Evas_Coord w, Evas_Coord h)
622 {
623    eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
624
625    elm_layout_sizing_eval(obj);
626 }
627
628 EOLIAN static void
629 _elm_hover_evas_object_smart_show(Eo *obj, Elm_Hover_Data *_pd EINA_UNUSED)
630 {
631    eo_do_super(obj, MY_CLASS, evas_obj_smart_show());
632
633    _hov_show_do(obj);
634 }
635
636 EOLIAN static void
637 _elm_hover_evas_object_smart_hide(Eo *obj, Elm_Hover_Data *sd EINA_UNUSED)
638 {
639    eo_do_super(obj, MY_CLASS, evas_obj_smart_hide());
640
641 /// TIZEN_ONLY(20150917): Delay hover dismiss while handling edje signal
642 /*
643    elm_layout_signal_emit(obj, "elm,action,hide", "elm");
644
645    ELM_HOVER_PARTS_FOREACH
646    {
647       char buf[1024];
648
649       if (sd->subs[i].obj)
650         {
651            snprintf(buf, sizeof(buf), "elm,action,slot,%s,hide",
652                     sd->subs[i].swallow);
653            elm_layout_signal_emit(obj, buf, "elm");
654         }
655    }
656 */
657 }
658
659 EOLIAN static const Elm_Layout_Part_Alias_Description*
660 _elm_hover_elm_layout_content_aliases_get(Eo *obj EINA_UNUSED, Elm_Hover_Data *_pd EINA_UNUSED)
661 {
662    return _content_aliases;
663 }
664
665 EAPI Evas_Object *
666 elm_hover_add(Evas_Object *parent)
667 {
668    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
669    Evas_Object *obj = eo_add(MY_CLASS, parent);
670    return obj;
671 }
672
673 EOLIAN static void
674 _elm_hover_eo_base_constructor(Eo *obj, Elm_Hover_Data *_pd EINA_UNUSED)
675 {
676    eo_do_super(obj, MY_CLASS, eo_constructor());
677    eo_do(obj,
678          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
679          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
680          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_POPUP_MENU));
681 }
682
683 EOLIAN static void
684 _elm_hover_target_set(Eo *obj, Elm_Hover_Data *sd, Evas_Object *target)
685 {
686
687    if (sd->target)
688      {
689         evas_object_event_callback_del_full
690           (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
691         evas_object_event_callback_del_full
692           (sd->target, EVAS_CALLBACK_MOVE, _target_move_cb, obj);
693         elm_widget_hover_object_set(sd->target, NULL);
694      }
695
696    sd->target = target;
697    if (sd->target)
698      {
699         evas_object_event_callback_add
700           (sd->target, EVAS_CALLBACK_DEL, _target_del_cb, obj);
701         evas_object_event_callback_add
702           (sd->target, EVAS_CALLBACK_MOVE, _target_move_cb, obj);
703         elm_widget_hover_object_set(target, obj);
704         elm_layout_sizing_eval(obj);
705      }
706 }
707
708 EAPI void
709 elm_hover_parent_set(Evas_Object *obj,
710                      Evas_Object *parent)
711 {
712    ELM_HOVER_CHECK(obj);
713    eo_do(obj, elm_obj_widget_parent_set(parent));
714 }
715
716 EOLIAN static void
717 _elm_hover_elm_widget_parent_set(Eo *obj, Elm_Hover_Data *sd, Evas_Object *parent)
718 {
719    _elm_hover_parent_detach(obj);
720
721    sd->parent = parent;
722    if (sd->parent)
723      {
724         evas_object_event_callback_add
725           (sd->parent, EVAS_CALLBACK_MOVE, _parent_move_cb, obj);
726         evas_object_event_callback_add
727           (sd->parent, EVAS_CALLBACK_RESIZE, _parent_resize_cb, obj);
728         evas_object_event_callback_add
729           (sd->parent, EVAS_CALLBACK_SHOW, _parent_show_cb, obj);
730         evas_object_event_callback_add
731           (sd->parent, EVAS_CALLBACK_HIDE, _parent_hide_cb, obj);
732         evas_object_event_callback_add
733           (sd->parent, EVAS_CALLBACK_DEL, _parent_del_cb, obj);
734      }
735
736    elm_layout_sizing_eval(obj);
737 }
738
739 EOLIAN static Evas_Object*
740 _elm_hover_target_get(Eo *obj EINA_UNUSED, Elm_Hover_Data *sd)
741 {
742    return sd->target;
743 }
744
745 EAPI Evas_Object *
746 elm_hover_parent_get(const Evas_Object *obj)
747 {
748    ELM_HOVER_CHECK(obj) NULL;
749    Evas_Object *ret = NULL;
750    eo_do((Eo *) obj, ret = elm_obj_widget_parent_get());
751    return ret;
752 }
753
754 EOLIAN static Evas_Object*
755 _elm_hover_elm_widget_parent_get(Eo *obj EINA_UNUSED, Elm_Hover_Data *sd)
756 {
757    return sd->parent;
758 }
759
760 EOLIAN static const char*
761 _elm_hover_best_content_location_get(Eo *obj EINA_UNUSED, Elm_Hover_Data *sd, Elm_Hover_Axis pref_axis)
762 {
763    Evas_Coord spc_l, spc_r, spc_t, spc_b;
764
765    _elm_hover_left_space_calc(sd, &spc_l, &spc_t, &spc_r, &spc_b);
766
767    if (pref_axis == ELM_HOVER_AXIS_HORIZONTAL)
768      {
769         if (spc_l < spc_r) return (_HOV_RIGHT)->swallow;
770         else return (_HOV_LEFT)->swallow;
771      }
772    else if (pref_axis == ELM_HOVER_AXIS_VERTICAL)
773      {
774         if (spc_t < spc_b) return (_HOV_BOTTOM)->swallow;
775         else return (_HOV_TOP)->swallow;
776      }
777
778    if (spc_l < spc_r)
779      {
780         if (spc_t > spc_r)
781            return (_HOV_TOP)->swallow;
782         else if (spc_b > spc_r)
783            return (_HOV_BOTTOM)->swallow;
784         else
785            return (_HOV_RIGHT)->swallow;
786      }
787
788    if (spc_t > spc_r)
789       return (_HOV_TOP)->swallow;
790    else if (spc_b > spc_r)
791       return (_HOV_BOTTOM)->swallow;
792    else
793       return (_HOV_LEFT)->swallow;
794
795    return NULL;
796 }
797
798 EOLIAN static void
799 _elm_hover_dismiss(Eo *obj, Elm_Hover_Data *_pd EINA_UNUSED)
800 {
801 /// TIZEN_ONLY(20150917): Delay removing hover until VI ends
802    //elm_layout_signal_emit(obj, "elm,action,dismiss", ""); // XXX: for compat
803 ///
804    elm_layout_signal_emit(obj, "elm,action,dismiss", "elm");
805 }
806
807 EOLIAN static Eina_Bool
808 _elm_hover_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Hover_Data *_pd EINA_UNUSED)
809 {
810    return EINA_TRUE;
811 }
812
813 EOLIAN static Eina_Bool
814 _elm_hover_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Hover_Data *_pd EINA_UNUSED)
815 {
816    return EINA_TRUE;
817 }
818
819
820 EOLIAN static void
821 _elm_hover_class_constructor(Eo_Class *klass)
822 {
823    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
824 }
825
826
827 EOLIAN static Elm_Atspi_State_Set
828 _elm_hover_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Hover_Data *pd EINA_UNUSED)
829 {
830    Elm_Atspi_State_Set states;
831
832    eo_do_super(obj, MY_CLASS, states = elm_interface_atspi_accessible_state_set_get());
833
834    STATE_TYPE_SET(states, ELM_ATSPI_STATE_MODAL);
835
836    return states;
837 }
838
839 static Eina_Bool
840 _action_dismiss(Evas_Object *obj, const char *params EINA_UNUSED)
841 {
842    elm_hover_dismiss(obj);
843    return EINA_TRUE;
844 }
845
846 EOLIAN const Elm_Atspi_Action *
847 _elm_hover_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Hover_Data *pd EINA_UNUSED)
848 {
849    static Elm_Atspi_Action atspi_actions[] = {
850           { "dismiss", "dismiss", NULL, _action_dismiss },
851           { NULL, NULL, NULL, NULL}
852    };
853    return &atspi_actions[0];
854 }
855
856 EOLIAN static Eina_Bool
857 _elm_hover_elm_interface_atspi_component_highlight_grab(Eo *obj, Elm_Hover_Data *sd)
858 {
859    ELM_HOVER_PARTS_FOREACH
860    {
861       if (sd->subs[i].obj)
862      {
863         elm_object_accessibility_highlight_set(sd->subs[i].obj, EINA_TRUE);
864         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
865         break;
866      }
867    }
868    return EINA_TRUE;
869 }
870
871 EOLIAN static Eina_Bool
872 _elm_hover_elm_interface_atspi_component_highlight_clear(Eo *obj, Elm_Hover_Data *sd)
873 {
874    ELM_HOVER_PARTS_FOREACH
875    {
876       if (sd->subs[i].obj)
877      {
878         elm_object_accessibility_highlight_set(sd->subs[i].obj, EINA_FALSE);
879         elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
880         break;
881      }
882    }
883    return EINA_TRUE;
884 }
885
886 #include "elm_hover.eo.c"