Sync with the private repository
[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.0 (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://www.tizenopensource.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 <dlog.h>
33 #include <debug.h>
34 #include <vconf.h>
35 #include <livebox-errno.h>
36 #include <livebox-service.h>
37
38 #include "script_port.h"
39
40 #define TEXT_CLASS      "tizen"
41 #define BASE_WIDTH      720.0f
42
43 #define PUBLIC __attribute__((visibility("default")))
44
45 struct image_option {
46         int orient;
47         int aspect;
48         enum {
49                 FILL_DISABLE,
50                 FILL_IN_SIZE,
51                 FILL_OVER_SIZE,
52         } fill;
53
54         int width;
55         int height;
56 };
57
58 struct info {
59         char *file;
60         char *group;
61         char *category;
62         int w;
63         int h;
64
65         Evas *e;
66
67         Eina_List *obj_list;
68 };
69
70 struct child {
71         Evas_Object *obj;
72         char *part;
73 };
74
75 struct obj_info {
76         char *id;
77         Eina_List *children;
78         Evas_Object *win;
79         Eina_List *access_chain;
80 };
81
82 static inline double scale_get(void)
83 {
84         int width;
85         int height;
86         ecore_x_window_size_get(0, &width, &height);
87         return (double)width / BASE_WIDTH;
88 }
89
90 static inline Evas_Object *find_edje(struct info *handle, const char *id)
91 {
92         Eina_List *l;
93         Evas_Object *edje;
94         struct obj_info *obj_info;
95
96         EINA_LIST_FOREACH(handle->obj_list, l, edje) {
97                 obj_info = evas_object_data_get(edje, "obj_info");
98                 if (!obj_info) {
99                         ErrPrint("Object info is not valid\n");
100                         continue;
101                 }
102
103                 if (!id) {
104                         if (!obj_info->id)
105                                 return edje;
106
107                         continue;
108                 } else if (!obj_info->id) {
109                         continue;
110                 }
111
112                 if (!strcmp(obj_info->id, id))
113                         return edje;
114         }
115
116         DbgPrint("EDJE[%s] is not found\n", id);
117         return NULL;
118 }
119
120 static inline void rebuild_focus_chain(Evas_Object *obj)
121 {
122         struct obj_info *obj_info;
123         Evas_Object *ao;
124         Eina_List *l;
125
126         obj_info = evas_object_data_get(obj, "obj_info");
127         if (!obj_info) {
128                 ErrPrint("Object info is not available\n");
129                 return;
130         }
131
132         elm_object_focus_custom_chain_unset(obj);
133
134         DbgPrint("Rebuild focus chain begin\n");
135         EINA_LIST_FOREACH(obj_info->access_chain, l, ao) {
136                 DbgPrint("Append %p\n", ao);
137                 elm_object_focus_custom_chain_append(obj, ao, NULL);
138         }
139         DbgPrint("Rebuild focus chain done\n");
140 }
141
142 PUBLIC const char *script_magic_id(void)
143 {
144         return "edje";
145 }
146
147 PUBLIC int script_update_color(void *h, Evas *e, const char *id, const char *part, const char *rgba)
148 {
149         struct info *handle = h;
150         Evas_Object *edje;
151         int r[3], g[3], b[3], a[3];
152         int ret;
153
154         edje = find_edje(handle, id);
155         if (!edje)
156                 return LB_STATUS_ERROR_NOT_EXIST;
157
158         ret = sscanf(rgba, "%d %d %d %d %d %d %d %d %d %d %d %d",
159                                         r, g, b, a,                     /* OBJECT */
160                                         r + 1, g + 1, b + 1, a + 1,     /* OUTLINE */
161                                         r + 2, g + 2, b + 2, a + 2);    /* SHADOW */
162         if (ret != 12) {
163                 DbgPrint("id[%s] part[%s] rgba[%s]\n", id, part, rgba);
164                 return LB_STATUS_ERROR_INVALID;
165         }
166
167         ret = edje_object_color_class_set(elm_layout_edje_get(edje), part,
168                                 r[0], g[0], b[0], a[0], /* OBJECT */
169                                 r[1], g[1], b[1], a[1], /* OUTLINE */
170                                 r[2], g[2], b[2], a[2]); /* SHADOW */
171
172         DbgPrint("EDJE[%s] color class is %s changed", id, ret == EINA_TRUE ? "successfully" : "not");
173         return LB_STATUS_SUCCESS;
174 }
175
176 PUBLIC int script_update_text(void *h, Evas *e, const char *id, const char *part, const char *text)
177 {
178         struct obj_info *obj_info;
179         struct info *handle = h;
180         Evas_Object *edje;
181         Evas_Object *to;
182
183         edje = find_edje(handle, id);
184         if (!edje) {
185                 ErrPrint("Failed to find EDJE\n");
186                 return LB_STATUS_ERROR_NOT_EXIST;
187         }
188
189         obj_info = evas_object_data_get(edje, "obj_info");
190         if (!obj_info) {
191                 ErrPrint("Object info is not available\n");
192                 return LB_STATUS_ERROR_FAULT;
193         }
194
195         elm_object_part_text_set(edje, part, text);
196
197         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
198         if (to) {
199                 Evas_Object *ao;
200
201                 ao = evas_object_data_get(to, "ao");
202                 if (ao) {
203                         /* Update Access Info */
204                         elm_access_info_set(ao, ELM_ACCESS_INFO, text);
205                         DbgPrint("[%s] Update access info: (%s)\n", part, text);
206                 } else {
207                         ao = elm_access_object_register(to, edje);
208                         if (!ao) {
209                                 ErrPrint("Failed to add access object\n");
210                         } else {
211                                 char *utf8;
212                                 utf8 = elm_entry_markup_to_utf8(text);
213                                 if (utf8) {
214                                         DbgPrint("[%s] Text is converted to [%s]\n", part, utf8);
215                                         elm_access_info_set(ao, ELM_ACCESS_INFO, utf8);
216                                         free(utf8);
217                                 } else {
218                                         DbgPrint("[%s] Unable to convert text to utf8: [%s]\n", part, text);
219                                         elm_access_info_set(ao, ELM_ACCESS_INFO, text);
220                                 }
221
222                                 obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
223                                 evas_object_data_set(to, "ao", ao);
224                                 elm_object_focus_custom_chain_append(edje, ao, NULL);
225                         }
226                 }
227         } else {
228                 ErrPrint("Unable to get text part[%s]\n", part);
229         }
230
231         return LB_STATUS_SUCCESS;
232 }
233
234 static void parse_aspect(struct image_option *img_opt, const char *value, int len)
235 {
236         while (len > 0 && *value == ' ') {
237                 value++;
238                 len--;
239         }
240
241         if (len < 4)
242                 return;
243
244         img_opt->aspect = !strncasecmp(value, "true", 4);
245         DbgPrint("Parsed ASPECT: %d (%s)\n", img_opt->aspect, value);
246 }
247
248 static void parse_orient(struct image_option *img_opt, const char *value, int len)
249 {
250         while (len > 0 && *value == ' ') {
251                 value++;
252                 len--;
253         }
254
255         if (len < 4)
256                 return;
257
258         img_opt->orient = !strncasecmp(value, "true", 4);
259         DbgPrint("Parsed ORIENT: %d (%s)\n", img_opt->aspect, value);
260 }
261
262 static void parse_size(struct image_option *img_opt, const char *value, int len)
263 {
264         int width;
265         int height;
266         char *buf;
267
268         while (len > 0 && *value == ' ') {
269                 value++;
270                 len--;
271         }
272
273         buf = strndup(value, len);
274         if (!buf) {
275                 ErrPrint("Heap: %s\n", strerror(errno));
276                 return;
277         }
278
279         if (sscanf(buf, "%dx%d", &width, &height) == 2) {
280                 img_opt->width = width;
281                 img_opt->height = height;
282                 DbgPrint("Parsed size : %dx%d (%s)\n", width, height, buf);
283         } else {
284                 DbgPrint("Invalid size tag[%s]\n", buf);
285         }
286
287         free(buf);
288 }
289
290 static void parse_fill(struct image_option *img_opt, const char *value, int len)
291 {
292         while (len > 0 && *value == ' ') {
293                 value++;
294                 len--;
295         }
296
297         if (!strncasecmp(value, "in-size", len))
298                 img_opt->fill = FILL_IN_SIZE;
299         else if (!strncasecmp(value, "over-size", len))
300                 img_opt->fill = FILL_OVER_SIZE;
301         else
302                 img_opt->fill = FILL_DISABLE;
303
304         DbgPrint("Parsed FILL: %d (%s)\n", img_opt->fill, value);
305 }
306
307 static inline void parse_image_option(const char *option, struct image_option *img_opt)
308 {
309         const char *ptr;
310         const char *cmd;
311         const char *value;
312         struct {
313                 const char *cmd;
314                 void (*handler)(struct image_option *img_opt, const char *value, int len);
315         } cmd_list[] = {
316                 {
317                         .cmd = "aspect", /* Keep the aspect ratio */
318                         .handler = parse_aspect,
319                 },
320                 {
321                         .cmd = "orient", /* Keep the orientation value: for the rotated images */
322                         .handler = parse_orient,
323                 },
324                 {
325                         .cmd = "fill", /* Fill the image to its container */
326                         .handler = parse_fill, /* Value: in-size, over-size, disable(default) */
327                 },
328                 {
329                         .cmd = "size",
330                         .handler = parse_size,
331                 },
332         };
333         enum {
334                 STATE_START,
335                 STATE_TOKEN,
336                 STATE_DATA,
337                 STATE_IGNORE,
338                 STATE_ERROR,
339                 STATE_END,
340         } state;
341         int idx;
342         int tag;
343
344         if (!option || !*option)
345                 return;
346
347         state = STATE_START;
348         /*!
349          * \note
350          * GCC 4.7 warnings uninitialized idx and tag value.
351          * But it will be initialized by the state machine. :(
352          * Anyway, I just reset idx and tag for reducing the GCC4.7 complains.
353          */
354         idx = 0;
355         tag = 0;
356         cmd = NULL;
357         value = NULL;
358
359         for (ptr = option; state != STATE_END; ptr++) {
360                 switch (state) {
361                 case STATE_START:
362                         if (*ptr == '\0') {
363                                 state = STATE_END;
364                                 continue;
365                         }
366
367                         if (isalpha(*ptr)) {
368                                 state = STATE_TOKEN;
369                                 ptr--;
370                         }
371                         tag = 0;
372                         idx = 0;
373
374                         cmd = cmd_list[tag].cmd;
375                         break;
376                 case STATE_IGNORE:
377                         if (*ptr == '=') {
378                                 state = STATE_DATA;
379                                 value = ptr;
380                         } else if (*ptr == '\0') {
381                                 state = STATE_END;
382                         }
383                         break;
384                 case STATE_TOKEN:
385                         if (cmd[idx] == '\0' && (*ptr == ' ' || *ptr == '\t' || *ptr == '=')) {
386                                 if (*ptr == '=') {
387                                         value = ptr;
388                                         state = STATE_DATA;
389                                 } else {
390                                         state = STATE_IGNORE;
391                                 }
392                                 idx = 0;
393                         } else if (*ptr == '\0') {
394                                 state = STATE_END;
395                         } else if (cmd[idx] == *ptr) {
396                                 idx++;
397                         } else {
398                                 ptr -= (idx + 1);
399
400                                 tag++;
401                                 if (tag == sizeof(cmd_list) / sizeof(cmd_list[0])) {
402                                         tag = 0;
403                                         state = STATE_ERROR;
404                                 } else {
405                                         cmd = cmd_list[tag].cmd;
406                                 }
407                                 idx = 0;
408                         }
409                         break;
410                 case STATE_DATA:
411                         if (*ptr == ';' || *ptr == '\0') {
412                                 cmd_list[tag].handler(img_opt, value + 1, idx);
413                                 state = *ptr ? STATE_START : STATE_END;
414                         } else {
415                                 idx++;
416                         }
417                         break;
418                 case STATE_ERROR:
419                         if (*ptr == ';')
420                                 state = STATE_START;
421                         else if (*ptr == '\0')
422                                 state = STATE_END;
423                         break;
424                 default:
425                         break;
426                 }
427         }
428 }
429
430 PUBLIC int script_update_access(void *_h, Evas *e, const char *id, const char *part, const char *text, const char *option)
431 {
432         struct info *handle = _h;
433         Evas_Object *edje;
434         struct obj_info *obj_info;
435         Evas_Object *to;
436
437         edje = find_edje(handle, id);
438         if (!edje) {
439                 ErrPrint("No such object: %s\n", id);
440                 return LB_STATUS_ERROR_NOT_EXIST;
441         }
442
443         obj_info = evas_object_data_get(edje, "obj_info");
444         if (!obj_info) {
445                 ErrPrint("Object info is not available\n");
446                 return LB_STATUS_ERROR_FAULT;
447         }
448
449         to = (Evas_Object *)edje_object_part_object_get(elm_layout_edje_get(edje), part);
450         if (to) {
451                 Evas_Object *ao;
452
453                 ao = evas_object_data_get(to, "ao");
454                 if (ao) {
455                         DbgPrint("[%s] Update access object (%s)\n", part, text);
456                         elm_access_info_set(ao, ELM_ACCESS_INFO, text);
457                 } else {
458                         ao = elm_access_object_register(to, edje);
459                         if (!ao) {
460                                 ErrPrint("Unable to register access object\n");
461                         } else {
462                                 elm_access_info_set(ao, ELM_ACCESS_INFO, text);
463                                 obj_info->access_chain = eina_list_append(obj_info->access_chain, ao);
464                                 evas_object_data_set(to, "ao", ao);
465                                 elm_object_focus_custom_chain_append(edje, ao, NULL);
466                                 DbgPrint("[%s] Register access info: (%s)\n", part, text);
467                         }
468                 }
469         } else {
470                 ErrPrint("[%s] is not exists\n", part);
471         }
472
473         return LB_STATUS_SUCCESS;
474 }
475
476 PUBLIC int script_update_image(void *_h, Evas *e, const char *id, const char *part, const char *path, const char *option)
477 {
478         struct info *handle = _h;
479         Evas_Load_Error err;
480         Evas_Object *edje;
481         Evas_Object *img;
482         Evas_Coord w, h;
483         struct obj_info *obj_info;
484         struct child *child;
485         struct image_option img_opt = {
486                 .aspect = 0,
487                 .orient = 0,
488                 .fill = FILL_DISABLE,
489                 .width = -1,
490                 .height = -1,
491         };
492
493         edje = find_edje(handle, id);
494         if (!edje) {
495                 ErrPrint("No such object: %s\n", id);
496                 return LB_STATUS_ERROR_NOT_EXIST;
497         }
498
499         obj_info = evas_object_data_get(edje, "obj_info");
500         if (!obj_info) {
501                 ErrPrint("Object info is not available\n");
502                 return LB_STATUS_ERROR_FAULT;
503         }
504
505         img = elm_object_part_content_unset(edje, part);
506         if (img) {
507                 Eina_List *l;
508                 Eina_List *n;
509                 Evas_Object *ao;
510
511                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
512                         if (child->obj != img)
513                                 continue;
514
515                         obj_info->children = eina_list_remove(obj_info->children, child);
516                         free(child->part);
517                         free(child);
518                         break;
519                 }
520
521                 DbgPrint("delete object %s %p\n", part, img);
522                 ao = evas_object_data_del(img, "ao");
523                 if (ao) {
524                         elm_access_object_unregister(ao);
525                         obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
526                         DbgPrint("Successfully unregistered\n");
527                 }
528                 evas_object_del(img);
529
530                 rebuild_focus_chain(edje);
531         }
532
533         if (!path || !strlen(path) || access(path, R_OK) != 0) {
534                 DbgPrint("SKIP - Path: [%s]\n", path);
535                 return LB_STATUS_SUCCESS;
536         }
537
538         child = malloc(sizeof(*child));
539         if (!child) {
540                 ErrPrint("Heap: %s\n", strerror(errno));
541                 return LB_STATUS_ERROR_MEMORY;
542         }
543
544         child->part = strdup(part);
545         if (!child->part) {
546                 ErrPrint("Heap: %s\n", strerror(errno));
547                 free(child);
548                 return LB_STATUS_ERROR_MEMORY;
549         }
550
551         img = evas_object_image_add(e);
552         if (!img) {
553                 ErrPrint("Failed to add an image object\n");
554                 free(child->part);
555                 free(child);
556                 return LB_STATUS_ERROR_FAULT;
557         }
558
559         evas_object_image_preload(img, EINA_FALSE);
560         parse_image_option(option, &img_opt);
561         evas_object_image_load_orientation_set(img, img_opt.orient);
562
563         evas_object_image_file_set(img, path, NULL);
564         err = evas_object_image_load_error_get(img);
565         if (err != EVAS_LOAD_ERROR_NONE) {
566                 ErrPrint("Load error: %s\n", evas_load_error_str(err));
567                 evas_object_del(img);
568                 free(child->part);
569                 free(child);
570                 return LB_STATUS_ERROR_IO;
571         }
572
573         evas_object_image_size_get(img, &w, &h);
574         if (img_opt.aspect) {
575                 if (img_opt.fill == FILL_OVER_SIZE) {
576                         Evas_Coord part_w;
577                         Evas_Coord part_h;
578
579                         if (img_opt.width >= 0 && img_opt.height >= 0) {
580                                 part_w = img_opt.width * scale_get();
581                                 part_h = img_opt.height * scale_get();
582                         } else {
583                                 part_w = 0;
584                                 part_h = 0;
585                                 edje_object_part_geometry_get(elm_layout_edje_get(edje), part, NULL, NULL, &part_w, &part_h);
586                         }
587                         DbgPrint("Original %dx%d (part: %dx%d)\n", w, h, part_w, part_h);
588
589                         if (part_w > w || part_h > h) {
590                                 double fw;
591                                 double fh;
592
593                                 fw = (double)part_w / (double)w;
594                                 fh = (double)part_h / (double)h;
595
596                                 if (fw > fh) {
597                                         w = part_w;
598                                         h = (double)h * fw;
599                                 } else {
600                                         h = part_h;
601                                         w = (double)w * fh;
602                                 }
603                         }
604                         DbgPrint("Size: %dx%d\n", w, h);
605
606                         evas_object_image_load_size_set(img, w, h);
607                         evas_object_image_load_region_set(img, (w - part_w) / 2, (h - part_h) / 2, part_w, part_h);
608                         evas_object_image_fill_set(img, 0, 0, part_w, part_h);
609                         evas_object_image_reload(img);
610                 } else {
611                         evas_object_image_fill_set(img, 0, 0, w, h);
612                         evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
613                         evas_object_size_hint_aspect_set(img, EVAS_ASPECT_CONTROL_BOTH, w, h);
614                 }
615         } else {
616                 if (img_opt.width >= 0 && img_opt.height >= 0) {
617                         w = img_opt.width;
618                         h = img_opt.height;
619                         DbgPrint("Using given image size: %dx%d\n", w, h);
620                 }
621
622                 evas_object_image_fill_set(img, 0, 0, w, h);
623                 evas_object_size_hint_fill_set(img, EVAS_HINT_FILL, EVAS_HINT_FILL);
624                 evas_object_size_hint_weight_set(img, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
625         }
626
627         /*!
628          * \note
629          * object will be shown by below statement automatically
630          */
631         DbgPrint("%s part swallow image %p (%dx%d)\n", part, img, w, h);
632         child->obj = img;
633         elm_object_part_content_set(edje, part, img);
634         obj_info->children = eina_list_append(obj_info->children, child);
635
636         /*!
637          * \note
638          * This object is not registered as an access object.
639          * So the developer should add it to access list manually, using DESC_ACCESS block.
640          */
641         return LB_STATUS_SUCCESS;
642 }
643
644 static void script_signal_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
645 {
646         struct info *handle = data;
647         Evas_Coord w;
648         Evas_Coord h;
649         Evas_Coord px = 0;
650         Evas_Coord py = 0;
651         Evas_Coord pw = 0;
652         Evas_Coord ph = 0;
653         double sx;
654         double sy;
655         double ex;
656         double ey;
657
658         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
659         edje_object_part_geometry_get(elm_layout_edje_get(obj), source, &px, &py, &pw, &ph);
660
661         sx = ex = 0.0f;
662         if (w) {
663                 sx = (double)px / (double)w;
664                 ex = (double)(px + pw) / (double)w;
665         }
666
667         sy = ey = 0.0f;
668         if (h) {
669                 sy = (double)py / (double)h;
670                 ey = (double)(py + ph) / (double)h;
671         }
672
673         DbgPrint("Signal emit: source[%s], emission[%s]\n", source, emission);
674         script_signal_emit(handle->e, source, emission, sx, sy, ex, ey);
675 }
676
677 static void edje_del_cb(void *_info, Evas *e, Evas_Object *obj, void *event_info)
678 {
679         struct info *handle = _info;
680         struct obj_info *obj_info;
681         struct child *child;
682         Evas_Object *ao;
683
684         handle->obj_list = eina_list_remove(handle->obj_list, obj);
685
686         obj_info = evas_object_data_del(obj, "obj_info");
687         if (!obj_info) {
688                 ErrPrint("Object info is not valid\n");
689                 return;
690         }
691
692         DbgPrint("delete object %s %p\n", obj_info->id, obj);
693
694         elm_object_signal_callback_del(obj, "*", "*", script_signal_cb);
695
696         elm_object_focus_custom_chain_unset(obj);
697
698         EINA_LIST_FREE(obj_info->children, child) {
699                 DbgPrint("delete object %s %p\n", child->part, child->obj);
700                 if (child->obj) {
701                         Evas_Object *ao;
702                         ao = evas_object_data_del(child->obj, "ao");
703                         if (ao) {
704                                 obj_info->access_chain = eina_list_remove(obj_info->access_chain, ao);
705                                 elm_access_object_unregister(ao);
706                         }
707                         evas_object_del(child->obj);
708                 }
709                 free(child->part);
710                 free(child);
711         }
712
713         EINA_LIST_FREE(obj_info->access_chain, ao) {
714                 elm_access_object_unregister(ao);
715         }
716
717         free(obj_info->id);
718         free(obj_info);
719 }
720
721 /*!
722         LB_ACCESS_HIGHLIGHT             0
723         LB_ACCESS_HIGHLIGHT_NEXT        1
724         LB_ACCESS_HIGHLIGHT_PREV        2
725         LB_ACCESS_ACTIVATE              3
726         LB_ACCESS_VALUE_CHANGE          4
727         LB_ACCESS_SCROLL                5
728 */
729 PUBLIC int script_feed_event(void *h, Evas *e, int event_type, int x, int y, double timestamp)
730 {
731         struct info *handle = h;
732         Evas_Object *edje;
733         struct obj_info *obj_info;
734         int ret = LB_STATUS_SUCCESS;
735
736         DbgPrint("event: %d, x: %d, y: %d\n", event_type, x, y);
737
738         edje = find_edje(handle, NULL); /*!< Get the base layout */
739         if (!edje) {
740                 ErrPrint("Base layout is not exist\n");
741                 return LB_STATUS_ERROR_NOT_EXIST;
742         }
743
744         obj_info = evas_object_data_get(edje, "obj_info");
745         if (!obj_info) {
746                 ErrPrint("Object info is not valid\n");
747                 return LB_STATUS_ERROR_INVALID;
748         }
749
750         if (event_type & LB_SCRIPT_ACCESS_EVENT) {
751                 Elm_Access_Action_Info *info;
752                 Elm_Access_Action_Type action;
753
754                 info = malloc(sizeof(*info));
755                 if (!info) {
756                         ErrPrint("Error: %s\n", strerror(errno));
757                         return LB_STATUS_ERROR_MEMORY;
758                 }
759
760                 {
761                         const Eina_List *chain;
762                         chain = elm_object_focus_custom_chain_get(edje);
763                         DbgPrint("Focus chain : %d\n", eina_list_count(chain));
764                 }
765
766                 switch (event_type) {
767                 case LB_SCRIPT_ACCESS_HIGHLIGHT: /*!< LB_ACCESS_HIGHLIGHT */
768                         action = ELM_ACCESS_ACTION_HIGHLIGHT;
769                         info->x = x;
770                         info->y = y;
771                         ret = elm_access_action(edje, action, info);
772                         DbgPrint("ACCESS_HIGHLIGHT: %dx%d returns %d\n", x, y, ret);
773                         if (ret == EINA_FALSE)
774                                 ret = LB_ACCESS_STATUS_ERROR;
775                         else
776                                 ret = LB_ACCESS_STATUS_DONE;
777                         break;
778                 case LB_SCRIPT_ACCESS_HIGHLIGHT_NEXT: /*!< LB_ACCESS_HIGHLIGHT_NEXT */
779                         action = ELM_ACCESS_ACTION_HIGHLIGHT_NEXT;
780                         info->highlight_cycle = EINA_FALSE;
781                         ret = elm_access_action(edje, action, info);
782                         DbgPrint("ACCESS_HIGHLIGHT_NEXT, returns %d\n", ret);
783                         if (ret == EINA_FALSE)
784                                 ret = LB_ACCESS_STATUS_LAST;
785                         else
786                                 ret = LB_ACCESS_STATUS_DONE;
787                         break;
788                 case LB_SCRIPT_ACCESS_HIGHLIGHT_PREV: /*!< LB_ACCESS_HIGHLIGHT_PREV */
789                         action = ELM_ACCESS_ACTION_HIGHLIGHT_PREV;
790                         info->highlight_cycle = EINA_FALSE;
791                         ret = elm_access_action(edje, action, info);
792                         DbgPrint("ACCESS_HIGHLIGHT_PREV, returns %d\n", ret);
793                         if (ret == EINA_FALSE)
794                                 ret = LB_ACCESS_STATUS_FIRST;
795                         else
796                                 ret = LB_ACCESS_STATUS_DONE;
797                         break;
798                 case LB_SCRIPT_ACCESS_ACTIVATE: /*!< LB_ACCESS_ACTIVATE */
799                         action = ELM_ACCESS_ACTION_ACTIVATE;
800                         ret = elm_access_action(edje, action, info);
801                         DbgPrint("ACCESS_HIGHLIGHT_ACTIVATE, returns %d\n", ret);
802                         if (ret == EINA_FALSE)
803                                 ret = LB_ACCESS_STATUS_ERROR;
804                         else
805                                 ret = LB_ACCESS_STATUS_DONE;
806                         break;
807                 case LB_SCRIPT_ACCESS_VALUE_CHANGE: /*!< LB_ACCESS_VALUE_CHANGE */
808                         action = ELM_ACCESS_ACTION_VALUE_CHANGE;
809                         ret = elm_access_action(edje, action, info);
810                         DbgPrint("ACCESS_HIGHLIGHT_VALUE_CHANGE, returns %d\n", ret);
811                         if (ret == EINA_FALSE)
812                                 ret = LB_ACCESS_STATUS_ERROR;
813                         else
814                                 ret = LB_ACCESS_STATUS_DONE;
815                         break;
816                 case LB_SCRIPT_ACCESS_SCROLL: /*!< LB_ACCESS_SCROLL */
817                         action = ELM_ACCESS_ACTION_SCROLL;
818                         ret = elm_access_action(edje, action, info);
819                         DbgPrint("ACCESS_HIGHLIGHT_SCROLL, returns %d\n", ret);
820                         if (ret == EINA_FALSE)
821                                 ret = LB_ACCESS_STATUS_ERROR;
822                         else
823                                 ret = LB_ACCESS_STATUS_DONE;
824                         break;
825                 case LB_SCRIPT_ACCESS_UNHIGHLIGHT:
826                         action = ELM_ACCESS_ACTION_UNHIGHLIGHT;
827                         ret = elm_access_action(edje, action, info);
828                         DbgPrint("ACCESS_UNHIGHLIGHT, returns %d\n", ret);
829                         if (ret == EINA_FALSE)
830                                 ret = LB_ACCESS_STATUS_ERROR;
831                         else
832                                 ret = LB_ACCESS_STATUS_DONE;
833                         break;
834                 default:
835                         DbgPrint("Invalid event\n");
836                         ret = LB_ACCESS_STATUS_ERROR;
837                 }
838
839                 free(info);
840         } else if (event_type & LB_SCRIPT_MOUSE_EVENT) {
841                 switch (event_type) {
842                 case LB_SCRIPT_MOUSE_DOWN:
843                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
844                         evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, timestamp + 0.01f, NULL);
845                         break;
846                 case LB_SCRIPT_MOUSE_MOVE:
847                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
848                         break;
849                 case LB_SCRIPT_MOUSE_UP:
850                         evas_event_feed_mouse_move(e, x, y, timestamp, NULL);
851                         evas_event_feed_mouse_up(e, 1, EVAS_BUTTON_NONE, timestamp + 0.1f, NULL);
852                         break;
853                 case LB_SCRIPT_MOUSE_IN:
854                         evas_event_feed_mouse_in(e, timestamp, NULL);
855                         break;
856                 case LB_SCRIPT_MOUSE_OUT:
857                         evas_event_feed_mouse_out(e, timestamp, NULL);
858                         break;
859                 default:
860                         return LB_STATUS_ERROR_INVALID;
861                 }
862         } else if (event_type & LB_SCRIPT_KEY_EVENT) {
863                 DbgPrint("Key event is not implemented\n");
864                 return LB_STATUS_ERROR_NOT_IMPLEMENTED;
865         }
866
867         return ret;
868 }
869
870 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)
871 {
872         struct info *handle = h;
873         Evas_Object *edje;
874         Evas_Object *obj;
875         struct obj_info *obj_info;
876         struct child *child;
877
878         DbgPrint("src_id[%s] target_id[%s] part[%s] path[%s] group[%s]\n", src_id, target_id, part, path, group);
879
880         edje = find_edje(handle, src_id);
881         if (!edje) {
882                 ErrPrint("Edje is not exists\n");
883                 return LB_STATUS_ERROR_NOT_EXIST;
884         }
885
886         obj_info = evas_object_data_get(edje, "obj_info");
887         if (!obj_info) {
888                 ErrPrint("Object info is not valid\n");
889                 return LB_STATUS_ERROR_INVALID;
890         }
891
892         obj = elm_object_part_content_unset(edje, part);
893         if (obj) {
894                 Eina_List *l;
895                 Eina_List *n;
896
897                 EINA_LIST_FOREACH_SAFE(obj_info->children, l, n, child) {
898                         if (child->obj != obj)
899                                 continue;
900
901                         obj_info->children = eina_list_remove(obj_info->children, child);
902
903                         free(child->part);
904                         free(child);
905                         break;
906                 }
907
908                 DbgPrint("delete object %s %p\n", part, obj);
909                 /*!
910                  * \note
911                  * This will call the edje_del_cb.
912                  * It will delete all access objects
913                  */
914                 evas_object_del(obj);
915         }
916
917         if (!path || !strlen(path) || access(path, R_OK) != 0) {
918                 DbgPrint("SKIP - Path: [%s]\n", path);
919                 return LB_STATUS_SUCCESS;
920         }
921
922         obj = elm_layout_add(edje);
923         if (!obj) {
924                 ErrPrint("Failed to add a new edje object\n");
925                 return LB_STATUS_ERROR_FAULT;
926         }
927
928         if (!elm_layout_file_set(obj, path, group)) {
929                 int err;
930                 const char *errmsg;
931
932                 err = edje_object_load_error_get(elm_layout_edje_get(obj));
933                 errmsg = edje_load_error_str(err);
934                 ErrPrint("Could not load %s from %s: %s\n", group, path, errmsg);
935                 evas_object_del(obj);
936                 return LB_STATUS_ERROR_IO;
937         }
938
939         evas_object_show(obj);
940
941         obj_info = calloc(1, sizeof(*obj_info));
942         if (!obj_info) {
943                 ErrPrint("Failed to add a obj_info\n");
944                 evas_object_del(obj);
945                 return LB_STATUS_ERROR_MEMORY;
946         }
947
948         obj_info->id = strdup(target_id);
949         if (!obj_info->id) {
950                 ErrPrint("Failed to add a obj_info\n");
951                 free(obj_info);
952                 evas_object_del(obj);
953                 return LB_STATUS_ERROR_MEMORY;
954         }
955
956         child = malloc(sizeof(*child));
957         if (!child) {
958                 ErrPrint("Error: %s\n", strerror(errno));
959                 free(obj_info->id);
960                 free(obj_info);
961                 evas_object_del(obj);
962                 return LB_STATUS_ERROR_MEMORY;
963         }
964
965         child->part = strdup(part);
966         if (!child->part) {
967                 ErrPrint("Error: %s\n", strerror(errno));
968                 free(child);
969                 free(obj_info->id);
970                 free(obj_info);
971                 evas_object_del(obj);
972                 return LB_STATUS_ERROR_MEMORY;
973         }
974
975         child->obj = obj;
976
977         evas_object_data_set(obj, "obj_info", obj_info);
978         evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, edje_del_cb, handle);
979         elm_object_signal_callback_add(obj, "*", "*", script_signal_cb, handle);
980         handle->obj_list = eina_list_append(handle->obj_list, obj);
981
982         DbgPrint("%s part swallow edje %p\n", part, obj);
983         elm_object_part_content_set(edje, part, obj);
984         obj_info = evas_object_data_get(edje, "obj_info");
985         obj_info->children = eina_list_append(obj_info->children, child);
986         return LB_STATUS_SUCCESS;
987 }
988
989 PUBLIC int script_update_signal(void *h, Evas *e, const char *id, const char *part, const char *signal)
990 {
991         struct info *handle = h;
992         Evas_Object *edje;
993
994         DbgPrint("id[%s], part[%s], signal[%s]\n", id, part, signal);
995
996         edje = find_edje(handle, id);
997         if (!edje)
998                 return LB_STATUS_ERROR_NOT_EXIST;
999
1000         elm_object_signal_emit(edje, signal, part);
1001         return LB_STATUS_SUCCESS;
1002 }
1003
1004 PUBLIC int script_update_drag(void *h, Evas *e, const char *id, const char *part, double x, double y)
1005 {
1006         struct info *handle = h;
1007         Evas_Object *edje;
1008
1009         DbgPrint("id[%s], part[%s], %lfx%lf\n", id, part, x, y);
1010
1011         edje = find_edje(handle, id);
1012         if (!edje)
1013                 return LB_STATUS_ERROR_NOT_EXIST;
1014
1015         edje_object_part_drag_value_set(elm_layout_edje_get(edje), part, x, y);
1016         return LB_STATUS_SUCCESS;
1017 }
1018
1019 PUBLIC int script_update_size(void *han, Evas *e, const char *id, int w, int h)
1020 {
1021         struct info *handle = han;
1022         Evas_Object *edje;
1023
1024         edje = find_edje(handle, id);
1025         if (!edje)
1026                 return LB_STATUS_ERROR_NOT_EXIST;
1027
1028         if (!id) {
1029                 handle->w = w;
1030                 handle->h = h;
1031         }
1032
1033         DbgPrint("Resize object to %dx%d\n", w, h);
1034         evas_object_resize(edje, w, h);
1035         return LB_STATUS_SUCCESS;
1036 }
1037
1038 PUBLIC int script_update_category(void *h, Evas *e, const char *id, const char *category)
1039 {
1040         struct info *handle = h;
1041
1042         DbgPrint("id[%s], category[%s]\n", id, category);
1043
1044         if (handle->category) {
1045                 free(handle->category);
1046                 handle->category = NULL;
1047         }
1048
1049         if (!category)
1050                 return LB_STATUS_SUCCESS;
1051
1052         handle->category = strdup(category);
1053         if (!handle->category) {
1054                 ErrPrint("Error: %s\n", strerror(errno));
1055                 return LB_STATUS_ERROR_MEMORY;
1056         }
1057
1058         return LB_STATUS_SUCCESS;
1059 }
1060
1061 PUBLIC void *script_create(const char *file, const char *group)
1062 {
1063         struct info *handle;
1064
1065         DbgPrint("file[%s], group[%s]\n", file, group);
1066
1067         handle = calloc(1, sizeof(*handle));
1068         if (!handle) {
1069                 ErrPrint("Error: %s\n", strerror(errno));
1070                 return NULL;
1071         }
1072
1073         handle->file = strdup(file);
1074         if (!handle->file) {
1075                 ErrPrint("Error: %s\n", strerror(errno));
1076                 free(handle);
1077                 return NULL;
1078         }
1079
1080         handle->group = strdup(group);
1081         if (!handle->group) {
1082                 ErrPrint("Error: %s\n", strerror(errno));
1083                 free(handle->file);
1084                 free(handle);
1085                 return NULL;
1086         }
1087
1088         return handle;
1089 }
1090
1091 PUBLIC int script_destroy(void *_handle)
1092 {
1093         struct info *handle;
1094         Evas_Object *edje;
1095
1096         handle = _handle;
1097
1098         edje = eina_list_nth(handle->obj_list, 0);
1099         if (edje)
1100                 evas_object_del(edje);
1101
1102         free(handle->category);
1103         free(handle->file);
1104         free(handle->group);
1105         free(handle);
1106         return LB_STATUS_SUCCESS;
1107 }
1108
1109 PUBLIC int script_load(void *_handle, Evas *e, int w, int h)
1110 {
1111         struct info *handle;
1112         Evas_Object *edje;
1113         struct obj_info *obj_info;
1114
1115         handle = _handle;
1116
1117         obj_info = calloc(1, sizeof(*obj_info));
1118         if (!obj_info) {
1119                 ErrPrint("Heap: %s\n", strerror(errno));
1120                 return LB_STATUS_ERROR_MEMORY;
1121         }
1122
1123         obj_info->win = evas_object_rectangle_add(e);
1124         if (!obj_info->win) {
1125                 free(obj_info);
1126                 return LB_STATUS_ERROR_FAULT;
1127         }
1128
1129         edje = elm_layout_add(obj_info->win);
1130         if (!edje) {
1131                 ErrPrint("Failed to create an edje object\n");
1132                 evas_object_del(obj_info->win);
1133                 free(obj_info);
1134                 return LB_STATUS_ERROR_FAULT;
1135         }
1136
1137         DbgPrint("Load edje: %s - %s\n", handle->file, handle->group);
1138         if (!elm_layout_file_set(edje, handle->file, handle->group)) {
1139                 int err;
1140                 const char *errmsg;
1141
1142                 err = edje_object_load_error_get(elm_layout_edje_get(edje));
1143                 errmsg = edje_load_error_str(err);
1144                 ErrPrint("Could not load %s from %s: %s\n", handle->group, handle->file, errmsg);
1145                 evas_object_del(edje);
1146                 evas_object_del(obj_info->win);
1147                 free(obj_info);
1148                 return LB_STATUS_ERROR_IO;
1149         }
1150
1151         handle->e = e;
1152         handle->w = w;
1153         handle->h = h;
1154
1155         elm_object_signal_callback_add(edje, "*", "*", script_signal_cb, handle);
1156         evas_object_event_callback_add(edje, EVAS_CALLBACK_DEL, edje_del_cb, handle);
1157         evas_object_size_hint_weight_set(edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1158         evas_object_size_hint_fill_set(edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1159         evas_object_resize(edje, handle->w, handle->h);
1160         evas_object_show(edje);
1161         evas_object_data_set(edje, "obj_info", obj_info);
1162
1163         handle->obj_list = eina_list_append(handle->obj_list, edje);
1164         return LB_STATUS_SUCCESS;
1165 }
1166
1167 PUBLIC int script_unload(void *_handle, Evas *e)
1168 {
1169         struct info *handle;
1170         Evas_Object *edje;
1171
1172         handle = _handle;
1173
1174         DbgPrint("Unload edje: %s - %s\n", handle->file, handle->group);
1175         edje = eina_list_nth(handle->obj_list, 0);
1176         if (edje)
1177                 evas_object_del(edje);
1178         handle->e = NULL;
1179         return LB_STATUS_SUCCESS;
1180 }
1181
1182 static void access_cb(keynode_t *node, void *user_data)
1183 {
1184         int state;
1185
1186         if (!node) {
1187                 if (vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &state) != 0) {
1188                         ErrPrint("Idle lock state is not valid\n");
1189                         state = 0; /* DISABLED */
1190                 }
1191         } else {
1192                 state = vconf_keynode_get_bool(node);
1193         }
1194
1195         elm_config_access_set(state);
1196 }
1197
1198 PUBLIC int script_init(void)
1199 {
1200         int ret;
1201         char *argv[] = {
1202                 "livebox.edje",
1203                 NULL,
1204         };
1205         /* ecore is already initialized */
1206         elm_init(1, argv);
1207         elm_config_scale_set(scale_get());
1208
1209         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb, NULL);
1210         if (ret < 0)
1211                 ErrPrint("Failed to access cb\n");
1212
1213         access_cb(NULL, NULL);
1214         return LB_STATUS_SUCCESS;
1215 }
1216
1217 PUBLIC int script_fini(void)
1218 {
1219         vconf_ignore_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, access_cb);
1220         elm_shutdown();
1221         return LB_STATUS_SUCCESS;
1222 }
1223
1224 /* End of a file */