merge with master
[framework/uifw/elementary.git] / src / lib / elm_access.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 static const char ACCESS_SMART_NAME[] = "elm_access";
5
6 ELM_INTERNAL_SMART_SUBCLASS_NEW
7   (ACCESS_SMART_NAME, _elm_access, Elm_Widget_Smart_Class,
8   Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
9
10 static Eina_Bool mouse_event_enable = EINA_TRUE;
11 static Eina_Bool read_mode = EINA_FALSE;
12
13 static Evas_Object * _elm_access_add(Evas_Object *parent);
14
15 static void
16 _elm_access_smart_add(Evas_Object *obj)
17 {
18    EVAS_SMART_DATA_ALLOC(obj, Elm_Widget_Smart_Data);
19    ELM_WIDGET_CLASS(_elm_access_parent_sc)->base.add(obj);
20
21    elm_widget_can_focus_set(obj, EINA_TRUE);
22 }
23
24 static Eina_Bool
25 _elm_access_smart_on_focus(Evas_Object *obj)
26 {
27    evas_object_focus_set(obj, elm_widget_focus_get(obj));
28
29    return EINA_TRUE;
30 }
31
32 static Eina_Bool
33 _elm_access_smart_activate(Evas_Object *obj, Elm_Activate act)
34 {
35    if (act != ELM_ACTIVATE_DEFAULT) return EINA_FALSE;
36
37    Elm_Access_Info *ac = evas_object_data_get(obj, "_elm_access");
38    if (!ac) return EINA_FALSE;
39
40    if (ac->activate)
41      ac->activate(ac->activate_data, ac->part_object,
42                   (Elm_Object_Item *)ac->widget_item);
43
44    return EINA_TRUE;
45 }
46
47 static void
48 _elm_access_smart_set_user(Elm_Widget_Smart_Class *sc)
49 {
50    sc->base.add = _elm_access_smart_add;
51
52    /* not a 'focus chain manager' */
53    sc->focus_next = NULL;
54    sc->focus_direction = NULL;
55    sc->on_focus = _elm_access_smart_on_focus;
56    sc->activate = _elm_access_smart_activate;
57
58    return;
59 }
60
61 typedef struct _Mod_Api Mod_Api;
62
63 struct _Mod_Api
64 {
65    void (*out_read) (const char *txt);
66    void (*out_read_done) (void);
67    void (*out_cancel) (void);
68    void (*out_done_callback_set) (void (*func) (void *data), const void *data);
69 };
70
71 static int initted = 0;
72 static Mod_Api *mapi = NULL;
73
74 static void
75 _access_init(void)
76 {
77    Elm_Module *m;
78    initted++;
79    if (initted > 1) return;
80    if (!(m = _elm_module_find_as("access/api"))) return;
81    m->api = malloc(sizeof(Mod_Api));
82    if (!m->api) return;
83    m->init_func(m);
84    ((Mod_Api *)(m->api)      )->out_read = // called to read out some text
85       _elm_module_symbol_get(m, "out_read");
86    ((Mod_Api *)(m->api)      )->out_read_done = // called to set a done marker so when it is reached the done callback is called
87       _elm_module_symbol_get(m, "out_read_done");
88    ((Mod_Api *)(m->api)      )->out_cancel = // called to read out some text
89       _elm_module_symbol_get(m, "out_cancel");
90    ((Mod_Api *)(m->api)      )->out_done_callback_set = // called when last read done
91       _elm_module_symbol_get(m, "out_done_callback_set");
92    mapi = m->api;
93 }
94
95 static void
96 _access_shutdown(void)
97 {
98    Elm_Module *m;
99    if (initted == 0) return;
100    if (!(m = _elm_module_find_as("access/api"))) return;
101
102    m->shutdown_func(m);
103
104    initted = 0;
105
106    free(mapi);
107    mapi = NULL;
108 }
109
110 static Elm_Access_Item *
111 _access_add_set(Elm_Access_Info *ac, int type)
112 {
113    Elm_Access_Item *ai;
114    Eina_List *l;
115
116    if (!ac) return NULL;
117    EINA_LIST_FOREACH(ac->items, l, ai)
118      {
119         if (ai->type == type)
120           {
121              if (!ai->func)
122                {
123                   if (ai->data) eina_stringshare_del(ai->data);
124                }
125              ai->func = NULL;
126              ai->data = NULL;
127              return ai;
128           }
129      }
130    ai = calloc(1, sizeof(Elm_Access_Item));
131    ai->type = type;
132    ac->items = eina_list_prepend(ac->items, ai);
133    return ai;
134 }
135
136 static Evas_Object *
137 _access_highlight_object_get(Evas_Object *obj)
138 {
139    Evas_Object *o, *ho;
140
141    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
142    if (!o) return NULL;
143
144    ho = evas_object_data_get(o, "_elm_access_target");
145
146    return ho;
147 }
148
149 static Eina_Bool
150 _access_obj_over_timeout_cb(void *data)
151 {
152    Elm_Access_Info *ac;
153    Evas_Object *ho;
154
155    if (!data) return EINA_FALSE;
156
157    ho = _access_highlight_object_get(data);
158    if (ho == data) return EINA_FALSE;
159
160    ac = evas_object_data_get(data, "_elm_access");
161    if (!ac) return EINA_FALSE;
162
163    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
164      {
165         if (ac->on_highlight) ac->on_highlight(ac->on_highlight_data);
166         _elm_access_object_hilight(data);
167         _elm_access_read(ac, ELM_ACCESS_CANCEL, data);
168         _elm_access_read(ac, ELM_ACCESS_INFO,   data);
169         _elm_access_read(ac, ELM_ACCESS_TYPE,   data);
170         _elm_access_read(ac, ELM_ACCESS_STATE,  data);
171         _elm_access_read(ac, ELM_ACCESS_CONTEXT_INFO,   data);
172         _elm_access_read(ac, ELM_ACCESS_DONE,   data);
173      }
174    ac->delay_timer = NULL;
175    return EINA_FALSE;
176 }
177
178 static void
179 _access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info  __UNUSED__)
180 {
181    Elm_Access_Info *ac;
182    if (!mouse_event_enable) return;
183
184    ac = evas_object_data_get(data, "_elm_access");
185    if (!ac) return;
186
187    if (ac->delay_timer)
188      {
189         ecore_timer_del(ac->delay_timer);
190         ac->delay_timer = NULL;
191      }
192    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
193       ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
194 }
195
196 static void
197 _access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
198 {
199    Elm_Access_Info *ac;
200    if (!mouse_event_enable) return;
201
202    ac = evas_object_data_get(data, "_elm_access");
203    if (!ac) return;
204
205    _elm_access_object_unhilight(data);
206    if (ac->delay_timer)
207      {
208         ecore_timer_del(ac->delay_timer);
209         ac->delay_timer = NULL;
210      }
211 }
212
213 static void
214 _access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
215 {
216    _elm_access_object_unregister(data, obj);
217
218    // _elm_access_edje_object_part_object_register(); set below object data
219    evas_object_data_del(obj, "_part_access_obj");
220 }
221
222 static void
223 _access_read_done(void *data __UNUSED__)
224 {
225    printf("read done\n");
226    // FIXME: produce event here
227 }
228
229 static void
230 _access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
231 {
232    Ecore_Timer *t;
233
234    evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
235                                        _access_2nd_click_del_cb, NULL);
236    t = evas_object_data_get(obj, "_elm_2nd_timeout");
237    if (t)
238      {
239         ecore_timer_del(t);
240         evas_object_data_del(obj, "_elm_2nd_timeout");
241      }
242 }
243
244 static Eina_Bool
245 _access_2nd_click_timeout_cb(void *data)
246 {
247    evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
248                                        _access_2nd_click_del_cb, NULL);
249    evas_object_data_del(data, "_elm_2nd_timeout");
250    return EINA_FALSE;
251 }
252
253 static void
254 _access_obj_hilight_del_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
255 {
256    _elm_access_object_hilight_disable(e);
257 }
258
259 static void
260 _access_obj_hilight_hide_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
261 {
262    _elm_access_object_hilight_disable(e);
263 }
264
265 static void
266 _access_obj_hilight_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
267 {
268    Evas_Coord x, y;
269    Evas_Object *o;
270
271    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
272    if (!o) return;
273    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
274    evas_object_move(o, x, y);
275 }
276
277 static void
278 _access_obj_hilight_resize_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
279 {
280    Evas_Coord w, h;
281    Evas_Object *o;
282
283    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
284    if (!o) return;
285    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
286    evas_object_resize(o, w, h);
287 }
288
289 void
290 _elm_access_mouse_event_enabled_set(Eina_Bool enabled)
291 {
292    enabled = !!enabled;
293    if (mouse_event_enable == enabled) return;
294    mouse_event_enable = enabled;
295 }
296
297 void
298 _elm_access_read_mode_set(Eina_Bool enabled)
299 {
300    enabled = !!enabled;
301    if (read_mode == enabled) return;
302    read_mode = enabled;
303 }
304
305 Eina_Bool
306 _elm_access_read_mode_get()
307 {
308    return read_mode;
309 }
310
311 void
312 _elm_access_shutdown()
313 {
314    _access_shutdown();
315 }
316
317 static void
318 _access_order_del_cb(void *data,
319                      Evas *e __UNUSED__,
320                      Evas_Object *obj,
321                      void *event_info __UNUSED__)
322 {
323    Elm_Widget_Item *item = data;
324
325    item->access_order = eina_list_remove(item->access_order, obj);
326 }
327
328 void
329 _elm_access_widget_item_access_order_set(Elm_Widget_Item *item,
330                                               Eina_List *objs)
331 {
332    Eina_List *l;
333    Evas_Object *o;
334
335    if (!item) return;
336
337    _elm_access_widget_item_access_order_unset(item);
338
339    EINA_LIST_FOREACH(objs, l, o)
340      {
341         evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
342                                        _access_order_del_cb, item);
343      }
344
345    item->access_order = objs;
346 }
347
348 const Eina_List *
349 _elm_access_widget_item_access_order_get(const Elm_Widget_Item *item)
350 {
351    if (!item) return NULL;
352    return item->access_order;
353 }
354
355 void
356 _elm_access_widget_item_access_order_unset(Elm_Widget_Item *item)
357 {
358    Eina_List *l, *l_next;
359    Evas_Object *o;
360
361    if (!item) return;
362
363    EINA_LIST_FOREACH_SAFE(item->access_order, l, l_next, o)
364      {
365         evas_object_event_callback_del_full
366           (o, EVAS_CALLBACK_DEL, _access_order_del_cb, item);
367         item->access_order = eina_list_remove_list(item->access_order, l);
368      }
369 }
370 //-------------------------------------------------------------------------//
371 EAPI void
372 _elm_access_highlight_set(Evas_Object* obj)
373 {
374    _access_obj_over_timeout_cb(obj);
375 }
376
377 EAPI void
378 _elm_access_clear(Elm_Access_Info *ac)
379 {
380    Elm_Access_Item *ai;
381
382    if (!ac) return;
383    if (ac->delay_timer)
384      {
385         ecore_timer_del(ac->delay_timer);
386         ac->delay_timer = NULL;
387      }
388    EINA_LIST_FREE(ac->items, ai)
389      {
390         if (!ai->func)
391           {
392              if (ai->data) eina_stringshare_del(ai->data);
393           }
394         free(ai);
395      }
396 }
397
398 EAPI void
399 _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
400 {
401    Elm_Access_Item *ai = _access_add_set(ac, type);
402    if (!ai) return;
403    ai->data = eina_stringshare_add(text);
404 }
405
406 EAPI void
407 _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Info_Cb func, const void *data)
408 {
409    Elm_Access_Item *ai = _access_add_set(ac, type);
410    if (!ai) return;
411    ai->func = func;
412    ai->data = data;
413 }
414
415 EAPI void
416 _elm_access_on_highlight_hook_set(Elm_Access_Info           *ac,
417                                   Elm_Access_On_Highlight_Cb func,
418                                   void                      *data)
419 {
420     if (!ac) return;
421     ac->on_highlight = func;
422     ac->on_highlight_data = data;
423 }
424
425 EAPI void
426 _elm_access_activate_callback_set(Elm_Access_Info           *ac,
427                                   Elm_Access_Activate_Cb     func,
428                                   void                      *data)
429 {
430    if (!ac) return;
431    ac->activate = func;
432    ac->activate_data = data;
433 }
434
435 EAPI void
436 _elm_access_highlight_object_activate(Evas_Object *obj, Elm_Activate act)
437 {
438    Evas_Object *highlight;
439
440    highlight = _access_highlight_object_get(obj);
441    if (!highlight) return;
442
443    _elm_access_read_mode_set(EINA_FALSE);
444
445    if (!elm_object_focus_get(highlight))
446      elm_object_focus_set(highlight, EINA_TRUE);
447
448    elm_widget_activate(highlight, act);
449    return;
450 }
451
452 EAPI void
453 _elm_access_highlight_cycle(Evas_Object *obj, Elm_Focus_Direction dir)
454 {
455    Evas_Object *ho;
456    ho = _access_highlight_object_get(obj);
457    if (!ho) return;
458
459    /* find highlight root */
460    do
461      {
462         ELM_WIDGET_DATA_GET(ho, sd);
463         if (sd->highlight_root)
464           {
465              /* change highlight root */
466              obj = ho;
467              break;
468           }
469         ho = elm_widget_parent_get(ho);
470      }
471    while (ho);
472
473    _elm_access_read_mode_set(EINA_TRUE);
474    elm_widget_focus_cycle(obj, dir);
475    _elm_access_read_mode_set(EINA_FALSE);
476 }
477
478 EAPI char *
479 _elm_access_text_get(const Elm_Access_Info *ac, int type, const Evas_Object *obj)
480 {
481    Elm_Access_Item *ai;
482    Eina_List *l;
483
484    if (!ac) return NULL;
485    EINA_LIST_FOREACH(ac->items, l, ai)
486      {
487         if (ai->type == type)
488           {
489              if (ai->func) return ai->func((void *)(ai->data), (Evas_Object *)obj);
490              else if (ai->data) return strdup(ai->data);
491              return NULL;
492           }
493      }
494    return NULL;
495 }
496
497 EAPI void
498 _elm_access_read(Elm_Access_Info *ac, int type, const Evas_Object *obj)
499 {
500    char *txt = _elm_access_text_get(ac, type, obj);
501
502    if (txt && strlen(txt) == 0) return; /* Tizen only: TTS engine does not work properly */
503
504    _access_init();
505    if (mapi)
506      {
507         if (mapi->out_done_callback_set)
508            mapi->out_done_callback_set(_access_read_done, NULL);
509         if (type == ELM_ACCESS_DONE)
510           {
511              if (mapi->out_read_done) mapi->out_read_done();
512           }
513         else if (type == ELM_ACCESS_CANCEL)
514           {
515              if (mapi->out_cancel) mapi->out_cancel();
516           }
517         else
518           {
519              if (txt && mapi->out_read) mapi->out_read(txt);
520           }
521      }
522    if (txt) free(txt);
523 }
524
525 EAPI void
526 _elm_access_say(const char *txt)
527 {
528    if (!_elm_config->access_mode) return;
529
530    if (txt && strlen(txt) == 0) return; /* Tizen only: TTS engine does not work properly */
531
532    _access_init();
533    if (mapi)
534      {
535         if (mapi->out_done_callback_set)
536            mapi->out_done_callback_set(_access_read_done, NULL);
537         if (mapi->out_cancel) mapi->out_cancel();
538         if (txt)
539           {
540              if (mapi->out_read) mapi->out_read(txt);
541              if (mapi->out_read) mapi->out_read(".\n");
542           }
543         if (mapi->out_read_done) mapi->out_read_done();
544      }
545 }
546
547 EAPI Elm_Access_Info *
548 _elm_access_object_get(const Evas_Object *obj)
549 {
550    return evas_object_data_get(obj, "_elm_access");
551 }
552
553 EAPI void
554 _elm_access_object_hilight(Evas_Object *obj)
555 {
556    Evas_Object *o;
557    Evas_Coord x, y, w, h;
558
559    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
560    if (!o)
561      {
562         o = edje_object_add(evas_object_evas_get(obj));
563         evas_object_name_set(o, "_elm_access_disp");
564         evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
565      }
566    else
567      {
568         Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
569         if (ptarget)
570           {
571              evas_object_data_del(o, "_elm_access_target");
572              elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
573
574              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
575                                                  _access_obj_hilight_del_cb, NULL);
576              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
577                                                  _access_obj_hilight_hide_cb, NULL);
578              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
579                                                  _access_obj_hilight_move_cb, NULL);
580              evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
581                                                  _access_obj_hilight_resize_cb, NULL);
582           }
583      }
584    evas_object_data_set(o, "_elm_access_target", obj);
585    elm_widget_parent_highlight_set(obj, EINA_TRUE);
586
587    elm_widget_theme_object_set(obj, o, "access", "base", "default");
588
589    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
590                                   _access_obj_hilight_del_cb, NULL);
591    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
592                                   _access_obj_hilight_hide_cb, NULL);
593    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
594                                   _access_obj_hilight_move_cb, NULL);
595    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
596                                   _access_obj_hilight_resize_cb, NULL);
597    evas_object_raise(o);
598    evas_object_geometry_get(obj, &x, &y, &w, &h);
599    evas_object_move(o, x, y);
600    evas_object_resize(o, w, h);
601    evas_object_show(o);
602 }
603
604 EAPI void
605 _elm_access_object_unhilight(Evas_Object *obj)
606 {
607    Evas_Object *o, *ptarget;
608
609    o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
610    if (!o) return;
611    ptarget = evas_object_data_get(o, "_elm_access_target");
612    if (ptarget == obj)
613      {
614         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
615                                             _access_obj_hilight_del_cb, NULL);
616         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
617                                             _access_obj_hilight_hide_cb, NULL);
618         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
619                                             _access_obj_hilight_move_cb, NULL);
620         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
621                                             _access_obj_hilight_resize_cb, NULL);
622         evas_object_del(o);
623         elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
624      }
625 }
626
627 static void
628 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
629                 void *event_info __UNUSED__)
630 {
631    Evas_Object *accessobj;
632    Evas_Coord w, h;
633
634    accessobj = data;
635    if (!accessobj) return;
636
637    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
638    evas_object_resize(accessobj, w, h);
639 }
640
641 static void
642 _content_move(void *data, Evas *e __UNUSED__, Evas_Object *obj,
643               void *event_info __UNUSED__)
644 {
645    Evas_Object *accessobj;
646    Evas_Coord x, y;
647
648    accessobj = data;
649    if (!accessobj) return;
650
651    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
652    evas_object_move(accessobj, x, y);
653 }
654
655 static Evas_Object *
656 _access_object_register(Evas_Object *obj, Evas_Object *parent)
657 {
658    Evas_Object *ao;
659    Elm_Access_Info *ac;
660    Evas_Coord x, y, w, h;
661
662    if (!obj) return NULL;
663
664    /* create access object */
665    ao = _elm_access_add(parent);
666    if (!ao) return NULL;
667
668    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
669                                   _content_resize, ao);
670    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
671                                   _content_move, ao);
672
673    evas_object_geometry_get(obj, &x, &y, &w, &h);
674    evas_object_move(ao, x, y);
675    evas_object_resize(ao, w, h);
676    evas_object_show(ao);
677
678    /* register access object */
679    _elm_access_object_register(ao, obj);
680
681    /* set access object */
682    evas_object_data_set(obj, "_part_access_obj", ao);
683
684    /* set owner part object */
685    ac = evas_object_data_get(ao, "_elm_access");
686    ac->part_object = obj;
687
688    return ao;
689 }
690
691 static void
692 _access_object_unregister(Evas_Object *obj)
693 {
694    Elm_Access_Info *ac;
695    Evas_Object *ao;
696
697    if (!obj) return;
698
699    ao = evas_object_data_get(obj, "_part_access_obj");
700
701    if (ao)
702      {
703         evas_object_data_del(obj, "_part_access_obj");
704
705         /* delete callbacks */
706         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
707                                             _content_resize, ao);
708         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
709                                             _content_move, ao);
710
711         /* unregister access object */
712         _elm_access_object_unregister(ao, obj);
713
714         evas_object_del(ao);
715      }
716    else
717      {
718         /* button, check, label etc. */
719         ac = evas_object_data_get(obj, "_elm_access");
720         if (ac && ac->hoverobj)
721           _elm_access_object_unregister(obj, ac->hoverobj);
722      }
723 }
724
725 EAPI Evas_Object *
726 _elm_access_edje_object_part_object_register(Evas_Object* obj,
727                                              const Evas_Object *eobj,
728                                              const char* part)
729 {
730    Evas_Object *ao, *po;
731
732    po = (Evas_Object *)edje_object_part_object_get(eobj, part);
733    if (!obj || !po) return NULL;
734
735    /* check previous access object */
736    ao = evas_object_data_get(po, "_part_access_obj");
737    if (ao)
738      _elm_access_edje_object_part_object_unregister(obj, eobj, part);
739
740    ao = _access_object_register(po, obj);
741
742    return ao;
743 }
744
745 //FIXME: unused obj should be removed from here and each widget.
746 EAPI void
747 _elm_access_edje_object_part_object_unregister(Evas_Object* obj __UNUSED__,
748                                                const Evas_Object *eobj,
749                                                const char* part)
750 {
751    Evas_Object *po;
752
753    po = (Evas_Object *)edje_object_part_object_get(eobj, part);
754    if (!po) return;
755
756    _access_object_unregister(po);
757 }
758
759 EAPI void
760 _elm_access_object_hilight_disable(Evas *e)
761 {
762    Evas_Object *o, *ptarget;
763
764    o = evas_object_name_find(e, "_elm_access_disp");
765    if (!o) return;
766    ptarget = evas_object_data_get(o, "_elm_access_target");
767    if (ptarget)
768      {
769         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
770                                             _access_obj_hilight_del_cb, NULL);
771         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
772                                             _access_obj_hilight_hide_cb, NULL);
773         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
774                                             _access_obj_hilight_move_cb, NULL);
775         evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
776                                             _access_obj_hilight_resize_cb, NULL);
777      }
778    evas_object_del(o);
779    elm_widget_parent_highlight_set(ptarget, EINA_FALSE);
780 }
781
782 EAPI void
783 _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
784 {
785    Elm_Access_Info *ac;
786
787    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
788                                   _access_obj_mouse_in_cb, obj);
789    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
790                                   _access_obj_mouse_out_cb, obj);
791    evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
792                                   _access_obj_del_cb, obj);
793    ac = calloc(1, sizeof(Elm_Access_Info));
794    evas_object_data_set(obj, "_elm_access", ac);
795
796    ac->hoverobj = hoverobj;
797 }
798
799 EAPI void
800 _elm_access_object_unregister(Evas_Object *obj, Evas_Object *hoverobj)
801 {
802    Elm_Access_Info *ac;
803
804    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_IN,
805                                        _access_obj_mouse_in_cb, obj);
806    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
807                                        _access_obj_mouse_out_cb, obj);
808    evas_object_event_callback_del_full(hoverobj, EVAS_CALLBACK_DEL,
809                                        _access_obj_del_cb, obj);
810
811    ac = evas_object_data_get(obj, "_elm_access");
812    evas_object_data_del(obj, "_elm_access");
813    if (ac)
814      {
815         _elm_access_clear(ac);
816         free(ac);
817      }
818 }
819
820 EAPI void
821 _elm_access_widget_item_register(Elm_Widget_Item *item)
822 {
823    Evas_Object *ao, *ho;
824    Evas_Coord x, y, w, h;
825    Elm_Access_Info *ac;
826
827    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
828
829    /* check previous access object */
830    if (item->access_obj)
831      _elm_access_widget_item_unregister(item);
832
833    // create access object
834    ho = item->view;
835    ao = _elm_access_add(item->widget);
836    if (!ao) return;
837
838    evas_object_event_callback_add(ho, EVAS_CALLBACK_RESIZE,
839                                   _content_resize, ao);
840    evas_object_event_callback_add(ho, EVAS_CALLBACK_MOVE,
841                                   _content_move, ao);
842
843    evas_object_geometry_get(ho, &x, &y, &w, &h);
844    evas_object_move(ao, x, y);
845    evas_object_resize(ao, w, h);
846    evas_object_show(ao);
847
848    // register access object
849    _elm_access_object_register(ao, ho);
850
851    item->access_obj = ao;
852
853    /* set owner widget item */
854    ac = evas_object_data_get(ao, "_elm_access");
855    ac->widget_item = item;
856 }
857
858 EAPI void
859 _elm_access_widget_item_unregister(Elm_Widget_Item *item)
860 {
861    Evas_Object *ho;
862
863    ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
864
865    if (!item->access_obj) return;
866
867    ho = item->view;
868    evas_object_event_callback_del_full(ho, EVAS_CALLBACK_RESIZE,
869                                   _content_resize, item->access_obj);
870    evas_object_event_callback_del_full(ho, EVAS_CALLBACK_MOVE,
871                                   _content_move, item->access_obj);
872
873    _elm_access_object_unregister(item->access_obj, ho);
874
875    evas_object_del(item->access_obj);
876    item->access_obj = NULL;
877 }
878
879 EAPI Eina_Bool
880 _elm_access_2nd_click_timeout(Evas_Object *obj)
881 {
882    Ecore_Timer *t;
883
884    t = evas_object_data_get(obj, "_elm_2nd_timeout");
885    if (t)
886      {
887         ecore_timer_del(t);
888         evas_object_data_del(obj, "_elm_2nd_timeout");
889         evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
890                                             _access_2nd_click_del_cb, NULL);
891         return EINA_TRUE;
892      }
893    t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
894    evas_object_data_set(obj, "_elm_2nd_timeout", t);
895    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
896                                   _access_2nd_click_del_cb, NULL);
897    return EINA_FALSE;
898 }
899
900 static Evas_Object *
901 _elm_access_add(Evas_Object *parent)
902 {
903    Evas_Object *obj;
904
905    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
906
907    obj = elm_widget_add(_elm_access_smart_class_new(), parent);
908    if (!obj) return NULL;
909
910    if (!elm_widget_sub_object_add(parent, obj))
911      ERR("could not add %p as sub object of %p", obj, parent);
912
913    return obj;
914 }
915
916 EAPI Evas_Object *
917 elm_access_object_register(Evas_Object *obj, Evas_Object *parent)
918 {
919    return _access_object_register(obj, parent);
920 }
921
922 EAPI void
923 elm_access_object_unregister(Evas_Object *obj)
924 {
925    _access_object_unregister(obj);
926 }
927
928 EAPI Evas_Object *
929 elm_access_object_get(const Evas_Object *obj)
930 {
931    return evas_object_data_get(obj, "_part_access_obj");
932 }
933
934 EAPI void
935 elm_access_info_set(Evas_Object *obj, int type, const char *text)
936 {
937    _elm_access_text_set(_elm_access_object_get(obj), type, text);
938 }
939
940 EAPI char *
941 elm_access_info_get(const Evas_Object *obj, int type)
942 {
943    return _elm_access_text_get(_elm_access_object_get(obj), type, obj);
944 }
945
946 EAPI void
947 elm_access_info_cb_set(Evas_Object *obj, int type,
948                           Elm_Access_Info_Cb func, const void *data)
949 {
950    _elm_access_callback_set(_elm_access_object_get(obj), type, func, data);
951 }
952
953 EAPI void
954 elm_access_activate_cb_set(Evas_Object *obj,
955                            Elm_Access_Activate_Cb  func, void *data)
956 {
957    Elm_Access_Info *ac;
958
959    ac = _elm_access_object_get(obj);
960    if (!ac) return;
961
962    ac->activate = func;
963    ac->activate_data = data;
964 }
965
966 EAPI void
967 elm_access_say(const char *text)
968 {
969    if (!text) return;
970
971    _elm_access_say(text);
972 }
973
974 EAPI void
975 elm_access_highlight_set(Evas_Object* obj)
976 {
977    _access_obj_over_timeout_cb(obj);
978 }
979
980 EAPI void
981 elm_access_external_info_set(Evas_Object *obj, const char *text)
982 {
983    _elm_access_text_set
984      (_elm_access_object_get(obj), ELM_ACCESS_CONTEXT_INFO, text);
985 }
986
987 EAPI char *
988 elm_access_external_info_get(const Evas_Object *obj)
989 {
990    Elm_Access_Info *ac;
991
992    ac = _elm_access_object_get(obj);
993    return _elm_access_text_get(ac, ELM_ACCESS_CONTEXT_INFO, obj);
994 }