1fab6d3c0b36ff5a8042fed0ff41f16e4ed294c2
[apps/native/widget/widget.git] / src / virtual_window_wayland.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 #include <Elementary.h>
18 #include <string.h>
19 #include <Ecore_Evas.h>
20 #include <Ecore_X.h>
21 #include <Evas.h>
22
23 #include <dlog.h>
24 #include <widget_errno.h>
25 #include <widget_service.h>
26
27 #include "widget.h"
28 #include "debug.h"
29
30 #define IS_GBAR 1
31
32 #define PUBLIC __attribute__((visibility("default")))
33 #define WIDGET_WIN_TAG "dynamic,box,win"
34
35 #define WIDGET_DEFAULT_WIDTH 1
36 #define WIDGET_DEFAULT_HEIGHT 1
37 #define GL_ENGINE "opengl_x11"
38
39 static struct static_info {
40         Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
41         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);
42         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);
43 } s_info = {
44         .alloc_canvas = NULL,
45         .alloc_canvas_with_stride = NULL,
46         .alloc_canvas_with_pixmap = NULL,
47 };
48
49 /**
50  * @brief
51  * Abstracted Data Type of Virtual Window
52  */
53 typedef struct virtual_window_info {
54         char *id; /**< Identification */
55         widget_buffer_h handle; /**< Livebox buffer handle */
56         enum win_type {
57                 VWIN_SW_BUF = 0x00, /**< S/W buffer */
58                 VWIN_GEM    = 0x01, /**< GEM buffer */
59                 VWIN_PIXMAP = 0x02, /**< PIXMAP */
60                 VWIN_ERROR  = 0x03  /**< Unknown */
61         } type;
62         Ecore_Evas *ee;
63         Evas *e;
64         int is_gbar;
65         int deleted;
66         int w;
67         int h;
68         unsigned int *resource_array;
69         int resource_cnt;
70
71         int pressed;
72 } *vwin_info_t;
73
74 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
75 {
76         Evas_Object *o, *ho;
77
78         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
79         if (!o) return NULL;
80
81         ho = evas_object_data_get(o, "_elm_access_target");
82         return ho;
83 }
84
85 /*!
86  * \note
87  * Every user event (mouse) on the buffer will be passed via this event callback
88  */
89 static int event_handler_cb(struct widget_buffer *handler, struct widget_buffer_event_data *event_info, void *data)
90 {
91         vwin_info_t info = data;
92         Elm_Access_Action_Info action_info;
93         Elm_Access_Action_Type action_type;
94         int ret = 0;
95         Evas_Object *parent_elm;
96         unsigned int flags = 0;
97         double timestamp;
98
99
100         if (!info->handle) {
101                 /* Just ignore this event */
102                 return 0;
103         }
104
105         if (WIDGET_CONF_USE_GETTIMEOFDAY) {
106                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
107                         struct timeval tv;
108
109                         if (gettimeofday(&tv, NULL) < 0) {
110                                 ErrPrint("gettimeofday: %s\n", strerror(errno));
111                         } else {
112                                 timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
113                                 timestamp -= event_info->timestamp;
114
115                                 if (timestamp > WIDGET_CONF_EVENT_FILTER) {
116                                         DbgPrint("Dropped %lf\n", timestamp);
117                                         return 0;
118                                 }
119                         }
120                 }
121
122                 /**
123                  * If the device doesn't use the clock monotic time, we have to emulate it for EVAS
124                  * Evas only use the monotic time for animating objects
125                  */
126                 timestamp = ecore_time_get() * 1000.0f;
127         } else {
128                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
129                         timestamp = ecore_time_get();
130
131                         timestamp -= event_info->timestamp;
132                         if (timestamp > WIDGET_CONF_EVENT_FILTER) {
133                                 DbgPrint("Dropped %lf\n", timestamp);
134                                 return 0;
135                         }
136                 }
137
138                 timestamp = event_info->timestamp * 1000.0f;
139         }
140
141         /*!
142          * \note
143          * Feed up events
144          */
145         switch (event_info->type) {
146         case WIDGET_BUFFER_EVENT_ON_HOLD:
147                 flags = evas_event_default_flags_get(info->e);
148                 flags |= EVAS_EVENT_FLAG_ON_HOLD;
149                 evas_event_default_flags_set(info->e, flags);
150                 ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
151                 break;
152         case WIDGET_BUFFER_EVENT_OFF_HOLD:
153                 flags = evas_event_default_flags_get(info->e);
154                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
155                 evas_event_default_flags_set(info->e, flags);
156                 break;
157         case WIDGET_BUFFER_EVENT_ON_SCROLL:
158                 flags = evas_event_default_flags_get(info->e);
159                 flags |= EVAS_EVENT_FLAG_ON_SCROLL;
160                 evas_event_default_flags_set(info->e, flags);
161                 break;
162         case WIDGET_BUFFER_EVENT_OFF_SCROLL:
163                 flags = evas_event_default_flags_get(info->e);
164                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
165                 evas_event_default_flags_set(info->e, flags);
166                 break;
167         case WIDGET_BUFFER_EVENT_ENTER:
168                 evas_event_feed_mouse_in(info->e, timestamp, NULL);
169                 break;
170         case WIDGET_BUFFER_EVENT_LEAVE:
171                 evas_event_feed_mouse_out(info->e, timestamp, NULL);
172                 break;
173         case WIDGET_BUFFER_EVENT_DOWN:
174                 if (info->pressed) {
175                         ErrPrint("MOUSE UP is not called\n");
176                         ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
177                         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
178                         evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
179                 }
180
181                 /**
182                  * @note
183                  * Before processing the DOWN event,
184                  * Reset the evas event flags regarding ON_HOLD option.
185                  * It can be re-enabled while processing down-move-up events.
186                  */
187                 flags = evas_event_default_flags_get(info->e);
188                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
189                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
190                 evas_event_default_flags_set(info->e, flags);
191                 /**
192                  * @note
193                  * Calculate the event occurred X & Y on the buffer
194                  */
195                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
196                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
197                 info->pressed = 1;
198                 ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
199                 break;
200         case WIDGET_BUFFER_EVENT_MOVE:
201                 /**
202                  * @note
203                  * Calculate the event occurred X & Y on the buffer
204                  */
205                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
206                 break;
207         case WIDGET_BUFFER_EVENT_UP:
208                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
209                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
210                 info->pressed = 0;
211                 /**
212                  * @note
213                  * We have to keep the event flags, so we should not clear them from here.
214                  * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
215                  * so if we reset them from here, those kind of callbacks will fails to do their job properly.
216                  */
217                 ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
218                 break;
219         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
220                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
221                 if (!parent_elm) {
222                         ret = WIDGET_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 = WIDGET_ACCESS_STATUS_ERROR;
238                         } else {
239                                 DbgPrint("Highlighted object is found\n");
240                                 ret = WIDGET_ACCESS_STATUS_DONE;
241                         }
242                 } else {
243                         ErrPrint("Action error\n");
244                         ret = WIDGET_ACCESS_STATUS_ERROR;
245                 }
246                 break;
247         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
248                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
249                 if (!parent_elm) {
250                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_LAST : WIDGET_ACCESS_STATUS_DONE;
258                 break;
259         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
260                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
261                 if (!parent_elm) {
262                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_FIRST : WIDGET_ACCESS_STATUS_DONE;
270                 break;
271         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
272                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
273                 if (!parent_elm) {
274                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
281                 break;
282         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
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_UP;
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_DOWN:
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_DOWN;
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_SCROLL_UP:
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_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
317                 break;
318         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
319                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
320                 if (!parent_elm) {
321                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
331                 break;
332         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
333                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
334                 if (!parent_elm) {
335                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
345                 break;
346         case WIDGET_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
347                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
348                 if (!parent_elm) {
349                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
356                 break;
357         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
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_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
370                 break;
371         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
372                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
373                 if (!parent_elm) {
374                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
384                 break;
385         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
386                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
387                 if (!parent_elm) {
388                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
398                 break;
399         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
400                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
401                 if (!parent_elm) {
402                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
412                 break;
413         case WIDGET_BUFFER_EVENT_ACCESS_READ:
414                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
415                 if (!parent_elm) {
416                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
426                 break;
427         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
428                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
429                 if (!parent_elm) {
430                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
440                 break;
441         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
442                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
443                 if (!parent_elm) {
444                         ret = WIDGET_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) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
454                 break;
455         case WIDGET_BUFFER_EVENT_KEY_DOWN:
456                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
457                 if (!parent_elm) {
458                         ret = WIDGET_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 = WIDGET_KEY_STATUS_ERROR;
475                 break;
476         case WIDGET_BUFFER_EVENT_KEY_UP:
477                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
478                 if (!parent_elm) {
479                         ret = WIDGET_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 = WIDGET_KEY_STATUS_ERROR;
496                 break;
497         case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN:
498                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
499                 if (!parent_elm) {
500                         ret = WIDGET_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 = WIDGET_KEY_STATUS_ERROR;
517                 break;
518         case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT:
519                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
520                 if (!parent_elm) {
521                         ret = WIDGET_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 = WIDGET_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 static void *alloc_fb(void *data, int size)
548 {
549         vwin_info_t info = data;
550         void *buffer;
551
552         if (info->ee) {
553                 ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
554                 DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
555         }
556
557         if (!info->handle) {
558                 ErrPrint("Failed to create a buffer\n");
559                 return NULL;
560         }
561
562         if (widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
563                 ErrPrint("Failed to acquire buffer\n");
564                 return NULL;
565         }
566
567         /**
568          * If it supports the H/W accelerated buffer,
569          * Use it.
570          */
571         if (widget_support_hw_buffer(info->handle)) {
572                 if (widget_create_hw_buffer(info->handle) == 0) {
573                         buffer = widget_buffer_hw_buffer(info->handle);
574                         if (buffer) {
575                                 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
576                                 info->type = VWIN_GEM;
577                                 return buffer;
578                         }
579                 }
580
581                 ErrPrint("Failed to allocate HW Accelerated buffer\n");
582         }
583
584         /**
585          * Or use the buffer of a S/W backend.
586          */
587         buffer = widget_ref_buffer(info->handle);
588         DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
589         info->type = VWIN_SW_BUF;
590         return buffer;
591 }
592
593 static void free_fb(void *data, void *ptr)
594 {
595         vwin_info_t info = data;
596
597         if (!info->handle) {
598                 return;
599         }
600
601         if (info->type == VWIN_GEM) {
602                 if (widget_destroy_hw_buffer(info->handle) == 0) {
603                         DbgPrint("HW Accelerated buffer is destroyed\n");
604                 }
605         } else if (info->type == VWIN_SW_BUF) {
606                 DbgPrint("SW buffer is destroyed, %p\n", info);
607                 widget_unref_buffer(ptr);
608         } else if (info->type == VWIN_PIXMAP) {
609                 ErrPrint("Unable to reach to here\n");
610         }
611
612         if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) {
613                 ErrPrint("Failed to release buffer\n");
614         }
615
616         if (info->deleted) {
617                 widget_destroy_buffer(info->handle);
618                 free(info->resource_array);
619                 free(info->id);
620                 free(info);
621         }
622 }
623
624 static void pre_render_cb(void *data, Evas *e, void *event_info)
625 {
626         vwin_info_t info = data;
627
628         if (!info->handle) {
629                 return;
630         }
631
632         if (widget_conf_premultiplied_alpha()) {
633                 Evas_Coord w;
634                 Evas_Coord h;
635
636                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
637                 evas_damage_rectangle_add(e, 0, 0, w, h);
638         }
639
640         if (info->type == VWIN_GEM) {
641                 widget_buffer_pre_render(info->handle);
642         } else if (info->type == VWIN_PIXMAP) {
643                 /**
644                  * Only the pixmap type Ecore_Evas uses this variable
645                  */
646         } else if (info->type == VWIN_SW_BUF) {
647                 /* Do nothing */
648         }
649 }
650
651 static void post_render_cb(void *data, Evas *e, void *event_info)
652 {
653         vwin_info_t info = data;
654
655         if (!info->handle) {
656                 return;
657         }
658
659         if (widget_conf_premultiplied_alpha()) {
660                 void *canvas;
661                 int x, y, w, h;
662
663                 // Get a pointer of a buffer of the virtual canvas
664                 canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
665                 if (!canvas) {
666                         ErrPrint("Failed to get pixel canvas\n");
667                         return;
668                 }
669
670                 ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
671                 evas_data_argb_unpremul(canvas, w * h);
672         }
673
674         if (info->type == VWIN_GEM) {
675                 widget_buffer_post_render(info->handle);
676         } else if (info->type == VWIN_PIXMAP) {
677                 int idx;
678                 unsigned int front_resource_id;
679
680                 front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
681
682                 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
683                         if (front_resource_id == info->resource_array[idx]) {
684                                 /**
685                                  */
686                                 widget_send_updated_by_idx(info->handle, idx);
687                                 break;
688                         }
689                 }
690
691                 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
692                         /* Send updated event for PRIMARY BUFFER */
693                         if (front_resource_id == widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)) {
694                                 widget_send_updated_by_idx(info->handle, WIDGET_PRIMARY_BUFFER);
695                         } else {
696                                 DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER));
697                         }
698                 }
699         } else if (info->type == VWIN_SW_BUF) {
700                 widget_viewer_sync_buffer(info->handle);
701         }
702 }
703
704 static void pre_destroy_cb(const char *id, void *data)
705 {
706         vwin_info_t info = data;
707
708         if (id && strcmp(info->id, widget_util_uri_to_path(id))) {
709                 /* Skip */
710                 DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id);
711                 return;
712         }
713
714         DbgPrint("Pre destroy event callback is called [%s]\n", id);
715
716         if (info->ee) {
717                 DbgPrint("Toggle manual render mode to prevent from unwanted rendering");
718                 ecore_evas_manual_render_set(info->ee, EINA_TRUE);
719         }
720 }
721
722 static void ecore_evas_free_cb(Ecore_Evas *ee)
723 {
724         vwin_info_t info;
725
726         info = ecore_evas_data_get(ee, "dynamic,box,info");
727         if (!info) {
728                 DbgPrint("Info is not valid\n");
729                 return;
730         }
731
732         widget_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
733
734         if (info->e) {
735                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
736                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
737         }
738
739         info->deleted = 1;
740         info->ee = NULL;
741 }
742
743 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
744 PUBLIC Evas *widget_get_evas(const char *id, int is_gbar)
745 #else /* WIDGET_FEATURE_GBAR_SUPPORTED */
746 PUBLIC Evas *widget_get_evas(const char *id)
747 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
748 {
749         vwin_info_t info;
750         Evas_Object *rect;
751         const char *engine;
752
753         /**
754          * @TODO
755          * If the evas object is already created,
756          * this function should returns ERROR.
757          */
758
759         if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
760                 /*
761                 s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
762                 if (!s_info.alloc_canvas_with_pixmap) {
763                         DbgPrint("pixmap_allocfunc_new is not found\n");
764                 }
765                 */
766
767                 s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
768                 if (!s_info.alloc_canvas_with_stride) {
769                         DbgPrint("allocfunc_with_stirde_new is not found\n");
770                 }
771
772                 s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
773                 if (!s_info.alloc_canvas) {
774                         ErrPrint("allocfunc_new is not found\n");
775                 }
776
777                 if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
778                         ErrPrint("No way to allocate canvas\n");
779                         return NULL;
780                 }
781         }
782
783         if (!id) {
784                 ErrPrint("Invalid parameter\n");
785                 return NULL;
786         }
787
788         info = calloc(1, sizeof(*info));
789         if (!info) {
790                 ErrPrint("Heap: %d\n", errno);
791                 return NULL;
792         }
793
794         info->id = strdup(id);
795         if (!info->id) {
796                 ErrPrint("Heap: %d\n", errno);
797                 free(info);
798                 return NULL;
799         }
800
801 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
802         info->is_gbar = is_gbar;
803 #else
804         info->is_gbar = 0;
805 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
806
807         /**
808          * Acquire a buffer for canvas.
809          */
810         info->handle = widget_create_buffer(info->id, info->is_gbar,
811                         (widget_conf_auto_align() || !s_info.alloc_canvas_with_stride),
812                         event_handler_cb, info);
813
814         if (!info->handle) {
815                 ErrPrint("Failed to create a widget buffer\n");
816                 free(info->id);
817                 free(info);
818                 return NULL;
819         }
820
821         /**
822          * Size information must be initialized before call the ecore_evas_buffer_new.
823          */
824         info->w = WIDGET_DEFAULT_WIDTH;
825         info->h = WIDGET_DEFAULT_HEIGHT;
826
827         engine = elm_config_preferred_engine_get();
828         DbgPrint("Preferred engine: %s (%s)\n", engine, GL_ENGINE);
829         if (engine && !strcmp(engine, GL_ENGINE)) {
830                 if (s_info.alloc_canvas_with_pixmap) {
831                         info->ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
832                         if (!info->ee) {
833                                 ErrPrint("Unable to create a ee for pixmap\n");
834                         }
835                 }
836         }
837
838         if (!info->ee) {
839                 if (!widget_conf_auto_align() && s_info.alloc_canvas_with_stride) {
840                         info->ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
841                 } else if (s_info.alloc_canvas) {
842                         info->ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
843                 }
844         }
845
846         if (!info->ee) {
847                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
848                 widget_destroy_buffer(info->handle);
849                 free(info->id);
850                 free(info);
851                 return NULL;
852         }
853
854         ecore_evas_data_set(info->ee, "dynamic,box,info", info);
855
856         /**
857          * @note
858          * Free callback must be prepared before use the ecore_evas_free()
859          */
860         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
861
862         info->e = ecore_evas_get(info->ee);
863         if (!info->e) {
864                 ErrPrint("Failed to get evas\n");
865                 ecore_evas_free(info->ee);
866                 return NULL;
867         }
868
869         pre_render_cb(info, NULL, NULL);
870         ecore_evas_alpha_set(info->ee, EINA_TRUE);
871         post_render_cb(info, NULL, NULL);
872
873         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
874         ecore_evas_resize(info->ee, info->w, info->h);
875
876         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
877         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
878
879         widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
880
881         return info->e;
882 }
883
884 /* End of a file */