Update for direct event path
[apps/native/widget/widget.git] / src / virtual_window.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18
19 #include <Elementary.h>
20 #include <string.h>
21 #include <Ecore_Evas.h>
22 #include <Ecore_X.h>
23 #include <Evas.h>
24 #include <dlfcn.h>
25
26 #include <X11/Xlib.h>
27
28 #include <dlog.h>
29 #include <livebox-errno.h>
30 #include <livebox-service.h>
31
32 #include "livebox.h"
33 #include "livebox_product.h"
34 #include "debug.h"
35
36 #define IS_PD 1
37
38 #define PUBLIC __attribute__((visibility("default")))
39
40 static struct static_info {
41         Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
42         Ecore_Evas *(*alloc_canvas_with_stride)(int w, int h, void *(*a)(void *data, int size, int *stride, int *bpp), void (*f)(void *data, void *ptr), void *data);
43 } s_info = {
44         .alloc_canvas = NULL,
45         .alloc_canvas_with_stride = NULL,
46 };
47
48 /*!
49  * \brief
50  * Abstracted Data Type of Virtual Window
51  */
52 struct info {
53         char *id; /*!< Identification */
54         struct livebox_buffer *handle; /*!< Livebox buffer handle */
55         int is_hw; /*!< 1 if a buffer is created on the H/W accelerated place or 0 */
56         Ecore_Evas *ee;
57         Evas *e;
58         int is_pd;
59         int deleted;
60         int w;
61         int h;
62 };
63
64 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
65 {
66         Evas_Object *o, *ho;
67
68         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
69         if (!o) return NULL;
70
71         ho = evas_object_data_get(o, "_elm_access_target");
72         return ho;
73 }
74
75 /*!
76  * \note
77  * Every user event (mouse) on the buffer will be passed via this event callback
78  */
79 static int event_handler_cb(struct livebox_buffer *handler, struct buffer_event_data *event_info, void *data)
80 {
81         struct info *info = data;
82         Elm_Access_Action_Info action_info;
83         Elm_Access_Action_Type action_type;
84         int ret = 0;
85         Evas_Object *parent_elm;
86         KeySym *key_symbol;
87         unsigned int flags = 0;
88
89         if (!info->handle) {
90                 /* Just ignore this event */
91                 return 0;
92         }
93
94         /*!
95          * \note
96          * Feed up events
97          */
98         switch (event_info->type) {
99         case BUFFER_EVENT_ON_HOLD:
100                 DbgPrint("ON_HOLD\n");
101                 flags = evas_event_default_flags_get(info->e);
102                 flags |= EVAS_EVENT_FLAG_ON_HOLD;
103                 evas_event_default_flags_set(info->e, flags);
104                 break;
105         case BUFFER_EVENT_OFF_HOLD:
106                 flags = evas_event_default_flags_get(info->e);
107                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
108                 evas_event_default_flags_set(info->e, flags);
109                 break;
110         case BUFFER_EVENT_ON_SCROLL:
111                 flags = evas_event_default_flags_get(info->e);
112                 flags |= EVAS_EVENT_FLAG_ON_SCROLL;
113                 evas_event_default_flags_set(info->e, flags);
114                 break;
115         case BUFFER_EVENT_OFF_SCROLL:
116                 flags = evas_event_default_flags_get(info->e);
117                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
118                 evas_event_default_flags_set(info->e, flags);
119                 break;
120         case BUFFER_EVENT_ENTER:
121                 evas_event_feed_mouse_in(info->e, event_info->timestamp * 1000, NULL);
122                 break;
123         case BUFFER_EVENT_LEAVE:
124                 evas_event_feed_mouse_out(info->e, event_info->timestamp * 1000, NULL);
125                 break;
126         case BUFFER_EVENT_DOWN:
127                 /*!
128                  * \note
129                  * Calculate the event occurred X & Y on the buffer
130                  */
131                 flags = evas_event_default_flags_get(info->e);
132                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
133                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
134                 evas_event_default_flags_set(info->e, flags);
135
136                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
137                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, event_info->timestamp * 1000, NULL); /* + 0.2f just for fake event */
138                 break;
139         case BUFFER_EVENT_MOVE:
140                 /*!
141                  * \note
142                  * Calculate the event occurred X & Y on the buffer
143                  */
144                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
145                 break;
146         case BUFFER_EVENT_UP:
147                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
148                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, event_info->timestamp * 1000, NULL);
149                 break;
150         case BUFFER_EVENT_HIGHLIGHT:
151                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
152                 if (!parent_elm) {
153                         ret = LB_ACCESS_STATUS_ERROR;
154                         break;
155                 }
156                 memset(&action_info, 0, sizeof(action_info));
157                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
158                 /*!
159                  * \note
160                  * Calculate the event occurred X & Y on the buffer
161                  */
162                 action_info.x = event_info->info.access.x;
163                 action_info.y = event_info->info.access.y;
164                 ret = elm_access_action(parent_elm, action_type, &action_info);
165                 if (ret == EINA_TRUE) {
166                         if (!get_highlighted_object(parent_elm)) {
167                                 LOGE("Highlighted object is not found\n");
168                                 ret = LB_ACCESS_STATUS_ERROR;
169                         } else {
170                                 LOGD("Highlighted object is found\n");
171                                 ret = LB_ACCESS_STATUS_DONE;
172                         }
173                 } else {
174                         LOGE("Action error\n");
175                         ret = LB_ACCESS_STATUS_ERROR;
176                 }
177                 break;
178         case BUFFER_EVENT_HIGHLIGHT_NEXT:
179                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
180                 if (!parent_elm) {
181                         ret = LB_ACCESS_STATUS_ERROR;
182                         break;
183                 }
184                 memset(&action_info, 0, sizeof(action_info));
185                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
186                 action_info.highlight_cycle = EINA_FALSE;
187                 ret = elm_access_action(parent_elm, action_type, &action_info);
188                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_LAST : LB_ACCESS_STATUS_DONE;
189                 break;
190         case BUFFER_EVENT_HIGHLIGHT_PREV:
191                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
192                 if (!parent_elm) {
193                         ret = LB_ACCESS_STATUS_ERROR;
194                         break;
195                 }
196                 memset(&action_info, 0, sizeof(action_info));
197                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
198                 action_info.highlight_cycle = EINA_FALSE;
199                 ret = elm_access_action(parent_elm, action_type, &action_info);
200                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_FIRST : LB_ACCESS_STATUS_DONE;
201                 break;
202         case BUFFER_EVENT_ACTIVATE:
203                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
204                 if (!parent_elm) {
205                         ret = LB_ACCESS_STATUS_ERROR;
206                         break;
207                 }
208                 memset(&action_info, 0, sizeof(action_info));
209                 action_type = ELM_ACCESS_ACTION_ACTIVATE;
210                 ret = elm_access_action(parent_elm, action_type, &action_info);
211                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
212                 break;
213         case BUFFER_EVENT_ACTION_UP:
214                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
215                 if (!parent_elm) {
216                         ret = LB_ACCESS_STATUS_ERROR;
217                         break;
218                 }
219                 memset(&action_info, 0, sizeof(action_info));
220                 action_type = ELM_ACCESS_ACTION_UP;
221                 ret = elm_access_action(parent_elm, action_type, &action_info);
222                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
223                 break;
224         case BUFFER_EVENT_ACTION_DOWN:
225                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
226                 if (!parent_elm) {
227                         ret = LB_ACCESS_STATUS_ERROR;
228                         break;
229                 }
230                 memset(&action_info, 0, sizeof(action_info));
231                 action_type = ELM_ACCESS_ACTION_DOWN;
232                 ret = elm_access_action(parent_elm, action_type, &action_info);
233                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
234                 break;
235         case BUFFER_EVENT_SCROLL_UP:
236                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
237                 if (!parent_elm) {
238                         ret = LB_ACCESS_STATUS_ERROR;
239                         break;
240                 }
241                 memset(&action_info, 0, sizeof(action_info));
242                 action_type = ELM_ACCESS_ACTION_SCROLL;
243                 action_info.x = event_info->info.access.x;
244                 action_info.y = event_info->info.access.y;
245                 action_info.mouse_type = event_info->info.access.mouse_type;
246                 ret = elm_access_action(parent_elm, action_type, &action_info);
247                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
248                 break;
249         case BUFFER_EVENT_SCROLL_MOVE:
250                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
251                 if (!parent_elm) {
252                         ret = LB_ACCESS_STATUS_ERROR;
253                         break;
254                 }
255                 memset(&action_info, 0, sizeof(action_info));
256                 action_type = ELM_ACCESS_ACTION_SCROLL;
257                 action_info.x = event_info->info.access.x;
258                 action_info.y = event_info->info.access.y;
259                 action_info.mouse_type = event_info->info.access.mouse_type;
260                 ret = elm_access_action(parent_elm, action_type, &action_info);
261                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
262                 break;
263         case BUFFER_EVENT_SCROLL_DOWN:
264                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
265                 if (!parent_elm) {
266                         ret = LB_ACCESS_STATUS_ERROR;
267                         break;
268                 }
269                 memset(&action_info, 0, sizeof(action_info));
270                 action_type = ELM_ACCESS_ACTION_SCROLL;
271                 action_info.x = event_info->info.access.x;
272                 action_info.y = event_info->info.access.y;
273                 action_info.mouse_type = event_info->info.access.mouse_type;
274                 ret = elm_access_action(parent_elm, action_type, &action_info);
275                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
276                 break;
277         case BUFFER_EVENT_UNHIGHLIGHT:
278                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
279                 if (!parent_elm) {
280                         ret = LB_ACCESS_STATUS_ERROR;
281                         break;
282                 }
283                 memset(&action_info, 0, sizeof(action_info));
284                 action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
285                 ret = elm_access_action(parent_elm, action_type, &action_info);
286                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
287                 break;
288         case BUFFER_EVENT_VALUE_CHANGE:
289                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
290                 if (!parent_elm) {
291                         ret = LB_ACCESS_STATUS_ERROR;
292                         break;
293                 }
294                 memset(&action_info, 0, sizeof(action_info));
295                 action_type = ELM_ACCESS_ACTION_VALUE_CHANGE;
296                 action_info.x = event_info->info.access.x;
297                 action_info.y = event_info->info.access.y;
298                 action_info.mouse_type = event_info->info.access.mouse_type;
299                 ret = elm_access_action(parent_elm, action_type, &action_info);
300                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
301                 break;
302         case BUFFER_EVENT_MOUSE:
303                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
304                 if (!parent_elm) {
305                         ret = LB_ACCESS_STATUS_ERROR;
306                         break;
307                 }
308                 memset(&action_info, 0, sizeof(action_info));
309                 action_type = ELM_ACCESS_ACTION_MOUSE;
310                 action_info.x = event_info->info.access.x;
311                 action_info.y = event_info->info.access.y;
312                 action_info.mouse_type = event_info->info.access.mouse_type;
313                 ret = elm_access_action(parent_elm, action_type, &action_info);
314                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
315                 break;
316         case BUFFER_EVENT_BACK:
317                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
318                 if (!parent_elm) {
319                         ret = LB_ACCESS_STATUS_ERROR;
320                         break;
321                 }
322                 memset(&action_info, 0, sizeof(action_info));
323                 action_type = ELM_ACCESS_ACTION_BACK;
324                 action_info.x = event_info->info.access.x;
325                 action_info.y = event_info->info.access.y;
326                 action_info.mouse_type = event_info->info.access.mouse_type;
327                 ret = elm_access_action(parent_elm, action_type, &action_info);
328                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
329                 break;
330         case BUFFER_EVENT_OVER:
331                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
332                 if (!parent_elm) {
333                         ret = LB_ACCESS_STATUS_ERROR;
334                         break;
335                 }
336                 memset(&action_info, 0, sizeof(action_info));
337                 action_type = ELM_ACCESS_ACTION_OVER;
338                 action_info.x = event_info->info.access.x;
339                 action_info.y = event_info->info.access.y;
340                 action_info.mouse_type = event_info->info.access.mouse_type;
341                 ret = elm_access_action(parent_elm, action_type, &action_info);
342                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
343                 break;
344         case BUFFER_EVENT_READ:
345                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
346                 if (!parent_elm) {
347                         ret = LB_ACCESS_STATUS_ERROR;
348                         break;
349                 }
350                 memset(&action_info, 0, sizeof(action_info));
351                 action_type = ELM_ACCESS_ACTION_READ;
352                 action_info.x = event_info->info.access.x;
353                 action_info.y = event_info->info.access.y;
354                 action_info.mouse_type = event_info->info.access.mouse_type;
355                 ret = elm_access_action(parent_elm, action_type, &action_info);
356                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
357                 break;
358         case BUFFER_EVENT_ENABLE:
359                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
360                 if (!parent_elm) {
361                         ret = LB_ACCESS_STATUS_ERROR;
362                         break;
363                 }
364                 memset(&action_info, 0, sizeof(action_info));
365                 action_type = ELM_ACCESS_ACTION_ENABLE;
366                 action_info.x = event_info->info.access.x;
367                 action_info.y = event_info->info.access.y;
368                 action_info.mouse_type = event_info->info.access.mouse_type;
369                 ret = elm_access_action(parent_elm, action_type, &action_info);
370                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
371                 break;
372         case BUFFER_EVENT_DISABLE:
373                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
374                 if (!parent_elm) {
375                         ret = LB_ACCESS_STATUS_ERROR;
376                         break;
377                 }
378                 memset(&action_info, 0, sizeof(action_info));
379                 action_type = ELM_ACCESS_ACTION_DISABLE;
380                 action_info.x = event_info->info.access.x;
381                 action_info.y = event_info->info.access.y;
382                 action_info.mouse_type = event_info->info.access.mouse_type;
383                 ret = elm_access_action(parent_elm, action_type, &action_info);
384                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
385                 break;
386         case BUFFER_EVENT_KEY_DOWN:
387                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
388                 if (!parent_elm) {
389                         ret = LB_ACCESS_STATUS_ERROR;
390                         break;
391                 }
392
393                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
394                 if (key_symbol) {
395                         char *key_name;
396                         char *key_string;
397
398                         key_string = XKeysymToString(*key_symbol);
399                         key_name = XKeysymToString(*key_symbol);
400                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
401                         XFree(key_symbol);
402                         XFree(key_name);
403                         XFree(key_string);
404                 }
405                 ret = LB_KEY_STATUS_ERROR;
406                 break;
407         case BUFFER_EVENT_KEY_UP:
408                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
409                 if (!parent_elm) {
410                         ret = LB_ACCESS_STATUS_ERROR;
411                         break;
412                 }
413
414                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
415                 if (key_symbol) {
416                         char *key_name;
417                         char *key_string;
418
419                         key_string = XKeysymToString(*key_symbol);
420                         key_name = XKeysymToString(*key_symbol);
421                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
422                         XFree(key_symbol);
423                         XFree(key_name);
424                         XFree(key_string);
425                 }
426                 ret = LB_KEY_STATUS_ERROR;
427                 break;
428         case BUFFER_EVENT_KEY_FOCUS_IN:
429                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
430                 if (!parent_elm) {
431                         ret = LB_ACCESS_STATUS_ERROR;
432                         break;
433                 }
434
435                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
436                 if (key_symbol) {
437                         char *key_name;
438                         char *key_string;
439
440                         key_string = XKeysymToString(*key_symbol);
441                         key_name = XKeysymToString(*key_symbol);
442                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
443                         XFree(key_symbol);
444                         XFree(key_name);
445                         XFree(key_string);
446                 }
447                 ret = LB_KEY_STATUS_ERROR;
448                 break;
449         case BUFFER_EVENT_KEY_FOCUS_OUT:
450                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
451                 if (!parent_elm) {
452                         ret = LB_ACCESS_STATUS_ERROR;
453                         break;
454                 }
455
456                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
457                 if (key_symbol) {
458                         char *key_name;
459                         char *key_string;
460
461                         key_string = XKeysymToString(*key_symbol);
462                         key_name = XKeysymToString(*key_symbol);
463                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
464                         XFree(key_symbol);
465                         XFree(key_name);
466                         XFree(key_string);
467                 }
468                 ret = LB_KEY_STATUS_ERROR;
469                 break;
470         default:
471                 LOGD("Unhandled buffer event (%d)\n", event_info->type);
472                 break;
473         }
474
475         return ret;
476 }
477
478 static void *alloc_fb(void *data, int size)
479 {
480         struct info *info = data;
481         void *buffer;
482
483         if (info->ee) {
484                 ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
485                 LOGD("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
486         }
487
488         /*!
489          * Acquire a buffer for canvas.
490          */
491         info->handle = livebox_acquire_buffer(info->id, info->is_pd,
492                                         info->w, info->h, sizeof(int), (livebox_conf_auto_align() || !s_info.alloc_canvas_with_stride),
493                                         event_handler_cb, info);
494
495         /*!
496          * If it supports the H/W accelerated buffer,
497          * Use it.
498          */
499         if (livebox_support_hw_buffer(info->handle)) {
500                 if (livebox_create_hw_buffer(info->handle) == 0) {
501                         buffer = livebox_buffer_hw_buffer(info->handle);
502                         if (buffer) {
503                                 LOGD("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
504                                 info->is_hw = 1;
505                                 return buffer;
506                         }
507                 }
508
509                 LOGE("Failed to allocate HW Accelerated buffer\n");
510         }
511
512         /*!
513          * Or use the buffer of a S/W backend.
514          */
515         buffer = livebox_ref_buffer(info->handle);
516         LOGD("SW buffer is created (%dx%d)\n", info->w, info->h);
517         info->is_hw = 0;
518         return buffer;
519 }
520
521 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
522 {
523         void *buffer;
524
525         buffer = alloc_fb(data, size);
526         if (buffer) {
527                 struct info *info = data;
528                 int _stride;
529
530                 *bpp = sizeof(int);
531                 _stride = livebox_buffer_stride(info->handle);
532                 if (_stride < 0) {
533                         _stride = info->w * *bpp;
534                 }
535
536                 *stride = _stride;
537                 *bpp <<= 3;
538                 DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
539         }
540
541         return buffer;
542 }
543
544 static void free_fb(void *data, void *ptr)
545 {
546         struct info *info = data;
547
548         if (!info->handle) {
549                 return;
550         }
551
552         if (info->is_hw) {
553                 if (livebox_destroy_hw_buffer(info->handle) == 0) {
554                         LOGD("HW Accelerated buffer is destroyed\n");
555                 }
556         } else {
557                 LOGD("SW buffer is destroyed, %p\n", info);
558                 livebox_unref_buffer(ptr);
559         }
560
561         livebox_release_buffer(info->handle);
562         info->handle = NULL;
563
564         if (info->deleted) {
565                 free(info->id);
566                 info->id = NULL;
567
568                 free(info);
569         }
570 }
571
572 static void pre_render_cb(void *data, Evas *e, void *event_info)
573 {
574         struct info *info = data;
575
576         if (!info->handle) {
577                 return;
578         }
579
580         if (livebox_conf_premultiplied_alpha()) {
581                 Evas_Coord w;
582                 Evas_Coord h;
583
584                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
585                 evas_damage_rectangle_add(e, 0, 0, w, h);
586         }
587
588         if (info->is_hw) {
589                 livebox_buffer_pre_render(info->handle);
590         }
591 }
592
593 static void post_render_cb(void *data, Evas *e, void *event_info)
594 {
595         struct info *info = data;
596
597         if (!info->handle) {
598                 return;
599         }
600
601         if (livebox_conf_premultiplied_alpha()) {
602                 void *canvas;
603                 int x, y, w, h;
604
605                 // Get a pointer of a buffer of the virtual canvas
606                 canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
607                 if (!canvas) {
608                         ErrPrint("Failed to get pixel canvas\n");
609                         return;
610                 }
611
612                 ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
613                 evas_data_argb_unpremul(canvas, w * h);
614         }
615
616         if (info->is_hw) {
617                 livebox_buffer_post_render(info->handle);
618         } else {
619                 livebox_sync_buffer(info->handle);
620         }
621 }
622
623 static void ecore_evas_free_cb(Ecore_Evas *ee)
624 {
625         struct info *info;
626
627         info = ecore_evas_data_get(ee, "dynamic,box,info");
628         if (!info) {
629                 LOGD("Info is not valid\n");
630                 return;
631         }
632
633         if (info->e) {
634                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
635                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
636         }
637
638         info->deleted = 1;
639         info->ee = NULL;
640 }
641
642 PUBLIC Evas_Object *livebox_get_evas_object(const char *id, int is_pd)
643 {
644         struct info *info;
645         Evas_Object *rect;
646
647         if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride) {
648                 s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
649                 if (!s_info.alloc_canvas_with_stride) {
650                         DbgPrint("allocfunc_with_stirde_new is not found\n");
651                 }
652
653                 s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
654                 if (!s_info.alloc_canvas) {
655                         ErrPrint("allocfunc_new is not found\n");
656                 }
657
658                 if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas) {
659                         ErrPrint("No way to allocate canvas\n");
660                         return NULL;
661                 }
662         }
663
664         if (!id) {
665                 ErrPrint("Invalid parameter\n");
666                 return NULL;
667         }
668
669         info = calloc(1, sizeof(*info));
670         if (!info) {
671                 ErrPrint("Heap: %s\n", strerror(errno));
672                 return NULL;
673         }
674
675         info->id = strdup(id);
676         if (!info->id) {
677                 ErrPrint("Heap: %s\n", strerror(errno));
678                 free(info);
679                 return NULL;
680         }
681
682         info->is_pd = is_pd;
683
684         /*!
685          * Size information must be initialized before call the ecore_evas_buffer_new.
686          */
687         info->w = 1;
688         info->h = 1;
689
690         if (!livebox_conf_auto_align() && s_info.alloc_canvas_with_stride) {
691                 info->ee = s_info.alloc_canvas_with_stride(1, 1, alloc_stride_fb, free_fb, info);
692         } else {
693                 info->ee = s_info.alloc_canvas(1, 1, alloc_fb, free_fb, info);
694         }
695
696         if (!info->ee) {
697                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", 1, 1);
698                 free(info->id);
699                 free(info);
700                 return NULL;
701         }
702
703         info->e = ecore_evas_get(info->ee);
704         if (!info->e) {
705                 ErrPrint("Failed to get evas\n");
706                 ecore_evas_free(info->ee);
707                 return NULL;
708         }
709
710         ecore_evas_data_set(info->ee, "dynamic,box,info", info);
711
712         pre_render_cb(info, NULL, NULL);
713         ecore_evas_alpha_set(info->ee, EINA_TRUE);
714         post_render_cb(info, NULL, NULL);
715
716         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
717         ecore_evas_resize(info->ee, 1, 1);
718
719         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
720         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
721         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
722
723         rect = evas_object_rectangle_add(info->e);
724         if (!rect) {
725                 ErrPrint("Failed to create evas_object\n");
726                 ecore_evas_free(info->ee);
727                 return NULL;
728         }
729
730         evas_object_resize(rect, 1, 1);
731         evas_object_color_set(rect, 0, 0, 0, 0);
732         return rect;
733 }
734
735 /* End of a file */