If "up" event is not comes before comes "down" event,
[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         if (info->pressed) {
184             ErrPrint("MOUSE UP is not called\n");
185             ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
186             evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
187             evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
188         }
189
190         /**
191          * @note
192          * Before processing the DOWN event,
193          * Reset the evas event flags regarding ON_HOLD option.
194          * It can be re-enabled while processing down-move-up events.
195          */
196         flags = evas_event_default_flags_get(info->e);
197         flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
198         flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
199         evas_event_default_flags_set(info->e, flags);
200         /**
201          * @note
202          * Calculate the event occurred X & Y on the buffer
203          */
204         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
205         evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
206         info->pressed = 1;
207         ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
208         break;
209     case DBOX_BUFFER_EVENT_MOVE:
210         /**
211          * @note
212          * Calculate the event occurred X & Y on the buffer
213          */
214         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
215         break;
216     case DBOX_BUFFER_EVENT_UP:
217         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
218         evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
219         info->pressed = 0;
220         /**
221          * @note
222          * We have to keep the event flags, so we should not clear them from here.
223          * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
224          * so if we reset them from here, those kind of callbacks will fails to do their job properly.
225          */
226         ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
227         break;
228     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT:
229         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
230         if (!parent_elm) {
231             ret = DBOX_ACCESS_STATUS_ERROR;
232             break;
233         }
234         memset(&action_info, 0, sizeof(action_info));
235         action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
236         /**
237          * @note
238          * Calculate the event occurred X & Y on the buffer
239          */
240         action_info.x = event_info->info.access.x;
241         action_info.y = event_info->info.access.y;
242         ret = elm_access_action(parent_elm, action_type, &action_info);
243         if (ret == EINA_TRUE) {
244             if (!get_highlighted_object(parent_elm)) {
245                 ErrPrint("Highlighted object is not found\n");
246                 ret = DBOX_ACCESS_STATUS_ERROR;
247             } else {
248                 DbgPrint("Highlighted object is found\n");
249                 ret = DBOX_ACCESS_STATUS_DONE;
250             }
251         } else {
252             ErrPrint("Action error\n");
253             ret = DBOX_ACCESS_STATUS_ERROR;
254         }
255         break;
256     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
257         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
258         if (!parent_elm) {
259             ret = DBOX_ACCESS_STATUS_ERROR;
260             break;
261         }
262         memset(&action_info, 0, sizeof(action_info));
263         action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
264         action_info.highlight_cycle = EINA_FALSE;
265         ret = elm_access_action(parent_elm, action_type, &action_info);
266         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_LAST : DBOX_ACCESS_STATUS_DONE;
267         break;
268     case DBOX_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
269         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
270         if (!parent_elm) {
271             ret = DBOX_ACCESS_STATUS_ERROR;
272             break;
273         }
274         memset(&action_info, 0, sizeof(action_info));
275         action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
276         action_info.highlight_cycle = EINA_FALSE;
277         ret = elm_access_action(parent_elm, action_type, &action_info);
278         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_FIRST : DBOX_ACCESS_STATUS_DONE;
279         break;
280     case DBOX_BUFFER_EVENT_ACCESS_ACTIVATE:
281         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
282         if (!parent_elm) {
283             ret = DBOX_ACCESS_STATUS_ERROR;
284             break;
285         }
286         memset(&action_info, 0, sizeof(action_info));
287         action_type = ELM_ACCESS_ACTION_ACTIVATE;
288         ret = elm_access_action(parent_elm, action_type, &action_info);
289         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
290         break;
291     case DBOX_BUFFER_EVENT_ACCESS_ACTION_UP:
292         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
293         if (!parent_elm) {
294             ret = DBOX_ACCESS_STATUS_ERROR;
295             break;
296         }
297         memset(&action_info, 0, sizeof(action_info));
298         action_type = ELM_ACCESS_ACTION_UP;
299         ret = elm_access_action(parent_elm, action_type, &action_info);
300         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
301         break;
302     case DBOX_BUFFER_EVENT_ACCESS_ACTION_DOWN:
303         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
304         if (!parent_elm) {
305             ret = DBOX_ACCESS_STATUS_ERROR;
306             break;
307         }
308         memset(&action_info, 0, sizeof(action_info));
309         action_type = ELM_ACCESS_ACTION_DOWN;
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_SCROLL_UP:
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_SCROLL;
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_SCROLL_MOVE:
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_SCROLL;
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_SCROLL_DOWN:
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_SCROLL;
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_UNHIGHLIGHT:
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_UNHIGHLIGHT;
363         ret = elm_access_action(parent_elm, action_type, &action_info);
364         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
365         break;
366     case DBOX_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
367         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
368         if (!parent_elm) {
369             ret = DBOX_ACCESS_STATUS_ERROR;
370             break;
371         }
372         memset(&action_info, 0, sizeof(action_info));
373         action_type = ELM_ACCESS_ACTION_VALUE_CHANGE;
374         action_info.x = event_info->info.access.x;
375         action_info.y = event_info->info.access.y;
376         action_info.mouse_type = event_info->info.access.mouse_type;
377         ret = elm_access_action(parent_elm, action_type, &action_info);
378         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
379         break;
380     case DBOX_BUFFER_EVENT_ACCESS_MOUSE:
381         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
382         if (!parent_elm) {
383             ret = DBOX_ACCESS_STATUS_ERROR;
384             break;
385         }
386         memset(&action_info, 0, sizeof(action_info));
387         action_type = ELM_ACCESS_ACTION_MOUSE;
388         action_info.x = event_info->info.access.x;
389         action_info.y = event_info->info.access.y;
390         action_info.mouse_type = event_info->info.access.mouse_type;
391         ret = elm_access_action(parent_elm, action_type, &action_info);
392         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
393         break;
394     case DBOX_BUFFER_EVENT_ACCESS_BACK:
395         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
396         if (!parent_elm) {
397             ret = DBOX_ACCESS_STATUS_ERROR;
398             break;
399         }
400         memset(&action_info, 0, sizeof(action_info));
401         action_type = ELM_ACCESS_ACTION_BACK;
402         action_info.x = event_info->info.access.x;
403         action_info.y = event_info->info.access.y;
404         action_info.mouse_type = event_info->info.access.mouse_type;
405         ret = elm_access_action(parent_elm, action_type, &action_info);
406         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
407         break;
408     case DBOX_BUFFER_EVENT_ACCESS_OVER:
409         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
410         if (!parent_elm) {
411             ret = DBOX_ACCESS_STATUS_ERROR;
412             break;
413         }
414         memset(&action_info, 0, sizeof(action_info));
415         action_type = ELM_ACCESS_ACTION_OVER;
416         action_info.x = event_info->info.access.x;
417         action_info.y = event_info->info.access.y;
418         action_info.mouse_type = event_info->info.access.mouse_type;
419         ret = elm_access_action(parent_elm, action_type, &action_info);
420         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
421         break;
422     case DBOX_BUFFER_EVENT_ACCESS_READ:
423         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
424         if (!parent_elm) {
425             ret = DBOX_ACCESS_STATUS_ERROR;
426             break;
427         }
428         memset(&action_info, 0, sizeof(action_info));
429         action_type = ELM_ACCESS_ACTION_READ;
430         action_info.x = event_info->info.access.x;
431         action_info.y = event_info->info.access.y;
432         action_info.mouse_type = event_info->info.access.mouse_type;
433         ret = elm_access_action(parent_elm, action_type, &action_info);
434         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
435         break;
436     case DBOX_BUFFER_EVENT_ACCESS_ENABLE:
437         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
438         if (!parent_elm) {
439             ret = DBOX_ACCESS_STATUS_ERROR;
440             break;
441         }
442         memset(&action_info, 0, sizeof(action_info));
443         action_type = ELM_ACCESS_ACTION_ENABLE;
444         action_info.x = event_info->info.access.x;
445         action_info.y = event_info->info.access.y;
446         action_info.mouse_type = event_info->info.access.mouse_type;
447         ret = elm_access_action(parent_elm, action_type, &action_info);
448         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
449         break;
450     case DBOX_BUFFER_EVENT_ACCESS_DISABLE:
451         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
452         if (!parent_elm) {
453             ret = DBOX_ACCESS_STATUS_ERROR;
454             break;
455         }
456         memset(&action_info, 0, sizeof(action_info));
457         action_type = ELM_ACCESS_ACTION_DISABLE;
458         action_info.x = event_info->info.access.x;
459         action_info.y = event_info->info.access.y;
460         action_info.mouse_type = event_info->info.access.mouse_type;
461         ret = elm_access_action(parent_elm, action_type, &action_info);
462         ret = (ret == EINA_FALSE) ? DBOX_ACCESS_STATUS_ERROR : DBOX_ACCESS_STATUS_DONE;
463         break;
464     case DBOX_BUFFER_EVENT_KEY_DOWN:
465         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
466         if (!parent_elm) {
467             ret = DBOX_ACCESS_STATUS_ERROR;
468             break;
469         }
470
471         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
472         if (key_symbol) {
473             char *key_name;
474             char *key_string;
475
476             key_string = XKeysymToString(*key_symbol);
477             key_name = XKeysymToString(*key_symbol);
478             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
479             XFree(key_symbol);
480             XFree(key_name);
481             XFree(key_string);
482         }
483         ret = DBOX_KEY_STATUS_ERROR;
484         break;
485     case DBOX_BUFFER_EVENT_KEY_UP:
486         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
487         if (!parent_elm) {
488             ret = DBOX_ACCESS_STATUS_ERROR;
489             break;
490         }
491
492         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
493         if (key_symbol) {
494             char *key_name;
495             char *key_string;
496
497             key_string = XKeysymToString(*key_symbol);
498             key_name = XKeysymToString(*key_symbol);
499             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
500             XFree(key_symbol);
501             XFree(key_name);
502             XFree(key_string);
503         }
504         ret = DBOX_KEY_STATUS_ERROR;
505         break;
506     case DBOX_BUFFER_EVENT_KEY_FOCUS_IN:
507         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
508         if (!parent_elm) {
509             ret = DBOX_ACCESS_STATUS_ERROR;
510             break;
511         }
512
513         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
514         if (key_symbol) {
515             char *key_name;
516             char *key_string;
517
518             key_string = XKeysymToString(*key_symbol);
519             key_name = XKeysymToString(*key_symbol);
520             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
521             XFree(key_symbol);
522             XFree(key_name);
523             XFree(key_string);
524         }
525         ret = DBOX_KEY_STATUS_ERROR;
526         break;
527     case DBOX_BUFFER_EVENT_KEY_FOCUS_OUT:
528         parent_elm = ecore_evas_data_get(info->ee, DBOX_WIN_TAG);
529         if (!parent_elm) {
530             ret = DBOX_ACCESS_STATUS_ERROR;
531             break;
532         }
533
534         key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
535         if (key_symbol) {
536             char *key_name;
537             char *key_string;
538
539             key_string = XKeysymToString(*key_symbol);
540             key_name = XKeysymToString(*key_symbol);
541             DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
542             XFree(key_symbol);
543             XFree(key_name);
544             XFree(key_string);
545         }
546         ret = DBOX_KEY_STATUS_ERROR;
547         break;
548     default:
549         DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
550         break;
551     }
552
553     return ret;
554 }
555
556 /**
557  * @note
558  * This callback can be called twice (or more) to get a several pixmaps
559  * Acquired pixmaps are used for double/tripple buffering for canvas
560  */
561 static Ecore_X_Pixmap alloc_pixmap_cb(void *data, Ecore_X_Window parent, int w, int h, int depth)
562 {
563     vwin_info_t info = data;
564     Ecore_X_Pixmap pixmap;
565
566     if (!info->handle) {
567         ErrPrint("Invalid handle\n");
568         return 0u;
569     }
570
571     info->w = w;
572     info->h = h;
573     DbgPrint("Size of ee is updated: %dx%d - %d (info: %p)\n", info->w, info->h, depth, info);
574     depth >>= 3;
575
576     if (dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER) == 0u) {
577         /**
578          * @note
579          * Need to allocate a primary buffer
580          */
581         dynamicbox_acquire_buffer(info->handle, DBOX_PRIMARY_BUFFER, info->w, info->h, depth);
582         if (!info->handle) {
583             ErrPrint("Failed to get the buffer\n");
584             return 0u;
585         }
586
587         pixmap = (Ecore_X_Pixmap)dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER);
588     } else if (DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT > 0) {
589         int idx;
590
591         if (!info->resource_array) {
592             info->resource_array = calloc(DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT, sizeof(*info->resource_array));
593             if (!info->resource_array) {
594                 ErrPrint("Out of memory: %s\n", strerror(errno));
595                 return 0u;
596             }
597
598             idx = 0;
599         } else {
600             for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
601                 if (info->resource_array[idx] == 0u) {
602                     break;
603                 }
604             }
605
606             if (idx == DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
607                 ErrPrint("Out of index: %d\n", idx);
608                 return 0u;
609             }
610         }
611
612         if (dynamicbox_acquire_buffer(info->handle, idx, info->w, info->h, depth) < 0) {
613             ErrPrint("Failed to acquire a buffer for %d\n", idx);
614             return 0u;
615         }
616
617         info->resource_array[idx] = dynamicbox_resource_id(info->handle, idx);
618         if (info->resource_array[idx] == 0u) {
619             ErrPrint("Failed to allocate pixmap\n");
620         }
621
622         DbgPrint("Allocated index: %d/%d - %u\n", idx, DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT, info->resource_array[idx]);
623         pixmap = info->resource_array[idx];
624     } else {
625         ErrPrint("Unable to allocate pixmap\n");
626         pixmap = 0u;
627     }
628
629     /**
630      * Acquire a buffer for canvas.
631      */
632     info->type = VWIN_PIXMAP;
633     info->resource_cnt += !!(unsigned int)pixmap;
634     return pixmap;
635 }
636
637 static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap)
638 {
639     vwin_info_t info = data;
640
641     if (!info->handle) {
642         return;
643     }
644
645     if (info->type != VWIN_PIXMAP) {
646         ErrPrint("Impossible\n");
647     }
648
649     if (dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER) == pixmap) {
650         if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
651             DbgPrint("Failed to release buffer\n");
652         }
653         info->resource_cnt--;
654     } else {
655         int idx;
656
657         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
658             /**
659              * @note
660              * Find a index to release it
661              */
662             if (info->resource_array[idx] == pixmap) {
663                 if (dynamicbox_release_buffer(info->handle, idx) < 0) {
664                     DbgPrint("Failed to release buffer\n");
665                 }
666                 info->resource_array[idx] = 0u;
667                 info->resource_cnt--;
668                 break;
669             }
670         }
671     }
672
673     if (info->deleted && info->resource_cnt == 0) {
674         DbgPrint("Destroy buffer handle\n");
675
676         dynamicbox_destroy_buffer(info->handle);
677         free(info->resource_array);
678         free(info->id);
679         free(info);
680     }
681 }
682
683 static void *alloc_fb(void *data, int size)
684 {
685     vwin_info_t info = data;
686     void *buffer;
687
688     if (info->ee) {
689         ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
690         DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
691     }
692
693     if (!info->handle) {
694         ErrPrint("Failed to create a buffer\n");
695         return NULL;
696     }
697
698     if (dynamicbox_acquire_buffer(info->handle, DBOX_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
699         ErrPrint("Failed to acquire buffer\n");
700         return NULL;
701     }
702
703     /**
704      * If it supports the H/W accelerated buffer,
705      * Use it.
706      */
707     if (dynamicbox_support_hw_buffer(info->handle)) {
708         if (dynamicbox_create_hw_buffer(info->handle) == 0) {
709             buffer = dynamicbox_buffer_hw_buffer(info->handle);
710             if (buffer) {
711                 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
712                 info->type = VWIN_GEM;
713                 return buffer;
714             }
715         }
716
717         ErrPrint("Failed to allocate HW Accelerated buffer\n");
718     }
719
720     /**
721      * Or use the buffer of a S/W backend.
722      */
723     buffer = dynamicbox_ref_buffer(info->handle);
724     DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
725     info->type = VWIN_SW_BUF;
726     return buffer;
727 }
728
729 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
730 {
731     void *buffer;
732
733     buffer = alloc_fb(data, size);
734     if (buffer) {
735         vwin_info_t info = data;
736         int _stride;
737
738         *bpp = sizeof(int);
739         _stride = dynamicbox_buffer_stride(info->handle);
740         if (_stride < 0) {
741             _stride = info->w * *bpp;
742         }
743
744         *stride = _stride;
745         *bpp <<= 3;
746         DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
747     }
748
749     return buffer;
750 }
751
752 static void free_fb(void *data, void *ptr)
753 {
754     vwin_info_t info = data;
755
756     if (!info->handle) {
757         return;
758     }
759
760     if (info->type == VWIN_GEM) {
761         if (dynamicbox_destroy_hw_buffer(info->handle) == 0) {
762             DbgPrint("HW Accelerated buffer is destroyed\n");
763         }
764     } else if (info->type == VWIN_SW_BUF) {
765         DbgPrint("SW buffer is destroyed, %p\n", info);
766         dynamicbox_unref_buffer(ptr);
767     } else if (info->type == VWIN_PIXMAP) {
768         ErrPrint("Unable to reach to here\n");
769     }
770
771     if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
772         ErrPrint("Failed to release buffer\n");
773     }
774
775     if (info->deleted) {
776         dynamicbox_destroy_buffer(info->handle);
777         free(info->resource_array);
778         free(info->id);
779         free(info);
780     }
781 }
782
783 static void pre_render_cb(void *data, Evas *e, void *event_info)
784 {
785     vwin_info_t info = data;
786
787     if (!info->handle) {
788         return;
789     }
790
791     if (dynamicbox_conf_premultiplied_alpha()) {
792         Evas_Coord w;
793         Evas_Coord h;
794
795         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
796         evas_damage_rectangle_add(e, 0, 0, w, h);
797     }
798
799     if (info->type == VWIN_GEM) {
800         dynamicbox_buffer_pre_render(info->handle);
801     } else if (info->type == VWIN_PIXMAP) {
802         /**
803          * Only the pixmap type Ecore_Evas uses this variable
804          */
805     } else if (info->type == VWIN_SW_BUF) {
806         /* Do nothing */
807     }
808 }
809
810 static void post_render_cb(void *data, Evas *e, void *event_info)
811 {
812     vwin_info_t info = data;
813
814     if (!info->handle) {
815         return;
816     }
817
818     if (dynamicbox_conf_premultiplied_alpha()) {
819         void *canvas;
820         int x, y, w, h;
821
822         // Get a pointer of a buffer of the virtual canvas
823         canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
824         if (!canvas) {
825             ErrPrint("Failed to get pixel canvas\n");
826             return;
827         }
828
829         ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
830         evas_data_argb_unpremul(canvas, w * h);
831     }
832
833     if (info->type == VWIN_GEM) {
834         dynamicbox_buffer_post_render(info->handle);
835     } else if (info->type == VWIN_PIXMAP) {
836         int idx;
837         unsigned int front_resource_id;
838
839         front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
840
841         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
842             if (front_resource_id == info->resource_array[idx]) {
843                 /**
844                  */
845                 dynamicbox_send_updated_by_idx(info->handle, idx);
846                 break;
847             }
848         }
849
850         if (idx == DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
851             /* Send updated event for PRIMARY BUFFER */
852             if (front_resource_id == dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER)) {
853                 dynamicbox_send_updated_by_idx(info->handle, DBOX_PRIMARY_BUFFER);
854             } else {
855                 DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER));
856             }
857         }
858     } else if (info->type == VWIN_SW_BUF) {
859         dynamicbox_sync_buffer(info->handle);
860     }
861 }
862
863 static void ecore_evas_free_cb(Ecore_Evas *ee)
864 {
865     vwin_info_t info;
866
867     info = ecore_evas_data_get(ee, "dynamic,box,info");
868     if (!info) {
869         DbgPrint("Info is not valid\n");
870         return;
871     }
872
873     if (info->e) {
874         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
875         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
876     }
877
878     info->deleted = 1;
879     info->ee = NULL;
880 }
881
882 PUBLIC void *dynamicbox_get_evas_object(const char *id, int is_gbar)
883 {
884     vwin_info_t info;
885     Evas_Object *rect;
886     const char *engine;
887
888     if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
889         s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
890         if (!s_info.alloc_canvas_with_pixmap) {
891             DbgPrint("pixmap_allocfunc_new is not found\n");
892         }
893
894         s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
895         if (!s_info.alloc_canvas_with_stride) {
896             DbgPrint("allocfunc_with_stirde_new is not found\n");
897         }
898
899         s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
900         if (!s_info.alloc_canvas) {
901             ErrPrint("allocfunc_new is not found\n");
902         }
903
904         if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
905             ErrPrint("No way to allocate canvas\n");
906             return NULL;
907         }
908     }
909
910     if (!id) {
911         ErrPrint("Invalid parameter\n");
912         return NULL;
913     }
914
915     info = calloc(1, sizeof(*info));
916     if (!info) {
917         ErrPrint("Heap: %s\n", strerror(errno));
918         return NULL;
919     }
920
921     info->id = strdup(id);
922     if (!info->id) {
923         ErrPrint("Heap: %s\n", strerror(errno));
924         free(info);
925         return NULL;
926     }
927
928     info->is_gbar = is_gbar;
929
930     /**
931      * Acquire a buffer for canvas.
932      */
933     info->handle = dynamicbox_create_buffer(info->id, info->is_gbar,
934             (dynamicbox_conf_auto_align() || !s_info.alloc_canvas_with_stride),
935             event_handler_cb, info);
936
937     if (!info->handle) {
938         ErrPrint("Failed to create a dynamicbox buffer\n");
939         free(info->id);
940         free(info);
941         return NULL;
942     }
943
944     /**
945      * Size information must be initialized before call the ecore_evas_buffer_new.
946      */
947     info->w = DBOX_DEFAULT_WIDTH;
948     info->h = DBOX_DEFAULT_HEIGHT;
949
950     engine = elm_config_preferred_engine_get();
951     DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE);
952     if (engine && !strcmp(engine, GL_ENGINE)) {
953         if (s_info.alloc_canvas_with_pixmap) {
954             info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
955             if (!info->ee) {
956                 ErrPrint("Unable to create a ee for pixmap\n");
957             }
958         }
959     }
960
961     if (!info->ee) {
962         if (!dynamicbox_conf_auto_align() && s_info.alloc_canvas_with_stride) {
963             info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
964         } else if (s_info.alloc_canvas) {
965             info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
966         }
967     }
968
969     if (!info->ee) {
970         ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
971         dynamicbox_destroy_buffer(info->handle);
972         free(info->id);
973         free(info);
974         return NULL;
975     }
976
977     ecore_evas_data_set(info->ee, "dynamic,box,info", info);
978
979     /**
980      * @note
981      * Free callback must be prepared before use the ecore_evas_free()
982      */
983     ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
984
985     info->e = ecore_evas_get(info->ee);
986     if (!info->e) {
987         ErrPrint("Failed to get evas\n");
988         ecore_evas_free(info->ee);
989         return NULL;
990     }
991
992     pre_render_cb(info, NULL, NULL);
993     ecore_evas_alpha_set(info->ee, EINA_TRUE);
994     post_render_cb(info, NULL, NULL);
995
996     ecore_evas_manual_render_set(info->ee, EINA_FALSE);
997     ecore_evas_resize(info->ee, info->w, info->h);
998
999     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
1000     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
1001
1002     rect = evas_object_rectangle_add(info->e);
1003     if (!rect) {
1004         ErrPrint("Failed to create evas_object\n");
1005         ecore_evas_free(info->ee);
1006         return NULL;
1007     }
1008
1009     evas_object_resize(rect, info->w, info->h);
1010     evas_object_color_set(rect, 0, 0, 0, 0);
1011     return rect;
1012 }
1013
1014 /* End of a file */