301f42754b792d77fd895a44d175098f730715f1
[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 #include <math.h>
27
28 #include <X11/Xlib.h>
29
30 #include <dlog.h>
31 #include <widget_errno.h>
32 #include <widget_service.h>
33 #include <widget_service_internal.h>
34 #include <widget_conf.h>
35 #include <widget_buffer.h>
36 #include <widget_provider.h>
37 #include <widget_util.h>
38
39 #include "widget.h"
40 #include "widget_internal.h"
41 #include "debug.h"
42 #include "binder.h"
43
44 #define IS_GBAR 1
45
46 #define PUBLIC __attribute__((visibility("default")))
47 #define WIDGET_WIN_TAG "dynamic,box,win"
48 #define WIN_INFO_TAG "dynamic,box,info"
49
50 #define WIDGET_DEFAULT_WIDTH 1
51 #define WIDGET_DEFAULT_HEIGHT 1
52
53 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
54 {
55         Evas_Object *o, *ho;
56
57         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
58         if (!o) return NULL;
59
60         ho = evas_object_data_get(o, "_elm_access_target");
61         return ho;
62 }
63
64 static inline void apply_orientation(int degree, int *x, int *y, int width, int height, input_event_source_e source)
65 {
66         int _x;
67         int _y;
68         int _angle;
69
70         if (source == INPUT_EVENT_SOURCE_VIEWER) {
71                 /* Already rotated */
72                 return;
73         }
74
75         _x = *x;
76         _y = *y;
77
78         switch (degree) {
79         case 0:
80                 return;
81         case 90:
82                 *x = _y;
83                 *y = width - _x;
84                 return;
85         case 180:
86                 *x = width - _x;
87                 *y = height - _y;
88                 return;
89         case 270:
90                 *x = height - _y;
91                 *y = _x;
92                 return;
93         default:
94                 /**
95                  * @FIXME
96                  * This rotation formular is not work correctly.
97                  * The pointer should be rotated by other way.
98                  * This is not what we want.
99                  */
100                 _angle = degree;
101
102                 *x = (double)_x * cos((double)_angle) - (double)_y * sin((double)_angle);
103                 *y = (double)_x * sin((double)_angle) + (double)_y * cos((double)_angle);
104                 return;
105         }
106 }
107
108 static inline int processing_events(vwin_info_t info, widget_buffer_event_data_t event_info, double timestamp)
109 {
110         Elm_Access_Action_Info action_info;
111         Elm_Access_Action_Type action_type;
112         Evas_Object *parent_elm;
113         KeySym *key_symbol;
114         unsigned int flags = 0;
115         int ret = 0;
116         /**
117          * @note
118          * Feed up events
119          */
120         switch (event_info->type) {
121         case WIDGET_BUFFER_EVENT_ON_HOLD:
122                 flags = evas_event_default_flags_get(info->e);
123                 flags |= EVAS_EVENT_FLAG_ON_HOLD;
124                 evas_event_default_flags_set(info->e, flags);
125                 ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
126                 break;
127         case WIDGET_BUFFER_EVENT_OFF_HOLD:
128                 flags = evas_event_default_flags_get(info->e);
129                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
130                 evas_event_default_flags_set(info->e, flags);
131                 break;
132         case WIDGET_BUFFER_EVENT_ON_SCROLL:
133                 flags = evas_event_default_flags_get(info->e);
134                 flags |= EVAS_EVENT_FLAG_ON_SCROLL;
135                 evas_event_default_flags_set(info->e, flags);
136                 break;
137         case WIDGET_BUFFER_EVENT_OFF_SCROLL:
138                 flags = evas_event_default_flags_get(info->e);
139                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
140                 evas_event_default_flags_set(info->e, flags);
141                 break;
142         case WIDGET_BUFFER_EVENT_ENTER:
143                 evas_event_feed_mouse_in(info->e, timestamp, NULL);
144                 break;
145         case WIDGET_BUFFER_EVENT_LEAVE:
146                 evas_event_feed_mouse_out(info->e, timestamp, NULL);
147                 break;
148         case WIDGET_BUFFER_EVENT_DOWN:
149                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
150
151                 if (info->pressed) {
152                         ErrPrint("MOUSE UP is not called\n");
153                         ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
154                         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
155                         evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
156                 }
157
158                 /**
159                  * @note
160                  * Before processing the DOWN event,
161                  * Reset the evas event flags regarding ON_HOLD option.
162                  * It can be re-enabled while processing down-move-up events.
163                  */
164                 flags = evas_event_default_flags_get(info->e);
165                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
166                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
167                 evas_event_default_flags_set(info->e, flags);
168                 /**
169                  * @note
170                  * Calculate the event occurred X & Y on the buffer
171                  */
172                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
173                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
174                 info->pressed = 1;
175                 ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
176                 break;
177         case WIDGET_BUFFER_EVENT_MOVE:
178                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
179                 /**
180                  * @note
181                  * Calculate the event occurred X & Y on the buffer
182                  */
183                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
184                 break;
185         case WIDGET_BUFFER_EVENT_UP:
186                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
187                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
188                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
189                 info->pressed = 0;
190                 /**
191                  * @note
192                  * We have to keep the event flags, so we should not clear them from here.
193                  * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
194                  * so if we reset them from here, those kind of callbacks will fails to do their job properly.
195                  */
196                 ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
197                 break;
198         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
199                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
200                 if (!parent_elm) {
201                         ret = WIDGET_ACCESS_STATUS_ERROR;
202                         break;
203                 }
204                 memset(&action_info, 0, sizeof(action_info));
205                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT;
206                 /**
207                  * @note
208                  * Calculate the event occurred X & Y on the buffer
209                  */
210                 action_info.x = event_info->info.access.x;
211                 action_info.y = event_info->info.access.y;
212                 ret = elm_access_action(parent_elm, action_type, &action_info);
213                 if (ret == EINA_TRUE) {
214                         if (!get_highlighted_object(parent_elm)) {
215                                 ErrPrint("Highlighted object is not found\n");
216                                 ret = WIDGET_ACCESS_STATUS_ERROR;
217                         } else {
218                                 DbgPrint("Highlighted object is found\n");
219                                 ret = WIDGET_ACCESS_STATUS_DONE;
220                         }
221                 } else {
222                         ErrPrint("Action error\n");
223                         ret = WIDGET_ACCESS_STATUS_ERROR;
224                 }
225                 break;
226         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
227                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
228                 if (!parent_elm) {
229                         ret = WIDGET_ACCESS_STATUS_ERROR;
230                         break;
231                 }
232                 memset(&action_info, 0, sizeof(action_info));
233                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
234                 action_info.highlight_cycle = EINA_FALSE;
235                 ret = elm_access_action(parent_elm, action_type, &action_info);
236                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_LAST : WIDGET_ACCESS_STATUS_DONE;
237                 break;
238         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
239                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
240                 if (!parent_elm) {
241                         ret = WIDGET_ACCESS_STATUS_ERROR;
242                         break;
243                 }
244                 memset(&action_info, 0, sizeof(action_info));
245                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
246                 action_info.highlight_cycle = EINA_FALSE;
247                 ret = elm_access_action(parent_elm, action_type, &action_info);
248                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_FIRST : WIDGET_ACCESS_STATUS_DONE;
249                 break;
250         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
251                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
252                 if (!parent_elm) {
253                         ret = WIDGET_ACCESS_STATUS_ERROR;
254                         break;
255                 }
256                 memset(&action_info, 0, sizeof(action_info));
257                 action_type = 0; //ELM_ACCESS_ACTION_ACTIVATE;
258                 ret = elm_access_action(parent_elm, action_type, &action_info);
259                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
260                 break;
261         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
262                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
263                 if (!parent_elm) {
264                         ret = WIDGET_ACCESS_STATUS_ERROR;
265                         break;
266                 }
267                 memset(&action_info, 0, sizeof(action_info));
268                 action_type = 0; //ELM_ACCESS_ACTION_UP;
269                 ret = elm_access_action(parent_elm, action_type, &action_info);
270                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
271                 break;
272         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_DOWN:
273                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
274                 if (!parent_elm) {
275                         ret = WIDGET_ACCESS_STATUS_ERROR;
276                         break;
277                 }
278                 memset(&action_info, 0, sizeof(action_info));
279                 action_type = 0; //ELM_ACCESS_ACTION_DOWN;
280                 ret = elm_access_action(parent_elm, action_type, &action_info);
281                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
282                 break;
283         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_UP:
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 = 0; //ELM_ACCESS_ACTION_SCROLL;
291                 action_info.x = event_info->info.access.x;
292                 action_info.y = event_info->info.access.y;
293                 action_info.mouse_type = event_info->info.access.mouse_type;
294                 ret = elm_access_action(parent_elm, action_type, &action_info);
295                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
296                 break;
297         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
298                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
299                 if (!parent_elm) {
300                         ret = WIDGET_ACCESS_STATUS_ERROR;
301                         break;
302                 }
303                 memset(&action_info, 0, sizeof(action_info));
304                 action_type = 0; //ELM_ACCESS_ACTION_SCROLL;
305                 action_info.x = event_info->info.access.x;
306                 action_info.y = event_info->info.access.y;
307                 action_info.mouse_type = event_info->info.access.mouse_type;
308                 ret = elm_access_action(parent_elm, action_type, &action_info);
309                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
310                 break;
311         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
312                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
313                 if (!parent_elm) {
314                         ret = WIDGET_ACCESS_STATUS_ERROR;
315                         break;
316                 }
317                 memset(&action_info, 0, sizeof(action_info));
318                 action_type = 0; //ELM_ACCESS_ACTION_SCROLL;
319                 action_info.x = event_info->info.access.x;
320                 action_info.y = event_info->info.access.y;
321                 action_info.mouse_type = event_info->info.access.mouse_type;
322                 ret = elm_access_action(parent_elm, action_type, &action_info);
323                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
324                 break;
325         case WIDGET_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
326                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
327                 if (!parent_elm) {
328                         ret = WIDGET_ACCESS_STATUS_ERROR;
329                         break;
330                 }
331                 memset(&action_info, 0, sizeof(action_info));
332                 action_type = 0; //ELM_ACCESS_ACTION_UNHIGHLIGHT;
333                 ret = elm_access_action(parent_elm, action_type, &action_info);
334                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
335                 break;
336         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
337                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
338                 if (!parent_elm) {
339                         ret = WIDGET_ACCESS_STATUS_ERROR;
340                         break;
341                 }
342                 memset(&action_info, 0, sizeof(action_info));
343                 action_type = 0; //ELM_ACCESS_ACTION_VALUE_CHANGE;
344                 action_info.x = event_info->info.access.x;
345                 action_info.y = event_info->info.access.y;
346                 action_info.mouse_type = event_info->info.access.mouse_type;
347                 ret = elm_access_action(parent_elm, action_type, &action_info);
348                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
349                 break;
350         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
351                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
352                 if (!parent_elm) {
353                         ret = WIDGET_ACCESS_STATUS_ERROR;
354                         break;
355                 }
356                 memset(&action_info, 0, sizeof(action_info));
357                 action_type = 0; //ELM_ACCESS_ACTION_MOUSE;
358                 action_info.x = event_info->info.access.x;
359                 action_info.y = event_info->info.access.y;
360                 action_info.mouse_type = event_info->info.access.mouse_type;
361                 ret = elm_access_action(parent_elm, action_type, &action_info);
362                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
363                 break;
364         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
365                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
366                 if (!parent_elm) {
367                         ret = WIDGET_ACCESS_STATUS_ERROR;
368                         break;
369                 }
370                 memset(&action_info, 0, sizeof(action_info));
371                 action_type = 0; //ELM_ACCESS_ACTION_BACK;
372                 action_info.x = event_info->info.access.x;
373                 action_info.y = event_info->info.access.y;
374                 action_info.mouse_type = event_info->info.access.mouse_type;
375                 ret = elm_access_action(parent_elm, action_type, &action_info);
376                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
377                 break;
378         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
379                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
380                 if (!parent_elm) {
381                         ret = WIDGET_ACCESS_STATUS_ERROR;
382                         break;
383                 }
384                 memset(&action_info, 0, sizeof(action_info));
385                 action_type = 0; //ELM_ACCESS_ACTION_OVER;
386                 action_info.x = event_info->info.access.x;
387                 action_info.y = event_info->info.access.y;
388                 action_info.mouse_type = event_info->info.access.mouse_type;
389                 ret = elm_access_action(parent_elm, action_type, &action_info);
390                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
391                 break;
392         case WIDGET_BUFFER_EVENT_ACCESS_READ:
393                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
394                 if (!parent_elm) {
395                         ret = WIDGET_ACCESS_STATUS_ERROR;
396                         break;
397                 }
398                 memset(&action_info, 0, sizeof(action_info));
399                 action_type = 0; //ELM_ACCESS_ACTION_READ;
400                 action_info.x = event_info->info.access.x;
401                 action_info.y = event_info->info.access.y;
402                 action_info.mouse_type = event_info->info.access.mouse_type;
403                 ret = elm_access_action(parent_elm, action_type, &action_info);
404                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
405                 break;
406         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
407                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
408                 if (!parent_elm) {
409                         ret = WIDGET_ACCESS_STATUS_ERROR;
410                         break;
411                 }
412                 memset(&action_info, 0, sizeof(action_info));
413                 action_type = 0; //ELM_ACCESS_ACTION_ENABLE;
414                 action_info.x = event_info->info.access.x;
415                 action_info.y = event_info->info.access.y;
416                 action_info.mouse_type = event_info->info.access.mouse_type;
417                 ret = elm_access_action(parent_elm, action_type, &action_info);
418                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
419                 break;
420         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
421                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
422                 if (!parent_elm) {
423                         ret = WIDGET_ACCESS_STATUS_ERROR;
424                         break;
425                 }
426                 memset(&action_info, 0, sizeof(action_info));
427                 action_type = 0; //ELM_ACCESS_ACTION_DISABLE;
428                 action_info.x = event_info->info.access.x;
429                 action_info.y = event_info->info.access.y;
430                 action_info.mouse_type = event_info->info.access.mouse_type;
431                 ret = elm_access_action(parent_elm, action_type, &action_info);
432                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
433                 break;
434         case WIDGET_BUFFER_EVENT_KEY_DOWN:
435                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
436                 if (!parent_elm) {
437                         ret = WIDGET_ACCESS_STATUS_ERROR;
438                         break;
439                 }
440
441                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
442                 if (key_symbol) {
443                         char *key_name;
444                         char *key_string;
445
446                         key_string = XKeysymToString(*key_symbol);
447                         key_name = XKeysymToString(*key_symbol);
448                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
449                         XFree(key_symbol);
450                         XFree(key_name);
451                         XFree(key_string);
452                 }
453                 ret = WIDGET_KEY_STATUS_ERROR;
454                 break;
455         case WIDGET_BUFFER_EVENT_KEY_UP:
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_FOCUS_IN:
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_OUT:
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         default:
519                 DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
520                 break;
521         }
522
523 }
524
525 static Eina_Bool pended_event_consumer_cb(void *data)
526 {
527         vwin_info_t info = data;
528         widget_buffer_event_data_t event_info;
529
530         event_info = eina_list_nth(info->pended_events_list, 0);
531         if (!event_info) {
532                 info->pended_events_consumer = NULL;
533                 return ECORE_CALLBACK_CANCEL;
534         }
535
536         DbgPrint("Consuming delayed events\n");
537         (void)processing_events(info, event_info, event_info->timestamp);
538
539         info->pended_events_list = eina_list_remove(info->pended_events_list, event_info);
540         free(event_info);
541         return ECORE_CALLBACK_RENEW;
542 }
543
544 /**
545  * @note
546  * Every user event (mouse) on the buffer will be passed via this event callback
547  */
548 static int event_handler_cb(widget_buffer_h handler, widget_buffer_event_data_t event_info, void *data)
549 {
550         vwin_info_t info = data;
551         double timestamp;
552
553         /**
554          * @note
555          * If the feeds event is accessibility or key event,
556          * "return 0" will confusing the viewer,
557          * because it will waiting result of event processing to do handles state properly.
558          */
559
560         if (!info || info->state != VWIN_INFO_CREATED || !info->handle || info->deleted) {
561                 /* Just ignore this event */
562                 return 0;
563         }
564
565         if (event_info->type == WIDGET_BUFFER_EVENT_FRAME_SKIP_CLEARED) {
566                 /**
567                  * Increase the count_of_rendering only if it meets conditions.
568                  * Or do not increase it to prevent from overflow problem.
569                  * If we trying to increase the count_of_rendering variable, it could be overflowed.
570                  * These conditions will prevents count_of_rendering from overflow issue.
571                  */
572                 if (info->pended_events_list && !info->pended_events_consumer) {
573                         info->pended_events_consumer = ecore_timer_add(0.0001f, pended_event_consumer_cb, info);
574                         if (info->pended_events_consumer) {
575                                 ErrPrint("Failed to create a pended event consumer\n");
576                         }
577                 }
578
579                 return;
580         }
581
582         if (WIDGET_CONF_USE_GETTIMEOFDAY) {
583                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
584                         struct timeval tv;
585
586                         if (gettimeofday(&tv, NULL) < 0) {
587                                 ErrPrint("gettimeofday: %d\n", errno);
588                         } else {
589                                 timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
590                                 timestamp -= event_info->timestamp;
591
592                                 if (timestamp > WIDGET_CONF_EVENT_FILTER) {
593                                         DbgPrint("Dropped %lf\n", timestamp);
594                                         return 0;
595                                 }
596                         }
597                 }
598
599                 /**
600                  * If the device doesn't use the clock monotic time, we have to emulate it for EVAS
601                  * Evas only use the monotic time for animating objects
602                  */
603                 timestamp = ecore_time_get() * 1000.0f;
604         } else {
605                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
606                         timestamp = ecore_time_get();
607
608                         timestamp -= event_info->timestamp;
609                         if (timestamp > WIDGET_CONF_EVENT_FILTER) {
610                                 DbgPrint("Dropped %lf\n", timestamp);
611                                 return 0;
612                         }
613                 }
614
615                 timestamp = event_info->timestamp * 1000.0f;
616         }
617
618         if ((info->w <= 1 && info->h <= 1) || widget_provider_buffer_frame_skip(info->handle) > 0 || info->pended_events_list) {
619                 widget_buffer_event_data_t _ev_info;
620                 _ev_info = malloc(sizeof(*_ev_info));
621                 if (_ev_info) {
622                         memcpy(_ev_info, event_info, sizeof(*_ev_info));
623                         info->pended_events_list = eina_list_append(info->pended_events_list, _ev_info);
624                         _ev_info->timestamp = timestamp;
625                         /**
626                          * @note
627                          * Push events to pending list,.
628                          * Consuming it first.
629                          */
630                         DbgPrint("Canvas is not prepared. pending the events (%dx%d)\n", info->w, info->h);
631                         return 0;
632                 } else {
633                         ErrPrint("malloc: %d\n", errno);
634                 }
635         }
636
637         return processing_events(info, event_info, timestamp);
638 }
639
640 static void pre_render_cb(void *data, Evas *e, void *event_info)
641 {
642         vwin_info_t info = data;
643
644         if (!info || info->state != VWIN_INFO_CREATED || !info->handle) {
645                 return;
646         }
647
648         if (widget_conf_premultiplied_alpha()) {
649                 Evas_Coord w;
650                 Evas_Coord h;
651
652                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
653                 evas_damage_rectangle_add(e, 0, 0, w, h);
654         }
655
656         if (info->type == VWIN_GEM) {
657                 widget_buffer_pre_render(info->handle);
658         } else if (info->type == VWIN_PIXMAP) {
659                 /**
660                  * Only the pixmap type Ecore_Evas uses this variable
661                  */
662         } else if (info->type == VWIN_SW_BUF) {
663                 /* Do nothing */
664         }
665 }
666
667 static void post_render_cb(void *data, Evas *e, void *event_info)
668 {
669         vwin_info_t info = data;
670
671         if (!info || info->state != VWIN_INFO_CREATED || !info->handle) {
672                 return;
673         }
674
675         if (widget_conf_premultiplied_alpha()) {
676                 void *canvas;
677                 int x, y, w, h;
678
679                 // Get a pointer of a buffer of the virtual canvas
680                 canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
681                 if (!canvas) {
682                         ErrPrint("Failed to get pixel canvas\n");
683                         return;
684                 }
685
686                 ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
687                 evas_data_argb_unpremul(canvas, w * h);
688         }
689
690         if (info->type == VWIN_GEM) {
691                 widget_buffer_post_render(info->handle);
692         } else if (info->type == VWIN_PIXMAP) {
693                 int idx;
694                 unsigned int front_resource_id;
695
696                 front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
697
698                 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
699                         if (front_resource_id == info->resource_array[idx]) {
700                                 /**
701                                  */
702                                 widget_send_updated_by_idx(info->handle, idx);
703                                 break;
704                         }
705                 }
706
707                 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
708                         /* Send updated event for PRIMARY BUFFER */
709                         if (front_resource_id == widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)) {
710                                 widget_send_updated_by_idx(info->handle, WIDGET_PRIMARY_BUFFER);
711                         } else {
712                                 DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER));
713                         }
714                 }
715         } else if (info->type == VWIN_SW_BUF) {
716                 widget_viewer_sync_buffer(info->handle);
717         }
718 }
719
720 static int pre_orientation_cb(const char *id, void *data)
721 {
722         vwin_info_t info = data;
723         const char *path;
724         int orientation;
725
726         /* Try provider_app first */
727         if (!info || info->state != VWIN_INFO_CREATED || !id || !info->id) {
728                 return WIDGET_ERROR_INVALID_PARAMETER;
729         }
730
731         path = widget_util_uri_to_path(id);
732         if (path && strcmp(info->id, path)) {
733                 /* Skip */
734                 DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id);
735                 return WIDGET_ERROR_INVALID_PARAMETER;
736         }
737
738         DbgPrint("Pre orientation event callback is called [%s]\n", id);
739         orientation = widget_get_orientation(path);
740         if (orientation < 0) {
741                 ErrPrint("Failed to get orientation: %X\n", orientation);
742         } else {
743                 info->orientation = orientation;
744         }
745
746         return WIDGET_ERROR_NONE;
747 }
748
749 static int pre_destroy_cb(const char *id, void *data)
750 {
751         vwin_info_t info = data;
752         const char *path = NULL;
753
754         if (!info || info->state != VWIN_INFO_CREATED) {
755                 return WIDGET_ERROR_INVALID_PARAMETER;
756         }
757
758         if (id) {
759                 path = widget_util_uri_to_path(id);
760
761                 if (path && strcmp(info->id, path)) {
762                         /* Skip */
763                         DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id);
764                         return WIDGET_ERROR_INVALID_PARAMETER;
765                 }
766         }
767
768         DbgPrint("Pre destroy event callback is called [%s]\n", id);
769
770         if (info->ee) {
771                 DbgPrint("Toggle manual render mode to prevent from unwanted rendering");
772                 ecore_evas_manual_render_set(info->ee, EINA_TRUE);
773         }
774
775         return WIDGET_ERROR_NONE;
776 }
777
778 static void ecore_evas_free_cb(Ecore_Evas *ee)
779 {
780         vwin_info_t info;
781
782         info = ecore_evas_data_get(ee, WIN_INFO_TAG);
783         if (!info) {
784                 DbgPrint("Info is not valid\n");
785                 return;
786         }
787
788         if (info->pended_events_consumer) {
789                 widget_buffer_event_data_t event_info;
790
791                 DbgPrint("Clearing pended event consumer\n");
792                 ecore_timer_del(info->pended_events_consumer);
793                 info->pended_events_consumer = NULL;
794
795                 EINA_LIST_FREE(info->pended_events_list, event_info) {
796                         free(event_info);
797                 }
798         }
799
800         widget_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
801
802         if (info->e) {
803                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
804                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
805         }
806
807         info->deleted = 1;
808         info->ee = NULL;
809 }
810
811 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
812 PUBLIC Evas *widget_get_evas(const char *id, int is_gbar)
813 #else /* WIDGET_FEATURE_GBAR_SUPPORTED */
814 PUBLIC Evas *widget_get_evas(const char *id)
815 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
816 {
817         vwin_info_t info;
818         int orientation;
819
820         /**
821          * @TODO
822          * If the evas object is already created,
823          * this function should returns ERROR.
824          */
825
826         if (!id) {
827                 ErrPrint("Invalid parameter\n");
828                 return NULL;
829         }
830
831         info = calloc(1, sizeof(*info));
832         if (!info) {
833                 ErrPrint("Heap: %d\n", errno);
834                 return NULL;
835         }
836
837         info->state = VWIN_INFO_CREATED;
838
839         info->id = strdup(id);
840         if (!info->id) {
841                 ErrPrint("Heap: %d\n", errno);
842                 info->state = VWIN_INFO_DESTROYED;
843                 free(info);
844                 return NULL;
845         }
846
847 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
848         info->is_gbar = is_gbar;
849 #else
850         info->is_gbar = 0;
851 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
852
853         /**
854          * Acquire a buffer for canvas.
855          */
856         info->handle = widget_create_buffer(info->id, info->is_gbar,
857                         binder_widget_auto_align(),
858                         event_handler_cb, info);
859
860         if (!info->handle) {
861                 ErrPrint("Failed to create a widget buffer\n");
862                 info->state = VWIN_INFO_DESTROYED;
863                 free(info->id);
864                 free(info);
865                 return NULL;
866         }
867
868         /**
869          * Size information must be initialized before call the ecore_evas_buffer_new.
870          */
871         info->w = WIDGET_DEFAULT_WIDTH;
872         info->h = WIDGET_DEFAULT_HEIGHT;
873
874         info->ee = binder_ecore_evas_new(info);
875         if (!info->ee) {
876                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
877                 widget_destroy_buffer(info->handle);
878                 info->state = VWIN_INFO_DESTROYED;
879                 free(info->id);
880                 free(info);
881                 return NULL;
882         }
883
884         ecore_evas_data_set(info->ee, WIN_INFO_TAG, info);
885
886         /**
887          * @note
888          * Free callback must be prepared before use the ecore_evas_free()
889          */
890         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
891
892         info->e = ecore_evas_get(info->ee);
893         if (!info->e) {
894                 ErrPrint("Failed to get evas\n");
895                 ecore_evas_free(info->ee);
896                 return NULL;
897         }
898
899         pre_render_cb(info, NULL, NULL);
900         ecore_evas_alpha_set(info->ee, EINA_TRUE);
901         post_render_cb(info, NULL, NULL);
902
903         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
904         ecore_evas_resize(info->ee, info->w, info->h);
905
906         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
907         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
908
909         widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
910         widget_add_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, pre_orientation_cb, info);
911
912         orientation = widget_get_orientation(info->id);
913         if (orientation < 0) {
914                 ErrPrint("Failed to get orientation[%s]: %X\n", info->id, orientation);
915         } else {
916                 info->orientation = orientation;
917         }
918
919         return info->e;
920 }
921
922 /* End of a file */