Update the accessibility event handler.
[apps/native/widget/widget.git] / src / virtual_window.c
1 #include <Elementary.h>
2 #include <string.h>
3 #include <Ecore_Evas.h>
4 #include <Evas.h>
5
6 #include <dlog.h>
7 #include <livebox-errno.h>
8 #include <livebox-service.h>
9
10 #include "livebox.h"
11
12 #define IS_PD 1
13
14 #define PUBLIC __attribute__((visibility("default")))
15 /*!
16  * \brief
17  * Abstracted Data Type of Virtual Window
18  */
19 struct info {
20         char *id; /*!< Identification */
21         int width; /*!< Width */
22         int height; /*!< Height */
23         struct livebox_buffer *handle; /*!< Livebox buffer handle */
24         Evas_Object *window; /*!< Parent evas object - WARN: Incompatible with the elm_win object */
25         int is_hw; /*!< 1 if a buffer is created on the H/W accelerated place or 0 */
26 };
27
28 /*!
29  * \note
30  * Every user event (mouse) on the buffer will be passed via this event callback
31  */
32 static int event_handler_cb(struct livebox_buffer *handler, enum buffer_event evt, double timestamp, double x, double y, void *data)
33 {
34         struct info *info = data;
35         Elm_Access_Action_Info action_info;
36         Elm_Access_Action_Type action_type;
37         Evas *e;
38         Ecore_Evas *ee;
39         Evas_Object *parent_elm;
40         int ix;
41         int iy;
42         int ret = 0;
43
44         if (!info->handle) {
45                 /* Just ignore this event */
46                 return 0;
47         }
48
49         /*!
50          * \note
51          * Calculate the event occurred X & Y on the buffer
52          */
53         ix = info->width * x;
54         iy = info->height * y;
55
56         memset(&action_info, 0, sizeof(action_info));
57
58         e = evas_object_evas_get(info->window);
59         ee = ecore_evas_ecore_evas_get(e);
60         parent_elm = ecore_evas_data_get(ee, "parent,elm");
61
62         /*!
63          * \note
64          * Feed up events
65          */
66         switch (evt) {
67         case BUFFER_EVENT_ENTER:
68                 evas_event_feed_mouse_in(e, timestamp * 1000, NULL);
69                 break;
70         case BUFFER_EVENT_LEAVE:
71                 evas_event_feed_mouse_out(e, timestamp * 1000, NULL);
72                 break;
73         case BUFFER_EVENT_DOWN:
74                 evas_event_feed_mouse_in(e, timestamp * 1000, NULL);
75                 evas_event_feed_mouse_move(e, ix, iy, (timestamp + 0.01f) * 1000, NULL); /* + 0.1f just for fake event */
76                 evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, (timestamp + 0.02f) * 1000, NULL); /* + 0.2f just for fake event */
77                 break;
78         case BUFFER_EVENT_MOVE:
79                 evas_event_feed_mouse_move(e, ix, iy, timestamp * 1000, NULL);
80                 break;
81         case BUFFER_EVENT_UP:
82                 evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, timestamp * 1000, NULL);
83                 evas_event_feed_mouse_out(e, (timestamp + 0.01f) * 1000, NULL); /* + 0.1f just for fake event */
84                 break;
85         case BUFFER_EVENT_HIGHLIGHT:
86                 if (!parent_elm) {
87                         ret = LB_ACCESS_STATUS_ERROR;
88                         break;
89                 }
90                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
91                 action_info.x = ix;
92                 action_info.y = iy;
93                 ret = elm_access_action(parent_elm, action_type, &action_info);
94                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
95                 break;
96         case BUFFER_EVENT_HIGHLIGHT_NEXT:
97                 if (!parent_elm) {
98                         ret = LB_ACCESS_STATUS_ERROR;
99                         break;
100                 }
101                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
102                 action_info.highlight_cycle = EINA_FALSE;
103                 ret = elm_access_action(parent_elm, action_type, &action_info);
104                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_LAST : LB_ACCESS_STATUS_DONE;
105                 break;
106         case BUFFER_EVENT_HIGHLIGHT_PREV:
107                 if (!parent_elm) {
108                         ret = LB_ACCESS_STATUS_ERROR;
109                         break;
110                 }
111                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
112                 action_info.highlight_cycle = EINA_FALSE;
113                 ret = elm_access_action(parent_elm, action_type, &action_info);
114                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_FIRST : LB_ACCESS_STATUS_DONE;
115                 break;
116         case BUFFER_EVENT_ACTIVATE:
117                 if (!parent_elm) {
118                         ret = LB_ACCESS_STATUS_ERROR;
119                         break;
120                 }
121                 action_type = ELM_ACCESS_ACTION_ACTIVATE;
122                 ret = elm_access_action(parent_elm, action_type, &action_info);
123                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
124                 break;
125         case BUFFER_EVENT_ACTION_UP:
126                 if (!parent_elm) {
127                         ret = LB_ACCESS_STATUS_ERROR;
128                         break;
129                 }
130                 action_type = ELM_ACCESS_ACTION_UP;
131                 ret = elm_access_action(parent_elm, action_type, &action_info);
132                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
133                 break;
134         case BUFFER_EVENT_ACTION_DOWN:
135                 if (!parent_elm) {
136                         ret = LB_ACCESS_STATUS_ERROR;
137                         break;
138                 }
139                 action_type = ELM_ACCESS_ACTION_DOWN;
140                 ret = elm_access_action(parent_elm, action_type, &action_info);
141                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
142                 break;
143         case BUFFER_EVENT_SCROLL_UP:
144                 if (!parent_elm) {
145                         ret = LB_ACCESS_STATUS_ERROR;
146                         break;
147                 }
148                 action_type = ELM_ACCESS_ACTION_SCROLL;
149                 action_info.x = ix;
150                 action_info.y = iy;
151                 action_info.mouse_type = 0;
152                 ret = elm_access_action(parent_elm, action_type, &action_info);
153                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
154                 break;
155         case BUFFER_EVENT_SCROLL_MOVE:
156                 if (!parent_elm) {
157                         ret = LB_ACCESS_STATUS_ERROR;
158                         break;
159                 }
160                 action_info.x = ix;
161                 action_info.y = iy;
162                 action_info.mouse_type = 1;
163                 ret = elm_access_action(parent_elm, action_type, &action_info);
164                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
165                 break;
166         case BUFFER_EVENT_SCROLL_DOWN:
167                 if (!parent_elm) {
168                         ret = LB_ACCESS_STATUS_ERROR;
169                         break;
170                 }
171                 action_info.mouse_type = 2;
172                 ret = elm_access_action(parent_elm, action_type, &action_info);
173                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
174                 break;
175         case BUFFER_EVENT_UNHIGHLIGHT:
176                 if (!parent_elm) {
177                         ret = LB_ACCESS_STATUS_ERROR;
178                         break;
179                 }
180                 action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
181                 ret = elm_access_action(parent_elm, action_type, &action_info);
182                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
183                 break;
184         default:
185                 LOGD("Unhandled buffer event (%d)\n", evt);
186                 break;
187         }
188
189         return ret;
190 }
191
192 static void *alloc_fb(void *data, int size)
193 {
194         struct info *info = data;
195         void *buffer;
196
197         /*!
198          * Acquire a buffer for canvas.
199          */
200         info->handle = livebox_acquire_buffer(info->id, IS_PD,
201                                         info->width, info->height,
202                                         event_handler_cb, info);
203
204         /*!
205          * If it supports the H/W accelerated buffer,
206          * Use it.
207          */
208         if (livebox_support_hw_buffer(info->handle)) {
209                 if (livebox_create_hw_buffer(info->handle) == 0) {
210                         buffer = livebox_buffer_hw_buffer(info->handle);
211                         if (buffer) {
212                                 LOGD("HW Accelerated buffer is created\n");
213                                 info->is_hw = 1;
214                                 return buffer;
215                         }
216                 }
217
218                 LOGE("Failed to allocate HW Accelerated buffer\n");
219         }
220
221         /*!
222          * Or use the buffer of a S/W backend.
223          */
224         buffer = livebox_ref_buffer(info->handle);
225         LOGD("SW buffer is created\n");
226         info->is_hw = 0;
227         return buffer;
228 }
229
230 static void free_fb(void *data, void *ptr)
231 {
232         struct info *info = data;
233
234         if (!info->handle)
235                 return;
236
237         if (info->is_hw) {
238                 if (livebox_destroy_hw_buffer(info->handle) == 0) {
239                         LOGD("HW Accelerated buffer is destroyed\n");
240                         goto out;
241                 }
242         }
243
244         livebox_unref_buffer(ptr);
245         LOGD("SW buffer is destroyed\n");
246 out:
247         livebox_release_buffer(info->handle);
248         info->handle = NULL;
249 }
250
251 static void resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
252 {
253         struct info *info = data;
254         Ecore_Evas *ee;
255
256         ee = ecore_evas_ecore_evas_get(e);
257         if (!ee)
258                 return;
259
260         evas_object_geometry_get(obj, NULL, NULL, &info->width, &info->height);
261         SECURE_LOGD("Resize to %dx%d\n", info->width, info->height);
262         /*!
263          * Box(parent object) is resized.
264          * Try to resize the canvas too.
265          */
266         ecore_evas_resize(ee, info->width, info->height);
267 }
268
269 /*!
270  * If a canvas is destroyed,
271  * Free all buffer of canvas.
272  */
273 static void del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
274 {
275         Ecore_Evas *ee;
276         struct info *info = data;
277
278         ee = ecore_evas_ecore_evas_get(e);
279         if (!ee)
280                 return;
281
282         ecore_evas_free(ee);
283         free(info->id);
284         free(info);
285 }
286
287 static void pre_render_cb(void *data, Evas *e, void *event_info)
288 {
289         struct info *info = data;
290
291         if (!info->handle)
292                 return;
293
294         if (info->is_hw)
295                 livebox_buffer_pre_render(info->handle);
296 }
297
298 static void post_render_cb(void *data, Evas *e, void *event_info)
299 {
300         struct info *info = data;
301
302         if (!info->handle)
303                 return;
304
305         if (info->is_hw)
306                 livebox_buffer_post_render(info->handle);
307         else
308                 livebox_sync_buffer(info->handle);
309 }
310
311 PUBLIC Evas_Object *virtual_window_create(const char *id, int width, int height)
312 {
313         Ecore_Evas *ee;
314         Evas *e;
315         struct info *info;
316
317         info = calloc(1, sizeof(*info));
318         if (!info) {
319                 return NULL;
320         }
321
322         info->id = strdup(id);
323         if (!info->id) {
324                 free(info);
325                 return NULL;
326         }
327
328         info->width = width;
329         info->height = height;
330
331         ee = ecore_evas_buffer_allocfunc_new(width, height, alloc_fb, free_fb, info);
332         if (!ee) {
333                 free(info->id);
334                 free(info);
335                 return NULL;
336         }
337
338         pre_render_cb(info, NULL, NULL);
339         ecore_evas_alpha_set(ee, EINA_TRUE);
340         post_render_cb(info, NULL, NULL);
341         
342         ecore_evas_manual_render_set(ee, EINA_FALSE);
343         ecore_evas_resize(ee, width, height);
344
345         e = ecore_evas_get(ee);
346         if (!e) {
347                 ecore_evas_free(ee);
348                 return NULL;
349         }
350
351         evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
352         evas_event_callback_add(e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
353
354         info->window = evas_object_rectangle_add(e);
355         if (!info->window) {
356                 ecore_evas_free(ee);
357                 return NULL;
358         }
359
360         evas_object_resize(info->window, width, height);
361         evas_object_color_set(info->window, 0, 0, 0, 0);
362         evas_object_event_callback_add(info->window, EVAS_CALLBACK_DEL, del_cb, info);
363         evas_object_event_callback_add(info->window, EVAS_CALLBACK_RESIZE, resize_cb, info);
364
365         return info->window;
366 }
367
368 PUBLIC int virtual_window_set_parent_elm(Evas_Object *win, Evas_Object *parent)
369 {
370         Evas *e;
371         Ecore_Evas *ee;
372
373         if (!win)
374                 return LB_STATUS_ERROR_INVALID;
375
376         e = evas_object_evas_get(win);
377         if (!e)
378                 return LB_STATUS_ERROR_FAULT;
379
380         ee = ecore_evas_ecore_evas_get(e);
381         if (!ee)
382                 return LB_STATUS_ERROR_FAULT;
383
384         ecore_evas_data_set(ee, "parent,elm", parent);
385         return 0;
386 }
387
388 /* End of a file */