Enable Wayland build
[apps/native/widget/widget.git] / src / virtual_window.c
1 #include <Elementary.h>
2 #include <string.h>
3 #include <Ecore_Evas.h>
4 #include <Ecore_X.h>
5 #include <Evas.h>
6
7 #include <X11/Xlib.h>
8
9 #include <dlog.h>
10 #include <livebox-errno.h>
11 #include <livebox-service.h>
12
13 #include "livebox.h"
14 #include "debug.h"
15
16 #define IS_PD 1
17
18 #define PUBLIC __attribute__((visibility("default")))
19
20 /*!
21  * \brief
22  * Abstracted Data Type of Virtual Window
23  */
24 struct info {
25         char *id; /*!< Identification */
26         struct livebox_buffer *handle; /*!< Livebox buffer handle */
27         int is_hw; /*!< 1 if a buffer is created on the H/W accelerated place or 0 */
28         Ecore_Evas *ee;
29         Evas *e;
30         int is_pd;
31 };
32
33 static inline Evas_Object *get_highlighted_object(Evas_Object *obj)
34 {
35         Evas_Object *o, *ho;
36
37         o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
38         if (!o) return NULL;
39
40         ho = evas_object_data_get(o, "_elm_access_target");
41         return ho;
42 }
43
44 /*!
45  * \note
46  * Every user event (mouse) on the buffer will be passed via this event callback
47  */
48 static int event_handler_cb(struct livebox_buffer *handler, struct buffer_event_data *event_info, void *data)
49 {
50         struct info *info = data;
51         Elm_Access_Action_Info action_info;
52         Elm_Access_Action_Type action_type;
53         int ret = 0;
54         Evas_Object *parent_elm;
55         KeySym *key_symbol;
56
57
58         if (!info->handle) {
59                 /* Just ignore this event */
60                 return 0;
61         }
62
63         /*!
64          * \note
65          * Feed up events
66          */
67         switch (event_info->type) {
68         case BUFFER_EVENT_ENTER:
69                 evas_event_feed_mouse_in(info->e, event_info->timestamp * 1000, NULL);
70                 break;
71         case BUFFER_EVENT_LEAVE:
72                 evas_event_feed_mouse_out(info->e, event_info->timestamp * 1000, NULL);
73                 break;
74         case BUFFER_EVENT_DOWN:
75                 /*!
76                  * \note
77                  * Calculate the event occurred X & Y on the buffer
78                  */
79                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, (event_info->timestamp - 0.001f) * 1000, NULL); /* + 0.1f just for fake event */
80                 evas_event_feed_mouse_down(info->e, 1, EVAS_BUTTON_NONE, event_info->timestamp * 1000, NULL); /* + 0.2f just for fake event */
81                 break;
82         case BUFFER_EVENT_MOVE:
83                 /*!
84                  * \note
85                  * Calculate the event occurred X & Y on the buffer
86                  */
87                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
88                 break;
89         case BUFFER_EVENT_UP:
90                 evas_event_feed_mouse_move(info->e, event_info->info.pointer.x, event_info->info.pointer.y, event_info->timestamp * 1000, NULL);
91                 evas_event_feed_mouse_up(info->e, 1, EVAS_BUTTON_NONE, (event_info->timestamp + 0.001f) * 1000, NULL);
92                 break;
93         case BUFFER_EVENT_HIGHLIGHT:
94                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
95                 if (!parent_elm) {
96                         ret = LB_ACCESS_STATUS_ERROR;
97                         break;
98                 }
99                 memset(&action_info, 0, sizeof(action_info));
100                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT;
101                 /*!
102                  * \note
103                  * Calculate the event occurred X & Y on the buffer
104                  */
105                 action_info.x = event_info->info.pointer.x;
106                 action_info.y = event_info->info.pointer.y;
107                 ret = elm_access_action(parent_elm, action_type, &action_info);
108                 if (ret == EINA_TRUE) {
109                         if (!get_highlighted_object(parent_elm)) {
110                                 LOGE("Highlighted object is not found\n");
111                                 ret = LB_ACCESS_STATUS_ERROR;
112                         } else {
113                                 LOGD("Highlighted object is found\n");
114                                 ret = LB_ACCESS_STATUS_DONE;
115                         }
116                 } else {
117                         LOGE("Action error\n");
118                         ret = LB_ACCESS_STATUS_ERROR;
119                 }
120                 break;
121         case BUFFER_EVENT_HIGHLIGHT_NEXT:
122                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
123                 if (!parent_elm) {
124                         ret = LB_ACCESS_STATUS_ERROR;
125                         break;
126                 }
127                 memset(&action_info, 0, sizeof(action_info));
128                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
129                 action_info.highlight_cycle = EINA_FALSE;
130                 ret = elm_access_action(parent_elm, action_type, &action_info);
131                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_LAST : LB_ACCESS_STATUS_DONE;
132                 break;
133         case BUFFER_EVENT_HIGHLIGHT_PREV:
134                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
135                 if (!parent_elm) {
136                         ret = LB_ACCESS_STATUS_ERROR;
137                         break;
138                 }
139                 memset(&action_info, 0, sizeof(action_info));
140                 action_type = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
141                 action_info.highlight_cycle = EINA_FALSE;
142                 ret = elm_access_action(parent_elm, action_type, &action_info);
143                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_FIRST : LB_ACCESS_STATUS_DONE;
144                 break;
145         case BUFFER_EVENT_ACTIVATE:
146                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
147                 if (!parent_elm) {
148                         ret = LB_ACCESS_STATUS_ERROR;
149                         break;
150                 }
151                 memset(&action_info, 0, sizeof(action_info));
152                 action_type = ELM_ACCESS_ACTION_ACTIVATE;
153                 ret = elm_access_action(parent_elm, action_type, &action_info);
154                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
155                 break;
156         case BUFFER_EVENT_ACTION_UP:
157                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
158                 if (!parent_elm) {
159                         ret = LB_ACCESS_STATUS_ERROR;
160                         break;
161                 }
162                 memset(&action_info, 0, sizeof(action_info));
163                 action_type = ELM_ACCESS_ACTION_UP;
164                 ret = elm_access_action(parent_elm, action_type, &action_info);
165                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
166                 break;
167         case BUFFER_EVENT_ACTION_DOWN:
168                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
169                 if (!parent_elm) {
170                         ret = LB_ACCESS_STATUS_ERROR;
171                         break;
172                 }
173                 memset(&action_info, 0, sizeof(action_info));
174                 action_type = ELM_ACCESS_ACTION_DOWN;
175                 ret = elm_access_action(parent_elm, action_type, &action_info);
176                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
177                 break;
178         case BUFFER_EVENT_SCROLL_UP:
179                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
180                 if (!parent_elm) {
181                         ret = LB_ACCESS_STATUS_ERROR;
182                         break;
183                 }
184                 memset(&action_info, 0, sizeof(action_info));
185                 action_type = ELM_ACCESS_ACTION_SCROLL;
186                 action_info.x = event_info->info.pointer.x;
187                 action_info.y = event_info->info.pointer.y;
188                 action_info.mouse_type = 2;
189                 ret = elm_access_action(parent_elm, action_type, &action_info);
190                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
191                 break;
192         case BUFFER_EVENT_SCROLL_MOVE:
193                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
194                 if (!parent_elm) {
195                         ret = LB_ACCESS_STATUS_ERROR;
196                         break;
197                 }
198                 memset(&action_info, 0, sizeof(action_info));
199                 action_type = ELM_ACCESS_ACTION_SCROLL;
200                 action_info.x = event_info->info.pointer.x;
201                 action_info.y = event_info->info.pointer.y;
202                 action_info.mouse_type = 1;
203                 ret = elm_access_action(parent_elm, action_type, &action_info);
204                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
205                 break;
206         case BUFFER_EVENT_SCROLL_DOWN:
207                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
208                 if (!parent_elm) {
209                         ret = LB_ACCESS_STATUS_ERROR;
210                         break;
211                 }
212                 memset(&action_info, 0, sizeof(action_info));
213                 action_type = ELM_ACCESS_ACTION_SCROLL;
214                 action_info.x = event_info->info.pointer.x;
215                 action_info.y = event_info->info.pointer.y;
216                 action_info.mouse_type = 0;
217                 ret = elm_access_action(parent_elm, action_type, &action_info);
218                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
219                 break;
220         case BUFFER_EVENT_UNHIGHLIGHT:
221                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
222                 if (!parent_elm) {
223                         ret = LB_ACCESS_STATUS_ERROR;
224                         break;
225                 }
226                 memset(&action_info, 0, sizeof(action_info));
227                 action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT;
228                 ret = elm_access_action(parent_elm, action_type, &action_info);
229                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
230                 break;
231         case BUFFER_EVENT_KEY_DOWN:
232                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
233                 if (!parent_elm) {
234                         ret = LB_ACCESS_STATUS_ERROR;
235                         break;
236                 }
237
238                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
239                 if (key_symbol) {
240                         char *key_name;
241                         char *key_string;
242
243                         key_string = XKeysymToString(*key_symbol);
244                         key_name = XKeysymToString(*key_symbol);
245                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
246                         XFree(key_symbol);
247                         XFree(key_name);
248                 }
249                 ret = LB_KEY_STATUS_ERROR;
250                 break;
251         case BUFFER_EVENT_KEY_UP:
252                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
253                 if (!parent_elm) {
254                         ret = LB_ACCESS_STATUS_ERROR;
255                         break;
256                 }
257
258                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
259                 if (key_symbol) {
260                         char *key_name;
261                         char *key_string;
262
263                         key_string = XKeysymToString(*key_symbol);
264                         key_name = XKeysymToString(*key_symbol);
265                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
266                         XFree(key_symbol);
267                         XFree(key_name);
268                 }
269                 ret = LB_KEY_STATUS_ERROR;
270                 break;
271         case BUFFER_EVENT_KEY_FOCUS_IN:
272                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
273                 if (!parent_elm) {
274                         ret = LB_ACCESS_STATUS_ERROR;
275                         break;
276                 }
277
278                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
279                 if (key_symbol) {
280                         char *key_name;
281                         char *key_string;
282
283                         key_string = XKeysymToString(*key_symbol);
284                         key_name = XKeysymToString(*key_symbol);
285                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
286                         XFree(key_symbol);
287                         XFree(key_name);
288                 }
289                 ret = LB_KEY_STATUS_ERROR;
290                 break;
291         case BUFFER_EVENT_KEY_FOCUS_OUT:
292                 parent_elm = ecore_evas_data_get(info->ee, "dynamic,box,win");
293                 if (!parent_elm) {
294                         ret = LB_ACCESS_STATUS_ERROR;
295                         break;
296                 }
297
298                 key_symbol = XGetKeyboardMapping(ecore_x_display_get(), event_info->info.keycode, 1, &ret);
299                 if (key_symbol) {
300                         char *key_name;
301                         char *key_string;
302
303                         key_string = XKeysymToString(*key_symbol);
304                         key_name = XKeysymToString(*key_symbol);
305                         DbgPrint("Key symbol: %s, name: %s\n", key_string, key_name);
306                         XFree(key_symbol);
307                         XFree(key_name);
308                 }
309                 ret = LB_KEY_STATUS_ERROR;
310                 break;
311         default:
312                 LOGD("Unhandled buffer event (%d)\n", event_info->type);
313                 break;
314         }
315
316         return ret;
317 }
318
319 static void *alloc_fb(void *data, int size)
320 {
321         struct info *info = data;
322         void *buffer;
323         int width = 0;
324         int height = 0;
325
326         if (info->ee == NULL) {
327                 width = 1;
328                 height = 1;
329         } else {
330                 ecore_evas_geometry_get(info->ee, NULL, NULL, &width, &height);
331         }
332
333         /*!
334          * Acquire a buffer for canvas.
335          */
336         info->handle = livebox_acquire_buffer_NEW(info->id, info->is_pd,
337                                         width, height,
338                                         event_handler_cb, info);
339
340         /*!
341          * If it supports the H/W accelerated buffer,
342          * Use it.
343          */
344         if (livebox_support_hw_buffer(info->handle)) {
345                 if (livebox_create_hw_buffer(info->handle) == 0) {
346                         buffer = livebox_buffer_hw_buffer(info->handle);
347                         if (buffer) {
348                                 LOGD("HW Accelerated buffer is created\n");
349                                 info->is_hw = 1;
350                                 return buffer;
351                         }
352                 }
353
354                 LOGE("Failed to allocate HW Accelerated buffer\n");
355         }
356
357         /*!
358          * Or use the buffer of a S/W backend.
359          */
360         buffer = livebox_ref_buffer(info->handle);
361         LOGD("SW buffer is created\n");
362         info->is_hw = 0;
363         return buffer;
364 }
365
366 static void free_fb(void *data, void *ptr)
367 {
368         struct info *info = data;
369
370         if (!info->handle) {
371                 return;
372         }
373
374         if (info->is_hw) {
375                 if (livebox_destroy_hw_buffer(info->handle) == 0) {
376                         LOGD("HW Accelerated buffer is destroyed\n");
377                         goto out;
378                 }
379         }
380
381         livebox_unref_buffer(ptr);
382         LOGD("SW buffer is destroyed\n");
383 out:
384         livebox_release_buffer(info->handle);
385         info->handle = NULL;
386 }
387
388 static void pre_render_cb(void *data, Evas *e, void *event_info)
389 {
390         struct info *info = data;
391
392         if (!info->handle) {
393                 return;
394         }
395
396         if (info->is_hw) {
397                 livebox_buffer_pre_render(info->handle);
398         }
399 }
400
401 static void post_render_cb(void *data, Evas *e, void *event_info)
402 {
403         struct info *info = data;
404
405         if (!info->handle) {
406                 return;
407         }
408
409         if (info->is_hw) {
410                 livebox_buffer_post_render(info->handle);
411         } else {
412                 livebox_sync_buffer(info->handle);
413         }
414 }
415
416 PUBLIC Evas_Object *livebox_get_evas_object(const char *id, int is_pd)
417 {
418         struct info *info;
419         Evas_Object *rect;
420
421         if (!id) {
422                 ErrPrint("Invalid parameter\n");
423                 return NULL;
424         }
425
426         info = calloc(1, sizeof(*info));
427         if (!info) {
428                 ErrPrint("Heap: %s\n", strerror(errno));
429                 return NULL;
430         }
431
432         info->id = strdup(id);
433         if (!info->id) {
434                 ErrPrint("Heap: %s\n", strerror(errno));
435                 free(info);
436                 return NULL;
437         }
438
439         info->is_pd = is_pd;
440
441         info->ee = ecore_evas_buffer_allocfunc_new(1, 1, alloc_fb, free_fb, info);
442         if (!info->ee) {
443                 ErrPrint("Failed to create ecore_evas (%dx%d)\n", 1, 1);
444                 free(info->id);
445                 free(info);
446                 return NULL;
447         }
448
449         pre_render_cb(info, NULL, NULL);
450         ecore_evas_alpha_set(info->ee, EINA_TRUE);
451         post_render_cb(info, NULL, NULL);
452
453         ecore_evas_data_set(info->ee, "dynamic,box,info", info);
454         
455         ecore_evas_manual_render_set(info->ee, EINA_FALSE);
456         ecore_evas_resize(info->ee, 1, 1);
457
458         info->e = ecore_evas_get(info->ee);
459         if (!info->e) {
460                 ErrPrint("Failed to get evas\n");
461                 ecore_evas_free(info->ee);
462                 return NULL;
463         }
464
465         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_POST, post_render_cb, info);
466         evas_event_callback_add(info->e, EVAS_CALLBACK_RENDER_PRE, pre_render_cb, info);
467
468         rect = evas_object_rectangle_add(info->e);
469         if (!rect) {
470                 ErrPrint("Failed to create evas_object\n");
471                 ecore_evas_free(info->ee);
472                 return NULL;
473         }
474
475         evas_object_resize(rect, 1, 1);
476         evas_object_color_set(rect, 0, 0, 0, 0);
477         return rect;
478 }
479
480 /* End of a file */