atspi: set elm_access layer to MAX
[platform/upstream/elementary.git] / src / lib / elm_access.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_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8
9 #include <Elementary.h>
10 #include "elm_priv.h"
11
12 #define MY_CLASS ELM_ACCESS_CLASS
13
14 #define MY_CLASS_NAME "Elm_Access"
15 #define MY_CLASS_NAME_LEGACY "elm_access"
16
17 struct _Func_Data
18 {
19    void                *user_data; /* Holds user data to CB */
20    Elm_Access_Action_Cb cb;
21 };
22
23 typedef struct _Func_Data Func_Data;
24
25 struct _Action_Info
26 {
27    Evas_Object      *obj;
28    Func_Data         fn[ELM_ACCESS_ACTION_LAST + 1]; /* Callback for specific action */
29 };
30
31 typedef struct _Action_Info Action_Info;
32
33 static Eina_Bool mouse_event_enable = EINA_TRUE;
34 static Eina_Bool auto_highlight = EINA_FALSE;
35 static Elm_Access_Action_Type action_by = ELM_ACCESS_ACTION_FIRST;
36
37 static Evas_Object * _elm_access_add(Evas_Object *parent);
38
39 static void _access_object_unregister(Evas_Object *obj);
40
41 static const char SIG_ACTIVATED[] = "access,activated";
42 static const Evas_Smart_Cb_Description _smart_callbacks[] =
43 {
44    {SIG_ACTIVATED, ""},
45    {NULL, NULL}
46 };
47
48 EOLIAN static void
49 _elm_access_evas_object_smart_add(Eo *obj, void *_pd EINA_UNUSED)
50 {
51    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
52    elm_widget_sub_object_parent_add(obj);
53 }
54
55 static Eina_Bool
56 _access_action_callback_call(Evas_Object *obj,
57                              Elm_Access_Action_Type type,
58                              Elm_Access_Action_Info *action_info)
59 {
60    Elm_Access_Action_Info *ai = NULL;
61    Action_Info *a;
62    Eina_Bool ret;
63
64    ret = EINA_FALSE;
65    a = evas_object_data_get(obj, "_elm_access_action_info");
66
67    if (!action_info)
68      {
69         ai = calloc(1, sizeof(Elm_Access_Action_Info));
70         action_info = ai;
71      }
72
73    action_info->action_type = type;
74
75    if ((type == ELM_ACCESS_ACTION_HIGHLIGHT) &&
76        (action_by != ELM_ACCESS_ACTION_FIRST))
77      action_info->action_by = action_by;
78
79    if (a && (a->fn[type].cb))
80      ret = a->fn[type].cb(a->fn[type].user_data, obj, action_info);
81
82    free(ai);
83
84    return ret;
85 }
86
87 EOLIAN static Eina_Bool
88 _elm_access_elm_widget_activate(Eo *obj, void *_pd EINA_UNUSED, Elm_Activate act)
89 {
90    int type = ELM_ACCESS_ACTION_FIRST;
91
92    Action_Info *a;
93    a = evas_object_data_get(obj, "_elm_access_action_info");
94
95    switch (act)
96      {
97       case ELM_ACTIVATE_DEFAULT:
98         type = ELM_ACCESS_ACTION_ACTIVATE;
99         break;
100
101       case ELM_ACTIVATE_UP:
102         type = ELM_ACCESS_ACTION_UP;
103         break;
104
105       case ELM_ACTIVATE_DOWN:
106         type = ELM_ACCESS_ACTION_DOWN;
107         break;
108
109       case ELM_ACTIVATE_RIGHT:
110         break;
111
112       case ELM_ACTIVATE_LEFT:
113         break;
114
115       case ELM_ACTIVATE_BACK:
116         type = ELM_ACCESS_ACTION_BACK;
117         break;
118
119       default:
120         break;
121      }
122
123    if (type == ELM_ACCESS_ACTION_FIRST) return EINA_FALSE;
124
125    /* if an access object has a callback, it would have the intention to do
126       something. so, check here and return EINA_TRUE. */
127    if ((a) && (type > ELM_ACCESS_ACTION_FIRST) &&
128               (type < ELM_ACCESS_ACTION_LAST) &&
129               (a->fn[type].cb))
130      {
131         _access_action_callback_call(obj, type, NULL);
132         return EINA_TRUE;
133      }
134
135    /* TODO: deprecate below? */
136    if (act != ELM_ACTIVATE_DEFAULT) return EINA_FALSE;
137
138    Elm_Access_Info *ac = evas_object_data_get(obj, "_elm_access");
139    if (!ac) return EINA_FALSE;
140
141    if (ac->activate)
142      ac->activate(ac->activate_data, ac->part_object,
143                   ac->widget_item->eo_obj);
144
145    return EINA_TRUE;
146 }
147
148 EOLIAN static Eina_Bool
149 _elm_access_elm_widget_on_focus(Eo *obj, void *_pd EINA_UNUSED, Elm_Object_Item *item EINA_UNUSED)
150 {
151    evas_object_focus_set(obj, elm_widget_focus_get(obj));
152
153    return EINA_TRUE;
154 }
155
156 typedef struct _Mod_Api Mod_Api;
157
158 struct _Mod_Api
159 {
160    void (*out_read) (const char *txt);
161    void (*out_read_done) (void);
162    void (*out_cancel) (void);
163    void (*out_done_callback_set) (void (*func) (void *data), const void *data);
164 };
165
166 static int initted = 0;
167 static Mod_Api *mapi = NULL;
168
169 static void
170 _access_init(void)
171 {
172    Elm_Module *m;
173
174    if (initted > 0) return;
175    if (!(m = _elm_module_find_as("access/api"))) return;
176    if (m->init_func(m) < 0) return;
177    initted++;
178
179    m->api = malloc(sizeof(Mod_Api));
180    if (!m->api) return;
181    ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
182       _elm_module_symbol_get(m, "out_read");
183    ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
184       _elm_module_symbol_get(m, "out_read_done");
185    ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
186       _elm_module_symbol_get(m, "out_cancel");
187    ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
188       _elm_module_symbol_get(m, "out_done_callback_set");
189    mapi = m->api;
190 }
191
192 static void
193 _access_shutdown(void)
194 {
195    Elm_Module *m;
196    if (initted == 0) return;
197    if (!(m = _elm_module_find_as("access/api"))) return;
198
199    m->shutdown_func(m);
200
201    initted = 0;
202
203    /* _elm_module_unload(); could access m->api and try to free(); */
204    ELM_SAFE_FREE(m->api, free);
205    mapi = NULL;
206 }
207
208 static Elm_Access_Item *
209 _access_add_set(Elm_Access_Info *ac, int type)
210 {
211    Elm_Access_Item *ai;
212    Eina_List *l;
213
214    if (!ac) return NULL;
215    EINA_LIST_FOREACH(ac->items, l, ai)
216      {
217         if (ai->type == type)
218           {
219              if (!ai->func)
220                {
221                   eina_stringshare_del(ai->data);
222                }
223              ai->func = NULL;
224              ai->data = NULL;
225              return ai;
226           }
227      }
228    ai = calloc(1, sizeof(Elm_Access_Item));
229    ai->type = type;
230    ac->items = eina_list_prepend(ac->items, ai);
231    return ai;
232 }
233
234 static Evas_Object *
235 _access_highlight_object_get(Evas_Object *obj)
236 {
237    Evas_Object *o, *ho;
238
239    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
240    if (!o) return NULL;
241
242    ho = evas_object_data_get(o, "_elm_access_target");
243
244    return ho;
245 }
246
247 static void
248 _access_highlight_read(Elm_Access_Info *ac, Evas_Object *obj)
249 {
250    int type;
251    char *txt = NULL;
252    Eina_Strbuf *strbuf;
253
254    strbuf = eina_strbuf_new();
255
256    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
257      {
258         if (ac->on_highlight) ac->on_highlight(ac->on_highlight_data);
259         _elm_access_object_highlight(obj);
260
261         for (type = ELM_ACCESS_INFO_FIRST + 1; type < ELM_ACCESS_INFO_LAST; type++)
262           {
263              txt = _elm_access_text_get(ac, type, obj);
264              if (txt && (strlen(txt) > 0))
265                {
266                   if (eina_strbuf_length_get(strbuf) > 0)
267                     eina_strbuf_append_printf(strbuf, ", %s", txt);
268                   else
269                     eina_strbuf_append(strbuf, txt);
270                }
271              free(txt);
272           }
273      }
274
275    txt = eina_strbuf_string_steal(strbuf);
276    eina_strbuf_free(strbuf);
277
278    _elm_access_say(txt);
279    free(txt);
280 }
281
282 static Eina_Bool
283 _access_obj_over_timeout_cb(void *data)
284 {
285    Elm_Access_Info *ac;
286    Evas_Object *ho;
287
288    if (!data) return EINA_FALSE;
289
290    ac = evas_object_data_get(data, "_elm_access");
291    if (!ac) return EINA_FALSE;
292
293    ho = _access_highlight_object_get(data);
294    if (ho != data) _access_highlight_read(ac, data);
295
296    ac->delay_timer = NULL;
297    return EINA_FALSE;
298 }
299
300 static void
301 _access_hover_mouse_in_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info  EINA_UNUSED)
302 {
303    Elm_Access_Info *ac;
304    if (!mouse_event_enable) return;
305
306     ac = evas_object_data_get(data, "_elm_access");
307    if (!ac) return;
308
309    ELM_SAFE_FREE(ac->delay_timer, ecore_timer_del);
310
311    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
312       ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
313 }
314
315 static void
316 _access_hover_mouse_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
317 {
318    Elm_Access_Info *ac;
319    if (!mouse_event_enable) return;
320
321    ac = evas_object_data_get(data, "_elm_access");
322    if (!ac) return;
323
324    _elm_access_object_unhighlight(data);
325
326    ELM_SAFE_FREE(ac->delay_timer, ecore_timer_del);
327 }
328
329 static void
330 _access_read_done(void *data EINA_UNUSED)
331 {
332    DBG("read done");
333    // FIXME: produce event here
334 }
335
336 static void
337 _access_2nd_click_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
338 {
339    Ecore_Timer *t;
340
341    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
342                                        _access_2nd_click_del_cb, NULL);
343    t = evas_object_data_get(obj, "_elm_2nd_timeout");
344    if (t)
345      {
346         ecore_timer_del(t);
347         evas_object_data_del(obj, "_elm_2nd_timeout");
348      }
349 }
350
351 static Eina_Bool
352 _access_2nd_click_timeout_cb(void *data)
353 {
354    evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
355                                        _access_2nd_click_del_cb, NULL);
356    evas_object_data_del(data, "_elm_2nd_timeout");
357    return EINA_FALSE;
358 }
359
360 static void
361 _access_obj_hilight_del_cb(void *data EINA_UNUSED, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
362 {
363    _elm_access_object_highlight_disable(e);
364 }
365
366 static void
367 _access_obj_hilight_hide_cb(void *data EINA_UNUSED, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
368 {
369    _elm_access_object_highlight_disable(e);
370 }
371
372 static void
373 _access_obj_hilight_move_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
374 {
375    Evas_Coord x, y;
376    Evas_Object *o;
377
378    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
379    if (!o) return;
380    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
381    evas_object_move(o, x, y);
382 }
383
384 static void
385 _access_obj_hilight_resize_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
386 {
387    Evas_Coord w, h;
388    Evas_Object *o;
389
390    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
391    if (!o) return;
392    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
393    evas_object_resize(o, w, h);
394 }
395
396 void
397 _elm_access_mouse_event_enabled_set(Eina_Bool enabled)
398 {
399    enabled = !!enabled;
400    if (mouse_event_enable == enabled) return;
401    mouse_event_enable = enabled;
402 }
403
404 void
405 _elm_access_auto_highlight_set(Eina_Bool enabled)
406 {
407    enabled = !!enabled;
408    if (auto_highlight == enabled) return;
409    auto_highlight = enabled;
410 }
411
412 Eina_Bool
413 _elm_access_auto_highlight_get(void)
414 {
415    return auto_highlight;
416 }
417
418 void
419 _elm_access_shutdown()
420 {
421    _access_shutdown();
422 }
423
424 static void
425 _access_order_del_cb(void *data,
426                      Evas *e EINA_UNUSED,
427                      Evas_Object *obj,
428                      void *event_info EINA_UNUSED)
429 {
430    Elm_Widget_Item_Data *item = data;
431
432    item->access_order = eina_list_remove(item->access_order, obj);
433 }
434
435 void
436 _elm_access_widget_item_access_order_set(Elm_Widget_Item_Data *item,
437                                          Eina_List *objs)
438 {
439    Eina_List *l;
440    Evas_Object *o;
441
442    if (!item) return;
443
444    _elm_access_widget_item_access_order_unset(item);
445
446    EINA_LIST_FOREACH(objs, l, o)
447      {
448         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
449                                        _access_order_del_cb, item);
450      }
451
452    item->access_order = objs;
453 }
454
455 const Eina_List *
456 _elm_access_widget_item_access_order_get(const Elm_Widget_Item_Data *item)
457 {
458    if (!item) return NULL;
459    return item->access_order;
460 }
461
462 void
463 _elm_access_widget_item_access_order_unset(Elm_Widget_Item_Data *item)
464 {
465    Eina_List *l, *l_next;
466    Evas_Object *o;
467
468    if (!item) return;
469
470    EINA_LIST_FOREACH_SAFE(item->access_order, l, l_next, o)
471      {
472         evas_object_event_callback_del_full
473           (o, EVAS_CALLBACK_DEL, _access_order_del_cb, item);
474         item->access_order = eina_list_remove_list(item->access_order, l);
475      }
476 }
477
478 static Eina_Bool
479 _access_highlight_next_get(Evas_Object *obj, Elm_Focus_Direction dir)
480 {
481    int type;
482    Evas_Object *ho, *parent, *target;
483    Eina_Bool ret;
484
485    target = NULL;
486    ret = EINA_FALSE;
487
488    if (!elm_widget_is(obj)) return ret;
489
490    ho = _access_highlight_object_get(obj);
491    if (!ho) ho = obj;
492
493    parent = ho;
494
495    /* find highlight root */
496    do
497      {
498         ELM_WIDGET_DATA_GET_OR_RETURN(parent, wd, ret);
499         if (wd->highlight_root)
500           {
501              /* change highlight root */
502              obj = parent;
503              break;
504           }
505         parent = elm_widget_parent_get(parent);
506      }
507    while (parent);
508
509    _elm_access_auto_highlight_set(EINA_TRUE);
510
511    if (dir == ELM_FOCUS_NEXT)
512      type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
513    else
514      type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
515
516    /* this value is used in _elm_access_object_highlight();
517       to inform the target object of how to get highlight */
518    action_by = type;
519
520    if (!_access_action_callback_call(ho, type, NULL))
521      {
522         if (ho)
523           {
524              Elm_Access_Info *info = _elm_access_info_get(ho);
525              if (type == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT && info->next)
526                target = info->next;
527              else if (type == ELM_ACCESS_ACTION_HIGHLIGHT_PREV && info->prev)
528                target = info->prev;
529           }
530
531         if (target)
532           {
533              _elm_access_highlight_set(target);
534              elm_widget_focus_region_show(target);
535              ret = EINA_TRUE;
536           }
537         else
538           {
539              ret = elm_widget_focus_next_get(obj, dir, &target, NULL);
540              if (ret && target)
541                _elm_access_highlight_set(target);
542           }
543      }
544
545    action_by = ELM_ACCESS_ACTION_FIRST;
546
547    _elm_access_auto_highlight_set(EINA_FALSE);
548
549    return ret;
550 }
551
552 //-------------------------------------------------------------------------//
553 EAPI void
554 _elm_access_highlight_set(Evas_Object* obj)
555 {
556    Elm_Access_Info *ac;
557    Evas_Object *ho;
558
559    if (!obj) return;
560
561    ho = _access_highlight_object_get(obj);
562    if (ho == obj) return;
563
564    ac = evas_object_data_get(obj, "_elm_access");
565    if (!ac) return;
566
567    _access_highlight_read(ac, obj);
568 }
569
570 EAPI void
571 _elm_access_clear(Elm_Access_Info *ac)
572 {
573    Elm_Access_Item *ai;
574
575    if (!ac) return;
576    ELM_SAFE_FREE(ac->delay_timer, ecore_timer_del);
577    EINA_LIST_FREE(ac->items, ai)
578      {
579         if (!ai->func)
580           {
581              eina_stringshare_del(ai->data);
582           }
583         free(ai);
584      }
585 }
586
587 EAPI void
588 _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
589 {
590    Elm_Access_Item *ai = _access_add_set(ac, type);
591    if (!ai) return;
592    ai->func = NULL;
593    ai->data = eina_stringshare_add(text);
594 }
595
596 EAPI void
597 _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Info_Cb func, const void *data)
598 {
599    Elm_Access_Item *ai = _access_add_set(ac, type);
600    if (!ai) return;
601    ai->func = func;
602    ai->data = data;
603 }
604
605 EAPI void
606 _elm_access_on_highlight_hook_set(Elm_Access_Info           *ac,
607                                   Elm_Access_On_Highlight_Cb func,
608                                   void                      *data)
609 {
610     if (!ac) return;
611     ac->on_highlight = func;
612     ac->on_highlight_data = data;
613 }
614
615 EAPI void
616 _elm_access_activate_callback_set(Elm_Access_Info           *ac,
617                                   Elm_Access_Activate_Cb     func,
618                                   void                      *data)
619 {
620    if (!ac) return;
621    ac->activate = func;
622    ac->activate_data = data;
623 }
624
625 EAPI void
626 _elm_access_highlight_object_activate(Evas_Object *obj, Elm_Activate act)
627 {
628    Evas_Object *highlight;
629
630    highlight = _access_highlight_object_get(obj);
631    if (!highlight) return;
632
633    _elm_access_auto_highlight_set(EINA_FALSE);
634
635    if (!elm_object_focus_get(highlight))
636      elm_object_focus_set(highlight, EINA_TRUE);
637
638    elm_widget_activate(highlight, act);
639    return;
640 }
641
642 EAPI void
643 _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
644 {
645    int type;
646    Evas_Object *ho, *parent;
647
648    ho = _access_highlight_object_get(obj);
649    if (!ho) return;
650
651    parent = ho;
652
653    /* find highlight root */
654    do
655      {
656         ELM_WIDGET_DATA_GET_OR_RETURN(parent, wd);
657         if (wd->highlight_root)
658           {
659              /* change highlight root */
660              obj = parent;
661              break;
662           }
663         parent = elm_widget_parent_get(parent);
664      }
665    while (parent);
666
667    _elm_access_auto_highlight_set(EINA_TRUE);
668
669    if (dir == ELM_FOCUS_NEXT)
670      type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
671    else
672      type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
673
674    action_by = type;
675
676    if (!_access_action_callback_call(ho, type, NULL))
677      {
678         Elm_Access_Info *info = _elm_access_info_get(ho);
679         Evas_Object *comming = NULL;
680         if (type == ELM_ACCESS_ACTION_HIGHLIGHT_NEXT)
681           {
682              if ((info) && (info->next)) comming = info->next;
683           }
684         else
685           {
686              if ((info) && (info->prev)) comming = info->prev;
687           }
688         if (comming)
689           {
690              _elm_access_highlight_set(comming);
691              elm_widget_focus_region_show(comming);
692           }
693         else
694           elm_widget_focus_cycle(obj, dir);
695      }
696
697    action_by = ELM_ACCESS_ACTION_FIRST;
698
699    _elm_access_auto_highlight_set(EINA_FALSE);
700 }
701
702 EAPI char *
703 _elm_access_text_get(const Elm_Access_Info *ac, int type, const Evas_Object *obj)
704 {
705    Elm_Access_Item *ai;
706    Eina_List *l;
707
708    if (!ac) return NULL;
709    EINA_LIST_FOREACH(ac->items, l, ai)
710      {
711         if (ai->type == type)
712           {
713              if (ai->func) return ai->func((void *)(ai->data), (Evas_Object *)obj);
714              else if (ai->data) return strdup(ai->data);
715              return NULL;
716           }
717      }
718    return NULL;
719 }
720
721 EAPI void
722 _elm_access_read(Elm_Access_Info *ac, int type, const Evas_Object *obj)
723 {
724    char *txt = _elm_access_text_get(ac, type, obj);
725
726    _access_init();
727    if (mapi)
728      {
729         if (mapi->out_done_callback_set)
730            mapi->out_done_callback_set(_access_read_done, NULL);
731         if (type == ELM_ACCESS_DONE)
732           {
733              if (mapi->out_read_done) mapi->out_read_done();
734           }
735         else if (type == ELM_ACCESS_CANCEL)
736           {
737              if (mapi->out_cancel) mapi->out_cancel();
738           }
739         else
740           {
741              if (txt)
742                {
743                   if (mapi->out_read) mapi->out_read(txt);
744                   if (mapi->out_read) mapi->out_read(".\n");
745                }
746           }
747      }
748    free(txt);
749 }
750
751 EAPI void
752 _elm_access_say(const char *txt)
753 {
754    if (!_elm_config->access_mode) return;
755
756    _access_init();
757    if (mapi)
758      {
759         if (mapi->out_done_callback_set)
760            mapi->out_done_callback_set(_access_read_done, NULL);
761         if (mapi->out_cancel) mapi->out_cancel();
762         if (txt)
763           {
764              if (mapi->out_read) mapi->out_read(txt);
765              if (mapi->out_read) mapi->out_read(".\n");
766           }
767         if (mapi->out_read_done) mapi->out_read_done();
768      }
769 }
770
771 EAPI Elm_Access_Info *
772 _elm_access_info_get(const Evas_Object *obj)
773 {
774    return evas_object_data_get(obj, "_elm_access");
775 }
776
777 EAPI Elm_Access_Info *
778 _elm_access_object_get(const Evas_Object *obj)
779 {
780    return _elm_access_info_get(obj);
781 }
782
783 static Evas_Object *
784 _elm_access_widget_target_get(Evas_Object *obj)
785 {
786    Evas_Object *o = obj;
787
788    do
789      {
790         if (elm_widget_is(o))
791           break;
792         else
793           {
794              o = elm_widget_parent_widget_get(o);
795              if (!o)
796                o = evas_object_smart_parent_get(o);
797           }
798      }
799    while (o);
800
801    return o;
802 }
803
804 EAPI void
805 _elm_access_object_highlight(Evas_Object *obj)
806 {
807    Evas_Object *o, *widget;
808    Evas_Coord x, y, w, h;
809    Eina_Bool in_theme = EINA_FALSE;
810
811    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
812    if (!o)
813      {
814         o = edje_object_add(evas_object_evas_get(obj));
815         evas_object_name_set(o, "_elm_access_disp");
816         evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
817      }
818    else
819      {
820         Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
821         if (ptarget)
822           {
823              evas_object_data_del(o, "_elm_access_target");
824              elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
825
826              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
827                                                  _access_obj_hilight_del_cb, NULL);
828              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
829                                                  _access_obj_hilight_hide_cb, NULL);
830              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
831                                                  _access_obj_hilight_move_cb, NULL);
832              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
833                                                  _access_obj_hilight_resize_cb, NULL);
834
835              widget = _elm_access_widget_target_get(ptarget);
836              if (widget)
837                {
838                   if (elm_widget_access_highlight_in_theme_get(widget))
839                     {
840                        elm_widget_signal_emit(widget, "elm,action,access_highlight,hide", "elm");
841                     }
842                }
843           }
844      }
845    evas_object_data_set(o, "_elm_access_target", obj);
846    elm_widget_parent_highlight_set(obj, EINA_TRUE);
847
848    elm_widget_theme_object_set(obj, o, "access", "base", "default");
849
850    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
851                                   _access_obj_hilight_del_cb, NULL);
852    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
853                                   _access_obj_hilight_hide_cb, NULL);
854    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
855                                   _access_obj_hilight_move_cb, NULL);
856    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
857                                   _access_obj_hilight_resize_cb, NULL);
858    evas_object_raise(o);
859    evas_object_geometry_get(obj, &x, &y, &w, &h);
860    evas_object_move(o, x, y);
861    evas_object_resize(o, w, h);
862
863    widget = _elm_access_widget_target_get(obj);
864    if (widget)
865      {
866         if (elm_widget_access_highlight_in_theme_get(widget))
867           {
868              in_theme = EINA_TRUE;
869              elm_widget_signal_emit(widget, "elm,action,access_highlight,show", "elm");
870           }
871      }
872    /* use callback, should an access object do below every time when
873     * a window gets a client message ECORE_X_ATOM_E_ILLMUE_ACTION_READ? */
874    if (!in_theme &&
875        !_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, NULL))
876      evas_object_show(o);
877    else
878      evas_object_hide(o);
879 }
880
881 EAPI void
882 _elm_access_object_unhighlight(Evas_Object *obj)
883 {
884    Evas_Object *o, *ptarget;
885
886    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
887    if (!o) return;
888    ptarget = evas_object_data_get(o, "_elm_access_target");
889    if (ptarget == obj)
890      {
891         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
892                                             _access_obj_hilight_del_cb, NULL);
893         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
894                                             _access_obj_hilight_hide_cb, NULL);
895         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
896                                             _access_obj_hilight_move_cb, NULL);
897         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
898                                             _access_obj_hilight_resize_cb, NULL);
899         evas_object_del(o);
900         elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
901      }
902 }
903
904 static void
905 _content_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
906                 void *event_info EINA_UNUSED)
907 {
908    Evas_Object *accessobj;
909    Evas_Coord w, h;
910
911    accessobj = data;
912    if (!accessobj) return;
913
914    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
915    evas_object_resize(accessobj, w, h);
916 }
917
918 static void
919 _content_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj,
920               void *event_info EINA_UNUSED)
921 {
922    Evas_Object *accessobj;
923    Evas_Coord x, y;
924
925    accessobj = data;
926    if (!accessobj) return;
927
928    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
929    evas_object_move(accessobj, x, y);
930 }
931
932 static Evas_Object *
933 _access_object_register(Evas_Object *obj, Evas_Object *parent)
934 {
935    Evas_Object *ao;
936    Elm_Access_Info *ac;
937    Evas_Coord x, y, w, h;
938
939    if (!obj) return NULL;
940
941    /* check previous access object */
942    ao = evas_object_data_get(obj, "_part_access_obj");
943    if (ao)
944      _access_object_unregister(obj);
945
946    /* create access object */
947    ao = _elm_access_add(parent);
948    if (!ao) return NULL;
949
950    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
951                                   _content_resize, ao);
952    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
953                                   _content_move, ao);
954
955    evas_object_geometry_get(obj, &x, &y, &w, &h);
956    evas_object_move(ao, x, y);
957    evas_object_resize(ao, w, h);
958    evas_object_show(ao);
959
960    /* register access object */
961    _elm_access_object_register(ao, obj);
962
963    /* set access object */
964    evas_object_data_set(obj, "_part_access_obj", ao);
965
966    /* set owner part object */
967    ac = evas_object_data_get(ao, "_elm_access");
968    ac->part_object = obj;
969
970    /* set access object layer to max, because the highlight
971       frame could be covered by other object which has higher layer */
972    evas_object_layer_set(ao, EVAS_LAYER_MAX);
973
974    return ao;
975 }
976
977 static void
978 _access_object_unregister(Evas_Object *obj)
979 {
980    Elm_Access_Info *ac;
981    Evas_Object *ao;
982
983    if (!obj) return;
984
985    ao = evas_object_data_get(obj, "_part_access_obj");
986
987    if (ao)
988      {
989         /* delete callbacks and unregister access object in _access_obj_del_cb*/
990         evas_object_del(ao);
991      }
992    else
993      {
994         /* button, check, label etc. */
995         ac = evas_object_data_get(obj, "_elm_access");
996         if (ac && ac->hoverobj)
997           _elm_access_object_unregister(obj, ac->hoverobj);
998      }
999 }
1000
1001 EAPI Evas_Object *
1002 _elm_access_edje_object_part_object_register(Evas_Object* obj,
1003                                              const Evas_Object *eobj,
1004                                              const char* part)
1005 {
1006    Evas_Object *ao, *po;
1007
1008    po = (Evas_Object *)edje_object_part_object_get(eobj, part);
1009    if (!obj || !po) return NULL;
1010
1011    /* check previous access object */
1012    ao = evas_object_data_get(po, "_part_access_obj");
1013    if (ao)
1014      _elm_access_edje_object_part_object_unregister(obj, eobj, part);
1015
1016    ao = _access_object_register(po, obj);
1017
1018    return ao;
1019 }
1020
1021 //FIXME: unused obj should be removed from here and each widget.
1022 EAPI void
1023 _elm_access_edje_object_part_object_unregister(Evas_Object* obj EINA_UNUSED,
1024                                                const Evas_Object *eobj,
1025                                                const char* part)
1026 {
1027    Evas_Object *po;
1028
1029    po = (Evas_Object *)edje_object_part_object_get(eobj, part);
1030    if (!po) return;
1031
1032    _access_object_unregister(po);
1033 }
1034
1035 EAPI void
1036 _elm_access_object_highlight_disable(Evas *e)
1037 {
1038    Evas_Object *o, *ptarget;
1039
1040    o = evas_object_name_find(e, "_elm_access_disp");
1041    if (!o) return;
1042    ptarget = evas_object_data_get(o, "_elm_access_target");
1043    if (ptarget)
1044      {
1045         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
1046                                             _access_obj_hilight_del_cb, NULL);
1047         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
1048                                             _access_obj_hilight_hide_cb, NULL);
1049         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
1050                                             _access_obj_hilight_move_cb, NULL);
1051         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
1052                                             _access_obj_hilight_resize_cb, NULL);
1053      }
1054    evas_object_del(o);
1055    elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
1056 }
1057
1058 static void
1059 _access_obj_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1060 {
1061
1062    Ecore_Job *ao_del_job = NULL;
1063
1064    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _access_obj_del_cb);
1065
1066    if (data) /* hover object */
1067      {
1068         evas_object_event_callback_del_full(data, EVAS_CALLBACK_RESIZE,
1069                                             _content_resize, obj);
1070         evas_object_event_callback_del_full(data, EVAS_CALLBACK_MOVE,
1071                                             _content_move, obj);
1072
1073         _elm_access_object_unregister(obj, data);
1074      }
1075
1076    ao_del_job = evas_object_data_get(obj, "_access_obj_del_job");
1077
1078    if (ao_del_job)
1079      {
1080         ecore_job_del(ao_del_job);
1081         evas_object_data_del(obj, "_access_obj_del_job");
1082      }
1083 }
1084
1085 static void
1086 _access_obj_del_job(void *data)
1087 {
1088    if (!data) return;
1089
1090    evas_object_data_del(data, "_access_obj_del_job");
1091
1092    evas_object_event_callback_del(data, EVAS_CALLBACK_DEL, _access_obj_del_cb);
1093    evas_object_del(data);
1094 }
1095
1096 static void
1097 _access_hover_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1098 {
1099    Ecore_Job *ao_del_job = NULL;
1100
1101    /* data - access object - could be NULL */
1102    if (!data) return;
1103
1104    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
1105                                        _content_resize, data);
1106    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
1107                                        _content_move, data);
1108
1109    _elm_access_object_unregister(data, obj);
1110
1111    /* delete access object in job */
1112    ao_del_job = evas_object_data_get(data, "_access_obj_del_job");
1113    if (ao_del_job)
1114      {
1115         ecore_job_del(ao_del_job);
1116         evas_object_data_del(data, "_access_obj_del_job");
1117      }
1118
1119    ao_del_job = ecore_job_add(_access_obj_del_job, data);
1120    evas_object_data_set(data, "_access_obj_del_job", ao_del_job);
1121 }
1122
1123 EAPI void
1124 _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
1125 {
1126    Elm_Access_Info *ac;
1127
1128    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
1129                                   _access_hover_mouse_in_cb, obj);
1130    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
1131                                   _access_hover_mouse_out_cb, obj);
1132    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
1133                                   _access_hover_del_cb, obj);
1134
1135    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1136                                   _access_obj_del_cb, hoverobj);
1137
1138    ac = calloc(1, sizeof(Elm_Access_Info));
1139    evas_object_data_set(obj, "_elm_access", ac);
1140
1141    ac->hoverobj = hoverobj;
1142 }
1143
1144 EAPI void
1145 _elm_access_object_unregister(Evas_Object *obj, Evas_Object *hoverobj)
1146 {
1147    Elm_Access_Info *ac;
1148    Evas_Object *ao;
1149
1150    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_IN,
1151                                        _access_hover_mouse_in_cb, obj);
1152    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
1153                                        _access_hover_mouse_out_cb, obj);
1154    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_DEL,
1155                                        _access_hover_del_cb, obj);
1156
1157    /* _access_obj_del_cb and _access_hover_del_cb calls this function,
1158       both do not need _part_access_obj data, so delete the data here. */
1159    ao = evas_object_data_get(hoverobj, "_part_access_obj");
1160    if (ao) evas_object_data_del(hoverobj, "_part_access_obj");
1161
1162    ac = evas_object_data_get(obj, "_elm_access");
1163    evas_object_data_del(obj, "_elm_access");
1164    if (ac)
1165      {
1166         /* widget could delete VIEW(it) only and register item again,
1167            in this case _elm_access_widget_item_register could try to delete
1168            access object again in _elm_access_widget_item_unregister */
1169         if (ac->widget_item) ac->widget_item->access_obj = NULL;
1170
1171         _elm_access_clear(ac);
1172         free(ac);
1173      }
1174
1175    Action_Info *a;
1176    a = evas_object_data_get(obj, "_elm_access_action_info");
1177    evas_object_data_del(obj,  "_elm_access_action_info");
1178    free(a);
1179 }
1180
1181 EAPI void
1182 _elm_access_widget_item_register(Elm_Widget_Item_Data *item)
1183 {
1184    Evas_Object *ao, *ho;
1185    Evas_Coord x, y, w, h;
1186    Elm_Access_Info *ac;
1187
1188    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
1189
1190    /* check previous access object */
1191    if (item->access_obj)
1192      _elm_access_widget_item_unregister(item);
1193
1194    // create access object
1195    ho = item->view;
1196    ao = _elm_access_add(item->widget);
1197    if (!ao) return;
1198
1199    evas_object_event_callback_add(ho, EVAS_CALLBACK_RESIZE,
1200                                   _content_resize, ao);
1201    evas_object_event_callback_add(ho, EVAS_CALLBACK_MOVE,
1202                                   _content_move, ao);
1203
1204    evas_object_geometry_get(ho, &x, &y, &w, &h);
1205    evas_object_move(ao, x, y);
1206    evas_object_resize(ao, w, h);
1207    evas_object_show(ao);
1208
1209    // register access object
1210    _elm_access_object_register(ao, ho);
1211
1212    item->access_obj = ao;
1213
1214    /* set owner widget item */
1215    ac = evas_object_data_get(ao, "_elm_access");
1216    ac->widget_item = item;
1217 }
1218
1219 EAPI void
1220 _elm_access_widget_item_unregister(Elm_Widget_Item_Data *item)
1221 {
1222    Evas_Object *ao;
1223
1224    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
1225
1226    if (!item->access_obj) return;
1227
1228    /* delete callbacks and unregister access object in _access_obj_del_cb*/
1229    ao = item->access_obj;
1230    item->access_obj = NULL;
1231
1232    evas_object_del(ao);
1233 }
1234
1235 EAPI Eina_Bool
1236 _elm_access_2nd_click_timeout(Evas_Object *obj)
1237 {
1238    Ecore_Timer *t;
1239
1240    t = evas_object_data_get(obj, "_elm_2nd_timeout");
1241    if (t)
1242      {
1243         ecore_timer_del(t);
1244         evas_object_data_del(obj, "_elm_2nd_timeout");
1245         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
1246                                             _access_2nd_click_del_cb, NULL);
1247         return EINA_TRUE;
1248      }
1249    t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
1250    evas_object_data_set(obj, "_elm_2nd_timeout", t);
1251    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1252                                   _access_2nd_click_del_cb, NULL);
1253    return EINA_FALSE;
1254 }
1255
1256 static Evas_Object *
1257 _elm_access_add(Evas_Object *parent)
1258 {
1259    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1260    Evas_Object *obj = eo_add(MY_CLASS, parent);
1261    return obj;
1262 }
1263
1264 EOLIAN static Eo *
1265 _elm_access_eo_base_constructor(Eo *obj, void *_pd EINA_UNUSED)
1266 {
1267    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
1268    eo_do(obj,
1269          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1270          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks));
1271
1272    return obj;
1273 }
1274
1275 EAPI Evas_Object *
1276 elm_access_object_register(Evas_Object *obj, Evas_Object *parent)
1277 {
1278    return _access_object_register(obj, parent);
1279 }
1280
1281 EAPI void
1282 elm_access_object_unregister(Evas_Object *obj)
1283 {
1284    _access_object_unregister(obj);
1285 }
1286
1287 EAPI Evas_Object *
1288 elm_access_object_get(const Evas_Object *obj)
1289 {
1290    return evas_object_data_get(obj, "_part_access_obj");
1291 }
1292
1293 EAPI void
1294 elm_access_info_set(Evas_Object *obj, int type, const char *text)
1295 {
1296    _elm_access_text_set(_elm_access_info_get(obj), type, text);
1297 }
1298
1299 EAPI char *
1300 elm_access_info_get(const Evas_Object *obj, int type)
1301 {
1302    return _elm_access_text_get(_elm_access_info_get(obj), type, obj);
1303 }
1304
1305 EAPI void
1306 elm_access_info_cb_set(Evas_Object *obj, int type,
1307                           Elm_Access_Info_Cb func, const void *data)
1308 {
1309    _elm_access_callback_set(_elm_access_info_get(obj), type, func, data);
1310 }
1311
1312 EAPI void
1313 elm_access_activate_cb_set(Evas_Object *obj,
1314                            Elm_Access_Activate_Cb  func, void *data)
1315 {
1316    Elm_Access_Info *ac;
1317
1318    ac = _elm_access_info_get(obj);
1319    if (!ac) return;
1320
1321    ac->activate = func;
1322    ac->activate_data = data;
1323 }
1324
1325 EAPI void
1326 elm_access_say(const char *text)
1327 {
1328    if (!text) return;
1329
1330    _elm_access_say(text);
1331 }
1332
1333 EAPI void
1334 elm_access_highlight_set(Evas_Object* obj)
1335 {
1336    _elm_access_highlight_set(obj);
1337 }
1338
1339 EAPI Eina_Bool
1340 elm_access_action(Evas_Object *obj, const Elm_Access_Action_Type type, Elm_Access_Action_Info *action_info)
1341 {
1342    Evas *evas;
1343    Evas_Object *ho;
1344    Elm_Access_Action_Info *a = action_info;
1345
1346    switch (type)
1347      {
1348       case ELM_ACCESS_ACTION_READ:
1349       case ELM_ACCESS_ACTION_HIGHLIGHT:
1350         evas = evas_object_evas_get(obj);
1351         if (!evas) return EINA_FALSE;
1352
1353         evas_event_feed_mouse_in(evas, 0, NULL);
1354
1355         _elm_access_mouse_event_enabled_set(EINA_TRUE);
1356         evas_event_feed_mouse_move(evas, a->x, a->y, 0, NULL);
1357         _elm_access_mouse_event_enabled_set(EINA_FALSE);
1358
1359         ho = _access_highlight_object_get(obj);
1360         if (ho)
1361           _access_action_callback_call(ho, ELM_ACCESS_ACTION_READ, a);
1362         break;
1363
1364       case ELM_ACCESS_ACTION_UNHIGHLIGHT:
1365         evas = evas_object_evas_get(obj);
1366         if (!evas) return EINA_FALSE;
1367         _elm_access_object_highlight_disable(evas);
1368         break;
1369
1370       case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT:
1371         if (a->highlight_cycle)
1372           _elm_access_highlight_cycle(obj, ELM_FOCUS_NEXT);
1373         else
1374           return _access_highlight_next_get(obj, ELM_FOCUS_NEXT);
1375         break;
1376
1377       case ELM_ACCESS_ACTION_HIGHLIGHT_PREV:
1378         if (a->highlight_cycle)
1379           _elm_access_highlight_cycle(obj, ELM_FOCUS_PREVIOUS);
1380         else
1381           return _access_highlight_next_get(obj, ELM_FOCUS_PREVIOUS);
1382         break;
1383
1384       case ELM_ACCESS_ACTION_ACTIVATE:
1385         _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DEFAULT);
1386         break;
1387
1388       case ELM_ACCESS_ACTION_UP:
1389         _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_UP);
1390         break;
1391
1392       case ELM_ACCESS_ACTION_DOWN:
1393         _elm_access_highlight_object_activate(obj, ELM_ACTIVATE_DOWN);
1394         break;
1395
1396       case ELM_ACCESS_ACTION_SCROLL:
1397         //TODO: SCROLL HIGHLIGHT OBJECT
1398         break;
1399
1400       case ELM_ACCESS_ACTION_BACK:
1401         break;
1402
1403       default:
1404         break;
1405      }
1406
1407    return EINA_TRUE;
1408 }
1409
1410 EAPI void
1411 elm_access_action_cb_set(Evas_Object *obj, const Elm_Access_Action_Type type, const Elm_Access_Action_Cb cb, const void *data)
1412 {
1413    Action_Info *a;
1414    a =  evas_object_data_get(obj, "_elm_access_action_info");
1415
1416    if (!a)
1417      {
1418         a = calloc(1, sizeof(Action_Info));
1419         evas_object_data_set(obj, "_elm_access_action_info", a);
1420      }
1421
1422    a->obj = obj;
1423    a->fn[type].cb = cb;
1424    a->fn[type].user_data = (void *)data;
1425 }
1426 EAPI void
1427 elm_access_external_info_set(Evas_Object *obj, const char *text)
1428 {
1429    _elm_access_text_set
1430      (_elm_access_info_get(obj), ELM_ACCESS_CONTEXT_INFO, text);
1431 }
1432
1433 EAPI char *
1434 elm_access_external_info_get(const Evas_Object *obj)
1435 {
1436    Elm_Access_Info *ac;
1437
1438    ac = _elm_access_info_get(obj);
1439    return _elm_access_text_get(ac, ELM_ACCESS_CONTEXT_INFO, obj);
1440 }
1441
1442 EAPI void
1443 elm_access_highlight_next_set(Evas_Object *obj, Elm_Highlight_Direction dir, Evas_Object *next)
1444 {
1445    EINA_SAFETY_ON_FALSE_RETURN(obj);
1446    EINA_SAFETY_ON_FALSE_RETURN(next);
1447
1448    Elm_Access_Info *info = _elm_access_info_get(obj);
1449    Elm_Access_Info *info_next = _elm_access_info_get(next);
1450
1451    if (!info || !info_next)
1452      {
1453         ERR("There is no access information");
1454         return;
1455      }
1456
1457    if (dir == ELM_HIGHLIGHT_DIR_NEXT)
1458      {
1459         info_next->prev = obj;
1460         info->next = next;
1461      }
1462    else if (dir == ELM_HIGHLIGHT_DIR_PREVIOUS)
1463      {
1464         info_next->next = obj;
1465         info->prev = next;
1466      }
1467    else
1468       ERR("Not supported focus direction for access highlight [%d]", dir);
1469 }
1470
1471 EOLIAN static void
1472 _elm_access_class_constructor(Eo_Class *klass)
1473 {
1474    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1475 }
1476
1477 EOLIAN static const char*
1478 _elm_access_elm_interface_atspi_accessible_name_get(Eo *obj, void *pd EINA_UNUSED)
1479 {
1480    char *accessible_name;
1481    //TIZEN_ONLY(20160919): make access object work with elm_interface_atspi_accessible_name,description_set
1482    const char *ret = NULL;
1483    eo_do_super(obj, ELM_ACCESS_CLASS, ret = elm_interface_atspi_accessible_name_get());
1484    if (ret) return ret;
1485    //
1486
1487    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1488
1489    accessible_name = elm_access_info_get(obj, ELM_ACCESS_INFO);
1490    eina_stringshare_del(wd->accessible_name);
1491    wd->accessible_name = eina_stringshare_add(accessible_name);
1492    free(accessible_name);
1493    return wd->accessible_name;
1494 }
1495
1496 EOLIAN static const char*
1497 _elm_access_elm_interface_atspi_accessible_description_get(Eo *obj, void *pd EINA_UNUSED)
1498 {
1499    //TIZEN_ONLY(20160919): make access object work with elm_interface_atspi_accessible_name,description_set
1500    const char *ret = NULL;
1501    eo_do_super(obj, ELM_ACCESS_CLASS, ret = elm_interface_atspi_accessible_description_get());
1502    if (ret) return ret;
1503    //
1504    return elm_access_info_get(obj, ELM_ACCESS_CONTEXT_INFO);
1505 }
1506
1507 EOLIAN static Elm_Atspi_State_Set
1508 _elm_access_elm_interface_atspi_accessible_state_set_get(Eo *obj, void *pd EINA_UNUSED)
1509 {
1510    Elm_Atspi_State_Set ret;
1511    eo_do_super(obj, ELM_ACCESS_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
1512
1513    Elm_Access_Info *info = _elm_access_info_get(obj);
1514    if (info && !evas_object_visible_get(info->part_object))
1515      {
1516         STATE_TYPE_UNSET(ret, ELM_ATSPI_STATE_VISIBLE);
1517         STATE_TYPE_UNSET(ret, ELM_ATSPI_STATE_SHOWING);
1518      }
1519
1520    return ret;
1521 }
1522
1523 EOLIAN static Eina_Bool
1524 _elm_access_elm_interface_atspi_component_highlight_grab(Eo *obj, void *pd EINA_UNUSED)
1525 {
1526    if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, NULL))
1527      eo_do_super(obj, ELM_ACCESS_CLASS, elm_interface_atspi_component_highlight_grab());
1528
1529    // TIZEN_ONLY(20160708) - support elm_access used for embedded toolkit
1530    action_by = ELM_ACCESS_ACTION_FIRST;
1531    //
1532
1533 ///TIZEN_ONLY(20170717) : expose highlight information on atspi
1534    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
1535 ///
1536    return EINA_TRUE;
1537 }
1538
1539 EOLIAN static Eina_Bool
1540 _elm_access_elm_interface_atspi_component_highlight_clear(Eo *obj, void *pd EINA_UNUSED)
1541 {
1542    if (!_access_action_callback_call(obj, ELM_ACCESS_ACTION_UNHIGHLIGHT, NULL))
1543      eo_do_super(obj, ELM_ACCESS_CLASS, elm_interface_atspi_component_highlight_clear());
1544
1545    // TIZEN_ONLY(20160708) - support elm_access used for embedded toolkit
1546    action_by = ELM_ACCESS_ACTION_FIRST;
1547    //
1548
1549 ///TIZEN_ONLY(20170717) : expose highlight information on atspi
1550    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
1551 ///
1552    return EINA_TRUE;
1553 }
1554
1555 static Eina_Bool
1556 _access_atspi_action_do(Evas_Object *obj, const char *params)
1557 {
1558    Eina_Bool ret;
1559
1560    ret = EINA_FALSE;
1561    if (!strcmp(params, "highlight"))
1562      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT, NULL);
1563    else if (!strcmp(params, "unhighlight"))
1564      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_UNHIGHLIGHT, NULL);
1565    // TIZEN_ONLY(20160708) - support elm_access used for embedded toolkit
1566    else if (!strcmp(params, "highlight,first"))
1567      action_by = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
1568    else if (!strcmp(params, "highlight,last"))
1569      action_by = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
1570    //
1571    else if (!strcmp(params, "highlight,next"))
1572      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, NULL);
1573    else if (!strcmp(params, "highlight,prev"))
1574      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_HIGHLIGHT_PREV, NULL);
1575    else if (!strcmp(params, "activate"))
1576      {
1577         evas_object_smart_callback_call(obj, SIG_ACTIVATED, NULL);
1578         ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_ACTIVATE, NULL);
1579      }
1580    else if (!strcmp(params, "value,up"))
1581      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_UP, NULL);
1582    else if (!strcmp(params, "value,down"))
1583      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_DOWN, NULL);
1584    else if (!strcmp(params, "read"))
1585      ret = _access_action_callback_call(obj, ELM_ACCESS_ACTION_READ, NULL);
1586
1587    return ret;
1588 }
1589
1590 EOLIAN const Elm_Atspi_Action *
1591 _elm_access_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
1592 {
1593    static Elm_Atspi_Action atspi_actions[] = {
1594           { "highlight", NULL, "highlight", _access_atspi_action_do},
1595           { "unhighlight", NULL, "unhighlight", _access_atspi_action_do},
1596           // TIZEN_ONLY(20160708) - support elm_access used for embedded toolkit
1597           { "highlight,first", NULL, "highlight,first", _access_atspi_action_do},
1598           { "highlight,last", NULL, "highlight,last", _access_atspi_action_do},
1599           //
1600           { "highlight,next", NULL, "highlight,next", _access_atspi_action_do},
1601           { "highlight,prev", NULL, "highlight,prev", _access_atspi_action_do},
1602           { "activate", NULL, "activate", _access_atspi_action_do},
1603           { "value,up", NULL, "value,up", _access_atspi_action_do},
1604           { "value,down", NULL, "value,down", _access_atspi_action_do},
1605           { "read", NULL, "read", _access_atspi_action_do},
1606           { NULL, NULL, NULL, NULL }
1607    };
1608    return &atspi_actions[0];
1609 }
1610
1611 #include "elm_access.eo.c"