Merge from tizen 2.3.1
[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
49 #define WIDGET_DEFAULT_WIDTH 1
50 #define WIDGET_DEFAULT_HEIGHT 1
51
52 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
53 {
54         Evas_Object *o, *ho;
55
56         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
57         if (!o) return NULL;
58
59         ho = evas_object_data_get(o, "_elm_access_target");
60         return ho;
61 }
62
63 static inline void apply_orientation(int degree, int *x, int *y)
64 {
65         int _x;
66         int _y;
67         int _angle;
68
69         switch (degree) {
70         case 0:
71                 return;
72         case 90:
73                 _x = *x;
74                 _y = *y;
75
76                 *x = -_y;
77                 *y = _x;
78                 return;
79         case 180:
80                 _x = *x;
81                 _y = *y;
82                 _angle = degree;
83
84                 *x = -_x;
85                 *y = -_y;
86                 return;
87         case 270:
88                 _x = *x;
89                 _y = *y;
90                 _angle = degree;
91
92                 *x = _y;
93                 *y = -_x;
94                 return;
95         default:
96                 _x = *x;
97                 _y = *y;
98                 _angle = degree;
99
100                 *x = (double)_x * cos((double)_angle) - (double)_y * sin((double)_angle);
101                 *y = (double)_x * sin((double)_angle) + (double)_y * cos((double)_angle);
102                 return;
103         }
104 }
105
106 /**
107  * @note
108  * Every user event (mouse) on the buffer will be passed via this event callback
109  */
110 static int event_handler_cb(widget_buffer_h handler, struct widget_buffer_event_data *event_info, void *data)
111 {
112         vwin_info_t info = data;
113         Elm_Access_Action_Info action_info;
114         Elm_Access_Action_Type action_type;
115         int ret = 0;
116         Evas_Object *parent_elm;
117         KeySym *key_symbol;
118         unsigned int flags = 0;
119         double timestamp;
120
121         if (!info->handle) {
122                 /* Just ignore this event */
123                 return 0;
124         }
125
126         if (WIDGET_CONF_USE_GETTIMEOFDAY) {
127                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
128                         struct timeval tv;
129
130                         if (gettimeofday(&tv, NULL) < 0) {
131                                 ErrPrint("gettimeofday: %d\n", errno);
132                         } else {
133                                 timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
134                                 timestamp -= event_info->timestamp;
135
136                                 if (timestamp > WIDGET_CONF_EVENT_FILTER) {
137                                         DbgPrint("Dropped %lf\n", timestamp);
138                                         return 0;
139                                 }
140                         }
141                 }
142
143                 /**
144                  * If the device doesn't use the clock monotic time, we have to emulate it for EVAS
145                  * Evas only use the monotic time for animating objects
146                  */
147                 timestamp = ecore_time_get() * 1000.0f;
148         } else {
149                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
150                         timestamp = ecore_time_get();
151
152                         timestamp -= event_info->timestamp;
153                         if (timestamp > WIDGET_CONF_EVENT_FILTER) {
154                                 DbgPrint("Dropped %lf\n", timestamp);
155                                 return 0;
156                         }
157                 }
158
159                 timestamp = event_info->timestamp * 1000.0f;
160         }
161
162         /**
163          * @note
164          * Feed up events
165          */
166         switch (event_info->type) {
167         case WIDGET_BUFFER_EVENT_ON_HOLD:
168                 flags = evas_event_default_flags_get(info->e);
169                 flags |= EVAS_EVENT_FLAG_ON_HOLD;
170                 evas_event_default_flags_set(info->e, flags);
171                 ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
172                 break;
173         case WIDGET_BUFFER_EVENT_OFF_HOLD:
174                 flags = evas_event_default_flags_get(info->e);
175                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
176                 evas_event_default_flags_set(info->e, flags);
177                 break;
178         case WIDGET_BUFFER_EVENT_ON_SCROLL:
179                 flags = evas_event_default_flags_get(info->e);
180                 flags |= EVAS_EVENT_FLAG_ON_SCROLL;
181                 evas_event_default_flags_set(info->e, flags);
182                 break;
183         case WIDGET_BUFFER_EVENT_OFF_SCROLL:
184                 flags = evas_event_default_flags_get(info->e);
185                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
186                 evas_event_default_flags_set(info->e, flags);
187                 break;
188         case WIDGET_BUFFER_EVENT_ENTER:
189                 evas_event_feed_mouse_in(info->e, timestamp, NULL);
190                 break;
191         case WIDGET_BUFFER_EVENT_LEAVE:
192                 evas_event_feed_mouse_out(info->e, timestamp, NULL);
193                 break;
194         case WIDGET_BUFFER_EVENT_DOWN:
195                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y);
196
197                 if (info->pressed) {
198                         ErrPrint("MOUSE UP is not called\n");
199                         ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
200                         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
201                         evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
202                 }
203
204                 /**
205                  * @note
206                  * Before processing the DOWN event,
207                  * Reset the evas event flags regarding ON_HOLD option.
208                  * It can be re-enabled while processing down-move-up events.
209                  */
210                 flags = evas_event_default_flags_get(info->e);
211                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
212                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
213                 evas_event_default_flags_set(info->e, flags);
214                 /**
215                  * @note
216                  * Calculate the event occurred X & Y on the buffer
217                  */
218                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
219                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
220                 info->pressed = 1;
221                 ErrPrint("DOWN[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
222                 break;
223         case WIDGET_BUFFER_EVENT_MOVE:
224                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y);
225                 /**
226                  * @note
227                  * Calculate the event occurred X & Y on the buffer
228                  */
229                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
230                 break;
231         case WIDGET_BUFFER_EVENT_UP:
232                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y);
233                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
234                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, timestamp, NULL);
235                 info->pressed = 0;
236                 /**
237                  * @note
238                  * We have to keep the event flags, so we should not clear them from here.
239                  * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
240                  * so if we reset them from here, those kind of callbacks will fails to do their job properly.
241                  */
242                 ErrPrint("UP[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
243                 break;
244         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
245                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
246                 if (!parent_elm) {
247                         ret = WIDGET_ACCESS_STATUS_ERROR;
248                         break;
249                 }
250                 memset(&action_info, 0, sizeof(action_info));
251                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
252                 /**
253                  * @note
254                  * Calculate the event occurred X & Y on the buffer
255                  */
256                 action_info.x = event_info->info.access.x;
257                 action_info.y = event_info->info.access.y;
258                 ret = elm_access_action(parent_elm, action_type, &action_info);
259                 if (ret == EINA_TRUE) {
260                         if (!get_highlighted_object(parent_elm)) {
261                                 ErrPrint("Highlighted object is not found\n");
262                                 ret = WIDGET_ACCESS_STATUS_ERROR;
263                         } else {
264                                 DbgPrint("Highlighted object is found\n");
265                                 ret = WIDGET_ACCESS_STATUS_DONE;
266                         }
267                 } else {
268                         ErrPrint("Action error\n");
269                         ret = WIDGET_ACCESS_STATUS_ERROR;
270                 }
271                 break;
272         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
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 = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
280                 action_info.highlight_cycle = EINA_FALSE;
281                 ret = elm_access_action(parent_elm, action_type, &action_info);
282                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_LAST : WIDGET_ACCESS_STATUS_DONE;
283                 break;
284         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
285                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
286                 if (!parent_elm) {
287                         ret = WIDGET_ACCESS_STATUS_ERROR;
288                         break;
289                 }
290                 memset(&action_info, 0, sizeof(action_info));
291                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
292                 action_info.highlight_cycle = EINA_FALSE;
293                 ret = elm_access_action(parent_elm, action_type, &action_info);
294                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_FIRST : WIDGET_ACCESS_STATUS_DONE;
295                 break;
296         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
297                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
298                 if (!parent_elm) {
299                         ret = WIDGET_ACCESS_STATUS_ERROR;
300                         break;
301                 }
302                 memset(&action_info, 0, sizeof(action_info));
303                 action_type = ELM_ACCESS_ACTION_ACTIVATE;
304                 ret = elm_access_action(parent_elm, action_type, &action_info);
305                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
306                 break;
307         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
308                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
309                 if (!parent_elm) {
310                         ret = WIDGET_ACCESS_STATUS_ERROR;
311                         break;
312                 }
313                 memset(&action_info, 0, sizeof(action_info));
314                 action_type = ELM_ACCESS_ACTION_UP;
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_ACTION_DOWN:
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_DOWN;
326                 ret = elm_access_action(parent_elm, action_type, &action_info);
327                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
328                 break;
329         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_UP:
330                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
331                 if (!parent_elm) {
332                         ret = WIDGET_ACCESS_STATUS_ERROR;
333                         break;
334                 }
335                 memset(&action_info, 0, sizeof(action_info));
336                 action_type = ELM_ACCESS_ACTION_SCROLL;
337                 action_info.x = event_info->info.access.x;
338                 action_info.y = event_info->info.access.y;
339                 action_info.mouse_type = event_info->info.access.mouse_type;
340                 ret = elm_access_action(parent_elm, action_type, &action_info);
341                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
342                 break;
343         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
344                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
345                 if (!parent_elm) {
346                         ret = WIDGET_ACCESS_STATUS_ERROR;
347                         break;
348                 }
349                 memset(&action_info, 0, sizeof(action_info));
350                 action_type = ELM_ACCESS_ACTION_SCROLL;
351                 action_info.x = event_info->info.access.x;
352                 action_info.y = event_info->info.access.y;
353                 action_info.mouse_type = event_info->info.access.mouse_type;
354                 ret = elm_access_action(parent_elm, action_type, &action_info);
355                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
356                 break;
357         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
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_SCROLL;
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_UNHIGHLIGHT:
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_UNHIGHLIGHT;
379                 ret = elm_access_action(parent_elm, action_type, &action_info);
380                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
381                 break;
382         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
383                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
384                 if (!parent_elm) {
385                         ret = WIDGET_ACCESS_STATUS_ERROR;
386                         break;
387                 }
388                 memset(&action_info, 0, sizeof(action_info));
389                 action_type = ELM_ACCESS_ACTION_VALUE_CHANGE;
390                 action_info.x = event_info->info.access.x;
391                 action_info.y = event_info->info.access.y;
392                 action_info.mouse_type = event_info->info.access.mouse_type;
393                 ret = elm_access_action(parent_elm, action_type, &action_info);
394                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
395                 break;
396         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
397                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
398                 if (!parent_elm) {
399                         ret = WIDGET_ACCESS_STATUS_ERROR;
400                         break;
401                 }
402                 memset(&action_info, 0, sizeof(action_info));
403                 action_type = ELM_ACCESS_ACTION_MOUSE;
404                 action_info.x = event_info->info.access.x;
405                 action_info.y = event_info->info.access.y;
406                 action_info.mouse_type = event_info->info.access.mouse_type;
407                 ret = elm_access_action(parent_elm, action_type, &action_info);
408                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
409                 break;
410         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
411                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
412                 if (!parent_elm) {
413                         ret = WIDGET_ACCESS_STATUS_ERROR;
414                         break;
415                 }
416                 memset(&action_info, 0, sizeof(action_info));
417                 action_type = ELM_ACCESS_ACTION_BACK;
418                 action_info.x = event_info->info.access.x;
419                 action_info.y = event_info->info.access.y;
420                 action_info.mouse_type = event_info->info.access.mouse_type;
421                 ret = elm_access_action(parent_elm, action_type, &action_info);
422                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
423                 break;
424         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
425                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
426                 if (!parent_elm) {
427                         ret = WIDGET_ACCESS_STATUS_ERROR;
428                         break;
429                 }
430                 memset(&action_info, 0, sizeof(action_info));
431                 action_type = ELM_ACCESS_ACTION_OVER;
432                 action_info.x = event_info->info.access.x;
433                 action_info.y = event_info->info.access.y;
434                 action_info.mouse_type = event_info->info.access.mouse_type;
435                 ret = elm_access_action(parent_elm, action_type, &action_info);
436                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
437                 break;
438         case WIDGET_BUFFER_EVENT_ACCESS_READ:
439                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
440                 if (!parent_elm) {
441                         ret = WIDGET_ACCESS_STATUS_ERROR;
442                         break;
443                 }
444                 memset(&action_info, 0, sizeof(action_info));
445                 action_type = ELM_ACCESS_ACTION_READ;
446                 action_info.x = event_info->info.access.x;
447                 action_info.y = event_info->info.access.y;
448                 action_info.mouse_type = event_info->info.access.mouse_type;
449                 ret = elm_access_action(parent_elm, action_type, &action_info);
450                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
451                 break;
452         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
453                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
454                 if (!parent_elm) {
455                         ret = WIDGET_ACCESS_STATUS_ERROR;
456                         break;
457                 }
458                 memset(&action_info, 0, sizeof(action_info));
459                 action_type = ELM_ACCESS_ACTION_ENABLE;
460                 action_info.x = event_info->info.access.x;
461                 action_info.y = event_info->info.access.y;
462                 action_info.mouse_type = event_info->info.access.mouse_type;
463                 ret = elm_access_action(parent_elm, action_type, &action_info);
464                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
465                 break;
466         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
467                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
468                 if (!parent_elm) {
469                         ret = WIDGET_ACCESS_STATUS_ERROR;
470                         break;
471                 }
472                 memset(&action_info, 0, sizeof(action_info));
473                 action_type = ELM_ACCESS_ACTION_DISABLE;
474                 action_info.x = event_info->info.access.x;
475                 action_info.y = event_info->info.access.y;
476                 action_info.mouse_type = event_info->info.access.mouse_type;
477                 ret = elm_access_action(parent_elm, action_type, &action_info);
478                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
479                 break;
480         case WIDGET_BUFFER_EVENT_KEY_DOWN:
481                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
482                 if (!parent_elm) {
483                         ret = WIDGET_ACCESS_STATUS_ERROR;
484                         break;
485                 }
486
487                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
488                 if (key_symbol) {
489                         char *key_name;
490                         char *key_string;
491
492                         key_string = XKeysymToString(*key_symbol);
493                         key_name = XKeysymToString(*key_symbol);
494                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
495                         XFree(key_symbol);
496                         XFree(key_name);
497                         XFree(key_string);
498                 }
499                 ret = WIDGET_KEY_STATUS_ERROR;
500                 break;
501         case WIDGET_BUFFER_EVENT_KEY_UP:
502                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
503                 if (!parent_elm) {
504                         ret = WIDGET_ACCESS_STATUS_ERROR;
505                         break;
506                 }
507
508                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
509                 if (key_symbol) {
510                         char *key_name;
511                         char *key_string;
512
513                         key_string = XKeysymToString(*key_symbol);
514                         key_name = XKeysymToString(*key_symbol);
515                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
516                         XFree(key_symbol);
517                         XFree(key_name);
518                         XFree(key_string);
519                 }
520                 ret = WIDGET_KEY_STATUS_ERROR;
521                 break;
522         case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN:
523                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
524                 if (!parent_elm) {
525                         ret = WIDGET_ACCESS_STATUS_ERROR;
526                         break;
527                 }
528
529                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
530                 if (key_symbol) {
531                         char *key_name;
532                         char *key_string;
533
534                         key_string = XKeysymToString(*key_symbol);
535                         key_name = XKeysymToString(*key_symbol);
536                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
537                         XFree(key_symbol);
538                         XFree(key_name);
539                         XFree(key_string);
540                 }
541                 ret = WIDGET_KEY_STATUS_ERROR;
542                 break;
543         case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT:
544                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
545                 if (!parent_elm) {
546                         ret = WIDGET_ACCESS_STATUS_ERROR;
547                         break;
548                 }
549
550                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
551                 if (key_symbol) {
552                         char *key_name;
553                         char *key_string;
554
555                         key_string = XKeysymToString(*key_symbol);
556                         key_name = XKeysymToString(*key_symbol);
557                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
558                         XFree(key_symbol);
559                         XFree(key_name);
560                         XFree(key_string);
561                 }
562                 ret = WIDGET_KEY_STATUS_ERROR;
563                 break;
564         default:
565                 DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
566                 break;
567         }
568
569         return ret;
570 }
571
572 static void pre_render_cb(void *data, Evas *e, void *event_info)
573 {
574         vwin_info_t info = data;
575
576         if (!info->handle) {
577                 return;
578         }
579
580         if (widget_conf_premultiplied_alpha()) {
581                 Evas_Coord w;
582                 Evas_Coord h;
583
584                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
585                 evas_damage_rectangle_add(e, 0, 0, w, h);
586         }
587
588         if (info->type == VWIN_GEM) {
589                 widget_buffer_pre_render(info->handle);
590         } else if (info->type == VWIN_PIXMAP) {
591                 /**
592                  * Only the pixmap type Ecore_Evas uses this variable
593                  */
594         } else if (info->type == VWIN_SW_BUF) {
595                 /* Do nothing */
596         }
597 }
598
599 static void post_render_cb(void *data, Evas *e, void *event_info)
600 {
601         vwin_info_t info = data;
602
603         if (!info->handle) {
604                 return;
605         }
606
607         if (widget_conf_premultiplied_alpha()) {
608                 void *canvas;
609                 int x, y, w, h;
610
611                 // Get a pointer of a buffer of the virtual canvas
612                 canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
613                 if (!canvas) {
614                         ErrPrint("Failed to get pixel canvas\n");
615                         return;
616                 }
617
618                 ecore_evas_geometry_get(info->ee, &x, &y, &w, &h);
619                 evas_data_argb_unpremul(canvas, w * h);
620         }
621
622         if (info->type == VWIN_GEM) {
623                 widget_buffer_post_render(info->handle);
624         } else if (info->type == VWIN_PIXMAP) {
625                 int idx;
626                 unsigned int front_resource_id;
627
628                 front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
629
630                 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
631                         if (front_resource_id == info->resource_array[idx]) {
632                                 /**
633                                  */
634                                 widget_send_updated_by_idx(info->handle, idx);
635                                 break;
636                         }
637                 }
638
639                 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
640                         /* Send updated event for PRIMARY BUFFER */
641                         if (front_resource_id == widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER)) {
642                                 widget_send_updated_by_idx(info->handle, WIDGET_PRIMARY_BUFFER);
643                         } else {
644                                 DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER));
645                         }
646                 }
647         } else if (info->type == VWIN_SW_BUF) {
648                 widget_viewer_sync_buffer(info->handle);
649         }
650 }
651
652 static int pre_orientation_cb(const char *id, void *data)
653 {
654         vwin_info_t info = data;
655         const char *path;
656         int orientation;
657
658         /* Try provider_app first */
659         if (!id) {
660                 return WIDGET_ERROR_INVALID_PARAMETER;
661         }
662
663         path = widget_util_uri_to_path(id);
664         if (path && strcmp(info->id, path)) {
665                 /* Skip */
666                 DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id);
667                 return WIDGET_ERROR_INVALID_PARAMETER;
668         }
669
670         DbgPrint("Pre orientation event callback is called [%s]\n", id);
671         orientation = widget_get_orientation(path);
672         if (orientation < 0) {
673                 ErrPrint("Failed to get orientation: %X\n", orientation);
674         } else {
675                 info->orientation = orientation;
676         }
677
678         return WIDGET_ERROR_NONE;
679 }
680
681 static int pre_destroy_cb(const char *id, void *data)
682 {
683         vwin_info_t info = data;
684         const char *path = NULL;
685
686         if (id) {
687                 path = widget_util_uri_to_path(id);
688
689                 if (path && strcmp(info->id, path)) {
690                         /* Skip */
691                         DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id);
692                         return WIDGET_ERROR_INVALID_PARAMETER;
693                 }
694         }
695
696         DbgPrint("Pre destroy event callback is called [%s]\n", id);
697
698         if (info->ee) {
699                 DbgPrint("Toggle manual render mode to prevent from unwanted rendering");
700                 ecore_evas_manual_render_set(info->ee, EINA_TRUE);
701         }
702
703         return WIDGET_ERROR_NONE;
704 }
705
706 static void ecore_evas_free_cb(Ecore_Evas *ee)
707 {
708         vwin_info_t info;
709
710         info = ecore_evas_data_get(ee, "dynamic,box,info");
711         if (!info) {
712                 DbgPrint("Info is not valid\n");
713                 return;
714         }
715
716         widget_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
717
718         if (info->e) {
719                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
720                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
721         }
722
723         info->deleted = 1;
724         info->ee = NULL;
725 }
726
727 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
728 PUBLIC Evas *widget_get_evas(const char *id, int is_gbar)
729 #else /* WIDGET_FEATURE_GBAR_SUPPORTED */
730 PUBLIC Evas *widget_get_evas(const char *id)
731 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
732 {
733         vwin_info_t info;
734         int orientation;
735
736         /**
737          * @TODO
738          * If the evas object is already created,
739          * this function should returns ERROR.
740          */
741
742         if (!id) {
743                 ErrPrint("Invalid parameter\n");
744                 return NULL;
745         }
746
747         info = calloc(1, sizeof(*info));
748         if (!info) {
749                 ErrPrint("Heap: %d\n", errno);
750                 return NULL;
751         }
752
753         info->id = strdup(id);
754         if (!info->id) {
755                 ErrPrint("Heap: %d\n", errno);
756                 free(info);
757                 return NULL;
758         }
759
760 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
761         info->is_gbar = is_gbar;
762 #else
763         info->is_gbar = 0;
764 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
765
766         /**
767          * Acquire a buffer for canvas.
768          */
769         info->handle = widget_create_buffer(info->id, info->is_gbar,
770                         binder_widget_auto_align(),
771                         event_handler_cb, info);
772
773         if (!info->handle) {
774                 ErrPrint("Failed to create a widget buffer\n");
775                 free(info->id);
776                 free(info);
777                 return NULL;
778         }
779
780         /**
781          * Size information must be initialized before call the ecore_evas_buffer_new.
782          */
783         info->w = WIDGET_DEFAULT_WIDTH;
784         info->h = WIDGET_DEFAULT_HEIGHT;
785
786         info->ee = binder_ecore_evas_new(info);
787         if (!info->ee) {
788                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
789                 widget_destroy_buffer(info->handle);
790                 free(info->id);
791                 free(info);
792                 return NULL;
793         }
794
795         ecore_evas_data_set(info->ee, "dynamic,box,info", info);
796
797         /**
798          * @note
799          * Free callback must be prepared before use the ecore_evas_free()
800          */
801         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
802
803         info->e = ecore_evas_get(info->ee);
804         if (!info->e) {
805                 ErrPrint("Failed to get evas\n");
806                 ecore_evas_free(info->ee);
807                 return NULL;
808         }
809
810         pre_render_cb(info, NULL, NULL);
811         ecore_evas_alpha_set(info->ee, EINA_TRUE);
812         post_render_cb(info, NULL, NULL);
813
814         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
815         ecore_evas_resize(info->ee, info->w, info->h);
816
817         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
818         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
819
820         widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
821         widget_add_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, pre_orientation_cb, info);
822
823         orientation = widget_get_orientation(info->id);
824         if (orientation < 0) {
825                 ErrPrint("Failed to get orientation[%s]: %X\n", info->id, orientation);
826         } else {
827                 info->orientation = orientation;
828         }
829
830         return info->e;
831 }
832
833 /* End of a file */