Change the sequence of last updated pixmap
[apps/native/widget/widget.git] / dynamicbox / 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 #include <Eina.h>
26
27 #include <X11/Xlib.h>
28
29 #include <dlog.h>
30 #include <dynamicbox_errno.h>
31 #include <dynamicbox_service.h>
32 #include <dynamicbox_conf.h>
33 #include <dynamicbox_buffer.h>
34
35 #include "dynamicbox.h"
36 #include "internal/dynamicbox.h"
37 #include "debug.h"
38
39 #define IS_GBAR 1
40
41 #define PUBLIC __attribute__((visibility("default")))
42 #define DBOX_WIN_TAG "dynamic,box,win"
43
44 #define DBOX_DEFAULT_WIDTH 1
45 #define DBOX_DEFAULT_HEIGHT 1
46 #define GL_ENGINE "opengl_x11"
47
48 static struct static_info {
49     Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
50     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);
51     Ecore_Evas *(*alloc_canvas_with_pixmap)(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h, Ecore_X_Pixmap (*alloc_cb)(void *data, Ecore_X_Window parent, int w, int h, int depth), void (*free_cb)(void *data, Ecore_X_Pixmap pixmap), void *data);
52 } s_info = {
53     .alloc_canvas = NULL,
54     .alloc_canvas_with_stride = NULL,
55     .alloc_canvas_with_pixmap = NULL,
56 };
57
58 /**
59  * @brief
60  * Abstracted Data Type of Virtual Window
61  */
62 typedef struct virtual_window_info {
63     char *id; /**< Identification */
64     dynamicbox_buffer_h handle; /**< Livebox buffer handle */
65     enum win_type {
66         VWIN_SW_BUF = 0x00, /**< S/W buffer */
67         VWIN_GEM    = 0x01, /**< GEM buffer */
68         VWIN_PIXMAP = 0x02, /**< PIXMAP */
69         VWIN_ERROR  = 0x03  /**< Unknown */
70     } type;
71     Ecore_Evas *ee;
72     Evas *e;
73     int is_gbar;
74     int deleted;
75     int w;
76     int h;
77     unsigned int *resource_array;
78     int resource_cnt;
79
80     int pressed;
81 } *vwin_info_t;
82
83 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
84 {
85     Evas_Object *o, *ho;
86
87     o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
88     if (!o) return NULL;
89
90     ho = evas_object_data_get(o, "_elm_access_target");
91     return ho;
92 }
93
94 /**
95  * @note
96  * Every user event (mouse) on the buffer will be passed via this event callback
97  */
98 static int event_handler_cb(dynamicbox_buffer_h handler, struct dynamicbox_buffer_event_data *event_info, void *data)
99 {
100     vwin_info_t info = data;
101     Elm_Access_Action_Info action_info;
102     Elm_Access_Action_Type action_type;
103     int ret = 0;
104     Evas_Object *parent_elm;
105     KeySym *key_symbol;
106     unsigned int flags = 0;
107     double timestamp;
108
109     if (!info->handle) {
110         /* Just ignore this event */
111         return 0;
112     }
113
114     if (DYNAMICBOX_CONF_USE_GETTIMEOFDAY) {
115         if (DYNAMICBOX_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == DBOX_BUFFER_EVENT_MOVE)) {
116             struct timeval tv;
117
118             if (gettimeofday(&tv, NULL) < 0) {
119                 ErrPrint("gettimeofday: %s\n", strerror(errno));
120             } else {
121                 timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
122                 timestamp -= event_info->timestamp;
123
124                 if (timestamp > DYNAMICBOX_CONF_EVENT_FILTER) {
125                     DbgPrint("Dropped %lf\n", timestamp);
126                     return 0;
127                 }
128             }
129         }
130
131         /**
132          * If the device doesn't use the clock monotic time, we have to emulate it for EVAS
133          * Evas only use the monotic time for animating objects
134          */
135         timestamp = ecore_time_get() * 1000.0f;
136     } else {
137         if (DYNAMICBOX_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == DBOX_BUFFER_EVENT_MOVE)) {
138             timestamp = ecore_time_get();
139
140             timestamp -= event_info->timestamp;
141             if (timestamp > DYNAMICBOX_CONF_EVENT_FILTER) {
142                 DbgPrint("Dropped %lf\n", timestamp);
143                 return 0;
144             }
145         }
146
147         timestamp = event_info->timestamp * 1000.0f;
148     }
149
150     /**
151      * @note
152      * Feed up events
153      */
154     switch (event_info->type) {
155     case DBOX_BUFFER_EVENT_ON_HOLD:
156         flags = evas_event_default_flags_get(info->e);
157         flags |= EVAS_EVENT_FLAG_ON_HOLD;
158         evas_event_default_flags_set(info->e, flags);
159         ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
160         break;
161     case DBOX_BUFFER_EVENT_OFF_HOLD:
162         flags = evas_event_default_flags_get(info->e);
163         flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
164         evas_event_default_flags_set(info->e, flags);
165         break;
166     case DBOX_BUFFER_EVENT_ON_SCROLL:
167         flags = evas_event_default_flags_get(info->e);
168         flags |= EVAS_EVENT_FLAG_ON_SCROLL;
169         evas_event_default_flags_set(info->e, flags);
170         break;
171     case DBOX_BUFFER_EVENT_OFF_SCROLL:
172         flags = evas_event_default_flags_get(info->e);
173         flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
174         evas_event_default_flags_set(info->e, flags);
175         break;
176     case DBOX_BUFFER_EVENT_ENTER:
177         evas_event_feed_mouse_in(info->e, timestamp, NULL);
178         break;
179     case DBOX_BUFFER_EVENT_LEAVE:
180         evas_event_feed_mouse_out(info->e, timestamp, NULL);
181         break;
182     case DBOX_BUFFER_EVENT_DOWN:
183         /**
184          * @note
185          * Before processing the DOWN event,
186          * Reset the evas event flags regarding ON_HOLD option.
187          * It can be re-enabled while processing down-move-up events.
188          */
189         flags = evas_event_default_flags_get(info->e);
190         flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
191         flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
192         evas_event_default_flags_set(info->e, flags);
193         /**
194          * @note
195          * Calculate the event occurred X & Y on the buffer
196          */
197         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
198         evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
199         info->pressed = 1;
200         ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
201         break;
202     case DBOX_BUFFER_EVENT_MOVE:
203         /**
204          * @note
205          * Calculate the event occurred X & Y on the buffer
206          */
207         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
208         break;
209     case DBOX_BUFFER_EVENT_UP:
210         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
211         evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
212         info->pressed = 0;
213         /**
214          * @note
215          * We have to keep the event flags, so we should not clear them from here.
216          * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
217          * so if we reset them from here, those kind of callbacks will fails to do their job properly.
218          */
219         ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
220         break;
221     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT:
222         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
223         if (!parent_elm) {
224             ret = DBOX_ACCESS_STATUS_ERROR;
225             break;
226         }
227         memset(&action_info, 0, sizeof(action_info));
228         action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
229         /**
230          * @note
231          * Calculate the event occurred X & Y on the buffer
232          */
233         action_info.x = event_info->info.access.x;
234         action_info.y = event_info->info.access.y;
235         ret = elm_access_action(parent_elm, action_type, &action_info);
236         if (ret == EINA_TRUE) {
237             if (!get_highlighted_object(parent_elm)) {
238                 ErrPrint("Highlighted object is not found\n");
239                 ret = DBOX_ACCESS_STATUS_ERROR;
240             } else {
241                 DbgPrint("Highlighted object is found\n");
242                 ret = DBOX_ACCESS_STATUS_DONE;
243             }
244         } else {
245             ErrPrint("Action error\n");
246             ret = DBOX_ACCESS_STATUS_ERROR;
247         }
248         break;
249     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
250         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
251         if (!parent_elm) {
252             ret = DBOX_ACCESS_STATUS_ERROR;
253             break;
254         }
255         memset(&action_info, 0, sizeof(action_info));
256         action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
257         action_info.highlight_cycle = EINA_FALSE;
258         ret = elm_access_action(parent_elm, action_type, &action_info);
259         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_LAST : DBOX_ACCESS_STATUS_DONE;
260         break;
261     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
262         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
263         if (!parent_elm) {
264             ret = DBOX_ACCESS_STATUS_ERROR;
265             break;
266         }
267         memset(&action_info, 0, sizeof(action_info));
268         action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
269         action_info.highlight_cycle = EINA_FALSE;
270         ret = elm_access_action(parent_elm, action_type, &action_info);
271         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_FIRST : DBOX_ACCESS_STATUS_DONE;
272         break;
273     case DBOX_BUFFER_EVENT_ACCESS_ACTIVATE:
274         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
275         if (!parent_elm) {
276             ret = DBOX_ACCESS_STATUS_ERROR;
277             break;
278         }
279         memset(&action_info, 0, sizeof(action_info));
280         action_type = ELM_ACCESS_ACTION_ACTIVATE;
281         ret = elm_access_action(parent_elm, action_type, &action_info);
282         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
283         break;
284     case DBOX_BUFFER_EVENT_ACCESS_ACTION_UP:
285         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
286         if (!parent_elm) {
287             ret = DBOX_ACCESS_STATUS_ERROR;
288             break;
289         }
290         memset(&action_info, 0, sizeof(action_info));
291         action_type = ELM_ACCESS_ACTION_UP;
292         ret = elm_access_action(parent_elm, action_type, &action_info);
293         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
294         break;
295     case DBOX_BUFFER_EVENT_ACCESS_ACTION_DOWN:
296         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
297         if (!parent_elm) {
298             ret = DBOX_ACCESS_STATUS_ERROR;
299             break;
300         }
301         memset(&action_info, 0, sizeof(action_info));
302         action_type = ELM_ACCESS_ACTION_DOWN;
303         ret = elm_access_action(parent_elm, action_type, &action_info);
304         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
305         break;
306     case DBOX_BUFFER_EVENT_ACCESS_SCROLL_UP:
307         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
308         if (!parent_elm) {
309             ret = DBOX_ACCESS_STATUS_ERROR;
310             break;
311         }
312         memset(&action_info, 0, sizeof(action_info));
313         action_type = ELM_ACCESS_ACTION_SCROLL;
314         action_info.x = event_info->info.access.x;
315         action_info.y = event_info->info.access.y;
316         action_info.mouse_type = event_info->info.access.mouse_type;
317         ret = elm_access_action(parent_elm, action_type, &action_info);
318         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
319         break;
320     case DBOX_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
321         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
322         if (!parent_elm) {
323             ret = DBOX_ACCESS_STATUS_ERROR;
324             break;
325         }
326         memset(&action_info, 0, sizeof(action_info));
327         action_type = ELM_ACCESS_ACTION_SCROLL;
328         action_info.x = event_info->info.access.x;
329         action_info.y = event_info->info.access.y;
330         action_info.mouse_type = event_info->info.access.mouse_type;
331         ret = elm_access_action(parent_elm, action_type, &action_info);
332         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
333         break;
334     case DBOX_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
335         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
336         if (!parent_elm) {
337             ret = DBOX_ACCESS_STATUS_ERROR;
338             break;
339         }
340         memset(&action_info, 0, sizeof(action_info));
341         action_type = ELM_ACCESS_ACTION_SCROLL;
342         action_info.x = event_info->info.access.x;
343         action_info.y = event_info->info.access.y;
344         action_info.mouse_type = event_info->info.access.mouse_type;
345         ret = elm_access_action(parent_elm, action_type, &action_info);
346         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
347         break;
348     case DBOX_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
349         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
350         if (!parent_elm) {
351             ret = DBOX_ACCESS_STATUS_ERROR;
352             break;
353         }
354         memset(&action_info, 0, sizeof(action_info));
355         action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
356         ret = elm_access_action(parent_elm, action_type, &action_info);
357         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
358         break;
359     case DBOX_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
360         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
361         if (!parent_elm) {
362             ret = DBOX_ACCESS_STATUS_ERROR;
363             break;
364         }
365         memset(&action_info, 0, sizeof(action_info));
366         action_type = ELM_ACCESS_ACTION_VALUE_CHANGE;
367         action_info.x = event_info->info.access.x;
368         action_info.y = event_info->info.access.y;
369         action_info.mouse_type = event_info->info.access.mouse_type;
370         ret = elm_access_action(parent_elm, action_type, &action_info);
371         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
372         break;
373     case DBOX_BUFFER_EVENT_ACCESS_MOUSE:
374         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
375         if (!parent_elm) {
376             ret = DBOX_ACCESS_STATUS_ERROR;
377             break;
378         }
379         memset(&action_info, 0, sizeof(action_info));
380         action_type = ELM_ACCESS_ACTION_MOUSE;
381         action_info.x = event_info->info.access.x;
382         action_info.y = event_info->info.access.y;
383         action_info.mouse_type = event_info->info.access.mouse_type;
384         ret = elm_access_action(parent_elm, action_type, &action_info);
385         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
386         break;
387     case DBOX_BUFFER_EVENT_ACCESS_BACK:
388         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
389         if (!parent_elm) {
390             ret = DBOX_ACCESS_STATUS_ERROR;
391             break;
392         }
393         memset(&action_info, 0, sizeof(action_info));
394         action_type = ELM_ACCESS_ACTION_BACK;
395         action_info.x = event_info->info.access.x;
396         action_info.y = event_info->info.access.y;
397         action_info.mouse_type = event_info->info.access.mouse_type;
398         ret = elm_access_action(parent_elm, action_type, &action_info);
399         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
400         break;
401     case DBOX_BUFFER_EVENT_ACCESS_OVER:
402         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
403         if (!parent_elm) {
404             ret = DBOX_ACCESS_STATUS_ERROR;
405             break;
406         }
407         memset(&action_info, 0, sizeof(action_info));
408         action_type = ELM_ACCESS_ACTION_OVER;
409         action_info.x = event_info->info.access.x;
410         action_info.y = event_info->info.access.y;
411         action_info.mouse_type = event_info->info.access.mouse_type;
412         ret = elm_access_action(parent_elm, action_type, &action_info);
413         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
414         break;
415     case DBOX_BUFFER_EVENT_ACCESS_READ:
416         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
417         if (!parent_elm) {
418             ret = DBOX_ACCESS_STATUS_ERROR;
419             break;
420         }
421         memset(&action_info, 0, sizeof(action_info));
422         action_type = ELM_ACCESS_ACTION_READ;
423         action_info.x = event_info->info.access.x;
424         action_info.y = event_info->info.access.y;
425         action_info.mouse_type = event_info->info.access.mouse_type;
426         ret = elm_access_action(parent_elm, action_type, &action_info);
427         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
428         break;
429     case DBOX_BUFFER_EVENT_ACCESS_ENABLE:
430         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
431         if (!parent_elm) {
432             ret = DBOX_ACCESS_STATUS_ERROR;
433             break;
434         }
435         memset(&action_info, 0, sizeof(action_info));
436         action_type = ELM_ACCESS_ACTION_ENABLE;
437         action_info.x = event_info->info.access.x;
438         action_info.y = event_info->info.access.y;
439         action_info.mouse_type = event_info->info.access.mouse_type;
440         ret = elm_access_action(parent_elm, action_type, &action_info);
441         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
442         break;
443     case DBOX_BUFFER_EVENT_ACCESS_DISABLE:
444         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
445         if (!parent_elm) {
446             ret = DBOX_ACCESS_STATUS_ERROR;
447             break;
448         }
449         memset(&action_info, 0, sizeof(action_info));
450         action_type = ELM_ACCESS_ACTION_DISABLE;
451         action_info.x = event_info->info.access.x;
452         action_info.y = event_info->info.access.y;
453         action_info.mouse_type = event_info->info.access.mouse_type;
454         ret = elm_access_action(parent_elm, action_type, &action_info);
455         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
456         break;
457     case DBOX_BUFFER_EVENT_KEY_DOWN:
458         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
459         if (!parent_elm) {
460             ret = DBOX_ACCESS_STATUS_ERROR;
461             break;
462         }
463
464         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
465         if (key_symbol) {
466             char *key_name;
467             char *key_string;
468
469             key_string = XKeysymToString(*key_symbol);
470             key_name = XKeysymToString(*key_symbol);
471             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
472             XFree(key_symbol);
473             XFree(key_name);
474             XFree(key_string);
475         }
476         ret = DBOX_KEY_STATUS_ERROR;
477         break;
478     case DBOX_BUFFER_EVENT_KEY_UP:
479         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
480         if (!parent_elm) {
481             ret = DBOX_ACCESS_STATUS_ERROR;
482             break;
483         }
484
485         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
486         if (key_symbol) {
487             char *key_name;
488             char *key_string;
489
490             key_string = XKeysymToString(*key_symbol);
491             key_name = XKeysymToString(*key_symbol);
492             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
493             XFree(key_symbol);
494             XFree(key_name);
495             XFree(key_string);
496         }
497         ret = DBOX_KEY_STATUS_ERROR;
498         break;
499     case DBOX_BUFFER_EVENT_KEY_FOCUS_IN:
500         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
501         if (!parent_elm) {
502             ret = DBOX_ACCESS_STATUS_ERROR;
503             break;
504         }
505
506         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
507         if (key_symbol) {
508             char *key_name;
509             char *key_string;
510
511             key_string = XKeysymToString(*key_symbol);
512             key_name = XKeysymToString(*key_symbol);
513             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
514             XFree(key_symbol);
515             XFree(key_name);
516             XFree(key_string);
517         }
518         ret = DBOX_KEY_STATUS_ERROR;
519         break;
520     case DBOX_BUFFER_EVENT_KEY_FOCUS_OUT:
521         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
522         if (!parent_elm) {
523             ret = DBOX_ACCESS_STATUS_ERROR;
524             break;
525         }
526
527         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
528         if (key_symbol) {
529             char *key_name;
530             char *key_string;
531
532             key_string = XKeysymToString(*key_symbol);
533             key_name = XKeysymToString(*key_symbol);
534             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
535             XFree(key_symbol);
536             XFree(key_name);
537             XFree(key_string);
538         }
539         ret = DBOX_KEY_STATUS_ERROR;
540         break;
541     default:
542         DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
543         break;
544     }
545
546     return ret;
547 }
548
549 /**
550  * @note
551  * This callback can be called twice (or more) to get a several pixmaps
552  * Acquired pixmaps are used for double/tripple buffering for canvas
553  */
554 static Ecore_X_Pixmap alloc_pixmap_cb(void *data, Ecore_X_Window parent, int w, int h, int depth)
555 {
556     vwin_info_t info = data;
557     Ecore_X_Pixmap pixmap;
558
559     if (!info->handle) {
560         ErrPrint("Invalid handle\n");
561         return 0u;
562     }
563
564     info->w = w;
565     info->h = h;
566     DbgPrint("Size of ee is updated: %dx%d - %d (info: %p)\n", info->w, info->h, depth, info);
567     depth >>= 3;
568
569     if (dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER) == 0u) {
570         /**
571          * @note
572          * Need to allocate a primary buffer
573          */
574         dynamicbox_acquire_buffer(info->handle, DBOX_PRIMARY_BUFFER, info->w, info->h, depth);
575         if (!info->handle) {
576             ErrPrint("Failed to get the buffer\n");
577             return 0u;
578         }
579
580         pixmap = (Ecore_X_Pixmap)dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER);
581     } else if (DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT > 0) {
582         int idx;
583
584         if (!info->resource_array) {
585             info->resource_array = calloc(DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT, sizeof(*info->resource_array));
586             if (!info->resource_array) {
587                 ErrPrint("Out of memory: %s\n", strerror(errno));
588                 return 0u;
589             }
590
591             idx = 0;
592         } else {
593             for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
594                 if (info->resource_array[idx] == 0u) {
595                     break;
596                 }
597             }
598
599             if (idx == DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
600                 ErrPrint("Out of index: %d\n", idx);
601                 return 0u;
602             }
603         }
604
605         if (dynamicbox_acquire_buffer(info->handle, idx, info->w, info->h, depth) < 0) {
606             ErrPrint("Failed to acquire a buffer for %d\n", idx);
607             return 0u;
608         }
609
610         info->resource_array[idx] = dynamicbox_resource_id(info->handle, idx);
611         if (info->resource_array[idx] == 0u) {
612             ErrPrint("Failed to allocate pixmap\n");
613         }
614
615         DbgPrint("Allocated index: %d/%d - %u\n", idx, DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT, info->resource_array[idx]);
616         pixmap = info->resource_array[idx];
617     } else {
618         ErrPrint("Unable to allocate pixmap\n");
619         pixmap = 0u;
620     }
621
622     /**
623      * Acquire a buffer for canvas.
624      */
625     info->type = VWIN_PIXMAP;
626     info->resource_cnt += !!(unsigned int)pixmap;
627     return pixmap;
628 }
629
630 static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap)
631 {
632     vwin_info_t info = data;
633
634     if (!info->handle) {
635         return;
636     }
637
638     if (info->type != VWIN_PIXMAP) {
639         ErrPrint("Impossible\n");
640     }
641
642     if (dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER) == pixmap) {
643         if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
644             DbgPrint("Failed to release buffer\n");
645         }
646         info->resource_cnt--;
647     } else {
648         int idx;
649
650         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
651             /**
652              * @note
653              * Find a index to release it
654              */
655             if (info->resource_array[idx] == pixmap) {
656                 if (dynamicbox_release_buffer(info->handle, idx) < 0) {
657                     DbgPrint("Failed to release buffer\n");
658                 }
659                 info->resource_array[idx] = 0u;
660                 info->resource_cnt--;
661                 break;
662             }
663         }
664     }
665
666     if (info->deleted && info->resource_cnt == 0) {
667         DbgPrint("Destroy buffer handle\n");
668
669         dynamicbox_destroy_buffer(info->handle);
670         free(info->resource_array);
671         free(info->id);
672         free(info);
673     }
674 }
675
676 static void *alloc_fb(void *data, int size)
677 {
678     vwin_info_t info = data;
679     void *buffer;
680
681     if (info->ee) {
682         ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
683         DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
684     }
685
686     if (!info->handle) {
687         ErrPrint("Failed to create a buffer\n");
688         return NULL;
689     }
690
691     if (dynamicbox_acquire_buffer(info->handle, DBOX_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
692         ErrPrint("Failed to acquire buffer\n");
693         return NULL;
694     }
695
696     /**
697      * If it supports the H/W accelerated buffer,
698      * Use it.
699      */
700     if (dynamicbox_support_hw_buffer(info->handle)) {
701         if (dynamicbox_create_hw_buffer(info->handle) == 0) {
702             buffer = dynamicbox_buffer_hw_buffer(info->handle);
703             if (buffer) {
704                 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
705                 info->type = VWIN_GEM;
706                 return buffer;
707             }
708         }
709
710         ErrPrint("Failed to allocate HW Accelerated buffer\n");
711     }
712
713     /**
714      * Or use the buffer of a S/W backend.
715      */
716     buffer = dynamicbox_ref_buffer(info->handle);
717     DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
718     info->type = VWIN_SW_BUF;
719     return buffer;
720 }
721
722 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
723 {
724     void *buffer;
725
726     buffer = alloc_fb(data, size);
727     if (buffer) {
728         vwin_info_t info = data;
729         int _stride;
730
731         *bpp = sizeof(int);
732         _stride = dynamicbox_buffer_stride(info->handle);
733         if (_stride < 0) {
734             _stride = info->w * *bpp;
735         }
736
737         *stride = _stride;
738         *bpp <<= 3;
739         DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
740     }
741
742     return buffer;
743 }
744
745 static void free_fb(void *data, void *ptr)
746 {
747     vwin_info_t info = data;
748
749     if (!info->handle) {
750         return;
751     }
752
753     if (info->type == VWIN_GEM) {
754         if (dynamicbox_destroy_hw_buffer(info->handle) == 0) {
755             DbgPrint("HW Accelerated buffer is destroyed\n");
756         }
757     } else if (info->type == VWIN_SW_BUF) {
758         DbgPrint("SW buffer is destroyed, %p\n", info);
759         dynamicbox_unref_buffer(ptr);
760     } else if (info->type == VWIN_PIXMAP) {
761         ErrPrint("Unable to reach to here\n");
762     }
763
764     if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
765         ErrPrint("Failed to release buffer\n");
766     }
767
768     if (info->deleted) {
769         dynamicbox_destroy_buffer(info->handle);
770         free(info->resource_array);
771         free(info->id);
772         free(info);
773     }
774 }
775
776 static void pre_render_cb(void *data, Evas *e, void *event_info)
777 {
778     vwin_info_t info = data;
779
780     if (!info->handle) {
781         return;
782     }
783
784     if (dynamicbox_conf_premultiplied_alpha()) {
785         Evas_Coord w;
786         Evas_Coord h;
787
788         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
789         evas_damage_rectangle_add(e, 0, 0, w, h);
790     }
791
792     if (info->type == VWIN_GEM) {
793         dynamicbox_buffer_pre_render(info->handle);
794     } else if (info->type == VWIN_PIXMAP) {
795         /**
796          * Only the pixmap type Ecore_Evas uses this variable
797          */
798     } else if (info->type == VWIN_SW_BUF) {
799         /* Do nothing */
800     }
801 }
802
803 static void post_render_cb(void *data, Evas *e, void *event_info)
804 {
805     vwin_info_t info = data;
806
807     if (!info->handle) {
808         return;
809     }
810
811     if (dynamicbox_conf_premultiplied_alpha()) {
812         void *canvas;
813         int x, y, w, h;
814
815         // Get a pointer of a buffer of the virtual canvas
816         canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
817         if (!canvas) {
818             ErrPrint("Failed to get pixel canvas\n");
819             return;
820         }
821
822         ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
823         evas_data_argb_unpremul(canvas, w * h);
824     }
825
826     if (info->type == VWIN_GEM) {
827         dynamicbox_buffer_post_render(info->handle);
828     } else if (info->type == VWIN_PIXMAP) {
829         int idx;
830         unsigned int front_resource_id;
831
832         front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
833
834         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
835             if (front_resource_id == info->resource_array[idx]) {
836                 /**
837                  */
838                 dynamicbox_send_updated_by_idx(info->handle, idx);
839                 break;
840             }
841         }
842
843         if (idx == DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
844             /* Send updated event for PRIMARY BUFFER */
845             if (front_resource_id == dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER)) {
846                 dynamicbox_send_updated_by_idx(info->handle, DBOX_PRIMARY_BUFFER);
847             } else {
848                 DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER));
849             }
850         }
851     } else if (info->type == VWIN_SW_BUF) {
852         dynamicbox_sync_buffer(info->handle);
853     }
854 }
855
856 static void ecore_evas_free_cb(Ecore_Evas *ee)
857 {
858     vwin_info_t info;
859
860     info = ecore_evas_data_get(ee, "dynamic,box,info");
861     if (!info) {
862         DbgPrint("Info is not valid\n");
863         return;
864     }
865
866     if (info->e) {
867         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
868         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
869     }
870
871     info->deleted = 1;
872     info->ee = NULL;
873 }
874
875 PUBLIC void *dynamicbox_get_evas_object(const char *id, int is_gbar)
876 {
877     vwin_info_t info;
878     Evas_Object *rect;
879     const char *engine;
880
881     if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
882         s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
883         if (!s_info.alloc_canvas_with_pixmap) {
884             DbgPrint("pixmap_allocfunc_new is not found\n");
885         }
886
887         s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
888         if (!s_info.alloc_canvas_with_stride) {
889             DbgPrint("allocfunc_with_stirde_new is not found\n");
890         }
891
892         s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
893         if (!s_info.alloc_canvas) {
894             ErrPrint("allocfunc_new is not found\n");
895         }
896
897         if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
898             ErrPrint("No way to allocate canvas\n");
899             return NULL;
900         }
901     }
902
903     if (!id) {
904         ErrPrint("Invalid parameter\n");
905         return NULL;
906     }
907
908     info = calloc(1, sizeof(*info));
909     if (!info) {
910         ErrPrint("Heap: %s\n", strerror(errno));
911         return NULL;
912     }
913
914     info->id = strdup(id);
915     if (!info->id) {
916         ErrPrint("Heap: %s\n", strerror(errno));
917         free(info);
918         return NULL;
919     }
920
921     info->is_gbar = is_gbar;
922
923     /**
924      * Acquire a buffer for canvas.
925      */
926     info->handle = dynamicbox_create_buffer(info->id, info->is_gbar,
927             (dynamicbox_conf_auto_align() || !s_info.alloc_canvas_with_stride),
928             event_handler_cb, info);
929
930     if (!info->handle) {
931         ErrPrint("Failed to create a dynamicbox buffer\n");
932         free(info->id);
933         free(info);
934         return NULL;
935     }
936
937     /**
938      * Size information must be initialized before call the ecore_evas_buffer_new.
939      */
940     info->w = DBOX_DEFAULT_WIDTH;
941     info->h = DBOX_DEFAULT_HEIGHT;
942
943     engine = elm_config_preferred_engine_get();
944     DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE);
945     if (engine && !strcmp(engine, GL_ENGINE)) {
946         if (s_info.alloc_canvas_with_pixmap) {
947             info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
948             if (!info->ee) {
949                 ErrPrint("Unable to create a ee for pixmap\n");
950             }
951         }
952     }
953
954     if (!info->ee) {
955         if (!dynamicbox_conf_auto_align() && s_info.alloc_canvas_with_stride) {
956             info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
957         } else if (s_info.alloc_canvas) {
958             info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
959         }
960     }
961
962     if (!info->ee) {
963         ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
964         dynamicbox_destroy_buffer(info->handle);
965         free(info->id);
966         free(info);
967         return NULL;
968     }
969
970     ecore_evas_data_set(info->ee, "dynamic,box,info", info);
971
972     /**
973      * @note
974      * Free callback must be prepared before use the ecore_evas_free()
975      */
976     ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
977
978     info->e = ecore_evas_get(info->ee);
979     if (!info->e) {
980         ErrPrint("Failed to get evas\n");
981         ecore_evas_free(info->ee);
982         return NULL;
983     }
984
985     pre_render_cb(info, NULL, NULL);
986     ecore_evas_alpha_set(info->ee, EINA_TRUE);
987     post_render_cb(info, NULL, NULL);
988
989     ecore_evas_manual_render_set(info->ee, EINA_FALSE);
990     ecore_evas_resize(info->ee, info->w, info->h);
991
992     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
993     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
994
995     rect = evas_object_rectangle_add(info->e);
996     if (!rect) {
997         ErrPrint("Failed to create evas_object\n");
998         ecore_evas_free(info->ee);
999         return NULL;
1000     }
1001
1002     evas_object_resize(rect, info->w, info->h);
1003     evas_object_color_set(rect, 0, 0, 0, 0);
1004     return rect;
1005 }
1006
1007 /* End of a file */