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