fix: x11 get priority over wayland when both available
[platform/core/uifw/efl-assist.git] / src / lib / efl_assist_screen_reader.c
1 #include "efl_assist.h"
2 #include "efl_assist_private.h"
3
4 #include <Ecore.h>
5
6 #ifdef HAVE_X
7 #include <Ecore_X.h>
8 #endif
9 #ifdef HAVE_WAYLAND
10 #include <Ecore_Wayland.h>
11 #endif
12
13 #include <vconf.h>
14 #include <tts.h>
15 #define UNAVAILABLE_TEXT "Screen reader is unavailable during using this application. You can press home or back key to go back to home screen."
16
17 static tts_h tts = NULL;
18
19 static void _tts_shutdown(void)
20 {
21    int ret = 0;
22    if (tts)
23      {
24         /* check current state */
25         tts_state_e state;
26         tts_get_state(tts, &state);
27         if (state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED)
28           {
29              ret = tts_stop(tts);
30              if (TTS_ERROR_NONE != ret)
31                {
32                   fprintf(stderr, "Fail to stop handle : result(%d)", ret);
33                   return;
34                }
35           }
36
37         /* it is possible to try to shutdown before the state is ready,
38            because tts_prepare(); works Asynchronously. see elm_modapi_init(): */
39         if (state == TTS_STATE_READY)
40           {
41              ret = tts_unprepare(tts);
42              if (TTS_ERROR_NONE != ret)
43                {
44                   fprintf(stderr, "Fail to unprepare handle : result(%d)", ret);
45                   return;
46                }
47
48              ret = tts_unset_state_changed_cb(tts);
49              if (TTS_ERROR_NONE != ret)
50                {
51                   fprintf(stderr, "Fail to set callback : result(%d)", ret);
52                   return;
53                }
54           }
55
56         ret = tts_destroy(tts);
57         if (TTS_ERROR_NONE != ret)
58           {
59              fprintf(stderr, "Fail to destroy handle : result(%d)", ret);
60              return;
61           }
62
63         if (tts) tts = NULL;
64      }
65 }
66
67 void _tts_state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* data)
68 {
69    int ret = 0;
70    int u_id = 0;
71
72    if (TTS_STATE_CREATED == previous && TTS_STATE_READY == current)
73      {
74         ret = tts_add_text(tts, UNAVAILABLE_TEXT, NULL, TTS_VOICE_TYPE_AUTO,
75                            TTS_SPEED_AUTO, &u_id);
76         if (TTS_ERROR_NONE != ret)
77           {
78              fprintf(stderr, "Fail to add kept text : ret(%d)\n", ret);
79           }
80
81         ret = tts_play(tts);
82         if (TTS_ERROR_NONE != ret)
83           {
84              fprintf(stderr, "Fail to play TTS : ret(%d)\n", ret);
85           }
86      }
87 }
88
89 static void _tts_init(void)
90 {
91    int ret = 0;
92
93    ret = tts_create(&tts);
94    if (TTS_ERROR_NONE != ret)
95      {
96         fprintf(stderr, "Fail to get handle : result(%d)", ret);
97         return;
98      }
99
100    ret = tts_set_state_changed_cb(tts, _tts_state_changed_cb, NULL);
101    if (TTS_ERROR_NONE != ret)
102      {
103         fprintf(stderr, "Fail to set callback : result(%d)", ret);
104         return;
105      }
106
107    ret = tts_set_mode(tts, TTS_MODE_SCREEN_READER);
108    if (TTS_ERROR_NONE != ret)
109      {
110         fprintf(stderr, "Fail to set mode : result(%d)", ret);
111         return;
112      }
113
114    ret = tts_prepare(tts);
115    if (TTS_ERROR_NONE != ret)
116      {
117         fprintf(stderr, "Fail to prepare handle : result(%d)", ret);
118         return;
119      }
120 }
121
122 static void _timeout_cb(void *data, Evas_Object *obj, void *event_info)
123 {
124 #ifdef HAVE_X
125    Ecore_X_Window w;
126 #elif defined HAVE_WAYLAND
127    Ecore_Wl_Window *w;
128 #endif
129
130    unsigned int val;
131
132 #ifdef HAVE_X
133    w = elm_win_xwindow_get(data);
134 #elif defined HAVE_WAYLAND
135    w = elm_win_wl_window_get(data);
136 #endif
137    if (!w) return;
138
139    evas_object_del(obj);
140
141 #ifdef HAVE_X
142    val = 2;
143    ecore_x_window_prop_card32_set
144      (win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, &val, 1);
145 #else
146    fprintf(stderr, "TODO: workaround: disabled code from "
147            __FILE__ ":%d:", __LINE__);
148 #endif
149    _tts_shutdown();
150
151 }
152
153 EAPI Eina_Bool
154 ea_screen_reader_support_set(Evas_Object *win, Eina_Bool support)
155 {
156 #ifdef HAVE_X
157    Ecore_X_Window w;
158 #elif defined HAVE_WAYLAND
159    Ecore_Wl_Window *w;
160 #endif
161    unsigned int val;
162    int tts_val;
163    Evas_Object *base;
164    Evas_Object *body;
165    Evas_Object *popup;
166
167    if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &tts_val) != 0)
168      return EINA_FALSE;
169
170    if (!tts_val) return EINA_FALSE;
171
172    if (!win) return EINA_FALSE;
173
174 #ifdef HAVE_WAYLAND
175    w = elm_win_wl_window_get(win);
176 #elif HAVE_X
177    w = elm_win_xwindow_get(win);
178 #endif
179
180    if (!w) return EINA_FALSE;
181
182    if (support)
183      {
184         val = 0;
185         elm_config_access_set(EINA_TRUE);
186 #ifdef HAVE_X
187         ecore_x_window_prop_card32_set
188           (w, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, &val, 1);
189 #else
190         fprintf(stderr, "TODO: workaround: disabled code from "
191                 __FILE__ ":%d:", __LINE__);
192 #endif
193      }
194    else
195      {
196         elm_config_access_set(EINA_FALSE);
197
198         popup = elm_popup_add(win);
199         evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
200         elm_object_text_set(popup, UNAVAILABLE_TEXT);
201         elm_popup_timeout_set(popup, 12.0);
202         evas_object_smart_callback_add(popup, "timeout", _timeout_cb, win);
203
204         _tts_init();
205         evas_object_show(popup);
206      }
207
208    return EINA_TRUE;
209 }
210
211 EAPI Eina_Bool
212 ea_screen_reader_support_get()
213 {
214    return elm_config_access_get();
215 }