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