Merge with devel/home/master branch
[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 <dynamicbox_errno.h>
30 #include <dynamicbox_service.h>
31 #include <dynamicbox_conf.h>
32
33 #include "dynamicbox.h"
34 #include "debug.h"
35
36 #define IS_PD 1
37
38 #define PUBLIC __attribute__((visibility("default")))
39 #define DBOX_WIN_TAG "dynamic,box,win"
40
41 static struct static_info {
42         Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
43         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);
44 } s_info = {
45         .alloc_canvas = NULL,
46         .alloc_canvas_with_stride = NULL,
47 };
48
49 /**
50  * @brief
51  * Abstracted Data Type of Virtual Window
52  */
53 struct info {
54         char *id; /**< Identification */
55         struct dynamicbox_buffer *handle; /**< Livebox buffer handle */
56         int is_hw; /**< 1 if a buffer is created on the H/W accelerated place or 0 */
57         Ecore_Evas *ee;
58         Evas *e;
59         int is_gbar;
60         int deleted;
61         int w;
62         int h;
63 };
64
65 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
66 {
67         Evas_Object *o, *ho;
68
69         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
70         if (!o) return NULL;
71
72         ho = evas_object_data_get(o, "_elm_access_target");
73         return ho;
74 }
75
76 /**
77  * @note
78  * Every user event (mouse) on the buffer will be passed via this event callback
79  */
80 static int event_handler_cb(struct dynamicbox_buffer *handler, struct dynamicbox_buffer_event_data *event_info, void *data)
81 {
82         struct info *info = data;
83         Elm_Access_Action_Info action_info;
84         Elm_Access_Action_Type action_type;
85         int ret = 0;
86         Evas_Object *parent_elm;
87         KeySym *key_symbol;
88         unsigned int flags = 0;
89
90         if (!info->handle) {
91                 /* Just ignore this event */
92                 return 0;
93         }
94
95         /**
96          * @note
97          * Feed up events
98          */
99         switch (event_info->type) {
100         case DBOX_BUFFER_EVENT_ON_HOLD:
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 DBOX_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 DBOX_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 DBOX_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 DBOX_BUFFER_EVENT_ENTER:
121                 evas_event_feed_mouse_in(info->e, event_info->timestamp * 1000, NULL);
122                 break;
123         case DBOX_BUFFER_EVENT_LEAVE:
124                 evas_event_feed_mouse_out(info->e, event_info->timestamp * 1000, NULL);
125                 break;
126         case DBOX_BUFFER_EVENT_DOWN:
127                 /**
128                  * @note
129                  * Before processing the DOWN event,
130                  * Reset the evas event flags regarding ON_HOLD option.
131                  * It can be re-enabled while processing down-move-up events.
132                  */
133                 flags = evas_event_default_flags_get(info->e);
134                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
135                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
136                 evas_event_default_flags_set(info->e, flags);
137                 /**
138                  * @note
139                  * Calculate the event occurred X & Y on the buffer
140                  */
141                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
142                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, event_info->timestamp * 1000, NULL); /* + 0.2f just for fake event */
143                 break;
144         case DBOX_BUFFER_EVENT_MOVE:
145                 /**
146                  * @note
147                  * Calculate the event occurred X & Y on the buffer
148                  */
149                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
150                 break;
151         case DBOX_BUFFER_EVENT_UP:
152                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
153                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, event_info->timestamp * 1000, NULL);
154                 /**
155                  * @note
156                  * We have to keep the event flags, so we should not clear them from here.
157                  * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
158                  * so if we reset them from here, those kind of callbacks will fails to do their job properly.
159                  */
160                 break;
161         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT:
162                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
163                 if (!parent_elm) {
164                         ret = DBOX_ACCESS_STATUS_ERROR;
165                         break;
166                 }
167                 memset(&action_info, 0, sizeof(action_info));
168                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
169                 /**
170                  * @note
171                  * Calculate the event occurred X & Y on the buffer
172                  */
173                 action_info.x = event_info->info.access.x;
174                 action_info.y = event_info->info.access.y;
175                 ret = elm_access_action(parent_elm, action_type, &action_info);
176                 if (ret == EINA_TRUE) {
177                         if (!get_highlighted_object(parent_elm)) {
178                                 ErrPrint("Highlighted object is not found\n");
179                                 ret = DBOX_ACCESS_STATUS_ERROR;
180                         } else {
181                                 DbgPrint("Highlighted object is found\n");
182                                 ret = DBOX_ACCESS_STATUS_DONE;
183                         }
184                 } else {
185                         ErrPrint("Action error\n");
186                         ret = DBOX_ACCESS_STATUS_ERROR;
187                 }
188                 break;
189         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
190                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
191                 if (!parent_elm) {
192                         ret = DBOX_ACCESS_STATUS_ERROR;
193                         break;
194                 }
195                 memset(&action_info, 0, sizeof(action_info));
196                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
197                 action_info.highlight_cycle = EINA_FALSE;
198                 ret = elm_access_action(parent_elm, action_type, &action_info);
199                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_LAST : DBOX_ACCESS_STATUS_DONE;
200                 break;
201         case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
202                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
203                 if (!parent_elm) {
204                         ret = DBOX_ACCESS_STATUS_ERROR;
205                         break;
206                 }
207                 memset(&action_info, 0, sizeof(action_info));
208                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
209                 action_info.highlight_cycle = EINA_FALSE;
210                 ret = elm_access_action(parent_elm, action_type, &action_info);
211                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_FIRST : DBOX_ACCESS_STATUS_DONE;
212                 break;
213         case DBOX_BUFFER_EVENT_ACCESS_ACTIVATE:
214                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
215                 if (!parent_elm) {
216                         ret = DBOX_ACCESS_STATUS_ERROR;
217                         break;
218                 }
219                 memset(&action_info, 0, sizeof(action_info));
220                 action_type = ELM_ACCESS_ACTION_ACTIVATE;
221                 ret = elm_access_action(parent_elm, action_type, &action_info);
222                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
223                 break;
224         case DBOX_BUFFER_EVENT_ACCESS_ACTION_UP:
225                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
226                 if (!parent_elm) {
227                         ret = DBOX_ACCESS_STATUS_ERROR;
228                         break;
229                 }
230                 memset(&action_info, 0, sizeof(action_info));
231                 action_type = ELM_ACCESS_ACTION_UP;
232                 ret = elm_access_action(parent_elm, action_type, &action_info);
233                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
234                 break;
235         case DBOX_BUFFER_EVENT_ACCESS_ACTION_DOWN:
236                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
237                 if (!parent_elm) {
238                         ret = DBOX_ACCESS_STATUS_ERROR;
239                         break;
240                 }
241                 memset(&action_info, 0, sizeof(action_info));
242                 action_type = ELM_ACCESS_ACTION_DOWN;
243                 ret = elm_access_action(parent_elm, action_type, &action_info);
244                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
245                 break;
246         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_UP:
247                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
248                 if (!parent_elm) {
249                         ret = DBOX_ACCESS_STATUS_ERROR;
250                         break;
251                 }
252                 memset(&action_info, 0, sizeof(action_info));
253                 action_type = ELM_ACCESS_ACTION_SCROLL;
254                 action_info.x = event_info->info.access.x;
255                 action_info.y = event_info->info.access.y;
256                 action_info.mouse_type = event_info->info.access.mouse_type;
257                 ret = elm_access_action(parent_elm, action_type, &action_info);
258                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
259                 break;
260         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
261                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
262                 if (!parent_elm) {
263                         ret = DBOX_ACCESS_STATUS_ERROR;
264                         break;
265                 }
266                 memset(&action_info, 0, sizeof(action_info));
267                 action_type = ELM_ACCESS_ACTION_SCROLL;
268                 action_info.x = event_info->info.access.x;
269                 action_info.y = event_info->info.access.y;
270                 action_info.mouse_type = event_info->info.access.mouse_type;
271                 ret = elm_access_action(parent_elm, action_type, &action_info);
272                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
273                 break;
274         case DBOX_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
275                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
276                 if (!parent_elm) {
277                         ret = DBOX_ACCESS_STATUS_ERROR;
278                         break;
279                 }
280                 memset(&action_info, 0, sizeof(action_info));
281                 action_type = ELM_ACCESS_ACTION_SCROLL;
282                 action_info.x = event_info->info.access.x;
283                 action_info.y = event_info->info.access.y;
284                 action_info.mouse_type = event_info->info.access.mouse_type;
285                 ret = elm_access_action(parent_elm, action_type, &action_info);
286                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
287                 break;
288         case DBOX_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
289                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
290                 if (!parent_elm) {
291                         ret = DBOX_ACCESS_STATUS_ERROR;
292                         break;
293                 }
294                 memset(&action_info, 0, sizeof(action_info));
295                 action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
296                 ret = elm_access_action(parent_elm, action_type, &action_info);
297                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
298                 break;
299         case DBOX_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
300                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
301                 if (!parent_elm) {
302                         ret = DBOX_ACCESS_STATUS_ERROR;
303                         break;
304                 }
305                 memset(&action_info, 0, sizeof(action_info));
306                 action_type = ELM_ACCESS_ACTION_VALUE_CHANGE;
307                 action_info.x = event_info->info.access.x;
308                 action_info.y = event_info->info.access.y;
309                 action_info.mouse_type = event_info->info.access.mouse_type;
310                 ret = elm_access_action(parent_elm, action_type, &action_info);
311                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
312                 break;
313         case DBOX_BUFFER_EVENT_ACCESS_MOUSE:
314                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
315                 if (!parent_elm) {
316                         ret = DBOX_ACCESS_STATUS_ERROR;
317                         break;
318                 }
319                 memset(&action_info, 0, sizeof(action_info));
320                 action_type = ELM_ACCESS_ACTION_MOUSE;
321                 action_info.x = event_info->info.access.x;
322                 action_info.y = event_info->info.access.y;
323                 action_info.mouse_type = event_info->info.access.mouse_type;
324                 ret = elm_access_action(parent_elm, action_type, &action_info);
325                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
326                 break;
327         case DBOX_BUFFER_EVENT_ACCESS_BACK:
328                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
329                 if (!parent_elm) {
330                         ret = DBOX_ACCESS_STATUS_ERROR;
331                         break;
332                 }
333                 memset(&action_info, 0, sizeof(action_info));
334                 action_type = ELM_ACCESS_ACTION_BACK;
335                 action_info.x = event_info->info.access.x;
336                 action_info.y = event_info->info.access.y;
337                 action_info.mouse_type = event_info->info.access.mouse_type;
338                 ret = elm_access_action(parent_elm, action_type, &action_info);
339                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
340                 break;
341         case DBOX_BUFFER_EVENT_ACCESS_OVER:
342                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
343                 if (!parent_elm) {
344                         ret = DBOX_ACCESS_STATUS_ERROR;
345                         break;
346                 }
347                 memset(&action_info, 0, sizeof(action_info));
348                 action_type = ELM_ACCESS_ACTION_OVER;
349                 action_info.x = event_info->info.access.x;
350                 action_info.y = event_info->info.access.y;
351                 action_info.mouse_type = event_info->info.access.mouse_type;
352                 ret = elm_access_action(parent_elm, action_type, &action_info);
353                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
354                 break;
355         case DBOX_BUFFER_EVENT_ACCESS_READ:
356                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
357                 if (!parent_elm) {
358                         ret = DBOX_ACCESS_STATUS_ERROR;
359                         break;
360                 }
361                 memset(&action_info, 0, sizeof(action_info));
362                 action_type = ELM_ACCESS_ACTION_READ;
363                 action_info.x = event_info->info.access.x;
364                 action_info.y = event_info->info.access.y;
365                 action_info.mouse_type = event_info->info.access.mouse_type;
366                 ret = elm_access_action(parent_elm, action_type, &action_info);
367                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
368                 break;
369         case DBOX_BUFFER_EVENT_ACCESS_ENABLE:
370                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
371                 if (!parent_elm) {
372                         ret = DBOX_ACCESS_STATUS_ERROR;
373                         break;
374                 }
375                 memset(&action_info, 0, sizeof(action_info));
376                 action_type = ELM_ACCESS_ACTION_ENABLE;
377                 action_info.x = event_info->info.access.x;
378                 action_info.y = event_info->info.access.y;
379                 action_info.mouse_type = event_info->info.access.mouse_type;
380                 ret = elm_access_action(parent_elm, action_type, &action_info);
381                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
382                 break;
383         case DBOX_BUFFER_EVENT_ACCESS_DISABLE:
384                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
385                 if (!parent_elm) {
386                         ret = DBOX_ACCESS_STATUS_ERROR;
387                         break;
388                 }
389                 memset(&action_info, 0, sizeof(action_info));
390                 action_type = ELM_ACCESS_ACTION_DISABLE;
391                 action_info.x = event_info->info.access.x;
392                 action_info.y = event_info->info.access.y;
393                 action_info.mouse_type = event_info->info.access.mouse_type;
394                 ret = elm_access_action(parent_elm, action_type, &action_info);
395                 ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
396                 break;
397         case DBOX_BUFFER_EVENT_KEY_DOWN:
398                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
399                 if (!parent_elm) {
400                         ret = DBOX_ACCESS_STATUS_ERROR;
401                         break;
402                 }
403
404                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
405                 if (key_symbol) {
406                         char *key_name;
407                         char *key_string;
408
409                         key_string = XKeysymToString(*key_symbol);
410                         key_name = XKeysymToString(*key_symbol);
411                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
412                         XFree(key_symbol);
413                         XFree(key_name);
414                         XFree(key_string);
415                 }
416                 ret = DBOX_KEY_STATUS_ERROR;
417                 break;
418         case DBOX_BUFFER_EVENT_KEY_UP:
419                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
420                 if (!parent_elm) {
421                         ret = DBOX_ACCESS_STATUS_ERROR;
422                         break;
423                 }
424
425                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
426                 if (key_symbol) {
427                         char *key_name;
428                         char *key_string;
429
430                         key_string = XKeysymToString(*key_symbol);
431                         key_name = XKeysymToString(*key_symbol);
432                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
433                         XFree(key_symbol);
434                         XFree(key_name);
435                         XFree(key_string);
436                 }
437                 ret = DBOX_KEY_STATUS_ERROR;
438                 break;
439         case DBOX_BUFFER_EVENT_KEY_FOCUS_IN:
440                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
441                 if (!parent_elm) {
442                         ret = DBOX_ACCESS_STATUS_ERROR;
443                         break;
444                 }
445
446                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
447                 if (key_symbol) {
448                         char *key_name;
449                         char *key_string;
450
451                         key_string = XKeysymToString(*key_symbol);
452                         key_name = XKeysymToString(*key_symbol);
453                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
454                         XFree(key_symbol);
455                         XFree(key_name);
456                         XFree(key_string);
457                 }
458                 ret = DBOX_KEY_STATUS_ERROR;
459                 break;
460         case DBOX_BUFFER_EVENT_KEY_FOCUS_OUT:
461                 parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
462                 if (!parent_elm) {
463                         ret = DBOX_ACCESS_STATUS_ERROR;
464                         break;
465                 }
466
467                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
468                 if (key_symbol) {
469                         char *key_name;
470                         char *key_string;
471
472                         key_string = XKeysymToString(*key_symbol);
473                         key_name = XKeysymToString(*key_symbol);
474                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
475                         XFree(key_symbol);
476                         XFree(key_name);
477                         XFree(key_string);
478                 }
479                 ret = DBOX_KEY_STATUS_ERROR;
480                 break;
481         default:
482                 DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
483                 break;
484         }
485
486         return ret;
487 }
488
489 static void *alloc_fb(void *data, int size)
490 {
491         struct info *info = data;
492         void *buffer;
493
494         if (info->ee) {
495                 ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
496                 DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
497         }
498
499         /**
500          * Acquire a buffer for canvas.
501          */
502         info->handle = dynamicbox_acquire_buffer(info->id, info->is_gbar,
503                                         info->w, info->h, sizeof(int), (dynamicbox_conf_auto_align() || !s_info.alloc_canvas_with_stride),
504                                         event_handler_cb, info);
505
506         /**
507          * If it supports the H/W accelerated buffer,
508          * Use it.
509          */
510         if (dynamicbox_support_hw_buffer(info->handle)) {
511                 if (dynamicbox_create_hw_buffer(info->handle) == 0) {
512                         buffer = dynamicbox_buffer_hw_buffer(info->handle);
513                         if (buffer) {
514                                 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
515                                 info->is_hw = 1;
516                                 return buffer;
517                         }
518                 }
519
520                 ErrPrint("Failed to allocate HW Accelerated buffer\n");
521         }
522
523         /**
524          * Or use the buffer of a S/W backend.
525          */
526         buffer = dynamicbox_ref_buffer(info->handle);
527         DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
528         info->is_hw = 0;
529         return buffer;
530 }
531
532 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
533 {
534         void *buffer;
535
536         buffer = alloc_fb(data, size);
537         if (buffer) {
538                 struct info *info = data;
539                 int _stride;
540
541                 *bpp = sizeof(int);
542                 _stride = dynamicbox_buffer_stride(info->handle);
543                 if (_stride < 0) {
544                         _stride = info->w * *bpp;
545                 }
546
547                 *stride = _stride;
548                 *bpp <<= 3;
549                 DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
550         }
551
552         return buffer;
553 }
554
555 static void free_fb(void *data, void *ptr)
556 {
557         struct info *info = data;
558
559         if (!info->handle) {
560                 return;
561         }
562
563         if (info->is_hw) {
564                 if (dynamicbox_destroy_hw_buffer(info->handle) == 0) {
565                         DbgPrint("HW Accelerated buffer is destroyed\n");
566                 }
567         } else {
568                 DbgPrint("SW buffer is destroyed, %p\n", info);
569                 dynamicbox_unref_buffer(ptr);
570         }
571
572         dynamicbox_release_buffer(info->handle);
573         info->handle = NULL;
574
575         if (info->deleted) {
576                 free(info->id);
577                 info->id = NULL;
578
579                 free(info);
580         }
581 }
582
583 static void pre_render_cb(void *data, Evas *e, void *event_info)
584 {
585         struct info *info = data;
586
587         if (!info->handle) {
588                 return;
589         }
590
591         if (dynamicbox_conf_premultiplied_alpha()) {
592                 Evas_Coord w;
593                 Evas_Coord h;
594
595                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
596                 evas_damage_rectangle_add(e, 0, 0, w, h);
597         }
598
599         if (info->is_hw) {
600                 dynamicbox_buffer_pre_render(info->handle);
601         }
602 }
603
604 static void post_render_cb(void *data, Evas *e, void *event_info)
605 {
606         struct info *info = data;
607
608         if (!info->handle) {
609                 return;
610         }
611
612         if (dynamicbox_conf_premultiplied_alpha()) {
613                 void *canvas;
614                 int x, y, w, h;
615
616                 // Get a pointer of a buffer of the virtual canvas
617                 canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
618                 if (!canvas) {
619                         ErrPrint("Failed to get pixel canvas\n");
620                         return;
621                 }
622
623                 ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
624                 evas_data_argb_unpremul(canvas, w * h);
625         }
626
627         if (info->is_hw) {
628                 dynamicbox_buffer_post_render(info->handle);
629         } else {
630                 dynamicbox_sync_buffer(info->handle);
631         }
632 }
633
634 static void ecore_evas_free_cb(Ecore_Evas *ee)
635 {
636         struct info *info;
637
638         info = ecore_evas_data_get(ee, "dynamic,box,info");
639         if (!info) {
640                 DbgPrint("Info is not valid\n");
641                 return;
642         }
643
644         if (info->e) {
645                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
646                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
647         }
648
649         info->deleted = 1;
650         info->ee = NULL;
651 }
652
653 PUBLIC void *dynamicbox_get_evas_object(const char *id, int is_gbar)
654 {
655         struct info *info;
656         Evas_Object *rect;
657
658         if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride) {
659                 s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
660                 if (!s_info.alloc_canvas_with_stride) {
661                         DbgPrint("allocfunc_with_stirde_new is not found\n");
662                 }
663
664                 s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
665                 if (!s_info.alloc_canvas) {
666                         ErrPrint("allocfunc_new is not found\n");
667                 }
668
669                 if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas) {
670                         ErrPrint("No way to allocate canvas\n");
671                         return NULL;
672                 }
673         }
674
675         if (!id) {
676                 ErrPrint("Invalid parameter\n");
677                 return NULL;
678         }
679
680         info = calloc(1, sizeof(*info));
681         if (!info) {
682                 ErrPrint("Heap: %s\n", strerror(errno));
683                 return NULL;
684         }
685
686         info->id = strdup(id);
687         if (!info->id) {
688                 ErrPrint("Heap: %s\n", strerror(errno));
689                 free(info);
690                 return NULL;
691         }
692
693         info->is_gbar = is_gbar;
694
695         /**
696          * Size information must be initialized before call the ecore_evas_buffer_new.
697          */
698         info->w = 1;
699         info->h = 1;
700
701         if (!dynamicbox_conf_auto_align() && s_info.alloc_canvas_with_stride) {
702                 info->ee = s_info.alloc_canvas_with_stride(1, 1, alloc_stride_fb, free_fb, info);
703         } else if (s_info.alloc_canvas) {
704                 info->ee = s_info.alloc_canvas(1, 1, alloc_fb, free_fb, info);
705         }
706
707         if (!info->ee) {
708                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", 1, 1);
709                 free(info->id);
710                 free(info);
711                 return NULL;
712         }
713
714         ecore_evas_data_set(info->ee, "dynamic,box,info", info);
715         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
716
717         info->e = ecore_evas_get(info->ee);
718         if (!info->e) {
719                 ErrPrint("Failed to get evas\n");
720                 ecore_evas_free(info->ee);
721                 return NULL;
722         }
723
724         pre_render_cb(info, NULL, NULL);
725         ecore_evas_alpha_set(info->ee, EINA_TRUE);
726         post_render_cb(info, NULL, NULL);
727
728         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
729         ecore_evas_resize(info->ee, 1, 1);
730
731         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
732         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
733
734         rect = evas_object_rectangle_add(info->e);
735         if (!rect) {
736                 ErrPrint("Failed to create evas_object\n");
737                 ecore_evas_free(info->ee);
738                 return NULL;
739         }
740
741         evas_object_resize(rect, 1, 1);
742         evas_object_color_set(rect, 0, 0, 0, 0);
743         return rect;
744 }
745
746 /* End of a file */