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