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