Fix the type of timestamp for feeding mouse event.
[apps/livebox/livebox-edje.git] / src / script_port.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 <libgen.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <ctype.h>
22
23 #include <Elementary.h>
24 #include <Evas.h>
25 #include <Edje.h>
26 #include <Eina.h>
27 #include <Ecore.h>
28 #include <Ecore_Evas.h>
29 #include <Eet.h>
30 #include <Ecore_X.h>
31
32 #include <system_settings.h>
33
34 #include <dlog.h>
35 #include <debug.h>
36 #include <vconf.h>
37 #include <livebox-errno.h>
38 #include <livebox-service.h>
39
40 #include "script_port.h"
41
42 #define TEXT_CLASS      "tizen"
43 #define DEFAULT_FONT_SIZE       -100
44 #define BASE_WIDTH      720.0f
45
46 #define PUBLIC __attribute__((visibility("default")))
47
48 struct image_option {
49         int orient;
50         int aspect;
51         enum {
52                 FILL_DISABLE,
53                 FILL_IN_SIZE,
54                 FILL_OVER_SIZE
55         } fill;
56
57         int width;
58         int height;
59 };
60
61 struct info {
62         char *file;
63         char *group;
64         char *category;
65         int w;
66         int h;
67
68         Evas *e;
69
70         Eina_List *obj_list;
71 };
72
73 struct child {
74         Evas_Object *obj;
75         char *part;
76 };
77
78 struct obj_info {
79         char *id;
80         Eina_List *children;
81         Evas_Object *parent;
82         Eina_List *access_chain;
83 };
84
85 static struct {
86         char *font_name;
87         int font_size;
88
89         Eina_List *handle_list;
90 } s_info = {
91         .font_name = NULL,
92         .font_size = -100,
93
94         .handle_list = NULL,
95 };
96
97 static inline double scale_get(void)
98 {
99         int width;
100         int height;
101         ecore_x_window_size_get(0, &width, &height);
102         return (double)width / BASE_WIDTH;
103 }
104
105 static inline Evas_Object *find_edje(struct info *handle, const char *id)
106 {
107         Eina_List *l;
108         Evas_Object *edje;
109         struct obj_info *obj_info;
110
111         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
112                 obj_info = evas_object_data_get(edje, "obj_info");
113                 if (!obj_info) {
114                         ErrPrint("Object info is not valid\n");
115                         continue;
116                 }
117
118                 if (!id) {
119                         if (!obj_info->id)
120                                 return edje;
121
122                         continue;
123                 } else if (!obj_info->id) {
124                         continue;
125                 }
126
127                 if (!strcmp(obj_info->id, id))
128                         return edje;
129         }
130
131         DbgPrint("EDJE[%s] is not found\n", id);
132         return NULL;
133 }
134
135 static inline void rebuild_focus_chain(Evas_Object *obj)
136 {
137         struct obj_info *obj_info;
138         Evas_Object *ao;
139         Eina_List *l;
140
141         obj_info = evas_object_data_get(obj, "obj_info");
142         if (!obj_info) {
143                 ErrPrint("Object info is not available\n");
144                 return;
145         }
146
147         elm_object_focus_custom_chain_unset(obj);
148
149         EINA_LIST_FOREACH(obj_info->access_chain, l, ao) {
150                 DbgPrint("Append %p\n", ao);
151                 elm_object_focus_custom_chain_append(obj, ao, NULL);
152         }
153 }
154
155 PUBLIC const char *script_magic_id(void)
156 {
157         return "edje";
158 }
159
160 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
161 {
162         struct info *handle = h;
163         Evas_Object *edje;
164         int r[3], g[3], b[3], a[3];
165         int ret;
166
167         edje = find_edje(handle, id);
168         if (!edje)
169                 return LB_STATUS_ERROR_NOT_EXIST;
170
171         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
172                                         r, g, b, a,                     /* OBJECT */
173                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
174                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
175         if (ret != 12) {
176                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
177                 return LB_STATUS_ERROR_INVALID;
178         }
179
180         ret = edje_object_color_class_set(elm_layout_edje_get(edje), part,
181                                 r[0], g[0], b[0], a[0], /* OBJECT */
182                                 r[1], g[1], b[1], a[1], /* OUTLINE */
183                                 r[2], g[2], b[2], a[2]); /* SHADOW */
184
185         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
186         return LB_STATUS_SUCCESS;
187 }
188
189 static void activate_cb(void *data, Evas_Object *part_obj, Elm_Object_Item *item)
190 {
191         Evas_Object *ao;
192         Evas_Object *edje;
193         Evas *e;
194         int x;
195         int y;
196         int w;
197         int h;
198         struct timeval tv;
199         double timestamp;
200
201         ao = evas_object_data_get(part_obj, "ao");
202         if (!ao)
203                 return;
204
205         edje = evas_object_data_get(ao, "edje");
206         if (!edje)
207                 return;
208
209         e = evas_object_evas_get(part_obj);
210         evas_object_geometry_get(part_obj, &x, &y, &w, &h);
211         x += w / 2;
212         y += h / 2;
213
214         if (gettimeofday(&tv, NULL) < 0) {
215                 ErrPrint("Failed to get time\n");
216                 timestamp = 0.0f;
217         } else {
218                 timestamp = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0f);
219         }
220
221         DbgPrint("Cursor is on %dx%d\n", x, y);
222         evas_event_feed_mouse_move(e, x, y, timestamp * 1000, NULL);
223         evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, (timestamp + 0.01f) * 1000, NULL);
224         evas_event_feed_mouse_move(e, x, y, (timestamp + 0.02f) * 1000, NULL);
225         evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, (timestamp + 0.03f) * 1000, NULL);
226 }
227
228 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
229 {
230         struct obj_info *obj_info;
231         struct info *handle = h;
232         Evas_Object *edje;
233         Evas_Object *to;
234
235         edje = find_edje(handle, id);
236         if (!edje) {
237                 ErrPrint("Failed to find EDJE\n");
238                 return LB_STATUS_ERROR_NOT_EXIST;
239         }
240
241         obj_info = evas_object_data_get(edje, "obj_info");
242         if (!obj_info) {
243                 ErrPrint("Object info is not available\n");
244                 return LB_STATUS_ERROR_FAULT;
245         }
246
247         elm_object_part_text_set(edje, part, text ? text : "");
248
249         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
250         if (to) {
251                 Evas_Object *ao;
252                 char *utf8;
253
254                 ao = evas_object_data_get(to, "ao");
255                 if (!ao) {
256                         ao = elm_access_object_register(to, edje);
257                         if (!ao) {
258                                 ErrPrint("Unable to add ao: %s\n", part);
259                                 goto out;
260                         }
261                         obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
262                         evas_object_data_set(to, "ao", ao);
263                         evas_object_data_set(ao, "edje", edje);
264                         elm_access_activate_cb_set(ao, activate_cb, NULL);
265                         elm_object_focus_custom_chain_append(edje, ao, NULL);
266                 }
267
268                 if (!text || !strlen(text)) {
269                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
270                         evas_object_data_del(to, "ao");
271                         evas_object_data_del(ao, "edje");
272                         elm_access_object_unregister(ao);
273                         DbgPrint("[%s] Remove access object\n", part);
274
275                         rebuild_focus_chain(edje);
276                         goto out;
277                 }
278
279                 utf8 = elm_entry_markup_to_utf8(text);
280                 if ((!utf8 || !strlen(utf8))) {
281                         free(utf8);
282
283                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
284                         evas_object_data_del(to, "ao");
285                         evas_object_data_del(ao, "edje");
286                         elm_access_object_unregister(ao);
287                         DbgPrint("[%s] Remove access object\n", part);
288
289                         rebuild_focus_chain(edje);
290                         goto out;
291                 }
292
293                 elm_access_info_set(ao, ELM_ACCESS_INFO, utf8);
294                 free(utf8);
295         } else {
296                 ErrPrint("Unable to get text part[%s]\n", part);
297         }
298
299 out:
300         return LB_STATUS_SUCCESS;
301 }
302
303 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
304 {
305         while (len > 0 && *value == ' ') {
306                 value++;
307                 len--;
308         }
309
310         if (len < 4)
311                 return;
312
313         img_opt->aspect = !strncasecmp(value, "true", 4);
314         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
315 }
316
317 static void parse_orient(struct image_option *img_opt, const char *value, int len)
318 {
319         while (len > 0 && *value == ' ') {
320                 value++;
321                 len--;
322         }
323
324         if (len < 4)
325                 return;
326
327         img_opt->orient = !strncasecmp(value, "true", 4);
328         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->orient, value);
329 }
330
331 static void parse_size(struct image_option *img_opt, const char *value, int len)
332 {
333         int width;
334         int height;
335         char *buf;
336
337         while (len > 0 && *value == ' ') {
338                 value++;
339                 len--;
340         }
341
342         buf = strndup(value, len);
343         if (!buf) {
344                 ErrPrint("Heap: %s\n", strerror(errno));
345                 return;
346         }
347
348         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
349                 img_opt->width = width;
350                 img_opt->height = height;
351                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
352         } else {
353                 DbgPrint("Invalid size tag[%s]\n", buf);
354         }
355
356         free(buf);
357 }
358
359 static void parse_fill(struct image_option *img_opt, const char *value, int len)
360 {
361         while (len > 0 && *value == ' ') {
362                 value++;
363                 len--;
364         }
365
366         if (!strncasecmp(value, "in-size", len))
367                 img_opt->fill = FILL_IN_SIZE;
368         else if (!strncasecmp(value, "over-size", len))
369                 img_opt->fill = FILL_OVER_SIZE;
370         else
371                 img_opt->fill = FILL_DISABLE;
372
373         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
374 }
375
376 static inline void parse_image_option(const char *option, struct image_option *img_opt)
377 {
378         const char *ptr;
379         const char *cmd;
380         const char *value;
381         struct {
382                 const char *cmd;
383                 void (*handler)(struct image_option *img_opt, const char *value, int len);
384         } cmd_list[] = {
385                 {
386                         .cmd = "aspect", /* Keep the aspect ratio */
387                         .handler = parse_aspect,
388                 },
389                 {
390                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
391                         .handler = parse_orient,
392                 },
393                 {
394                         .cmd = "fill", /* Fill the image to its container */
395                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
396                 },
397                 {
398                         .cmd = "size",
399                         .handler = parse_size,
400                 },
401         };
402         enum {
403                 STATE_START,
404                 STATE_TOKEN,
405                 STATE_DATA,
406                 STATE_IGNORE,
407                 STATE_ERROR,
408                 STATE_END
409         } state;
410         int idx;
411         int tag;
412
413         if (!option || !*option)
414                 return;
415
416         state = STATE_START;
417         /*!
418          * \note
419          * GCC 4.7 warnings uninitialized idx and tag value.
420          * But it will be initialized by the state machine. :(
421          * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
422          */
423         idx = 0;
424         tag = 0;
425         cmd = NULL;
426         value = NULL;
427
428         for (ptr = option; state != STATE_END; ptr++) {
429                 switch (state) {
430                 case STATE_START:
431                         if (*ptr == '\0') {
432                                 state = STATE_END;
433                                 continue;
434                         }
435
436                         if (isalpha(*ptr)) {
437                                 state = STATE_TOKEN;
438                                 ptr--;
439                         }
440                         tag = 0;
441                         idx = 0;
442
443                         cmd = cmd_list[tag].cmd;
444                         break;
445                 case STATE_IGNORE:
446                         if (*ptr == '=') {
447                                 state = STATE_DATA;
448                                 value = ptr;
449                         } else if (*ptr == '\0') {
450                                 state = STATE_END;
451                         }
452                         break;
453                 case STATE_TOKEN:
454                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
455                                 if (*ptr == '=') {
456                                         value = ptr;
457                                         state = STATE_DATA;
458                                 } else {
459                                         state = STATE_IGNORE;
460                                 }
461                                 idx = 0;
462                         } else if (*ptr == '\0') {
463                                 state = STATE_END;
464                         } else if (cmd[idx] == *ptr) {
465                                 idx++;
466                         } else {
467                                 ptr -= (idx + 1);
468
469                                 tag++;
470                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
471                                         tag = 0;
472                                         state = STATE_ERROR;
473                                 } else {
474                                         cmd = cmd_list[tag].cmd;
475                                 }
476                                 idx = 0;
477                         }
478                         break;
479                 case STATE_DATA:
480                         if (*ptr == ';' || *ptr == '\0') {
481                                 cmd_list[tag].handler(img_opt, value + 1, idx);
482                                 state = *ptr ? STATE_START : STATE_END;
483                         } else {
484                                 idx++;
485                         }
486                         break;
487                 case STATE_ERROR:
488                         if (*ptr == ';')
489                                 state = STATE_START;
490                         else if (*ptr == '\0')
491                                 state = STATE_END;
492                         break;
493                 default:
494                         break;
495                 }
496         }
497 }
498
499 PUBLIC int script_update_access(void *_h, Evas *e, const char *id, const char *part, const char *text, const char *option)
500 {
501         struct info *handle = _h;
502         Evas_Object *edje;
503         struct obj_info *obj_info;
504         Evas_Object *to;
505
506         edje = find_edje(handle, id);
507         if (!edje) {
508                 ErrPrint("No such object: %s\n", id);
509                 return LB_STATUS_ERROR_NOT_EXIST;
510         }
511
512         obj_info = evas_object_data_get(edje, "obj_info");
513         if (!obj_info) {
514                 ErrPrint("Object info is not available\n");
515                 return LB_STATUS_ERROR_FAULT;
516         }
517
518         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
519         if (to) {
520                 Evas_Object *ao;
521
522                 ao = evas_object_data_get(to, "ao");
523                 if (ao) {
524                         if (text && strlen(text)) {
525                                 elm_access_info_set(ao, ELM_ACCESS_INFO, text);
526                         } else {
527                                 obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
528                                 evas_object_data_del(to, "ao");
529                                 evas_object_data_del(ao, "edje");
530                                 elm_access_object_unregister(ao);
531                                 DbgPrint("Successfully unregistered\n");
532
533                                 rebuild_focus_chain(edje);
534                         }
535                 } else if (text && strlen(text)) {
536                         ao = elm_access_object_register(to, edje);
537                         if (!ao) {
538                                 ErrPrint("Unable to register access object\n");
539                         } else {
540                                 elm_access_info_set(ao, ELM_ACCESS_INFO, text);
541                                 obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
542                                 evas_object_data_set(to, "ao", ao);
543                                 elm_object_focus_custom_chain_append(edje, ao, NULL);
544                                 DbgPrint("[%s] Register access info: (%s)\n", part, text);
545                                 evas_object_data_set(ao, "edje", edje);
546                                 elm_access_activate_cb_set(ao, activate_cb, NULL);
547                         }
548                 }
549         } else {
550                 ErrPrint("[%s] is not exists\n", part);
551         }
552
553         return LB_STATUS_SUCCESS;
554 }
555
556 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
557 {
558         struct info *handle = _h;
559         Evas_Load_Error err;
560         Evas_Object *edje;
561         Evas_Object *img;
562         Evas_Coord w, h;
563         struct obj_info *obj_info;
564         struct child *child;
565         struct image_option img_opt = {
566                 .aspect = 0,
567                 .orient = 0,
568                 .fill = FILL_DISABLE,
569                 .width = -1,
570                 .height = -1,
571         };
572
573         edje = find_edje(handle, id);
574         if (!edje) {
575                 ErrPrint("No such object: %s\n", id);
576                 return LB_STATUS_ERROR_NOT_EXIST;
577         }
578
579         obj_info = evas_object_data_get(edje, "obj_info");
580         if (!obj_info) {
581                 ErrPrint("Object info is not available\n");
582                 return LB_STATUS_ERROR_FAULT;
583         }
584
585         img = elm_object_part_content_unset(edje, part);
586         if (img) {
587                 Eina_List *l;
588                 Eina_List *n;
589                 Evas_Object *ao;
590
591                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
592                         if (child->obj != img)
593                                 continue;
594
595                         obj_info->children = eina_list_remove(obj_info->children, child);
596                         free(child->part);
597                         free(child);
598                         break;
599                 }
600
601                 DbgPrint("delete object %s %p\n", part, img);
602                 ao = evas_object_data_del(img, "ao");
603                 if (ao) {
604                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
605                         evas_object_data_del(ao, "edje");
606                         elm_access_object_unregister(ao);
607                         DbgPrint("Successfully unregistered\n");
608                 }
609                 evas_object_del(img);
610
611                 rebuild_focus_chain(edje);
612         }
613
614         if (!path || !strlen(path) || access(path, R_OK) != 0) {
615                 DbgPrint("SKIP - Path: [%s]\n", path);
616                 return LB_STATUS_SUCCESS;
617         }
618
619         child = malloc(sizeof(*child));
620         if (!child) {
621                 ErrPrint("Heap: %s\n", strerror(errno));
622                 return LB_STATUS_ERROR_MEMORY;
623         }
624
625         child->part = strdup(part);
626         if (!child->part) {
627                 ErrPrint("Heap: %s\n", strerror(errno));
628                 free(child);
629                 return LB_STATUS_ERROR_MEMORY;
630         }
631
632         img = evas_object_image_add(e);
633         if (!img) {
634                 ErrPrint("Failed to add an image object\n");
635                 free(child->part);
636                 free(child);
637                 return LB_STATUS_ERROR_FAULT;
638         }
639
640         evas_object_image_preload(img, EINA_FALSE);
641         parse_image_option(option, &img_opt);
642         evas_object_image_load_orientation_set(img, img_opt.orient);
643
644         evas_object_image_file_set(img, path, NULL);
645         err = evas_object_image_load_error_get(img);
646         if (err != EVAS_LOAD_ERROR_NONE) {
647                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
648                 evas_object_del(img);
649                 free(child->part);
650                 free(child);
651                 return LB_STATUS_ERROR_IO;
652         }
653
654         evas_object_image_size_get(img, &w, &h);
655         if (img_opt.aspect) {
656                 if (img_opt.fill == FILL_OVER_SIZE) {
657                         Evas_Coord part_w;
658                         Evas_Coord part_h;
659
660                         if (img_opt.width >= 0 && img_opt.height >= 0) {
661                                 part_w = img_opt.width * scale_get();
662                                 part_h = img_opt.height * scale_get();
663                         } else {
664                                 part_w = 0;
665                                 part_h = 0;
666                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
667                         }
668                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
669
670                         if (part_w > w || part_h > h) {
671                                 double fw;
672                                 double fh;
673
674                                 fw = (double)part_w / (double)w;
675                                 fh = (double)part_h / (double)h;
676
677                                 if (fw > fh) {
678                                         w = part_w;
679                                         h = (double)h * fw;
680                                 } else {
681                                         h = part_h;
682                                         w = (double)w * fh;
683                                 }
684                         }
685
686                         if (!part_w || !part_h || !w || !h) {
687                                 evas_object_del(img);
688                                 free(child->part);
689                                 free(child);
690                                 return LB_STATUS_ERROR_INVALID;
691                         }
692
693                         if (evas_object_image_region_support_get(img)) {
694                                 evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
695                                 evas_object_image_load_size_set(img, part_w, part_h);
696                                 evas_object_image_filled_set(img, EINA_TRUE);
697                                 //evas_object_image_fill_set(img, 0, 0, part_w, part_h);
698                                 DbgPrint("Size: %dx%d (region: %dx%d - %dx%d)\n", w, h, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
699                         } else {
700                                 Ecore_Evas *ee;
701                                 Evas *e;
702                                 Evas_Object *src_img;
703                                 Evas_Coord rw, rh;
704                                 const void *data;
705
706                                 DbgPrint("Part loading is not supported\n");
707                                 ee = ecore_evas_buffer_new(part_w, part_h);
708                                 if (!ee) {
709                                         ErrPrint("Failed to create a EE\n");
710                                         evas_object_del(img);
711                                         free(child->part);
712                                         free(child);
713                                         return LB_STATUS_ERROR_FAULT;
714                                 }
715
716                                 ecore_evas_alpha_set(ee, EINA_TRUE);
717
718                                 e = ecore_evas_get(ee);
719                                 if (!e) {
720                                         ErrPrint("Unable to get Evas\n");
721                                         ecore_evas_free(ee);
722
723                                         evas_object_del(img);
724                                         free(child->part);
725                                         free(child);
726                                         return LB_STATUS_ERROR_FAULT;
727                                 }
728
729                                 src_img = evas_object_image_filled_add(e);
730                                 if (!src_img) {
731                                         ErrPrint("Unable to add an image\n");
732                                         ecore_evas_free(ee);
733
734                                         evas_object_del(img);
735                                         free(child->part);
736                                         free(child);
737                                         return LB_STATUS_ERROR_FAULT;
738                                 }
739
740                                 evas_object_image_alpha_set(src_img, EINA_TRUE);
741                                 evas_object_image_colorspace_set(src_img, EVAS_COLORSPACE_ARGB8888);
742                                 evas_object_image_smooth_scale_set(src_img, EINA_TRUE);
743                                 evas_object_image_load_orientation_set(src_img, img_opt.orient);
744                                 evas_object_image_file_set(src_img, path, NULL);
745                                 err = evas_object_image_load_error_get(src_img);
746                                 if (err != EVAS_LOAD_ERROR_NONE) {
747                                         ErrPrint("Load error: %s\n", evas_load_error_str(err));
748                                         evas_object_del(src_img);
749                                         ecore_evas_free(ee);
750
751                                         evas_object_del(img);
752                                         free(child->part);
753                                         free(child);
754                                         return LB_STATUS_ERROR_IO;
755                                 }
756                                 evas_object_image_size_get(src_img, &rw, &rh);
757                                 evas_object_image_fill_set(src_img, 0, 0, rw, rh);
758                                 evas_object_resize(src_img, w, h);
759                                 evas_object_move(src_img, -(w - part_w) / 2, -(h - part_h) / 2);
760                                 evas_object_show(src_img);
761
762                                 data = ecore_evas_buffer_pixels_get(ee);
763                                 if (!data) {
764                                         ErrPrint("Unable to get pixels\n");
765                                         evas_object_del(src_img);
766                                         ecore_evas_free(ee);
767
768                                         evas_object_del(img);
769                                         free(child->part);
770                                         free(child);
771                                         return LB_STATUS_ERROR_IO;
772                                 }
773
774                                 e = evas_object_evas_get(img);
775                                 evas_object_del(img);
776                                 img = evas_object_image_filled_add(e);
777                                 if (!img) {
778                                         evas_object_del(src_img);
779                                         ecore_evas_free(ee);
780
781                                         free(child->part);
782                                         free(child);
783                                         return LB_STATUS_ERROR_MEMORY;
784                                 }
785
786                                 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
787                                 evas_object_image_smooth_scale_set(img, EINA_TRUE);
788                                 evas_object_image_alpha_set(img, EINA_TRUE);
789                                 evas_object_image_data_set(img, NULL);
790                                 evas_object_image_size_set(img, part_w, part_h);
791                                 evas_object_resize(img, part_w, part_h);
792                                 evas_object_image_data_copy_set(img, (void *)data);
793                                 evas_object_image_fill_set(img, 0, 0, part_w, part_h);
794                                 evas_object_image_data_update_add(img, 0, 0, part_w, part_h);
795
796                                 evas_object_del(src_img);
797                                 ecore_evas_free(ee);
798                         }
799                 } else if (img_opt.fill == FILL_IN_SIZE) {
800                         Evas_Coord part_w;
801                         Evas_Coord part_h;
802
803                         if (img_opt.width >= 0 && img_opt.height >= 0) {
804                                 part_w = img_opt.width * scale_get();
805                                 part_h = img_opt.height * scale_get();
806                         } else {
807                                 part_w = 0;
808                                 part_h = 0;
809                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
810                         }
811                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
812
813                         if (part_w > w || part_h > h) {
814                                 double fw;
815                                 double fh;
816
817                                 fw = (double)part_w / (double)w;
818                                 fh = (double)part_h / (double)h;
819
820                                 if (fw > fh) {
821                                         w = part_w;
822                                         h = (double)h * fw;
823                                 } else {
824                                         h = part_h;
825                                         w = (double)w * fh;
826                                 }
827                         }
828                         DbgPrint("Size: %dx%d\n", w, h);
829                         evas_object_image_fill_set(img, 0, 0, part_w, part_h);
830                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
831                         evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
832                 } else {
833                         evas_object_image_fill_set(img, 0, 0, w, h);
834                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
835                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
836                 }
837         } else {
838                 if (img_opt.width >= 0 && img_opt.height >= 0) {
839                         w = img_opt.width;
840                         h = img_opt.height;
841                         DbgPrint("Using given image size: %dx%d\n", w, h);
842                 }
843
844                 evas_object_image_fill_set(img, 0, 0, w, h);
845                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
846                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
847                 evas_object_image_filled_set(img, EINA_TRUE);
848         }
849
850         /*!
851          * \note
852          * object will be shown by below statement automatically
853          */
854         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
855         child->obj = img;
856         elm_object_part_content_set(edje, part, img);
857         obj_info->children = eina_list_append(obj_info->children, child);
858
859         /*!
860          * \note
861          * This object is not registered as an access object.
862          * So the developer should add it to access list manually, using DESC_ACCESS block.
863          */
864         return LB_STATUS_SUCCESS;
865 }
866
867 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
868 {
869         struct info *handle = data;
870         Evas_Coord w;
871         Evas_Coord h;
872         Evas_Coord px = 0;
873         Evas_Coord py = 0;
874         Evas_Coord pw = 0;
875         Evas_Coord ph = 0;
876         double sx;
877         double sy;
878         double ex;
879         double ey;
880
881         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
882         edje_object_part_geometry_get(elm_layout_edje_get(obj), source, &px, &py, &pw, &ph);
883
884         sx = ex = 0.0f;
885         if (w) {
886                 sx = (double)px / (double)w;
887                 ex = (double)(px + pw) / (double)w;
888         }
889
890         sy = ey = 0.0f;
891         if (h) {
892                 sy = (double)py / (double)h;
893                 ey = (double)(py + ph) / (double)h;
894         }
895
896         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
897 }
898
899 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
900 {
901         struct info *handle = _info;
902         struct obj_info *obj_info;
903         struct obj_info *parent_obj_info;
904         struct child *child;
905         Evas_Object *ao;
906
907         handle->obj_list = eina_list_remove(handle->obj_list, obj);
908
909         obj_info = evas_object_data_del(obj, "obj_info");
910         if (!obj_info) {
911                 ErrPrint("Object info is not valid\n");
912                 return;
913         }
914
915         DbgPrint("delete object %s %p\n", obj_info->id, obj);
916         parent_obj_info = evas_object_data_get(obj_info->parent, "obj_info");
917         if (parent_obj_info) {
918                 Eina_List *l;
919                 Eina_List *n;
920
921                 EINA_LIST_FOREACH_SAFE(parent_obj_info->children, l, n, child) {
922                         if (child->obj != obj)
923                                 continue;
924
925                         /*!
926                          * \note
927                          * If this code is executed,
928                          * The parent is not deleted by desc, this object is deleted by itself.
929                          * It is not possible, but we care it.
930                          */
931                         DbgPrint("Parent's children is updated: %s\n", child->part);
932                         parent_obj_info->children = eina_list_remove(parent_obj_info->children, child);
933                         free(child->part);
934                         free(child);
935                         break;
936                 }
937         } else {
938                 DbgPrint("Parent EDJE\n");
939         }
940
941         elm_object_signal_callback_del(obj, "*", "*", script_signal_cb);
942
943         elm_object_focus_custom_chain_unset(obj);
944
945         EINA_LIST_FREE(obj_info->children, child) {
946                 DbgPrint("delete object %s %p\n", child->part, child->obj);
947                 if (child->obj) {
948                         Evas_Object *ao;
949                         ao = evas_object_data_del(child->obj, "ao");
950                         if (ao) {
951                                 obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
952                                 evas_object_data_del(ao, "edje");
953                                 elm_access_object_unregister(ao);
954                         }
955                         evas_object_del(child->obj);
956                 }
957                 free(child->part);
958                 free(child);
959         }
960
961         EINA_LIST_FREE(obj_info->access_chain, ao) {
962                 evas_object_data_del(ao, "edje");
963                 elm_access_object_unregister(ao);
964         }
965
966         free(obj_info->id);
967         free(obj_info);
968 }
969
970 /*!
971         LB_ACCESS_HIGHLIGHT             0
972         LB_ACCESS_HIGHLIGHT_NEXT        1
973         LB_ACCESS_HIGHLIGHT_PREV        2
974         LB_ACCESS_ACTIVATE              3
975         LB_ACCESS_ACTION                4
976         LB_ACCESS_SCROLL                5
977 */
978 PUBLIC int script_feed_event(void *h, Evas *e, int event_type, int x, int y, int down, double timestamp)
979 {
980         struct info *handle = h;
981         Evas_Object *edje;
982         struct obj_info *obj_info;
983         int ret = LB_STATUS_SUCCESS;
984
985         edje = find_edje(handle, NULL); /*!< Get the base layout */
986         if (!edje) {
987                 ErrPrint("Base layout is not exist\n");
988                 return LB_STATUS_ERROR_NOT_EXIST;
989         }
990
991         obj_info = evas_object_data_get(edje, "obj_info");
992         if (!obj_info) {
993                 ErrPrint("Object info is not valid\n");
994                 return LB_STATUS_ERROR_INVALID;
995         }
996
997         if (event_type & LB_SCRIPT_ACCESS_EVENT) {
998                 Elm_Access_Action_Info *info;
999                 Elm_Access_Action_Type action;
1000                 const Eina_List *chain;
1001
1002                 info = calloc(1, sizeof(*info));
1003                 if (!info) {
1004                         ErrPrint("Error: %s\n", strerror(errno));
1005                         return LB_STATUS_ERROR_MEMORY;
1006                 }
1007
1008                 chain = elm_object_focus_custom_chain_get(edje);
1009                 DbgPrint("Focus chain : %d\n", eina_list_count(chain));
1010
1011                 if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT) == LB_SCRIPT_ACCESS_HIGHLIGHT) {
1012                         action = ELM_ACCESS_ACTION_HIGHLIGHT;
1013                         info->x = x;
1014                         info->y = y;
1015                         ret = elm_access_action(edje, action, info);
1016                         DbgPrint("ACCESS_HIGHLIGHT: %dx%d returns %d\n", x, y, ret);
1017                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1018                 } else if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT_NEXT) == LB_SCRIPT_ACCESS_HIGHLIGHT_NEXT) {
1019                         action = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
1020                         info->highlight_cycle = EINA_FALSE;
1021                         ret = elm_access_action(edje, action, info);
1022                         DbgPrint("ACCESS_HIGHLIGHT_NEXT, returns %d\n", ret);
1023                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_LAST : LB_ACCESS_STATUS_DONE;
1024                 } else if ((event_type & LB_SCRIPT_ACCESS_HIGHLIGHT_PREV) == LB_SCRIPT_ACCESS_HIGHLIGHT_PREV) {
1025                         action = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
1026                         info->highlight_cycle = EINA_FALSE;
1027                         ret = elm_access_action(edje, action, info);
1028                         DbgPrint("ACCESS_HIGHLIGHT_PREV, returns %d\n", ret);
1029                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_FIRST : LB_ACCESS_STATUS_DONE;
1030                 } else if ((event_type & LB_SCRIPT_ACCESS_ACTIVATE) == LB_SCRIPT_ACCESS_ACTIVATE) {
1031                         action = ELM_ACCESS_ACTION_ACTIVATE;
1032                         ret = elm_access_action(edje, action, info);
1033                         DbgPrint("ACCESS_ACTIVATE, returns %d\n", ret);
1034                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1035                 } else if ((event_type & LB_SCRIPT_ACCESS_ACTION) == LB_SCRIPT_ACCESS_ACTION) {
1036                         if (down == 0) {
1037                                 action = ELM_ACCESS_ACTION_UP;
1038                                 ret = elm_access_action(edje, action, info);
1039                                 DbgPrint("ACCESS_ACTION(%d), returns %d\n", down, ret);
1040                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1041                         } else if (down == 1) {
1042                                 action = ELM_ACCESS_ACTION_DOWN;
1043                                 ret = elm_access_action(edje, action, info);
1044                                 DbgPrint("ACCESS_ACTION(%d), returns %d\n", down, ret);
1045                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1046                         } else {
1047                                 ErrPrint("Invalid access event\n");
1048                                 ret = LB_ACCESS_STATUS_ERROR;
1049                         }
1050                 } else if ((event_type & LB_SCRIPT_ACCESS_SCROLL) == LB_SCRIPT_ACCESS_SCROLL) {
1051                         action = ELM_ACCESS_ACTION_SCROLL;
1052                         info->x = x;
1053                         info->y = y;
1054                         switch (down) {
1055                         case 0:
1056                                 info->mouse_type = 0;
1057                                 ret = elm_access_action(edje, action, info);
1058                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1059                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1060                                 break;
1061                         case -1:
1062                                 info->mouse_type = 1;
1063                                 ret = elm_access_action(edje, action, info);
1064                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1065                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1066                                 break;
1067                         case 1:
1068                                 info->mouse_type = 2;
1069                                 ret = elm_access_action(edje, action, info);
1070                                 DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
1071                                 ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1072                                 break;
1073                         default:
1074                                 ret = LB_ACCESS_STATUS_ERROR;
1075                                 break;
1076                         }
1077                 } else if ((event_type & LB_SCRIPT_ACCESS_UNHIGHLIGHT) == LB_SCRIPT_ACCESS_UNHIGHLIGHT) {
1078                         action = ELM_ACCESS_ACTION_UNHIGHLIGHT;
1079                         ret = elm_access_action(edje, action, info);
1080                         DbgPrint("ACCESS_UNHIGHLIGHT, returns %d\n", ret);
1081                         ret = (ret == EINA_FALSE) ? LB_ACCESS_STATUS_ERROR : LB_ACCESS_STATUS_DONE;
1082                 } else {
1083                         DbgPrint("Invalid event\n");
1084                         ret = LB_ACCESS_STATUS_ERROR;
1085                 }
1086
1087                 free(info);
1088         } else if (event_type & LB_SCRIPT_MOUSE_EVENT) {
1089                 switch (event_type) {
1090                 case LB_SCRIPT_MOUSE_DOWN:
1091                         evas_event_feed_mouse_move(e, x, y, timestamp * 1000, NULL);
1092                         evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, (timestamp + 0.01f) * 1000, NULL);
1093                         break;
1094                 case LB_SCRIPT_MOUSE_MOVE:
1095                         evas_event_feed_mouse_move(e, x, y, timestamp * 1000, NULL);
1096                         break;
1097                 case LB_SCRIPT_MOUSE_UP:
1098                         evas_event_feed_mouse_move(e, x, y, timestamp * 1000, NULL);
1099                         evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, (timestamp + 0.1f) * 1000, NULL);
1100                         break;
1101                 case LB_SCRIPT_MOUSE_IN:
1102                         evas_event_feed_mouse_in(e, timestamp * 1000, NULL);
1103                         break;
1104                 case LB_SCRIPT_MOUSE_OUT:
1105                         evas_event_feed_mouse_out(e, timestamp * 1000, NULL);
1106                         break;
1107                 default:
1108                         return LB_STATUS_ERROR_INVALID;
1109                 }
1110         } else if (event_type & LB_SCRIPT_KEY_EVENT) {
1111                 DbgPrint("Key event is not implemented\n");
1112                 return LB_STATUS_ERROR_NOT_IMPLEMENTED;
1113         }
1114
1115         return ret;
1116 }
1117
1118 PUBLIC int script_update_script(void *h, Evas *e, const char *src_id, const char *target_id, const char *part, const char *path, const char *group)
1119 {
1120         struct info *handle = h;
1121         Evas_Object *edje;
1122         Evas_Object *obj;
1123         struct obj_info *obj_info;
1124         struct child *child;
1125         char _target_id[32];
1126
1127         edje = find_edje(handle, src_id);
1128         if (!edje) {
1129                 ErrPrint("Edje is not exists (%s)\n", src_id);
1130                 return LB_STATUS_ERROR_NOT_EXIST;
1131         }
1132
1133         obj_info = evas_object_data_get(edje, "obj_info");
1134         if (!obj_info) {
1135                 ErrPrint("Object info is not valid\n");
1136                 return LB_STATUS_ERROR_INVALID;
1137         }
1138
1139         obj = elm_object_part_content_unset(edje, part);
1140         if (obj) {
1141                 Eina_List *l;
1142                 Eina_List *n;
1143
1144                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
1145                         if (child->obj != obj)
1146                                 continue;
1147
1148                         obj_info->children = eina_list_remove(obj_info->children, child);
1149
1150                         free(child->part);
1151                         free(child);
1152                         break;
1153                 }
1154
1155                 DbgPrint("delete object %s %p\n", part, obj);
1156                 /*!
1157                  * \note
1158                  * This will call the edje_del_cb.
1159                  * It will delete all access objects
1160                  */
1161                 evas_object_del(obj);
1162         }
1163
1164         if (!path || !strlen(path) || access(path, R_OK) != 0) {
1165                 DbgPrint("SKIP - Path: [%s]\n", path);
1166                 return LB_STATUS_SUCCESS;
1167         }
1168
1169         if (!target_id) {
1170                 if (find_edje(handle, part)) {
1171                         double timestamp;
1172                         struct timeval tv;
1173
1174                         do {
1175                                 if (gettimeofday(&tv, NULL) < 0) {
1176                                         static int local_idx = 0;
1177                                         timestamp = (double)(local_idx++);
1178                                 } else {
1179                                         timestamp = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0f);
1180                                 }
1181
1182                                 snprintf(_target_id, sizeof(_target_id), "%lf", timestamp);
1183                         } while (find_edje(handle, _target_id));
1184
1185                         target_id = _target_id;
1186                 } else {
1187                         target_id = part;
1188                 }
1189
1190                 DbgPrint("Anonymouse target id: %s\n", target_id);
1191         }
1192
1193         obj = elm_layout_add(edje);
1194         if (!obj) {
1195                 ErrPrint("Failed to add a new edje object\n");
1196                 return LB_STATUS_ERROR_FAULT;
1197         }
1198
1199         if (!elm_layout_file_set(obj, path, group)) {
1200                 int err;
1201                 const char *errmsg;
1202
1203                 err = edje_object_load_error_get(elm_layout_edje_get(obj));
1204                 errmsg = edje_load_error_str(err);
1205                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
1206                 evas_object_del(obj);
1207                 return LB_STATUS_ERROR_IO;
1208         }
1209
1210         evas_object_show(obj);
1211
1212         obj_info = calloc(1, sizeof(*obj_info));
1213         if (!obj_info) {
1214                 ErrPrint("Failed to add a obj_info\n");
1215                 evas_object_del(obj);
1216                 return LB_STATUS_ERROR_MEMORY;
1217         }
1218
1219         obj_info->id = strdup(target_id);
1220         if (!obj_info->id) {
1221                 ErrPrint("Failed to add a obj_info\n");
1222                 free(obj_info);
1223                 evas_object_del(obj);
1224                 return LB_STATUS_ERROR_MEMORY;
1225         }
1226
1227         obj_info->parent = edje;
1228
1229         child = malloc(sizeof(*child));
1230         if (!child) {
1231                 ErrPrint("Error: %s\n", strerror(errno));
1232                 free(obj_info->id);
1233                 free(obj_info);
1234                 evas_object_del(obj);
1235                 return LB_STATUS_ERROR_MEMORY;
1236         }
1237
1238         child->part = strdup(part);
1239         if (!child->part) {
1240                 ErrPrint("Error: %s\n", strerror(errno));
1241                 free(child);
1242                 free(obj_info->id);
1243                 free(obj_info);
1244                 evas_object_del(obj);
1245                 return LB_STATUS_ERROR_MEMORY;
1246         }
1247
1248         child->obj = obj;
1249
1250         evas_object_data_set(obj, "obj_info", obj_info);
1251         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
1252         elm_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
1253         handle->obj_list = eina_list_append(handle->obj_list, obj);
1254
1255         DbgPrint("%s part swallow edje %p\n", part, obj);
1256         elm_object_part_content_set(edje, part, obj);
1257
1258         obj_info = evas_object_data_get(edje, "obj_info");
1259         obj_info->children = eina_list_append(obj_info->children, child);
1260         return LB_STATUS_SUCCESS;
1261 }
1262
1263 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
1264 {
1265         struct info *handle = h;
1266         Evas_Object *edje;
1267
1268         edje = find_edje(handle, id);
1269         if (!edje)
1270                 return LB_STATUS_ERROR_NOT_EXIST;
1271
1272         elm_object_signal_emit(edje, signal, part);
1273         return LB_STATUS_SUCCESS;
1274 }
1275
1276 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
1277 {
1278         struct info *handle = h;
1279         Evas_Object *edje;
1280
1281         edje = find_edje(handle, id);
1282         if (!edje)
1283                 return LB_STATUS_ERROR_NOT_EXIST;
1284
1285         edje_object_part_drag_value_set(elm_layout_edje_get(edje), part, x, y);
1286         return LB_STATUS_SUCCESS;
1287 }
1288
1289 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
1290 {
1291         struct info *handle = han;
1292         Evas_Object *edje;
1293
1294         edje = find_edje(handle, id);
1295         if (!edje)
1296                 return LB_STATUS_ERROR_NOT_EXIST;
1297
1298         if (!id) {
1299                 handle->w = w;
1300                 handle->h = h;
1301         }
1302
1303         DbgPrint("Resize object to %dx%d\n", w, h);
1304         evas_object_resize(edje, w, h);
1305         return LB_STATUS_SUCCESS;
1306 }
1307
1308 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
1309 {
1310         struct info *handle = h;
1311
1312         if (handle->category) {
1313                 free(handle->category);
1314                 handle->category = NULL;
1315         }
1316
1317         if (!category)
1318                 return LB_STATUS_SUCCESS;
1319
1320         handle->category = strdup(category);
1321         if (!handle->category) {
1322                 ErrPrint("Error: %s\n", strerror(errno));
1323                 return LB_STATUS_ERROR_MEMORY;
1324         }
1325
1326         return LB_STATUS_SUCCESS;
1327 }
1328
1329 PUBLIC void *script_create(const char *file, const char *group)
1330 {
1331         struct info *handle;
1332
1333         handle = calloc(1, sizeof(*handle));
1334         if (!handle) {
1335                 ErrPrint("Error: %s\n", strerror(errno));
1336                 return NULL;
1337         }
1338
1339         handle->file = strdup(file);
1340         if (!handle->file) {
1341                 ErrPrint("Error: %s\n", strerror(errno));
1342                 free(handle);
1343                 return NULL;
1344         }
1345
1346         handle->group = strdup(group);
1347         if (!handle->group) {
1348                 ErrPrint("Error: %s\n", strerror(errno));
1349                 free(handle->file);
1350                 free(handle);
1351                 return NULL;
1352         }
1353
1354         s_info.handle_list = eina_list_append(s_info.handle_list, handle);
1355
1356         return handle;
1357 }
1358
1359 PUBLIC int script_destroy(void *_handle)
1360 {
1361         struct info *handle;
1362         Evas_Object *edje;
1363
1364         handle = _handle;
1365
1366         if (!eina_list_data_find(s_info.handle_list, handle)) {
1367                 DbgPrint("Not found (already deleted?)\n");
1368                 return LB_STATUS_ERROR_NOT_EXIST;
1369         }
1370
1371         s_info.handle_list = eina_list_remove(s_info.handle_list, handle);
1372
1373         edje = eina_list_nth(handle->obj_list, 0);
1374         if (edje)
1375                 evas_object_del(edje);
1376
1377         free(handle->category);
1378         free(handle->file);
1379         free(handle->group);
1380         free(handle);
1381         return LB_STATUS_SUCCESS;
1382 }
1383
1384 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
1385 {
1386         struct info *handle;
1387         Evas_Object *edje;
1388         struct obj_info *obj_info;
1389
1390         handle = _handle;
1391
1392         obj_info = calloc(1, sizeof(*obj_info));
1393         if (!obj_info) {
1394                 ErrPrint("Heap: %s\n", strerror(errno));
1395                 return LB_STATUS_ERROR_MEMORY;
1396         }
1397
1398         obj_info->parent = evas_object_rectangle_add(e);
1399         if (!obj_info->parent) {
1400                 ErrPrint("Unable to create a parent box\n");
1401                 free(obj_info);
1402                 return LB_STATUS_ERROR_FAULT;
1403         }
1404
1405         edje = elm_layout_add(obj_info->parent);
1406         if (!edje) {
1407                 ErrPrint("Failed to create an edje object\n");
1408                 evas_object_del(obj_info->parent);
1409                 free(obj_info);
1410                 return LB_STATUS_ERROR_FAULT;
1411         }
1412
1413         if (!elm_layout_file_set(edje, handle->file, handle->group)) {
1414                 int err;
1415                 const char *errmsg;
1416
1417                 err = edje_object_load_error_get(elm_layout_edje_get(edje));
1418                 errmsg = edje_load_error_str(err);
1419                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
1420                 evas_object_del(edje);
1421                 evas_object_del(obj_info->parent);
1422                 free(obj_info);
1423                 return LB_STATUS_ERROR_IO;
1424         }
1425
1426         handle->e = e;
1427         handle->w = w;
1428         handle->h = h;
1429
1430         elm_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
1431         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
1432         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1433         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1434         evas_object_resize(edje, handle->w, handle->h);
1435         evas_object_show(edje);
1436         evas_object_data_set(edje, "obj_info", obj_info);
1437
1438         handle->obj_list = eina_list_append(handle->obj_list, edje);
1439         return LB_STATUS_SUCCESS;
1440 }
1441
1442 PUBLIC int script_unload(void *_handle, Evas *e)
1443 {
1444         struct info *handle;
1445         Evas_Object *edje;
1446         Evas_Object *parent = NULL;
1447
1448         handle = _handle;
1449
1450         edje = eina_list_nth(handle->obj_list, 0);
1451         if (edje) {
1452                 struct obj_info *obj_info;
1453
1454                 obj_info = evas_object_data_get(edje, "obj_info");
1455                 if (obj_info)
1456                         parent = obj_info->parent;
1457                 evas_object_del(edje);
1458         }
1459
1460         if (parent) {
1461                 DbgPrint("Delete parent box\n");
1462                 evas_object_del(parent);
1463         }
1464
1465         handle->e = NULL;
1466         return LB_STATUS_SUCCESS;
1467 }
1468
1469 static void access_cb(keynode_t *node, void *user_data)
1470 {
1471         int state;
1472
1473         if (!node) {
1474                 if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &state) != 0) {
1475                         ErrPrint("Idle lock state is not valid\n");
1476                         state = 0; /* DISABLED */
1477                 }
1478         } else {
1479                 state = vconf_keynode_get_bool(node);
1480         }
1481
1482         DbgPrint("ELM CONFIG ACCESS: %d\n", state);
1483         elm_config_access_set(state);
1484 }
1485
1486 static void update_font_cb(void *data)
1487 {
1488         elm_config_font_overlay_set(TEXT_CLASS, s_info.font_name, DEFAULT_FONT_SIZE);
1489         DbgPrint("Update text class %s (%s, %d)\n", TEXT_CLASS, s_info.font_name, DEFAULT_FONT_SIZE);
1490 }
1491
1492 static void font_changed_cb(keynode_t *node, void *user_data)
1493 {
1494         char *font_name;
1495
1496         if (s_info.font_name) {
1497                 font_name = vconf_get_str("db/setting/accessibility/font_name");
1498                 if (!font_name) {
1499                         ErrPrint("Invalid font name (NULL)\n");
1500                         return;
1501                 }
1502
1503                 if (!strcmp(s_info.font_name, font_name)) {
1504                         DbgPrint("Font is not changed (Old: %s(%p) <> New: %s(%p))\n", s_info.font_name, s_info.font_name, font_name, font_name);
1505                         free(font_name);
1506                         return;
1507                 }
1508
1509                 DbgPrint("Release old font name: %s(%p)\n", s_info.font_name, s_info.font_name);
1510                 free(s_info.font_name);
1511         } else {
1512                 int ret;
1513
1514                 /*!
1515                  * Get the first font name using system_settings API.
1516                  */
1517                 font_name = NULL;
1518                 ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_FONT_TYPE, &font_name);
1519                 if (ret != SYSTEM_SETTINGS_ERROR_NONE || !font_name) {
1520                         ErrPrint("System setting get: %d, font_name[%p]\n", ret, font_name);
1521                         return;
1522                 }
1523         }
1524
1525         s_info.font_name = font_name;
1526         DbgPrint("Font name is changed to %s(%p)\n", s_info.font_name, s_info.font_name);
1527
1528         /*!
1529          * \NOTE
1530          * Try to update all liveboxes
1531          */
1532         update_font_cb(NULL);
1533 }
1534
1535 static inline int convert_font_size(int size)
1536 {
1537         switch (size) {
1538         case SYSTEM_SETTINGS_FONT_SIZE_SMALL:
1539                 size = -80;
1540                 break;
1541         case SYSTEM_SETTINGS_FONT_SIZE_NORMAL:
1542                 size = -100;
1543                 break;
1544         case SYSTEM_SETTINGS_FONT_SIZE_LARGE:
1545                 size = -150;
1546                 break;
1547         case SYSTEM_SETTINGS_FONT_SIZE_HUGE:
1548                 size = -190;
1549                 break;
1550         case SYSTEM_SETTINGS_FONT_SIZE_GIANT:
1551                 size = -250;
1552                 break;
1553         default:
1554                 size = -100;
1555                 break;
1556         }
1557
1558         DbgPrint("Return size: %d\n", size);
1559         return size;
1560 }
1561
1562 static void font_size_cb(system_settings_key_e key, void *user_data)
1563 {
1564         int size;
1565
1566         if (system_settings_get_value_int(SYSTEM_SETTINGS_KEY_FONT_SIZE, &size) != SYSTEM_SETTINGS_ERROR_NONE)
1567                 return;
1568
1569         size = convert_font_size(size);
1570
1571         if (size == s_info.font_size) {
1572                 DbgPrint("Font size is not changed\n");
1573                 return;
1574         }
1575
1576         s_info.font_size = size;
1577         DbgPrint("Font size is changed to %d, but don't update the font info\n", size);
1578 }
1579
1580 PUBLIC int script_init(void)
1581 {
1582         int ret;
1583         char *argv[] = {
1584                 "livebox.edje",
1585                 NULL,
1586         };
1587
1588         /* ecore is already initialized */
1589         elm_init(1, argv);
1590         elm_config_scale_set(scale_get());
1591
1592         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb, NULL);
1593         DbgPrint("TTS changed: %d\n", ret);
1594
1595         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_changed_cb, NULL);
1596         DbgPrint("System font is changed: %d\n", ret);
1597         
1598         ret = system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_FONT_SIZE, font_size_cb, NULL);
1599         DbgPrint("System font size is changed: %d\n", ret);
1600
1601         access_cb(NULL, NULL);
1602         font_changed_cb(NULL, NULL);
1603         font_size_cb(SYSTEM_SETTINGS_KEY_FONT_SIZE, NULL);
1604         return LB_STATUS_SUCCESS;
1605 }
1606
1607 PUBLIC int script_fini(void)
1608 {
1609         int ret;
1610         Eina_List *l;
1611         Eina_List *n;
1612         struct info *handle;
1613
1614         EINA_LIST_FOREACH_SAFE(s_info.handle_list, l, n, handle) {
1615                 script_destroy(handle);
1616         }
1617
1618         ret = system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_FONT_SIZE);
1619         DbgPrint("Unset font size change event callback: %d\n", ret);
1620
1621         ret = vconf_ignore_key_changed("db/setting/accessibility/font_name", font_changed_cb);
1622         DbgPrint("Unset font name change event callback: %d\n", ret);
1623
1624         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb);
1625         DbgPrint("Unset tts: %d\n", ret);
1626
1627         elm_shutdown();
1628
1629         free(s_info.font_name);
1630         s_info.font_name = NULL;
1631         return LB_STATUS_SUCCESS;
1632 }
1633
1634 /* End of a file */