Sync with the latest tizen 2.x
[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 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31
32 #include <X11/Xlib.h>
33
34 #include <dlog.h>
35 #include <widget_errno.h>
36 #include <widget_service.h>
37 #include <widget_service_internal.h>
38 #include <widget_conf.h>
39 #include <widget_buffer.h>
40 #include <widget_provider.h>
41 #include <widget_provider_buffer.h>
42 #include <widget_util.h>
43 #include <libgen.h>
44
45 #include "widget.h"
46 #include "widget_internal.h"
47 #include "debug.h"
48 #include "binder.h"
49
50 #define IS_GBAR 1
51
52 #define PUBLIC __attribute__((visibility("default")))
53 #define WIDGET_WIN_TAG "dynamic,box,win"
54 #define WIN_INFO_TAG "dynamic,box,info"
55
56 #define WIDGET_DEFAULT_WIDTH 1
57 #define WIDGET_DEFAULT_HEIGHT 1
58
59 #define MOUSE_BUTTON_LEFT 1
60
61 /**
62  * @note
63  * Supported touch devices are limited to 32.
64  * Because of count of bits of integer type. (32 bits)
65  */
66 #define MAX_DEVICE 32
67
68 #define IS_PRESSED(info, device)        (((device) < MAX_DEVICE) ? (((info)->pressed & (0x01 << (device))) == (0x01 << (device))) : 0)
69
70 /**
71  * @note
72  * Short-Circuit
73  */
74 #define SET_PRESSED(info, device)       ((void)(((device) < MAX_DEVICE) && (((info)->pressed |= (0x01 << (device))))))
75 #define SET_RELEASED(info, device)      ((void)(((device) < MAX_DEVICE) && (((info)->pressed &= (~(0x01 << (device)))))))
76
77 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
78 {
79         Evas_Object *o, *ho;
80
81         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
82         if (!o) return NULL;
83
84         ho = evas_object_data_get(o, "_elm_access_target");
85         return ho;
86 }
87
88 static inline void apply_orientation(int degree, int *x, int *y, int width, int height, input_event_source_e source)
89 {
90         int _x;
91         int _y;
92         int _angle;
93
94         if (source == INPUT_EVENT_SOURCE_VIEWER) {
95                 /* Already rotated */
96                 return;
97         }
98
99         _x = *x;
100         _y = *y;
101
102         switch (degree) {
103         case 0:
104                 return;
105         case 90:
106                 *x = _y;
107                 *y = width - _x;
108                 return;
109         case 180:
110                 *x = width - _x;
111                 *y = height - _y;
112                 return;
113         case 270:
114                 *x = height - _y;
115                 *y = _x;
116                 return;
117         default:
118                 /**
119                  * @FIXME
120                  * This rotation formular is not work correctly.
121                  * The pointer should be rotated by other way.
122                  * This is not what we want.
123                  */
124                 _angle = degree;
125
126                 *x = (double)_x * cos((double)_angle) - (double)_y * sin((double)_angle);
127                 *y = (double)_x * sin((double)_angle) + (double)_y * cos((double)_angle);
128                 return;
129         }
130 }
131
132 static inline int processing_events(vwin_info_t info, widget_buffer_event_data_t event_info, double timestamp)
133 {
134         Elm_Access_Action_Info action_info;
135         Elm_Access_Action_Type action_type;
136         Evas_Object *parent_elm;
137         KeySym *key_symbol;
138         unsigned int flags = 0;
139         int ret = 0;
140         /**
141          * @note
142          * Feed up events
143          */
144         switch (event_info->type) {
145         case WIDGET_BUFFER_EVENT_ON_HOLD:
146                 flags = evas_event_default_flags_get(info->e);
147                 flags |= EVAS_EVENT_FLAG_ON_HOLD;
148                 evas_event_default_flags_set(info->e, flags);
149                 ErrPrint("ON_HOLD[%s] %dx%d - %lf\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp);
150                 if (info->pressed == 0) {
151                         info->flags.field.on_hold_before_down = 1;
152                 }
153                 break;
154         case WIDGET_BUFFER_EVENT_OFF_HOLD:
155                 flags = evas_event_default_flags_get(info->e);
156                 flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
157                 evas_event_default_flags_set(info->e, flags);
158                 break;
159         case WIDGET_BUFFER_EVENT_ON_SCROLL:
160                 flags = evas_event_default_flags_get(info->e);
161                 flags |= EVAS_EVENT_FLAG_ON_SCROLL;
162                 evas_event_default_flags_set(info->e, flags);
163                 if (info->pressed == 0) {
164                         info->flags.field.on_scroll_before_down = 1;
165                 }
166                 break;
167         case WIDGET_BUFFER_EVENT_OFF_SCROLL:
168                 flags = evas_event_default_flags_get(info->e);
169                 flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
170                 evas_event_default_flags_set(info->e, flags);
171                 break;
172         case WIDGET_BUFFER_EVENT_ENTER:
173                 evas_event_feed_mouse_in(info->e, timestamp, NULL);
174                 break;
175         case WIDGET_BUFFER_EVENT_LEAVE:
176                 evas_event_feed_mouse_out(info->e, timestamp, NULL);
177                 break;
178         case WIDGET_BUFFER_EVENT_DOWN:
179                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
180
181                 if (IS_PRESSED(info, event_info->info.pointer.device)) {
182                         ErrPrint("MOUSE UP is not called\n");
183                         ErrPrint("UP[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device);
184                         if (event_info->info.pointer.device > 0) {
185                                 /**
186                                  * @multi touch up
187                                  */
188                                 evas_event_feed_multi_up(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y,
189                                                                                         0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */
190                                                                                         0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */
191                                                                                         EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */
192                         } else {
193                                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
194                                 evas_event_feed_mouse_up(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL);
195                         }
196                 }
197
198                 /**
199                  * @note
200                  * Before processing the DOWN event,
201                  * Reset the evas event flags regarding ON_HOLD option.
202                  * It can be re-enabled while processing down-move-up events.
203                  * However if those events are occurred right before DOWN,
204                  * Do not clear it.
205                  * Some speicific cases, the ON_HOLD(ON_SCROLL) event can be delievered
206                  * before MOUSE_DOWN event.
207                  */
208                 flags = evas_event_default_flags_get(info->e);
209                 if (!info->flags.field.on_hold_before_down) {
210                         flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
211                 }
212                 if (!info->flags.field.on_scroll_before_down) {
213                         flags &= ~EVAS_EVENT_FLAG_ON_SCROLL;
214                 }
215                 evas_event_default_flags_set(info->e, flags);
216
217                 /**
218                  * @note
219                  * Reset flags after dealing with the ON_HOLD/ON_SCROLL event
220                  */
221                 info->flags.field.on_scroll_before_down = 0;
222                 info->flags.field.on_hold_before_down = 0;
223                 /**
224                  * @note
225                  * Calculate the event occurred X & Y on the buffer
226                  */
227                 if (event_info->info.pointer.device > 0) {
228                         evas_event_feed_multi_down(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y,
229                                                                                         0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */
230                                                                                         0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */
231                                                                                         EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */
232                 } else {
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_down(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL); /* + 0.2f just for fake event */
235                 }
236
237                 SET_PRESSED(info, event_info->info.pointer.device);
238                 ErrPrint("DOWN[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device);
239                 break;
240         case WIDGET_BUFFER_EVENT_MOVE:
241                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
242                 /**
243                  * @note
244                  * Calculate the event occurred X & Y on the buffer
245                  */
246                 if (event_info->info.pointer.device > 0) {
247                         evas_event_feed_multi_move(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y,
248                                                                                         0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */
249                                                                                         0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */
250                                                                                         timestamp, NULL); /* timestamp, ... */
251                 } else {
252                         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
253                 }
254                 break;
255         case WIDGET_BUFFER_EVENT_UP:
256                 apply_orientation(info->orientation, &event_info->info.pointer.x, &event_info->info.pointer.y, info->w, info->h, event_info->info.pointer.source);
257
258                 if (event_info->info.pointer.device > 0) {
259                         evas_event_feed_multi_up(info->e, event_info->info.pointer.device, event_info->info.pointer.x, event_info->info.pointer.y,
260                                                                                         0.0f, 0.0f, 0.0f, /* radius, radius_x, radius_y */
261                                                                                         0.0f, 0.0f, 0.0f, 0.0f, /* pressure, angle, fx, fy */
262                                                                                         EVAS_BUTTON_NONE, timestamp, NULL); /* button_flags, timestamp, ... */
263                 } else {
264                         evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, NULL);
265                         evas_event_feed_mouse_up(info->e, MOUSE_BUTTON_LEFT, EVAS_BUTTON_NONE, timestamp, NULL);
266                 }
267                 SET_RELEASED(info, event_info->info.pointer.device);
268                 /**
269                  * @note
270                  * We have to keep the event flags, so we should not clear them from here.
271                  * Sometimes, asynchronously callable Callbacks can refer the evas event flags after up event.
272                  * so if we reset them from here, those kind of callbacks will fails to do their job properly.
273                  */
274                 ErrPrint("UP[%s] %dx%d - %lf (%d)\n", info->id, event_info->info.pointer.x, event_info->info.pointer.y, timestamp, event_info->info.pointer.device);
275                 break;
276         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
277                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
278                 if (!parent_elm) {
279                         ret = WIDGET_ACCESS_STATUS_ERROR;
280                         break;
281                 }
282                 memset(&action_info, 0, sizeof(action_info));
283                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT;
284                 /**
285                  * @note
286                  * Calculate the event occurred X & Y on the buffer
287                  */
288                 action_info.x = event_info->info.access.x;
289                 action_info.y = event_info->info.access.y;
290                 ret = elm_access_action(parent_elm, action_type, &action_info);
291                 if (ret == EINA_TRUE) {
292                         if (!get_highlighted_object(parent_elm)) {
293                                 ErrPrint("Highlighted object is not found\n");
294                                 ret = WIDGET_ACCESS_STATUS_ERROR;
295                         } else {
296                                 DbgPrint("Highlighted object is found\n");
297                                 ret = WIDGET_ACCESS_STATUS_DONE;
298                         }
299                 } else {
300                         ErrPrint("Action error\n");
301                         ret = WIDGET_ACCESS_STATUS_ERROR;
302                 }
303                 break;
304         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
305                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
306                 if (!parent_elm) {
307                         ret = WIDGET_ACCESS_STATUS_ERROR;
308                         break;
309                 }
310                 memset(&action_info, 0, sizeof(action_info));
311                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
312                 action_info.highlight_cycle = EINA_FALSE;
313                 ret = elm_access_action(parent_elm, action_type, &action_info);
314                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_LAST : WIDGET_ACCESS_STATUS_DONE;
315                 break;
316         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
317                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
318                 if (!parent_elm) {
319                         ret = WIDGET_ACCESS_STATUS_ERROR;
320                         break;
321                 }
322                 memset(&action_info, 0, sizeof(action_info));
323                 action_type = 0; //ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
324                 action_info.highlight_cycle = EINA_FALSE;
325                 ret = elm_access_action(parent_elm, action_type, &action_info);
326                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_FIRST : WIDGET_ACCESS_STATUS_DONE;
327                 break;
328         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
329                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
330                 if (!parent_elm) {
331                         ret = WIDGET_ACCESS_STATUS_ERROR;
332                         break;
333                 }
334                 memset(&action_info, 0, sizeof(action_info));
335                 action_type = 0; //ELM_ACCESS_ACTION_ACTIVATE;
336                 ret = elm_access_action(parent_elm, action_type, &action_info);
337                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
338                 break;
339         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
340                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
341                 if (!parent_elm) {
342                         ret = WIDGET_ACCESS_STATUS_ERROR;
343                         break;
344                 }
345                 memset(&action_info, 0, sizeof(action_info));
346                 action_type = 0; //ELM_ACCESS_ACTION_UP;
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_ACTION_DOWN:
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_DOWN;
358                 ret = elm_access_action(parent_elm, action_type, &action_info);
359                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
360                 break;
361         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_UP:
362                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
363                 if (!parent_elm) {
364                         ret = WIDGET_ACCESS_STATUS_ERROR;
365                         break;
366                 }
367                 memset(&action_info, 0, sizeof(action_info));
368                 action_type = 0; //ELM_ACCESS_ACTION_SCROLL;
369                 action_info.x = event_info->info.access.x;
370                 action_info.y = event_info->info.access.y;
371                 action_info.mouse_type = event_info->info.access.mouse_type;
372                 ret = elm_access_action(parent_elm, action_type, &action_info);
373                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
374                 break;
375         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
376                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
377                 if (!parent_elm) {
378                         ret = WIDGET_ACCESS_STATUS_ERROR;
379                         break;
380                 }
381                 memset(&action_info, 0, sizeof(action_info));
382                 action_type = 0; //ELM_ACCESS_ACTION_SCROLL;
383                 action_info.x = event_info->info.access.x;
384                 action_info.y = event_info->info.access.y;
385                 action_info.mouse_type = event_info->info.access.mouse_type;
386                 ret = elm_access_action(parent_elm, action_type, &action_info);
387                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
388                 break;
389         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
390                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
391                 if (!parent_elm) {
392                         ret = WIDGET_ACCESS_STATUS_ERROR;
393                         break;
394                 }
395                 memset(&action_info, 0, sizeof(action_info));
396                 action_type = 0; //ELM_ACCESS_ACTION_SCROLL;
397                 action_info.x = event_info->info.access.x;
398                 action_info.y = event_info->info.access.y;
399                 action_info.mouse_type = event_info->info.access.mouse_type;
400                 ret = elm_access_action(parent_elm, action_type, &action_info);
401                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
402                 break;
403         case WIDGET_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
404                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
405                 if (!parent_elm) {
406                         ret = WIDGET_ACCESS_STATUS_ERROR;
407                         break;
408                 }
409                 memset(&action_info, 0, sizeof(action_info));
410                 action_type = 0; //ELM_ACCESS_ACTION_UNHIGHLIGHT;
411                 ret = elm_access_action(parent_elm, action_type, &action_info);
412                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
413                 break;
414         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
415                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
416                 if (!parent_elm) {
417                         ret = WIDGET_ACCESS_STATUS_ERROR;
418                         break;
419                 }
420                 memset(&action_info, 0, sizeof(action_info));
421                 action_type = 0; //ELM_ACCESS_ACTION_VALUE_CHANGE;
422                 action_info.x = event_info->info.access.x;
423                 action_info.y = event_info->info.access.y;
424                 action_info.mouse_type = event_info->info.access.mouse_type;
425                 ret = elm_access_action(parent_elm, action_type, &action_info);
426                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
427                 break;
428         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
429                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
430                 if (!parent_elm) {
431                         ret = WIDGET_ACCESS_STATUS_ERROR;
432                         break;
433                 }
434                 memset(&action_info, 0, sizeof(action_info));
435                 action_type = 0; //ELM_ACCESS_ACTION_MOUSE;
436                 action_info.x = event_info->info.access.x;
437                 action_info.y = event_info->info.access.y;
438                 action_info.mouse_type = event_info->info.access.mouse_type;
439                 ret = elm_access_action(parent_elm, action_type, &action_info);
440                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
441                 break;
442         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
443                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
444                 if (!parent_elm) {
445                         ret = WIDGET_ACCESS_STATUS_ERROR;
446                         break;
447                 }
448                 memset(&action_info, 0, sizeof(action_info));
449                 action_type = 0; //ELM_ACCESS_ACTION_BACK;
450                 action_info.x = event_info->info.access.x;
451                 action_info.y = event_info->info.access.y;
452                 action_info.mouse_type = event_info->info.access.mouse_type;
453                 ret = elm_access_action(parent_elm, action_type, &action_info);
454                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
455                 break;
456         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
457                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
458                 if (!parent_elm) {
459                         ret = WIDGET_ACCESS_STATUS_ERROR;
460                         break;
461                 }
462                 memset(&action_info, 0, sizeof(action_info));
463                 action_type = 0; //ELM_ACCESS_ACTION_OVER;
464                 action_info.x = event_info->info.access.x;
465                 action_info.y = event_info->info.access.y;
466                 action_info.mouse_type = event_info->info.access.mouse_type;
467                 ret = elm_access_action(parent_elm, action_type, &action_info);
468                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
469                 break;
470         case WIDGET_BUFFER_EVENT_ACCESS_READ:
471                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
472                 if (!parent_elm) {
473                         ret = WIDGET_ACCESS_STATUS_ERROR;
474                         break;
475                 }
476                 memset(&action_info, 0, sizeof(action_info));
477                 action_type = 0; //ELM_ACCESS_ACTION_READ;
478                 action_info.x = event_info->info.access.x;
479                 action_info.y = event_info->info.access.y;
480                 action_info.mouse_type = event_info->info.access.mouse_type;
481                 ret = elm_access_action(parent_elm, action_type, &action_info);
482                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
483                 break;
484         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
485                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
486                 if (!parent_elm) {
487                         ret = WIDGET_ACCESS_STATUS_ERROR;
488                         break;
489                 }
490                 memset(&action_info, 0, sizeof(action_info));
491                 action_type = 0; //ELM_ACCESS_ACTION_ENABLE;
492                 action_info.x = event_info->info.access.x;
493                 action_info.y = event_info->info.access.y;
494                 action_info.mouse_type = event_info->info.access.mouse_type;
495                 ret = elm_access_action(parent_elm, action_type, &action_info);
496                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
497                 break;
498         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
499                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
500                 if (!parent_elm) {
501                         ret = WIDGET_ACCESS_STATUS_ERROR;
502                         break;
503                 }
504                 memset(&action_info, 0, sizeof(action_info));
505                 action_type = 0; //ELM_ACCESS_ACTION_DISABLE;
506                 action_info.x = event_info->info.access.x;
507                 action_info.y = event_info->info.access.y;
508                 action_info.mouse_type = event_info->info.access.mouse_type;
509                 ret = elm_access_action(parent_elm, action_type, &action_info);
510                 ret = (ret == EINA_FALSE) ? WIDGET_ACCESS_STATUS_ERROR : WIDGET_ACCESS_STATUS_DONE;
511                 break;
512         case WIDGET_BUFFER_EVENT_KEY_DOWN:
513                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
514                 if (!parent_elm) {
515                         ret = WIDGET_ACCESS_STATUS_ERROR;
516                         break;
517                 }
518
519                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
520                 if (key_symbol) {
521                         char *key_name;
522                         char *key_string;
523
524                         key_string = XKeysymToString(*key_symbol);
525                         key_name = XKeysymToString(*key_symbol);
526                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
527                         XFree(key_symbol);
528                         XFree(key_name);
529                         XFree(key_string);
530                 }
531                 ret = WIDGET_KEY_STATUS_ERROR;
532                 break;
533         case WIDGET_BUFFER_EVENT_KEY_UP:
534                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
535                 if (!parent_elm) {
536                         ret = WIDGET_ACCESS_STATUS_ERROR;
537                         break;
538                 }
539
540                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
541                 if (key_symbol) {
542                         char *key_name;
543                         char *key_string;
544
545                         key_string = XKeysymToString(*key_symbol);
546                         key_name = XKeysymToString(*key_symbol);
547                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
548                         XFree(key_symbol);
549                         XFree(key_name);
550                         XFree(key_string);
551                 }
552                 ret = WIDGET_KEY_STATUS_ERROR;
553                 break;
554         case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN:
555                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
556                 if (!parent_elm) {
557                         ret = WIDGET_ACCESS_STATUS_ERROR;
558                         break;
559                 }
560
561                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
562                 if (key_symbol) {
563                         char *key_name;
564                         char *key_string;
565
566                         key_string = XKeysymToString(*key_symbol);
567                         key_name = XKeysymToString(*key_symbol);
568                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
569                         XFree(key_symbol);
570                         XFree(key_name);
571                         XFree(key_string);
572                 }
573                 ret = WIDGET_KEY_STATUS_ERROR;
574                 break;
575         case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT:
576                 parent_elm = ecore_evas_data_get(info->ee, WIDGET_WIN_TAG);
577                 if (!parent_elm) {
578                         ret = WIDGET_ACCESS_STATUS_ERROR;
579                         break;
580                 }
581
582                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
583                 if (key_symbol) {
584                         char *key_name;
585                         char *key_string;
586
587                         key_string = XKeysymToString(*key_symbol);
588                         key_name = XKeysymToString(*key_symbol);
589                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
590                         XFree(key_symbol);
591                         XFree(key_name);
592                         XFree(key_string);
593                 }
594                 ret = WIDGET_KEY_STATUS_ERROR;
595                 break;
596         default:
597                 DbgPrint("Unhandled buffer event (%d)\n", event_info->type);
598                 break;
599         }
600
601         return ret;
602 }
603
604 static Eina_Bool pended_event_consumer_cb(void *data)
605 {
606         vwin_info_t info = data;
607         widget_buffer_event_data_t event_info;
608
609         event_info = eina_list_nth(info->pended_events_list, 0);
610         if (!event_info) {
611                 info->pended_events_consumer = NULL;
612                 return ECORE_CALLBACK_CANCEL;
613         }
614
615         DbgPrint("Consuming delayed events\n");
616         (void)processing_events(info, event_info, event_info->timestamp);
617
618         info->pended_events_list = eina_list_remove(info->pended_events_list, event_info);
619         free(event_info);
620         return ECORE_CALLBACK_RENEW;
621 }
622
623 /**
624  * @note
625  * Every user event (mouse) on the buffer will be passed via this event callback
626  */
627 static int event_handler_cb(widget_buffer_h handler, widget_buffer_event_data_t event_info, void *data)
628 {
629         vwin_info_t info = data;
630         double timestamp;
631
632         /**
633          * @note
634          * If the feeds event is accessibility or key event,
635          * "return 0" will confusing the viewer,
636          * because it will waiting result of event processing to do handles state properly.
637          */
638
639         if (!info || info->state != VWIN_INFO_CREATED || !info->handle || info->flags.field.deleted) {
640                 /* Just ignore this event */
641                 return 0;
642         }
643
644         if (event_info->type == WIDGET_BUFFER_EVENT_FRAME_SKIP_CLEARED) {
645                 /**
646                  * Increase the count_of_rendering only if it meets conditions.
647                  * Or do not increase it to prevent from overflow problem.
648                  * If we trying to increase the count_of_rendering variable, it could be overflowed.
649                  * These conditions will prevents count_of_rendering from overflow issue.
650                  */
651                 if (info->pended_events_list && !info->pended_events_consumer) {
652                         info->pended_events_consumer = ecore_timer_add(0.0001f, pended_event_consumer_cb, info);
653                         if (info->pended_events_consumer) {
654                                 ErrPrint("Failed to create a pended event consumer\n");
655                         }
656                 }
657
658                 return 0;
659         }
660
661         if (WIDGET_CONF_USE_GETTIMEOFDAY) {
662                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
663                         struct timeval tv;
664
665                         if (gettimeofday(&tv, NULL) < 0) {
666                                 ErrPrint("gettimeofday: %d\n", errno);
667                         } else {
668                                 timestamp = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
669                                 timestamp -= event_info->timestamp;
670
671                                 if (timestamp > WIDGET_CONF_EVENT_FILTER) {
672                                         DbgPrint("Dropped %lf\n", timestamp);
673                                         return 0;
674                                 }
675                         }
676                 }
677
678                 /**
679                  * If the device doesn't use the clock monotic time, we have to emulate it for EVAS
680                  * Evas only use the monotic time for animating objects
681                  */
682                 timestamp = ecore_time_get() * 1000.0f;
683         } else {
684                 if (WIDGET_CONF_EVENT_FILTER > 0.0f && (info->pressed == 0 || event_info->type == WIDGET_BUFFER_EVENT_MOVE)) {
685                         timestamp = ecore_time_get();
686
687                         timestamp -= event_info->timestamp;
688                         if (timestamp > WIDGET_CONF_EVENT_FILTER) {
689                                 DbgPrint("Dropped %lf\n", timestamp);
690                                 return 0;
691                         }
692                 }
693
694                 timestamp = event_info->timestamp * 1000.0f;
695         }
696
697         if ((info->w <= 1 && info->h <= 1) || widget_provider_buffer_frame_skip(info->handle) > 0 || info->pended_events_list) {
698                 widget_buffer_event_data_t _ev_info;
699                 _ev_info = malloc(sizeof(*_ev_info));
700                 if (_ev_info) {
701                         memcpy(_ev_info, event_info, sizeof(*_ev_info));
702                         info->pended_events_list = eina_list_append(info->pended_events_list, _ev_info);
703                         _ev_info->timestamp = timestamp;
704                         /**
705                          * @note
706                          * Push events to pending list,.
707                          * Consuming it first.
708                          */
709                         DbgPrint("Canvas is not prepared. pending the events (%dx%d)\n", info->w, info->h);
710                         return 0;
711                 } else {
712                         ErrPrint("malloc: %d\n", errno);
713                 }
714         }
715
716         return processing_events(info, event_info, timestamp);
717 }
718
719 static void pre_render_cb(void *data, Evas *e, void *event_info)
720 {
721         vwin_info_t info = data;
722
723         if (!info || info->state != VWIN_INFO_CREATED || !info->handle) {
724                 return;
725         }
726
727         if (WIDGET_CONF_PREMULTIPLIED_COLOR) {
728                 Evas_Coord w;
729                 Evas_Coord h;
730
731                 ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
732                 evas_damage_rectangle_add(e, 0, 0, w, h);
733         }
734
735         if (info->type == VWIN_GEM) {
736                 widget_buffer_pre_render(info->handle);
737         } else if (info->type == VWIN_PIXMAP) {
738                 /**
739                  * Only the pixmap type Ecore_Evas uses this variable
740                  */
741         } else if (info->type == VWIN_SW_BUF) {
742                 /* Do nothing */
743         }
744 }
745
746 static inline void dump_to_file(void *buffer, int size, const char *fname)
747 {
748         int fd;
749
750         fd = open(fname, O_WRONLY | O_CREAT, 0644);
751         if (fd >= 0) {
752                 if (write(fd, buffer, size) != size) {
753                         ErrPrint("write: %d\n", errno);
754                 }
755
756                 if (close(fd) < 0) {
757                         ErrPrint("close: %d\n", errno);
758                 }
759         }
760 }
761
762 static void post_render_cb(void *data, Evas *e, void *event_info)
763 {
764         vwin_info_t info = data;
765         const char *ee_key;
766
767         if (!info || info->state != VWIN_INFO_CREATED || !info->handle) {
768                 return;
769         }
770
771         ee_key = WIDGET_CONF_EE_KEY_FOR_UPDATE;
772         if (ee_key) {
773                 const char *value;
774                 value = ecore_evas_data_get(info->ee, ee_key);
775                 if (value && strcmp(value, "true")) {
776                         DbgPrint("Frame skipped[%s]\n", value);
777                         return;
778                 }
779                 ecore_evas_data_set(info->ee, ee_key, "false");
780         }
781
782         if (info->type == VWIN_PIXMAP) {
783                 int idx;
784                 unsigned int front_resource_id;
785
786                 front_resource_id = ecore_evas_gl_x11_pixmap_get(info->ee);
787
788                 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
789                         if (front_resource_id == info->resource_array[idx]) {
790                                 break;
791                         }
792                 }
793
794                 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
795                         idx = WIDGET_PRIMARY_BUFFER;
796                 }
797
798                 /* Send updated event for PRIMARY BUFFER */
799                 if (front_resource_id == widget_viewer_get_resource_id(info->handle, idx)) {
800                         if (info->ctrl_mode.dump_to_file) {
801                                 char fname[512];
802                                 void *canvas;
803
804                                 snprintf(fname, sizeof(fname) - 1, "/tmp/%s.%u.%lf.raw", widget_util_basename(info->id), front_resource_id, ecore_time_get());
805                                 canvas = widget_provider_buffer_dump_frame(info->handle, idx);
806                                 if (canvas) {
807                                         int w, h;
808                                         int size;
809
810                                         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
811                                         size = w * h * sizeof(int);
812
813                                         dump_to_file(canvas, size, fname);
814                                         free(canvas);
815                                 }
816                         }
817                         widget_send_updated_by_idx(info->handle, idx);
818                 } else {
819                         DbgPrint("Unable to send updated: %u (%u)\n", front_resource_id, widget_viewer_get_resource_id(info->handle, idx));
820                 }
821         } else {
822                 if (WIDGET_CONF_PREMULTIPLIED_COLOR) {
823                         void *canvas;
824                         int w, h;
825
826                         // Get a pointer of a buffer of the virtual canvas
827                         canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
828                         if (!canvas) {
829                                 ErrPrint("Failed to get pixel canvas\n");
830                                 return;
831                         }
832
833                         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
834                         evas_data_argb_unpremul(canvas, w * h);
835                 }
836
837                 if (info->ctrl_mode.dump_to_file) {
838                         void *canvas;
839                         char fname[512];
840                         int size;
841                         int w, h;
842
843                         canvas = (void *)ecore_evas_buffer_pixels_get(info->ee);
844                         if (!canvas) {
845                                 ErrPrint("Failed to get pixel canvas\n");
846                                 return;
847                         }
848
849                         /**
850                          * TODO
851                          * Save to a file
852                          */
853                         ecore_evas_geometry_get(info->ee, NULL, NULL, &w, &h);
854                         size = w * h * sizeof(int);
855
856                         snprintf(fname, sizeof(fname) - 1, "/tmp/%s.%lf.raw", widget_util_basename(info->id), ecore_time_get());
857                         dump_to_file(canvas, size, fname);
858                 }
859
860                 if (info->type == VWIN_GEM) {
861                         widget_buffer_post_render(info->handle);
862                 } else if (info->type == VWIN_SW_BUF) {
863                         widget_viewer_sync_buffer(info->handle);
864                 }
865         }
866 }
867
868 static int pre_ctrl_mode_cb(const char *id, void *data)
869 {
870         vwin_info_t info = data;
871         const char *path;
872         int cmd;
873         int value;
874
875         /* Try provider_app first */
876         if (!info || info->state != VWIN_INFO_CREATED || !id || !info->id) {
877                 return WIDGET_ERROR_INVALID_PARAMETER;
878         }
879
880         path = widget_util_uri_to_path(id);
881         if (path && strcmp(info->id, path)) {
882                 /* Skip */
883                 DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id);
884                 return WIDGET_ERROR_INVALID_PARAMETER;
885         }
886
887         widget_get_last_ctrl_mode(path, &cmd, &value);
888
889         if (cmd == WIDGET_CTRL_MODE_DUMP_FRAME) {
890                 info->ctrl_mode.dump_to_file = !!value;
891                 DbgPrint("CtrlMode: DumpToFile: %d\n", info->ctrl_mode.dump_to_file);
892         }
893
894         return WIDGET_ERROR_NONE;
895 }
896
897 static int pre_orientation_cb(const char *id, void *data)
898 {
899         vwin_info_t info = data;
900         const char *path;
901         int orientation;
902
903         /* Try provider_app first */
904         if (!info || info->state != VWIN_INFO_CREATED || !id || !info->id) {
905                 return WIDGET_ERROR_INVALID_PARAMETER;
906         }
907
908         path = widget_util_uri_to_path(id);
909         if (path && strcmp(info->id, path)) {
910                 /* Skip */
911                 DbgPrint("SKIP: Pre orientation event callback is called [%s], %s\n", id, info->id);
912                 return WIDGET_ERROR_INVALID_PARAMETER;
913         }
914
915         DbgPrint("Pre orientation event callback is called [%s]\n", id);
916         orientation = widget_get_orientation(path);
917         if (orientation < 0) {
918                 ErrPrint("Failed to get orientation: %X\n", orientation);
919         } else {
920                 info->orientation = orientation;
921         }
922
923         return WIDGET_ERROR_NONE;
924 }
925
926 static int pre_destroy_cb(const char *id, void *data)
927 {
928         vwin_info_t info = data;
929         const char *path = NULL;
930
931         if (!info || info->state != VWIN_INFO_CREATED) {
932                 return WIDGET_ERROR_INVALID_PARAMETER;
933         }
934
935         if (id) {
936                 path = widget_util_uri_to_path(id);
937
938                 if (path && strcmp(info->id, path)) {
939                         /* Skip */
940                         DbgPrint("SKIP: Pre destroy event callback is called [%s], %s\n", id, info->id);
941                         return WIDGET_ERROR_INVALID_PARAMETER;
942                 }
943         }
944
945         DbgPrint("Pre destroy event callback is called [%s]\n", id);
946
947         if (info->ee) {
948                 DbgPrint("Toggle manual render mode to prevent from unwanted rendering");
949                 ecore_evas_manual_render_set(info->ee, EINA_TRUE);
950         }
951
952         return WIDGET_ERROR_NONE;
953 }
954
955 static void ecore_evas_free_cb(Ecore_Evas *ee)
956 {
957         vwin_info_t info;
958
959         info = ecore_evas_data_get(ee, WIN_INFO_TAG);
960         if (!info) {
961                 DbgPrint("Info is not valid\n");
962                 return;
963         }
964
965         if (info->pended_events_consumer) {
966                 widget_buffer_event_data_t event_info;
967
968                 DbgPrint("Clearing pended event consumer\n");
969                 ecore_timer_del(info->pended_events_consumer);
970                 info->pended_events_consumer = NULL;
971
972                 EINA_LIST_FREE(info->pended_events_list, event_info) {
973                         free(event_info);
974                 }
975         }
976
977         widget_del_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
978         widget_del_pre_callback(WIDGET_PRE_CTRL_MODE_CALLBACK, pre_ctrl_mode_cb, info);
979
980         if (info->e) {
981                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb);
982                 evas_event_callback_del(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb);
983         }
984
985         info->flags.field.deleted = 1;
986         info->ee = NULL;
987 }
988
989 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
990 PUBLIC Evas *widget_get_evas(const char *id, int is_gbar)
991 #else /* WIDGET_FEATURE_GBAR_SUPPORTED */
992 PUBLIC Evas *widget_get_evas(const char *id)
993 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
994 {
995         vwin_info_t info;
996         int orientation;
997
998         /**
999          * @TODO
1000          * If the evas object is already created,
1001          * this function should returns ERROR.
1002          */
1003
1004         if (!id) {
1005                 ErrPrint("Invalid parameter\n");
1006                 return NULL;
1007         }
1008
1009         info = calloc(1, sizeof(*info));
1010         if (!info) {
1011                 ErrPrint("Heap: %d\n", errno);
1012                 return NULL;
1013         }
1014
1015         info->state = VWIN_INFO_CREATED;
1016
1017         info->id = strdup(id);
1018         if (!info->id) {
1019                 ErrPrint("Heap: %d\n", errno);
1020                 info->state = VWIN_INFO_DESTROYED;
1021                 free(info);
1022                 return NULL;
1023         }
1024
1025 #ifdef WIDGET_FEATURE_GBAR_SUPPORTED
1026         info->flags.field.is_gbar = is_gbar;
1027 #else
1028         info->flags.field.is_gbar = 0;
1029 #endif /* WIDGET_FEATURE_GBAR_SUPPORTED */
1030
1031         /**
1032          * Acquire a buffer for canvas.
1033          */
1034         info->handle = widget_create_buffer(info->id, info->flags.field.is_gbar,
1035                         binder_widget_auto_align(),
1036                         event_handler_cb, info);
1037
1038         if (!info->handle) {
1039                 ErrPrint("Failed to create a widget buffer\n");
1040                 info->state = VWIN_INFO_DESTROYED;
1041                 free(info->id);
1042                 free(info);
1043                 return NULL;
1044         }
1045
1046         /**
1047          * Size information must be initialized before call the ecore_evas_buffer_new.
1048          */
1049         info->w = WIDGET_DEFAULT_WIDTH;
1050         info->h = WIDGET_DEFAULT_HEIGHT;
1051
1052         info->ee = binder_ecore_evas_new(info);
1053         if (!info->ee) {
1054                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", info->w, info->h);
1055                 widget_destroy_buffer(info->handle);
1056                 info->state = VWIN_INFO_DESTROYED;
1057                 free(info->id);
1058                 free(info);
1059                 return NULL;
1060         }
1061
1062         ecore_evas_data_set(info->ee, WIN_INFO_TAG, info);
1063
1064         /**
1065          * @note
1066          * Free callback must be prepared before use the ecore_evas_free()
1067          */
1068         ecore_evas_callback_pre_free_set(info->ee, ecore_evas_free_cb);
1069
1070         info->e = ecore_evas_get(info->ee);
1071         if (!info->e) {
1072                 ErrPrint("Failed to get evas\n");
1073                 ecore_evas_free(info->ee);
1074                 return NULL;
1075         }
1076
1077         pre_render_cb(info, NULL, NULL);
1078         ecore_evas_alpha_set(info->ee, EINA_TRUE);
1079         post_render_cb(info, NULL, NULL);
1080
1081         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
1082         ecore_evas_resize(info->ee, info->w, info->h);
1083
1084         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
1085         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
1086
1087         widget_add_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, pre_destroy_cb, info);
1088         widget_add_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, pre_orientation_cb, info);
1089         widget_add_pre_callback(WIDGET_PRE_CTRL_MODE_CALLBACK, pre_ctrl_mode_cb, info);
1090
1091         orientation = widget_get_orientation(info->id);
1092         if (orientation < 0) {
1093                 ErrPrint("Failed to get orientation[%s]: %X\n", info->id, orientation);
1094         } else {
1095                 info->orientation = orientation;
1096         }
1097
1098         return info->e;
1099 }
1100
1101 /* End of a file */