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