Merge from tizen 2.3.1
[apps/native/widget/widget.git] / src / widget.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 <stdio.h>
18 #include <errno.h>
19 #include <stdlib.h> /* malloc */
20 #include <string.h> /* strdup */
21 #include <libgen.h>
22 #include <unistd.h> /* access */
23
24 #include <Ecore_Evas.h> /* binder.h */
25
26 #include <dlog.h>
27 #include <widget_errno.h>
28 #include <widget_service.h>
29 #include <widget_service_internal.h>
30 #include <widget_provider.h>
31 #include <widget_provider_buffer.h>
32 #include <widget_buffer.h>
33 #include <widget_util.h>
34 #include <widget_conf.h>
35
36 #include "debug.h"
37 #include "dlist.h"
38 #include "util.h"
39 #include "widget.h"
40 #include "widget_internal.h"
41 #include "binder.h"
42
43 #define PUBLIC __attribute__((visibility("default")))
44
45 /**
46  * @note
47  * This value is configurable value.
48  */
49 #define FRAME_WAIT_INTERVAL (1.0f/6.0f)
50
51 struct block {
52         unsigned int idx;
53
54         char *type;
55         char *part;
56         char *data;
57         char *option;
58         char *id;
59         char *file;
60         char *target_id;
61 };
62
63 struct widget_desc {
64         FILE *fp;
65         int for_pd;
66
67         unsigned int last_idx;
68
69         struct dlist *block_list;
70 };
71
72 struct widget_buffer_data {
73         int is_gbar;
74         int accelerated;
75
76         /* for Buffer event wrapper */
77         int (*handler)(widget_buffer_h , widget_buffer_event_data_t, void *);
78         void *cbdata;
79
80         char *content;
81         char *title;
82         char *icon;
83         char *name;
84
85         Ecore_Timer *frame_wait_timer;
86 };
87
88 static inline int event_handler_wrapper(widget_buffer_h buffer, widget_buffer_event_data_t event_info, void *data)
89 {
90         const char *pkgname;
91         const char *id;
92         struct widget_buffer_data *cbdata = data;
93         int ret;
94
95         pkgname = widget_provider_buffer_pkgname(buffer);
96         if (!pkgname) {
97                 ErrPrint("pkgname is not valid\n");
98                 return WIDGET_ERROR_INVALID_PARAMETER;
99         }
100
101         id = widget_provider_buffer_id(buffer);
102         if (!id) {
103                 ErrPrint("id is not valid[%s]\n", pkgname);
104                 return WIDGET_ERROR_INVALID_PARAMETER;
105         }
106
107         if (cbdata->handler) {
108                 ret = cbdata->handler(buffer, event_info, cbdata->cbdata);
109         } else {
110                 ret = WIDGET_ERROR_FAULT;
111         }
112
113         switch (event_info->type) {
114         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT:
115         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_NEXT:
116         case WIDGET_BUFFER_EVENT_ACCESS_HIGHLIGHT_PREV:
117         case WIDGET_BUFFER_EVENT_ACCESS_ACTIVATE:
118         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_UP:
119         case WIDGET_BUFFER_EVENT_ACCESS_ACTION_DOWN:
120         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_UP:
121         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_MOVE:
122         case WIDGET_BUFFER_EVENT_ACCESS_SCROLL_DOWN:
123         case WIDGET_BUFFER_EVENT_ACCESS_UNHIGHLIGHT:
124         case WIDGET_BUFFER_EVENT_ACCESS_VALUE_CHANGE:
125         case WIDGET_BUFFER_EVENT_ACCESS_MOUSE:
126         case WIDGET_BUFFER_EVENT_ACCESS_BACK:
127         case WIDGET_BUFFER_EVENT_ACCESS_OVER:
128         case WIDGET_BUFFER_EVENT_ACCESS_READ:
129         case WIDGET_BUFFER_EVENT_ACCESS_ENABLE:
130         case WIDGET_BUFFER_EVENT_ACCESS_DISABLE:
131                 DbgPrint("Accessibility event: %d\n", event_info->type);
132                 if (ret < 0) {
133                         (void)widget_provider_send_access_status(pkgname, id, WIDGET_ACCESS_STATUS_ERROR);
134                 } else {
135                         (void)widget_provider_send_access_status(pkgname, id, ret);
136                 }
137                 break;
138         case WIDGET_BUFFER_EVENT_KEY_UP:
139         case WIDGET_BUFFER_EVENT_KEY_DOWN:
140         case WIDGET_BUFFER_EVENT_KEY_FOCUS_IN:
141         case WIDGET_BUFFER_EVENT_KEY_FOCUS_OUT:
142                 DbgPrint("Key event: %d\n", event_info->type);
143                 if (ret < 0) {
144                         (void)widget_provider_send_key_status(pkgname, id, WIDGET_KEY_STATUS_ERROR);
145                 } else {
146                         (void)widget_provider_send_key_status(pkgname, id, ret);
147                 }
148                 break;
149         default:
150                 break;
151         }
152
153         return ret;
154 }
155
156 static inline int default_event_handler(widget_buffer_h buffer, widget_buffer_event_data_t event_info, void *data)
157 {
158         /* NOP */
159         return 0;
160 }
161
162 PUBLIC struct widget_desc *widget_desc_open(const char *filename, int for_pd)
163 {
164         struct widget_desc *handle;
165         char *new_fname;
166
167         handle = calloc(1, sizeof(*handle));
168         if (!handle) {
169                 ErrPrint("Error: %d\n", errno);
170                 return NULL;
171         }
172
173         if (for_pd) {
174                 int len;
175                 len = strlen(filename) + strlen(".desc") + 1;
176                 new_fname = malloc(len);
177                 if (!new_fname) {
178                         ErrPrint("Error: %d\n", errno);
179                         free(handle);
180                         return NULL;
181                 }
182                 snprintf(new_fname, len, "%s.desc", filename);
183         } else {
184                 new_fname = strdup(filename);
185                 if (!new_fname) {
186                         ErrPrint("Error: %d\n", errno);
187                         free(handle);
188                         return NULL;
189                 }
190         }
191
192         DbgPrint("Open a file %s with merge mode %s\n",
193                         new_fname,
194                         access(new_fname, F_OK) == 0 ? "enabled" : "disabled");
195
196         handle->fp = fopen(new_fname, "at");
197         free(new_fname);
198         if (!handle->fp) {
199                 ErrPrint("Failed to open a file: %d\n", errno);
200                 free(handle);
201                 return NULL;
202         }
203
204         return handle;
205 }
206
207 PUBLIC int widget_desc_close(struct widget_desc *handle)
208 {
209         struct dlist *l;
210         struct dlist *n;
211         struct block *block;
212
213         if (!handle) {
214                 return WIDGET_ERROR_INVALID_PARAMETER;
215         }
216
217         dlist_foreach_safe(handle->block_list, l, n, block) {
218                 handle->block_list = dlist_remove(handle->block_list, l);
219
220                 fprintf(handle->fp, "{\n");
221                 if (block->type) {
222                         fprintf(handle->fp, "type=%s\n", block->type);
223                 }
224
225                 if (block->part) {
226                         fprintf(handle->fp, "part=%s\n", block->part);
227                 }
228
229                 if (block->data) {
230                         fprintf(handle->fp, "data=%s\n", block->data);
231                 }
232
233                 if (block->option) {
234                         fprintf(handle->fp, "option=%s\n", block->option);
235                 }
236
237                 if (block->id) {
238                         fprintf(handle->fp, "id=%s\n", block->id);
239                 }
240
241                 if (block->target_id) {
242                         fprintf(handle->fp, "target=%s\n", block->target_id);
243                 }
244                 fprintf(handle->fp, "}\n");
245
246                 free(block->type);
247                 free(block->part);
248                 free(block->data);
249                 free(block->option);
250                 free(block->id);
251                 free(block->target_id);
252                 free(block);
253         }
254
255         if (fclose(handle->fp) != 0) {
256                 ErrPrint("fclose: %d\n", errno);
257         }
258         free(handle);
259         return WIDGET_ERROR_NONE;
260 }
261
262 PUBLIC int widget_desc_set_category(struct widget_desc *handle, const char *id, const char *category)
263 {
264         struct block *block;
265
266         if (!handle || !category) {
267                 return WIDGET_ERROR_INVALID_PARAMETER;
268         }
269
270         block = calloc(1, sizeof(*block));
271         if (!block) {
272                 return WIDGET_ERROR_OUT_OF_MEMORY;
273         }
274
275         block->type = strdup(WIDGET_DESC_TYPE_INFO);
276         if (!block->type) {
277                 free(block);
278                 return WIDGET_ERROR_OUT_OF_MEMORY;
279         }
280
281         block->part = strdup("category");
282         if (!block->part) {
283                 free(block->type);
284                 free(block);
285                 return WIDGET_ERROR_OUT_OF_MEMORY;
286         }
287
288         block->data = strdup(category);
289         if (!block->data) {
290                 free(block->type);
291                 free(block->part);
292                 free(block);
293                 return WIDGET_ERROR_OUT_OF_MEMORY;
294         }
295
296         if (id) {
297                 block->id = strdup(id);
298                 if (!block->id) {
299                         free(block->data);
300                         free(block->type);
301                         free(block->part);
302                         free(block);
303                         return WIDGET_ERROR_OUT_OF_MEMORY;
304                 }
305         }
306
307         block->idx = handle->last_idx++;
308         handle->block_list = dlist_append(handle->block_list, block);
309         return block->idx;
310 }
311
312 PUBLIC int widget_desc_set_size(struct widget_desc *handle, const char *id, int w, int h)
313 {
314         struct block *block;
315         char buffer[BUFSIZ];
316
317         if (!handle) {
318                 return WIDGET_ERROR_INVALID_PARAMETER;
319         }
320
321         block = calloc(1, sizeof(*block));
322         if (!block) {
323                 return WIDGET_ERROR_OUT_OF_MEMORY;
324         }
325
326         block->type = strdup(WIDGET_DESC_TYPE_INFO);
327         if (!block->type) {
328                 free(block);
329                 return WIDGET_ERROR_OUT_OF_MEMORY;
330         }
331
332         block->part = strdup("size");
333         if (!block->part) {
334                 free(block->type);
335                 free(block);
336                 return WIDGET_ERROR_OUT_OF_MEMORY;
337         }
338
339         if (id) {
340                 block->id = strdup(id);
341                 if (!block->id) {
342                         free(block->part);
343                         free(block->type);
344                         free(block);
345                         return WIDGET_ERROR_OUT_OF_MEMORY;
346                 }
347         }
348
349         snprintf(buffer, sizeof(buffer), "%dx%d", w, h);
350         block->data = strdup(buffer);
351         if (!block->data) {
352                 free(block->id);
353                 free(block->part);
354                 free(block->type);
355                 free(block);
356                 return WIDGET_ERROR_OUT_OF_MEMORY;
357         }
358
359         block->idx = handle->last_idx++;
360         handle->block_list = dlist_append(handle->block_list, block);
361         return block->idx;
362 }
363
364 PUBLIC int widget_desc_set_id(struct widget_desc *handle, int idx, const char *id)
365 {
366         struct dlist *l;
367         struct block *block;
368
369         dlist_foreach(handle->block_list, l, block) {
370                 if (block->idx == idx) {
371                         if (strcasecmp(block->type, WIDGET_DESC_TYPE_SCRIPT)) {
372                                 ErrPrint("Invalid block is used\n");
373                                 return WIDGET_ERROR_INVALID_PARAMETER;
374                         }
375
376                         free(block->target_id);
377                         block->target_id = NULL;
378
379                         if (!id || !strlen(id)) {
380                                 return WIDGET_ERROR_NONE;
381                         }
382
383                         block->target_id = strdup(id);
384                         if (!block->target_id) {
385                                 ErrPrint("Heap: %d\n", errno);
386                                 return WIDGET_ERROR_OUT_OF_MEMORY;
387                         }
388
389                         return WIDGET_ERROR_NONE;
390                 }
391         }
392
393         return WIDGET_ERROR_NOT_EXIST;
394 }
395
396 /*!
397  * \return idx
398  */
399 PUBLIC int widget_desc_add_block(struct widget_desc *handle, const char *id, const char *type, const char *part, const char *data, const char *option)
400 {
401         struct block *block;
402
403         if (!handle || !type) {
404                 return WIDGET_ERROR_INVALID_PARAMETER;
405         }
406
407         if (!part) {
408                 part = "";
409         }
410
411         if (!data) {
412                 data = "";
413         }
414
415         block = calloc(1, sizeof(*block));
416         if (!block) {
417                 ErrPrint("Heap: %d\n", errno);
418                 return WIDGET_ERROR_OUT_OF_MEMORY;
419         }
420
421         block->type = strdup(type);
422         if (!block->type) {
423                 ErrPrint("Heap: %d\n", errno);
424                 free(block);
425                 return WIDGET_ERROR_OUT_OF_MEMORY;
426         }
427
428         block->part = strdup(part);
429         if (!block->part) {
430                 ErrPrint("Heap: %d\n", errno);
431                 free(block->type);
432                 free(block);
433                 return WIDGET_ERROR_OUT_OF_MEMORY;
434         }
435
436         block->data = strdup(data);
437         if (!block->data) {
438                 ErrPrint("Heap: %d\n", errno);
439                 free(block->type);
440                 free(block->part);
441                 free(block);
442                 return WIDGET_ERROR_OUT_OF_MEMORY;
443         }
444
445         if (option) {
446                 block->option = strdup(option);
447                 if (!block->option) {
448                         ErrPrint("Heap: %d\n", errno);
449                         free(block->data);
450                         free(block->type);
451                         free(block->part);
452                         free(block);
453                         return WIDGET_ERROR_OUT_OF_MEMORY;
454                 }
455         }
456
457         if (id) {
458                 block->id = strdup(id);
459                 if (!block->id) {
460                         ErrPrint("Heap: %d\n", errno);
461                         free(block->option);
462                         free(block->data);
463                         free(block->type);
464                         free(block->part);
465                         free(block);
466                         return WIDGET_ERROR_OUT_OF_MEMORY;
467                 }
468         }
469
470         block->idx = handle->last_idx++;
471         handle->block_list = dlist_append(handle->block_list, block);
472         return block->idx;
473 }
474
475 PUBLIC int widget_desc_del_block(struct widget_desc *handle, int idx)
476 {
477         struct dlist *l;
478         struct block *block;
479
480         if (!handle || idx < 0) {
481                 return WIDGET_ERROR_INVALID_PARAMETER;
482         }
483
484         dlist_foreach(handle->block_list, l, block) {
485                 if (block->idx == idx) {
486                         handle->block_list = dlist_remove(handle->block_list, l);
487                         free(block->type);
488                         free(block->part);
489                         free(block->data);
490                         free(block->option);
491                         free(block->id);
492                         free(block->target_id);
493                         free(block);
494                         return WIDGET_ERROR_NONE;
495                 }
496         }
497
498         return WIDGET_ERROR_NOT_EXIST;
499 }
500
501 PUBLIC int widget_viewer_acquire_buffer(widget_buffer_h handle, int idx, int width, int height, int pixel_size)
502 {
503         int ret;
504
505         if (!handle || width <= 0 || height <= 0 || pixel_size <= 0 || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
506                 return WIDGET_ERROR_INVALID_PARAMETER;
507         }
508
509         if (idx >= 0) {
510                 int _width = 0;
511                 int _height = 0;
512                 int _pixel_size = 0;
513                 /* To validate the buffer */
514                 if (widget_provider_buffer_get_size(handle, &_width, &_height, &_pixel_size) < 0) {
515                         ErrPrint("Failed to get buffer size\n");
516                 }
517
518                 if (_width != width || _height != height || pixel_size != _pixel_size) {
519                         DbgPrint("Extra buffer's geometry is not matched with primary one\n");
520                 }
521
522                 ret = widget_provider_buffer_extra_acquire(handle, idx, width, height, pixel_size);
523         } else {
524                 ret = widget_provider_buffer_acquire(handle, width, height, pixel_size);
525         }
526
527         return ret;
528 }
529
530 PUBLIC widget_buffer_h widget_create_buffer(const char *filename, int is_gbar, int auto_align, int (*handler)(widget_buffer_h , widget_buffer_event_data_t, void *), void *data)
531 {
532         struct widget_buffer_data *user_data;
533         const char *pkgname;
534         widget_buffer_h handle;
535         char *uri;
536
537         if (!filename) {
538                 ErrPrint("Invalid argument: %p(%dx%d)\n", filename);
539                 return NULL;
540         }
541
542         user_data = calloc(1, sizeof(*user_data));
543         if (!user_data) {
544                 ErrPrint("Heap: %d\n", errno);
545                 return NULL;
546         }
547
548         user_data->is_gbar = is_gbar;
549         user_data->handler = handler ? handler : default_event_handler;
550         user_data->cbdata = data;
551
552         uri = util_id_to_uri(filename);
553         if (!uri) {
554                 ErrPrint("Heap: %d\n", errno);
555                 free(user_data);
556                 return NULL;
557         }
558
559         pkgname = binder_widget_find_pkgname(uri);
560         if (!pkgname) {
561                 ErrPrint("Invalid Request\n");
562                 free(user_data);
563                 free(uri);
564                 return NULL;
565         }
566
567         handle = widget_provider_buffer_create((!!is_gbar) ? WIDGET_TYPE_GBAR : WIDGET_TYPE_WIDGET, pkgname, uri, auto_align, event_handler_wrapper, user_data);
568         free(uri);
569         if (!handle) {
570                 free(user_data);
571                 return NULL;
572         }
573
574         (void)widget_provider_buffer_set_user_data(handle, user_data);
575         return handle;
576 }
577
578 PUBLIC unsigned int widget_viewer_get_resource_id(widget_buffer_h handle, int idx)
579 {
580         int ret;
581
582         if (!handle || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
583                 return WIDGET_ERROR_INVALID_PARAMETER;
584         }
585
586         if (idx >= 0) {
587                 ret = widget_provider_buffer_extra_resource_id(handle, idx);
588         } else {
589                 ret = widget_provider_buffer_resource_id(handle);
590         }
591
592         return ret;
593 }
594
595 PUBLIC int widget_viewer_release_buffer(widget_buffer_h handle, int idx)
596 {
597         int ret;
598
599         if (!handle || idx > WIDGET_CONF_EXTRA_BUFFER_COUNT) {
600                 return WIDGET_ERROR_INVALID_PARAMETER;
601         }
602
603         if (idx >= 0) {
604                 ret = widget_provider_buffer_extra_release(handle, idx);
605         } else {
606                 ret = widget_provider_buffer_release(handle);
607         }
608
609         DbgPrint("Release buffer: %d (%d)\n", idx, ret);
610         return ret;
611 }
612
613 PUBLIC int widget_destroy_buffer(widget_buffer_h handle)
614 {
615         struct widget_buffer_data *user_data;
616
617         if (!handle) {
618                 return WIDGET_ERROR_INVALID_PARAMETER;
619         }
620
621         user_data = widget_provider_buffer_user_data(handle);
622         if (user_data) {
623                 if (user_data->frame_wait_timer) {
624                         ecore_timer_del(user_data->frame_wait_timer);
625                         user_data->frame_wait_timer = NULL;
626                 }
627                 free(user_data->content);
628                 free(user_data->title);
629                 free(user_data->icon);
630                 free(user_data->name);
631                 free(user_data);
632                 widget_provider_buffer_set_user_data(handle, NULL);
633         }
634
635         DbgPrint("Destroy buffer\n");
636         return widget_provider_buffer_destroy(handle);
637 }
638
639 PUBLIC void *widget_ref_buffer(widget_buffer_h handle)
640 {
641         struct widget_buffer_data *user_data;
642         void *data;
643         int w, h, size;
644         int ret;
645
646         if (!handle) {
647                 return NULL;
648         }
649
650         user_data = widget_provider_buffer_user_data(handle);
651         if (!user_data) {
652                 return NULL;
653         }
654
655         if (user_data->accelerated) {
656                 DbgPrint("H/W accelerated buffer is allocated\n");
657                 return NULL;
658         }
659
660         ret = widget_provider_buffer_get_size(handle, &w, &h, &size);
661
662         data = widget_provider_buffer_ref(handle);
663         if (data && !ret && w > 0 && h > 0 && size > 0) {
664                 memset(data, 0, w * h * size);
665                 (void)widget_provider_buffer_sync(handle);
666         }
667
668         DbgPrint("Ref buffer %ds%d(%d)\n", w, h, size);
669         return data;
670 }
671
672 PUBLIC int widget_unref_buffer(void *buffer)
673 {
674         if (!buffer) {
675                 return WIDGET_ERROR_INVALID_PARAMETER;
676         }
677
678         DbgPrint("Unref buffer\n");
679         return widget_provider_buffer_unref(buffer);
680 }
681
682 PUBLIC int widget_viewer_sync_buffer(widget_buffer_h handle)
683 {
684         struct widget_buffer_data *user_data;
685         const char *pkgname;
686         const char *id;
687         int w;
688         int h;
689         int pixel_size;
690         int ret;
691
692         if (!handle) {
693                 return WIDGET_ERROR_INVALID_PARAMETER;
694         }
695
696         user_data = widget_provider_buffer_user_data(handle);
697         if (!user_data) {
698                 ErrPrint("Invalid buffer\n");
699                 return WIDGET_ERROR_INVALID_PARAMETER;
700         }
701
702         if (user_data->accelerated) {
703                 DbgPrint("H/W Buffer allocated. skip the sync buffer\n");
704                 return WIDGET_ERROR_NONE;
705         }
706
707         pkgname = widget_provider_buffer_pkgname(handle);
708         if (!pkgname) {
709                 ErrPrint("Invalid buffer handler\n");
710                 return WIDGET_ERROR_INVALID_PARAMETER;
711         }
712
713         id = widget_provider_buffer_id(handle);
714         if (!id) {
715                 ErrPrint("Invalid buffer handler\n");
716                 return WIDGET_ERROR_INVALID_PARAMETER;
717         }
718
719         (void)widget_provider_buffer_sync(handle);
720
721         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
722                 ErrPrint("Failed to get size (%s)\n", id);
723         }
724
725         /**
726          * @todo
727          * manipulate the damaged region, so send update event only for the damaged region.
728          * to make more efficient updates
729          */
730         ret = binder_widget_send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
731         if (ret < 0) {
732                 ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
733         }
734
735         return ret;
736 }
737
738 PUBLIC int widget_send_updated_by_idx(widget_buffer_h handle, int idx)
739 {
740         struct widget_buffer_data *user_data;
741         const char *pkgname;
742         const char *id;
743         int w;
744         int h;
745         int pixel_size;
746         int ret;
747
748         user_data = widget_provider_buffer_user_data(handle);
749         if (!user_data) {
750                 ErrPrint("Invalid buffer\n");
751                 return WIDGET_ERROR_INVALID_PARAMETER;
752         }
753
754         pkgname = widget_provider_buffer_pkgname(handle);
755         if (!pkgname) {
756                 ErrPrint("Invalid buffer handler\n");
757                 return WIDGET_ERROR_INVALID_PARAMETER;
758         }
759
760         id = widget_provider_buffer_id(handle);
761         if (!id) {
762                 ErrPrint("Invalid buffer handler\n");
763                 return WIDGET_ERROR_INVALID_PARAMETER;
764         }
765
766         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
767                 ErrPrint("Failed to get size (%s)\n", id);
768         }
769
770         ret = binder_widget_send_updated(pkgname, id, handle, idx, 0, 0, w, h, user_data->is_gbar, NULL);
771         if (ret < 0) {
772                 ErrPrint("Failed to send%supdated (%s) %d\n", user_data->is_gbar ? " GBAR " : " ", id, idx);
773         }
774
775         return ret;
776 }
777
778 PUBLIC int widget_support_hw_buffer(widget_buffer_h handle)
779 {
780         if (!handle) {
781                 return WIDGET_ERROR_INVALID_PARAMETER;
782         }
783
784         return widget_provider_buffer_is_support_hw(handle);
785 }
786
787 PUBLIC int widget_create_hw_buffer(widget_buffer_h handle)
788 {
789         struct widget_buffer_data *user_data;
790         int ret;
791
792         if (!handle) {
793                 return WIDGET_ERROR_INVALID_PARAMETER;
794         }
795
796         user_data = widget_provider_buffer_user_data(handle);
797         if (!user_data) {
798                 return WIDGET_ERROR_INVALID_PARAMETER;
799         }
800
801         if (user_data->accelerated) {
802                 return WIDGET_ERROR_ALREADY_EXIST;
803         }
804
805         ret = widget_provider_buffer_create_hw(handle);
806         user_data->accelerated = (ret == 0);
807         return ret;
808 }
809
810 PUBLIC int widget_destroy_hw_buffer(widget_buffer_h handle)
811 {
812         struct widget_buffer_data *user_data;
813
814         if (!handle) {
815                 LOGD("handle is NULL\n");
816                 return WIDGET_ERROR_INVALID_PARAMETER;
817         }
818
819         user_data = widget_provider_buffer_user_data(handle);
820         if (!user_data || !user_data->accelerated) {
821                 LOGD("user_data is NULL\n");
822                 return WIDGET_ERROR_INVALID_PARAMETER;
823         }
824
825         user_data->accelerated = 0;
826
827         return widget_provider_buffer_destroy_hw(handle);
828 }
829
830 PUBLIC void *widget_buffer_hw_buffer(widget_buffer_h handle)
831 {
832         struct widget_buffer_data *user_data;
833
834         if (!handle) {
835                 return NULL;
836         }
837
838         user_data = widget_provider_buffer_user_data(handle);
839         if (!user_data || !user_data->accelerated) {
840                 return NULL;
841         }
842
843         return widget_provider_buffer_hw_addr(handle);
844 }
845
846 PUBLIC int widget_buffer_pre_render(widget_buffer_h handle)
847 {
848         struct widget_buffer_data *user_data;
849
850         if (!handle) {
851                 return WIDGET_ERROR_INVALID_PARAMETER;
852         }
853
854         user_data = widget_provider_buffer_user_data(handle);
855         if (!user_data) {
856                 return WIDGET_ERROR_INVALID_PARAMETER;
857         }
858
859         if (!user_data->accelerated) {
860                 return WIDGET_ERROR_NONE;
861         }
862
863         /*!
864          * \note
865          * Do preprocessing for accessing the H/W render buffer
866          */
867         return widget_provider_buffer_pre_render(handle);
868 }
869
870 static Eina_Bool frame_wait_cb(void *data)
871 {
872         widget_buffer_h handle = data;
873         struct widget_buffer_data *user_data;
874         const char *pkgname;
875         const char *id;
876         int pixel_size;
877         int ret;
878         int w;
879         int h;
880
881         user_data = widget_provider_buffer_user_data(handle);
882         if (!user_data) {
883                 ErrPrint("Failed to get a user data\n");
884                 return ECORE_CALLBACK_CANCEL;
885         }
886
887         pkgname = widget_provider_buffer_pkgname(handle);
888         id = widget_provider_buffer_id(handle);
889
890         if (!pkgname || !id) {
891                 ErrPrint("Failed to get instance information (%s), (%s)\n", pkgname, id);
892                 user_data->frame_wait_timer = NULL;
893                 return ECORE_CALLBACK_CANCEL;
894         }
895
896         if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
897                 ErrPrint("Failed to get size (%s)\n", id);
898                 w = 0;
899                 h = 0;
900                 pixel_size = sizeof(int);
901         }
902
903         DbgPrint("Frame skip waiting timer is fired (%s)\n", id);
904
905         /**
906          * @todo
907          * manipulate the damaged region, so send update event only for the damaged region.
908          * to make more efficient updates
909          */
910         ret = binder_widget_send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
911         if (ret < 0) {
912                 ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
913         }
914
915         (void)widget_provider_buffer_clear_frame_skip(handle);
916
917         user_data->frame_wait_timer = NULL;
918         return ECORE_CALLBACK_CANCEL;
919 }
920
921 PUBLIC int widget_buffer_post_render(widget_buffer_h handle)
922 {
923         int ret;
924         const char *pkgname;
925         const char *id;
926         struct widget_buffer_data *user_data;
927         int w;
928         int h;
929         int pixel_size;
930         PERF_INIT();
931         PERF_BEGIN();
932
933         if (!handle) {
934                 PERF_MARK("post_render");
935                 return WIDGET_ERROR_INVALID_PARAMETER;
936         }
937
938         user_data = widget_provider_buffer_user_data(handle);
939         if (!user_data) {
940                 PERF_MARK("post_render");
941                 return WIDGET_ERROR_INVALID_PARAMETER;
942         }
943
944         if (!user_data->accelerated) {
945                 PERF_MARK("post_render");
946                 return WIDGET_ERROR_NONE;
947         }
948
949         pkgname = widget_provider_buffer_pkgname(handle);
950         if (!pkgname) {
951                 ErrPrint("Invalid buffer handle\n");
952                 PERF_MARK("post_render");
953                 return WIDGET_ERROR_INVALID_PARAMETER;
954         }
955
956         id = widget_provider_buffer_id(handle);
957         if (!id) {
958                 ErrPrint("Invalid buffer handler\n");
959                 PERF_MARK("post_render");
960                 return WIDGET_ERROR_INVALID_PARAMETER;
961         }
962
963         ret = widget_provider_buffer_post_render(handle);
964         if (ret < 0) {
965                 ErrPrint("Failed to post render processing\n");
966                 PERF_MARK("post_render");
967                 return ret;
968         }
969
970         if (widget_provider_buffer_frame_skip(handle) == 0) {
971                 if (widget_provider_buffer_get_size(handle, &w, &h, &pixel_size) < 0) {
972                         ErrPrint("Failed to get size (%s)\n", id);
973                 }
974
975                 /**
976                  * @todo
977                  * manipulate the damaged region, so send update event only for the damaged region.
978                  * to make more efficient updates
979                  */
980                 ret = binder_widget_send_updated(pkgname, id, handle, WIDGET_PRIMARY_BUFFER, 0, 0, w, h, user_data->is_gbar, NULL);
981                 if (ret < 0) {
982                         ErrPrint("Failed to send%supdated (%s)\n", user_data->is_gbar ? " GBAR " : " ", id);
983                 }
984
985                 if (user_data->frame_wait_timer) {
986                         ecore_timer_del(user_data->frame_wait_timer);
987                         user_data->frame_wait_timer = NULL;
988                 }
989         } else {
990                 if (user_data->frame_wait_timer) {
991                         ecore_timer_reset(user_data->frame_wait_timer);
992                 } else {
993                         user_data->frame_wait_timer = ecore_timer_add(FRAME_WAIT_INTERVAL, frame_wait_cb, handle);
994                         if (!user_data->frame_wait_timer) {
995                                 ErrPrint("Failed to add waiting timer for next frame\n");
996                         }
997                 }
998         }
999
1000         PERF_MARK("post_render");
1001         return ret;
1002 }
1003
1004 PUBLIC int widget_buffer_stride(widget_buffer_h handle)
1005 {
1006         if (!handle) {
1007                 return WIDGET_ERROR_INVALID_PARAMETER;
1008         }
1009
1010         return widget_provider_buffer_stride(handle);
1011 }
1012
1013 PUBLIC int widget_request_close_glance_bar(const char *pkgname, const char *id, int reason)
1014 {
1015         char *uri;
1016         int schema_len = strlen(FILE_SCHEMA);
1017         int ret;
1018
1019         if (!pkgname || !id) {
1020                 ErrPrint("Invalid parameters (%s) (%s)\n", pkgname, id);
1021                 return WIDGET_ERROR_INVALID_PARAMETER;
1022         }
1023
1024         if (strncmp(id, FILE_SCHEMA, schema_len)) {
1025                 uri = util_id_to_uri(id);
1026                 if (!uri) {
1027                         ErrPrint("Heap: %d\n", errno);
1028                         return WIDGET_ERROR_OUT_OF_MEMORY;
1029                 }
1030         } else {
1031                 uri = strdup(id);
1032                 if (!uri) {
1033                         ErrPrint("Heap: %d\n", errno);
1034                         return WIDGET_ERROR_OUT_OF_MEMORY;
1035                 }
1036         }
1037
1038         ret = widget_provider_send_request_close_gbar(pkgname, uri, reason);
1039         free(uri);
1040         return ret;
1041 }
1042
1043 PUBLIC int widget_freeze_scroller(const char *pkgname, const char *id)
1044 {
1045         char *uri;
1046         int ret;
1047
1048         if (!pkgname || !id) {
1049                 return WIDGET_ERROR_INVALID_PARAMETER;
1050         }
1051
1052         uri = util_id_to_uri(id);
1053         if (!uri) {
1054                 ErrPrint("Heap: %d\n", errno);
1055                 return WIDGET_ERROR_OUT_OF_MEMORY;
1056         }
1057
1058         ret = widget_provider_send_hold_scroll(pkgname, uri, 1);
1059         free(uri);
1060         return ret;
1061 }
1062
1063 PUBLIC int widget_thaw_scroller(const char *pkgname, const char *id)
1064 {
1065         char *uri;
1066         int ret;
1067
1068         if (!pkgname || !id) {
1069                 return WIDGET_ERROR_INVALID_PARAMETER;
1070         }
1071
1072         uri = util_id_to_uri(id);
1073         if (!uri) {
1074                 ErrPrint("Heap: %d\n", errno);
1075                 return WIDGET_ERROR_OUT_OF_MEMORY;
1076         }
1077
1078         ret = widget_provider_send_hold_scroll(pkgname, uri, 0);
1079         free(uri);
1080         return ret;
1081 }
1082
1083 PUBLIC int widget_set_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1084 {
1085         widget_buffer_h handle;
1086         const char *pkgname;
1087         char *uri;
1088
1089         uri = util_id_to_uri(id);
1090         if (!uri) {
1091                 ErrPrint("Heap: %d\n", errno);
1092                 return WIDGET_ERROR_OUT_OF_MEMORY;
1093         }
1094
1095         pkgname = binder_widget_find_pkgname(uri);
1096         if (!pkgname) {
1097                 ErrPrint("Failed to find a package (%s)\n", uri);
1098                 free(uri);
1099                 return WIDGET_ERROR_INVALID_PARAMETER;
1100         }
1101
1102         handle = widget_provider_buffer_find_buffer(WIDGET_TYPE_WIDGET, pkgname, uri);
1103         if (handle) {
1104                 struct widget_buffer_data *user_data;
1105
1106                 user_data = widget_provider_buffer_user_data(handle);
1107                 if (!user_data) {
1108                         ErrPrint("User data is not available\n");
1109                         free(uri);
1110                         return WIDGET_ERROR_FAULT;
1111                 }
1112
1113                 if (content && strlen(content)) {
1114                         char *_content;
1115
1116                         _content = strdup(content);
1117                         if (_content) {
1118                                 if (user_data->content) {
1119                                         free(user_data->content);
1120                                 }
1121
1122                                 user_data->content = _content;
1123                         } else {
1124                                 ErrPrint("Heap: %d\n", errno);
1125                         }
1126                 }
1127
1128                 if (title && strlen(title)) {
1129                         char *_title;
1130
1131                         _title = strdup(title);
1132                         if (_title) {
1133                                 if (user_data->title) {
1134                                         free(user_data->title);
1135                                 }
1136
1137                                 user_data->title = _title;
1138                         } else {
1139                                 ErrPrint("Heap: %d\n", errno);
1140                         }
1141                 }
1142
1143                 if (icon && strlen(icon)) {
1144                         char *_icon;
1145
1146                         _icon = strdup(icon);
1147                         if (_icon) {
1148                                 if (user_data->icon) {
1149                                         free(user_data->icon);
1150                                 }
1151
1152                                 user_data->icon = _icon;
1153                         } else {
1154                                 ErrPrint("Heap: %d\n", errno);
1155                         }
1156                 }
1157
1158                 if (name && strlen(name)) {
1159                         char *_name;
1160
1161                         _name = strdup(name);
1162                         if (_name) {
1163                                 if (user_data->name) {
1164                                         free(user_data->name);
1165                                 }
1166
1167                                 user_data->name = _name;
1168                         } else {
1169                                 ErrPrint("Heap: %d\n", errno);
1170                         }
1171                 }
1172
1173                 if (widget_provider_send_extra_info(pkgname, uri, -1.0f, user_data->content, user_data->title, user_data->icon, user_data->name) < 0) {
1174                         ErrPrint("Failed to send extra info (%s)\n", id);
1175                 }
1176
1177                 free(uri);
1178                 return WIDGET_ERROR_NONE;
1179         }
1180         free(uri);
1181
1182         return binder_widget_update_extra_info(id, content, title, icon, name);
1183 }
1184
1185 /* End of a file */