aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/elementary/src/lib/elm_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/elementary/src/lib/elm_access.c')
-rw-r--r--libraries/elementary/src/lib/elm_access.c536
1 files changed, 536 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_access.c b/libraries/elementary/src/lib/elm_access.c
new file mode 100644
index 0000000..4ea5582
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_access.c
@@ -0,0 +1,536 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Mod_Api Mod_Api;
5
6struct _Mod_Api
7{
8 void (*out_read) (const char *txt);
9 void (*out_read_done) (void);
10 void (*out_cancel) (void);
11 void (*out_done_callback_set) (void (*func) (void *data), const void *data);
12};
13
14static int initted = 0;
15static Mod_Api *mapi = NULL;
16
17static void
18_access_init(void)
19{
20 Elm_Module *m;
21 initted++;
22 if (initted > 1) return;
23 if (!(m = _elm_module_find_as("access/api"))) return;
24 m->api = malloc(sizeof(Mod_Api));
25 if (!m->api) return;
26 m->init_func(m);
27 ((Mod_Api *)(m->api) )->out_read = // called to read out some text
28 _elm_module_symbol_get(m, "out_read");
29 ((Mod_Api *)(m->api) )->out_read_done = // called to set a done marker so when it is reached the done callback is called
30 _elm_module_symbol_get(m, "out_read_done");
31 ((Mod_Api *)(m->api) )->out_cancel = // called to read out some text
32 _elm_module_symbol_get(m, "out_cancel");
33 ((Mod_Api *)(m->api) )->out_done_callback_set = // called when last read done
34 _elm_module_symbol_get(m, "out_done_callback_set");
35 mapi = m->api;
36}
37
38static Elm_Access_Item *
39_access_add_set(Elm_Access_Info *ac, int type)
40{
41 Elm_Access_Item *ai;
42 Eina_List *l;
43
44 if (!ac) return NULL;
45 EINA_LIST_FOREACH(ac->items, l, ai)
46 {
47 if (ai->type == type)
48 {
49 if (!ai->func)
50 {
51 if (ai->data) eina_stringshare_del(ai->data);
52 }
53 ai->func = NULL;
54 ai->data = NULL;
55 return ai;
56 }
57 }
58 ai = calloc(1, sizeof(Elm_Access_Item));
59 ai->type = type;
60 ac->items = eina_list_prepend(ac->items, ai);
61 return ai;
62}
63
64static Eina_Bool
65_access_obj_over_timeout_cb(void *data)
66{
67 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
68 if (!ac) return EINA_FALSE;
69 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
70 {
71 _elm_access_object_hilight(data);
72 _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
73 _elm_access_read(ac, ELM_ACCESS_TYPE, data, NULL);
74 _elm_access_read(ac, ELM_ACCESS_INFO, data, NULL);
75 _elm_access_read(ac, ELM_ACCESS_STATE, data, NULL);
76 _elm_access_read(ac, ELM_ACCESS_DONE, data, NULL);
77 }
78 ac->delay_timer = NULL;
79 return EINA_FALSE;
80}
81
82static void
83_access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
84{
85 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
86 if (!ac) return;
87
88 if (ac->delay_timer)
89 {
90 ecore_timer_del(ac->delay_timer);
91 ac->delay_timer = NULL;
92 }
93 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
94 ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
95}
96
97static void
98_access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
99{
100 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
101 if (!ac) return;
102 _elm_access_object_unhilight(data);
103 if (ac->delay_timer)
104 {
105 ecore_timer_del(ac->delay_timer);
106 ac->delay_timer = NULL;
107 }
108}
109
110static void
111_access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
112{
113 Elm_Access_Info *ac;
114
115 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
116 _access_obj_mouse_in_cb, data);
117 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
118 _access_obj_mouse_out_cb, data);
119 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
120 _access_obj_del_cb, data);
121 ac = evas_object_data_get(data, "_elm_access");
122 evas_object_data_del(data, "_elm_access");
123 if (ac)
124 {
125 _elm_access_clear(ac);
126 free(ac);
127 }
128}
129
130static void
131_access_read_done(void *data __UNUSED__)
132{
133 printf("read done\n");
134 // FIXME: produce event here
135}
136
137static void
138_access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
139{
140 Ecore_Timer *t;
141
142 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
143 _access_2nd_click_del_cb, NULL);
144 t = evas_object_data_get(obj, "_elm_2nd_timeout");
145 if (t)
146 {
147 ecore_timer_del(t);
148 evas_object_data_del(obj, "_elm_2nd_timeout");
149 }
150}
151
152static Eina_Bool
153_access_2nd_click_timeout_cb(void *data)
154{
155 evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
156 _access_2nd_click_del_cb, NULL);
157 evas_object_data_del(data, "_elm_2nd_timeout");
158 return EINA_FALSE;
159}
160
161static void
162_access_obj_hilight_del_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
163{
164 _elm_access_object_hilight_disable(e);
165}
166
167static void
168_access_obj_hilight_hide_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
169{
170 _elm_access_object_hilight_disable(e);
171}
172
173static void
174_access_obj_hilight_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
175{
176 Evas_Coord x, y;
177 Evas_Object *o;
178
179 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
180 if (!o) return;
181 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
182 evas_object_move(o, x, y);
183}
184
185static void
186_access_obj_hilight_resize_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
187{
188 Evas_Coord w, h;
189 Evas_Object *o;
190
191 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
192 if (!o) return;
193 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
194 evas_object_resize(o, w, h);
195}
196
197
198
199//-------------------------------------------------------------------------//
200
201EAPI void
202_elm_access_clear(Elm_Access_Info *ac)
203{
204 Elm_Access_Item *ai;
205
206 if (!ac) return;
207 if (ac->delay_timer)
208 {
209 ecore_timer_del(ac->delay_timer);
210 ac->delay_timer = NULL;
211 }
212 EINA_LIST_FREE(ac->items, ai)
213 {
214 if (!ai->func)
215 {
216 if (ai->data) eina_stringshare_del(ai->data);
217 }
218 free(ai);
219 }
220}
221
222EAPI void
223_elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
224{
225 Elm_Access_Item *ai = _access_add_set(ac, type);
226 if (!ai) return;
227 ai->data = eina_stringshare_add(text);
228}
229
230EAPI void
231_elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
232{
233 Elm_Access_Item *ai = _access_add_set(ac, type);
234 if (!ai) return;
235 ai->func = func;
236 ai->data = data;
237}
238
239EAPI char *
240_elm_access_text_get(const Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
241{
242 Elm_Access_Item *ai;
243 Eina_List *l;
244
245 if (!ac) return NULL;
246 EINA_LIST_FOREACH(ac->items, l, ai)
247 {
248 if (ai->type == type)
249 {
250 if (ai->func) return ai->func((void *)(ai->data), obj, item);
251 else if (ai->data) return strdup(ai->data);
252 return NULL;
253 }
254 }
255 return NULL;
256}
257
258EAPI void
259_elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
260{
261 char *txt = _elm_access_text_get(ac, type, obj, item);
262
263 _access_init();
264 if (mapi)
265 {
266 if (mapi->out_done_callback_set)
267 mapi->out_done_callback_set(_access_read_done, NULL);
268 if (type == ELM_ACCESS_DONE)
269 {
270 if (mapi->out_read_done) mapi->out_read_done();
271 }
272 else if (type == ELM_ACCESS_CANCEL)
273 {
274 if (mapi->out_cancel) mapi->out_cancel();
275 }
276 else
277 {
278 if (txt)
279 {
280 if (mapi->out_read) mapi->out_read(txt);
281 if (mapi->out_read) mapi->out_read(".\n");
282 }
283 }
284 }
285 if (txt) free(txt);
286}
287
288EAPI void
289_elm_access_say(const char *txt)
290{
291 _access_init();
292 if (mapi)
293 {
294 if (mapi->out_done_callback_set)
295 mapi->out_done_callback_set(_access_read_done, NULL);
296 if (mapi->out_cancel) mapi->out_cancel();
297 if (txt)
298 {
299 if (mapi->out_read) mapi->out_read(txt);
300 if (mapi->out_read) mapi->out_read(".\n");
301 }
302 if (mapi->out_read_done) mapi->out_read_done();
303 }
304}
305
306EAPI Elm_Access_Info *
307_elm_access_object_get(const Evas_Object *obj)
308{
309 return evas_object_data_get(obj, "_elm_access");
310}
311
312EAPI Elm_Access_Info *
313_elm_access_item_get(const Elm_Widget_Item *it)
314{
315 return it->access;
316}
317
318EAPI void
319_elm_access_object_hilight(Evas_Object *obj)
320{
321 Evas_Object *o;
322 Evas_Coord x, y, w, h;
323
324 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
325 if (!o)
326 {
327 o = edje_object_add(evas_object_evas_get(obj));
328 evas_object_name_set(o, "_elm_access_disp");
329 evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
330 }
331 else
332 {
333 Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
334 if (ptarget)
335 {
336 evas_object_data_del(o, "_elm_access_target");
337 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
338 _access_obj_hilight_del_cb, NULL);
339 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
340 _access_obj_hilight_hide_cb, NULL);
341 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
342 _access_obj_hilight_move_cb, NULL);
343 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
344 _access_obj_hilight_resize_cb, NULL);
345 }
346 }
347 evas_object_data_set(o, "_elm_access_target", obj);
348 _elm_theme_object_set(obj, o, "access", "base", "default");
349 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
350 _access_obj_hilight_del_cb, NULL);
351 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
352 _access_obj_hilight_hide_cb, NULL);
353 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
354 _access_obj_hilight_move_cb, NULL);
355 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
356 _access_obj_hilight_resize_cb, NULL);
357 evas_object_raise(o);
358 evas_object_geometry_get(obj, &x, &y, &w, &h);
359 evas_object_move(o, x, y);
360 evas_object_resize(o, w, h);
361 evas_object_show(o);
362}
363
364EAPI void
365_elm_access_object_unhilight(Evas_Object *obj)
366{
367 Evas_Object *o, *ptarget;
368
369 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
370 if (!o) return;
371 ptarget = evas_object_data_get(o, "_elm_access_target");
372 if (ptarget == obj)
373 {
374 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
375 _access_obj_hilight_del_cb, NULL);
376 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
377 _access_obj_hilight_hide_cb, NULL);
378 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
379 _access_obj_hilight_move_cb, NULL);
380 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
381 _access_obj_hilight_resize_cb, NULL);
382 evas_object_del(o);
383 }
384}
385
386EAPI void
387_elm_access_object_hilight_disable(Evas *e)
388{
389 Evas_Object *o, *ptarget;
390
391 o = evas_object_name_find(e, "_elm_access_disp");
392 if (!o) return;
393 ptarget = evas_object_data_get(o, "_elm_access_target");
394 if (ptarget)
395 {
396 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
397 _access_obj_hilight_del_cb, NULL);
398 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
399 _access_obj_hilight_hide_cb, NULL);
400 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
401 _access_obj_hilight_move_cb, NULL);
402 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
403 _access_obj_hilight_resize_cb, NULL);
404 }
405 evas_object_del(o);
406}
407
408EAPI void
409_elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
410{
411 Elm_Access_Info *ac;
412
413 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
414 _access_obj_mouse_in_cb, obj);
415 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
416 _access_obj_mouse_out_cb, obj);
417 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
418 _access_obj_del_cb, obj);
419 ac = calloc(1, sizeof(Elm_Access_Info));
420 evas_object_data_set(obj, "_elm_access", ac);
421}
422
423static Eina_Bool
424_access_item_over_timeout_cb(void *data)
425{
426 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
427 if (!ac) return EINA_FALSE;
428 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
429 {
430 _elm_access_object_hilight(((Elm_Widget_Item *)data)->view);
431 _elm_access_read(ac, ELM_ACCESS_CANCEL, NULL, data);
432 _elm_access_read(ac, ELM_ACCESS_TYPE, NULL, data);
433 _elm_access_read(ac, ELM_ACCESS_INFO, NULL, data);
434 _elm_access_read(ac, ELM_ACCESS_STATE, NULL, data);
435 _elm_access_read(ac, ELM_ACCESS_DONE, NULL, data);
436 }
437 ac->delay_timer = NULL;
438 return EINA_FALSE;
439}
440
441static void
442_access_item_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
443{
444 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
445 if (!ac) return;
446
447 if (ac->delay_timer)
448 {
449 ecore_timer_del(ac->delay_timer);
450 ac->delay_timer = NULL;
451 }
452 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
453 ac->delay_timer = ecore_timer_add(0.2, _access_item_over_timeout_cb, data);
454}
455
456static void
457_access_item_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
458{
459 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
460 if (!ac) return;
461
462 _elm_access_object_unhilight(((Elm_Widget_Item *)data)->view);
463 if (ac->delay_timer)
464 {
465 ecore_timer_del(ac->delay_timer);
466 ac->delay_timer = NULL;
467 }
468}
469
470static void _access_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
471
472EAPI void
473_elm_access_item_unregister(Elm_Widget_Item *item)
474{
475 Elm_Access_Info *ac;
476
477 ac = item->access;
478 if (ac)
479 {
480 evas_object_event_callback_del_full(ac->hoverobj,
481 EVAS_CALLBACK_MOUSE_IN,
482 _access_item_mouse_in_cb, item);
483 evas_object_event_callback_del_full(ac->hoverobj,
484 EVAS_CALLBACK_MOUSE_OUT,
485 _access_item_mouse_out_cb, item);
486 evas_object_event_callback_del_full(ac->hoverobj,
487 EVAS_CALLBACK_DEL,
488 _access_item_del_cb, item);
489 item->access = NULL;
490 _elm_access_clear(ac);
491 free(ac);
492 }
493}
494
495static void
496_access_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
497{
498 _elm_access_item_unregister((Elm_Widget_Item *)data);
499}
500
501EAPI void
502_elm_access_item_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
503{
504 Elm_Access_Info *ac;
505
506 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
507 _access_item_mouse_in_cb, item);
508 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
509 _access_item_mouse_out_cb, item);
510 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
511 _access_item_del_cb, item);
512 ac = calloc(1, sizeof(Elm_Access_Info));
513 ac->hoverobj = hoverobj;
514 item->access = ac;
515}
516
517EAPI Eina_Bool
518_elm_access_2nd_click_timeout(Evas_Object *obj)
519{
520 Ecore_Timer *t;
521
522 t = evas_object_data_get(obj, "_elm_2nd_timeout");
523 if (t)
524 {
525 ecore_timer_del(t);
526 evas_object_data_del(obj, "_elm_2nd_timeout");
527 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
528 _access_2nd_click_del_cb, NULL);
529 return EINA_TRUE;
530 }
531 t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
532 evas_object_data_set(obj, "_elm_2nd_timeout", t);
533 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
534 _access_2nd_click_del_cb, NULL);
535 return EINA_FALSE;
536}