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