bd60bd5ab38aae104e2940b9b221aa5602a08eb6
[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     } else {
616         ErrPrint("Unable to allocate pixmap\n");
617         pixmap = 0u;
618     }
619
620     /**
621      * Acquire a buffer for canvas.
622      */
623     info->type = VWIN_PIXMAP;
624     info->resource_cnt += !!(unsigned int)pixmap;
625     return pixmap;
626 }
627
628 static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap)
629 {
630     vwin_info_t info = data;
631
632     if (!info->handle) {
633         return;
634     }
635
636     if (info->type != VWIN_PIXMAP) {
637         ErrPrint("Impossible\n");
638     }
639
640     if (dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER) == pixmap) {
641         if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
642             DbgPrint("Failed to release buffer\n");
643         }
644         info->resource_cnt--;
645     } else {
646         int idx;
647
648         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
649             /**
650              * @note
651              * Find a index to release it
652              */
653             if (info->resource_array[idx] == pixmap) {
654                 if (dynamicbox_release_buffer(info->handle, idx) < 0) {
655                     DbgPrint("Failed to release buffer\n");
656                 }
657                 info->resource_array[idx] = 0u;
658                 info->resource_cnt--;
659                 break;
660             }
661         }
662     }
663
664     if (info->deleted && info->resource_cnt == 0) {
665         DbgPrint("Destroy buffer handle\n");
666
667         dynamicbox_destroy_buffer(info->handle);
668         free(info->resource_array);
669         free(info->id);
670         free(info);
671     }
672 }
673
674 static void *alloc_fb(void *data, int size)
675 {
676     vwin_info_t info = data;
677     void *buffer;
678
679     if (info->ee) {
680         ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
681         DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
682     }
683
684     if (!info->handle) {
685         ErrPrint("Failed to create a buffer\n");
686         return NULL;
687     }
688
689     if (dynamicbox_acquire_buffer(info->handle, DBOX_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
690         ErrPrint("Failed to acquire buffer\n");
691         return NULL;
692     }
693
694     /**
695      * If it supports the H/W accelerated buffer,
696      * Use it.
697      */
698     if (dynamicbox_support_hw_buffer(info->handle)) {
699         if (dynamicbox_create_hw_buffer(info->handle) == 0) {
700             buffer = dynamicbox_buffer_hw_buffer(info->handle);
701             if (buffer) {
702                 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
703                 info->type = VWIN_GEM;
704                 return buffer;
705             }
706         }
707
708         ErrPrint("Failed to allocate HW Accelerated buffer\n");
709     }
710
711     /**
712      * Or use the buffer of a S/W backend.
713      */
714     buffer = dynamicbox_ref_buffer(info->handle);
715     DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
716     info->type = VWIN_SW_BUF;
717     return buffer;
718 }
719
720 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
721 {
722     void *buffer;
723
724     buffer = alloc_fb(data, size);
725     if (buffer) {
726         vwin_info_t info = data;
727         int _stride;
728
729         *bpp = sizeof(int);
730         _stride = dynamicbox_buffer_stride(info->handle);
731         if (_stride < 0) {
732             _stride = info->w * *bpp;
733         }
734
735         *stride = _stride;
736         *bpp <<= 3;
737         DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
738     }
739
740     return buffer;
741 }
742
743 static void free_fb(void *data, void *ptr)
744 {
745     vwin_info_t info = data;
746
747     if (!info->handle) {
748         return;
749     }
750
751     if (info->type == VWIN_GEM) {
752         if (dynamicbox_destroy_hw_buffer(info->handle) == 0) {
753             DbgPrint("HW Accelerated buffer is destroyed\n");
754         }
755     } else if (info->type == VWIN_SW_BUF) {
756         DbgPrint("SW buffer is destroyed, %p\n", info);
757         dynamicbox_unref_buffer(ptr);
758     } else if (info->type == VWIN_PIXMAP) {
759         ErrPrint("Unable to reach to here\n");
760     }
761
762     if (dynamicbox_release_buffer(info->handle, DBOX_PRIMARY_BUFFER) < 0) {
763         ErrPrint("Failed to release buffer\n");
764     }
765
766     if (info->deleted) {
767         dynamicbox_destroy_buffer(info->handle);
768         free(info->resource_array);
769         free(info->id);
770         free(info);
771     }
772 }
773
774 static void pre_render_cb(void *data, Evas *e, void *event_info)
775 {
776     vwin_info_t info = data;
777
778     if (!info->handle) {
779         return;
780     }
781
782     if (dynamicbox_conf_premultiplied_alpha()) {
783         Evas_Coord w;
784         Evas_Coord h;
785
786         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
787         evas_damage_rectangle_add(e, 0, 0, w, h);
788     }
789
790     if (info->type == VWIN_GEM) {
791         dynamicbox_buffer_pre_render(info->handle);
792     } else if (info->type == VWIN_PIXMAP) {
793         /**
794          * Only the pixmap type Ecore_Evas uses this variable
795          */
796         info->front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
797     } else if (info->type == VWIN_SW_BUF) {
798         /* Do nothing */
799     }
800 }
801
802 static void post_render_cb(void *data, Evas *e, void *event_info)
803 {
804     vwin_info_t info = data;
805
806     if (!info->handle) {
807         return;
808     }
809
810     if (dynamicbox_conf_premultiplied_alpha()) {
811         void *canvas;
812         int x, y, w, h;
813
814         // Get a pointer of a buffer of the virtual canvas
815         canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
816         if (!canvas) {
817             ErrPrint("Failed to get pixel canvas\n");
818             return;
819         }
820
821         ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
822         evas_data_argb_unpremul(canvas, w * h);
823     }
824
825     if (info->type == VWIN_GEM) {
826         dynamicbox_buffer_post_render(info->handle);
827     } else if (info->type == VWIN_PIXMAP) {
828         int idx;
829
830         for (idx = 0; idx < DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT; idx++) {
831             if (info->front_resource_id == info->resource_array[idx]) {
832                 /**
833                  */
834                 dynamicbox_send_updated_by_idx(info->handle, idx);
835                 break;
836             }
837         }
838
839         if (idx == DYNAMICBOX_CONF_EXTRA_BUFFER_COUNT) {
840             /* Send updated event for PRIMARY BUFFER */
841             if (info->front_resource_id == dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER)) {
842                 dynamicbox_send_updated_by_idx(info->handle, DBOX_PRIMARY_BUFFER);
843             } else {
844                 DbgPrint("Unable to send updated: %u (%u)\n", info->front_resource_id, dynamicbox_resource_id(info->handle, DBOX_PRIMARY_BUFFER));
845             }
846         }
847     } else if (info->type == VWIN_SW_BUF) {
848         dynamicbox_sync_buffer(info->handle);
849     }
850 }
851
852 static void ecore_evas_free_cb(Ecore_Evas *ee)
853 {
854     vwin_info_t info;
855
856     info = ecore_evas_data_get(ee, "dynamic,box,info");
857     if (!info) {
858         DbgPrint("Info is not valid\n");
859         return;
860     }
861
862     if (info->e) {
863         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
864         evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
865     }
866
867     info->deleted = 1;
868     info->ee = NULL;
869 }
870
871 PUBLIC void *dynamicbox_get_evas_object(const char *id, int is_gbar)
872 {
873     vwin_info_t info;
874     Evas_Object *rect;
875     const char *engine;
876     int gl_is_turned_on = 0;
877
878     if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
879         s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
880         if (!s_info.alloc_canvas_with_pixmap) {
881             DbgPrint("pixmap_allocfunc_new is not found\n");
882         }
883
884         s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
885         if (!s_info.alloc_canvas_with_stride) {
886             DbgPrint("allocfunc_with_stirde_new is not found\n");
887         }
888
889         s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
890         if (!s_info.alloc_canvas) {
891             ErrPrint("allocfunc_new is not found\n");
892         }
893
894         if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
895             ErrPrint("No way to allocate canvas\n");
896             return NULL;
897         }
898     }
899
900     if (!id) {
901         ErrPrint("Invalid parameter\n");
902         return NULL;
903     }
904
905     info = calloc(1, sizeof(*info));
906     if (!info) {
907         ErrPrint("Heap: %s\n", strerror(errno));
908         return NULL;
909     }
910
911     info->id = strdup(id);
912     if (!info->id) {
913         ErrPrint("Heap: %s\n", strerror(errno));
914         free(info);
915         return NULL;
916     }
917
918     info->is_gbar = is_gbar;
919
920     /**
921      * Acquire a buffer for canvas.
922      */
923     info->handle = dynamicbox_create_buffer(info->id, info->is_gbar,
924             (dynamicbox_conf_auto_align() || !s_info.alloc_canvas_with_stride),
925             event_handler_cb, info);
926
927     if (!info->handle) {
928         ErrPrint("Failed to create a dynamicbox buffer\n");
929         free(info->id);
930         free(info);
931         return NULL;
932     }
933
934     /**
935      * Size information must be initialized before call the ecore_evas_buffer_new.
936      */
937     info->w = DBOX_DEFAULT_WIDTH;
938     info->h = DBOX_DEFAULT_HEIGHT;
939
940     engine = elm_config_preferred_engine_get();
941     DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE);
942     if (engine && !strcmp(engine, GL_ENGINE)) {
943         if (s_info.alloc_canvas_with_pixmap) {
944             info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
945             if (!info->ee) {
946                 ErrPrint("Unable to create a ee for pixmap\n");
947             } else {
948                 gl_is_turned_on = 1;
949             }
950         }
951     }
952
953     if (!info->ee) {
954         if (!dynamicbox_conf_auto_align() && s_info.alloc_canvas_with_stride) {
955             info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
956         } else if (s_info.alloc_canvas) {
957             info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
958         }
959     }
960
961     if (!info->ee) {
962         ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
963         dynamicbox_destroy_buffer(info->handle);
964         free(info->id);
965         free(info);
966         return NULL;
967     }
968
969     ecore_evas_data_set(info->ee, "dynamic,box,info", info);
970
971     /**
972      * @note
973      * Free callback must be prepared before use the ecore_evas_free()
974      */
975     ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
976
977     info->e = ecore_evas_get(info->ee);
978     if (!info->e) {
979         ErrPrint("Failed to get evas\n");
980         ecore_evas_free(info->ee);
981         return NULL;
982     }
983
984     if (!gl_is_turned_on) {
985         pre_render_cb(info, NULL, NULL);
986         ecore_evas_alpha_set(info->ee, EINA_TRUE);
987         post_render_cb(info, NULL, NULL);
988     } else {
989         DbgPrint("opengl-x11 engine should not turn on the alpha\n");
990     }
991
992     ecore_evas_manual_render_set(info->ee, EINA_FALSE);
993     ecore_evas_resize(info->ee, info->w, info->h);
994
995     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
996     evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
997
998     rect = evas_object_rectangle_add(info->e);
999     if (!rect) {
1000         ErrPrint("Failed to create evas_object\n");
1001         ecore_evas_free(info->ee);
1002         return NULL;
1003     }
1004
1005     evas_object_resize(rect, info->w, info->h);
1006     evas_object_color_set(rect, 0, 0, 0, 0);
1007     return rect;
1008 }
1009
1010 /* End of a file */