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