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