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