diff --git a/legacy/edje/src/lib/edje_callbacks.c b/legacy/edje/src/lib/edje_callbacks.c index fa0f8622ab..3c235b3708 100644 --- a/legacy/edje/src/lib/edje_callbacks.c +++ b/legacy/edje/src/lib/edje_callbacks.c @@ -128,13 +128,17 @@ _edje_timer_cb(void *data) double t; Evas_List *l; Evas_List *animl = NULL; + Edje *ed; t = ecore_time_get(); for (l = _edje_animators; l; l = l->next) - animl = evas_list_append(animl, l->data); + { + ed = l->data; + _edje_ref(ed); + animl = evas_list_append(animl, l->data); + } while (animl) { - Edje *ed; Evas_List *newl = NULL; ed = animl->data; @@ -151,6 +155,7 @@ _edje_timer_cb(void *data) _edje_program_run_iterate(runp, t); } _edje_thaw(ed); + _edje_unref(ed); } if (_edje_anim_count > 0) return 1; _edje_timer = NULL; diff --git a/legacy/edje/src/lib/edje_load.c b/legacy/edje/src/lib/edje_load.c index 3138c40bb3..17d0346519 100644 --- a/legacy/edje/src/lib/edje_load.c +++ b/legacy/edje/src/lib/edje_load.c @@ -72,6 +72,8 @@ edje_file_set(Evas_Object *obj, const char *file, const char *part) ed); evas_object_data_set(rp->object, "real_part", rp); } + else + evas_object_pass_events_set(rp->object, 1); evas_object_clip_set(rp->object, ed->clipper); evas_object_show(rp->object); rp->part = ep; @@ -89,7 +91,10 @@ edje_file_set(Evas_Object *obj, const char *file, const char *part) { rp->clip_to = evas_list_nth(ed->parts, rp->part->clip_to_id); if (rp->clip_to) - evas_object_clip_set(rp->object, rp->clip_to->object); + { + evas_object_pass_events_set(rp->clip_to->object, 1); + evas_object_clip_set(rp->object, rp->clip_to->object); + } } } ed->dirty = 1; @@ -110,7 +115,6 @@ _edje_file_add(Edje *ed) Evas_List *l; int id = -1; - /* FIXME: look in hash table first */ ed->file = evas_hash_find(_edje_file_hash, ed->path); if (ed->file) { @@ -128,7 +132,7 @@ _edje_file_add(Edje *ed) ed->file->path = strdup(ed->path); if (!ed->file->collection_dir) { - /* FIXME: free up ed->file */ + _edje_file_free(ed->file); ed->file = NULL; goto out; } @@ -167,6 +171,13 @@ _edje_file_add(Edje *ed) ed->collection->references = 1; ed->file->collection_hash = evas_hash_add(ed->file->collection_hash, ed->part, ed->collection); } + else + { + ed->file->references--; + if (ed->file->references <= 0) + _edje_file_free(ed->file); + ed->file = NULL; + } } out: if (ef) eet_close(ef); @@ -206,8 +217,16 @@ _edje_file_del(Edje *ed) } if (ed->actions) { -// printf("FIXME: leak!\n"); - ed->actions = NULL; + while (ed->actions) + { + Edje_Running_Program *runp; + + _edje_anim_count--; + runp = ed->actions->data; + ed->actions = evas_list_remove(ed->actions, runp); + free(runp); + } + _edje_animators = evas_list_remove(_edje_animators, ed); } } diff --git a/legacy/edje/src/lib/edje_main.c b/legacy/edje/src/lib/edje_main.c index 0967180312..e1fb85f6c3 100644 --- a/legacy/edje/src/lib/edje_main.c +++ b/legacy/edje/src/lib/edje_main.c @@ -24,6 +24,9 @@ _edje_add(Evas_Object *obj) evas_object_color_set(ed->clipper, 255, 255, 255, 255); evas_object_move(ed->clipper, 0, 0); evas_object_resize(ed->clipper, 0, 0); + evas_object_pass_events_set(ed->clipper, 1); + ed->have_objects = 1; + ed->references = 1; return ed; } @@ -31,9 +34,60 @@ void _edje_del(Edje *ed) { _edje_file_del(ed); + _edje_clean_objects(ed); if (ed->path) free(ed->path); if (ed->part) free(ed->part); - evas_object_del(ed->clipper); - printf("FIXME: leak: ed->callbacks\n"); + while (ed->callbacks) + { + Edje_Signal_Callback *escb; + + escb = ed->callbacks->data; + ed->callbacks = evas_list_remove(ed->callbacks, escb); + free(escb->signal); + free(escb->source); + free(escb); + } free(ed); } + +void +_edje_clean_part_objects(Edje *ed) +{ + Evas_List *l; + + for (l = ed->parts; l; l = l->next) + { + Edje_Real_Part *rp; + + rp = l->data; + evas_object_del(rp->object); + rp->object = NULL; + } +} + +void +_edje_clean_objects(Edje *ed) +{ + Evas_List *l; + + ed->have_objects = 0; + _edje_clean_part_objects(ed); + evas_object_del(ed->clipper); + ed->evas = NULL; + ed->obj = NULL; + ed->clipper = NULL; +} + +void +_edje_ref(Edje *ed) +{ + ed->references++; +} + +void +_edje_unref(Edje *ed) +{ + ed->references--; + if (ed->references <= 0) + _edje_del(ed); +} diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 87970175aa..3a85dd62e3 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -12,7 +12,6 @@ /* FIXME: * add a smooth scale option to fill params - * reference count programs since the tmp lists can be screwed if a program is ended by another * need "random" signals and events for hooking to, and "random" durations * free stuff - no more leaks * dragables have to work @@ -24,19 +23,17 @@ * text and color classes need to work * reduce linked list walking and list_nth calls * named parts need to be able to be "replaced" with new evas objects + * part replacement with object callbacks should be possible * real part size and "before min/max limit" sizes need to be stored per part * need to be able to calculate min & max size of a whole edje - * add code to list collections in an eet file + * need to be able to list collections in an eet file * externally sourced images need to be supported in edje_cc and edje - * part replacement with object callbacks should be possible * part queries for geometry etc. * need to be able to "pause" edjes from API * need to be able to force anim times to 0.0 from API to turn off animation - * need to detect relative loops - * need to detect clip_to loops + * need to detect relative part loops + * need to detect clip_to part loops * need to detect anim time 0.0 loops - * need to check frametime 0.0 works - * need to check mouse_events flag works * edje_cc should be able to force lossy, lossless, min and max quality and compression of encoded images * edje_cc needs to prune out unused images * edje_cc might need an option for limiting number of tween images @@ -342,6 +339,10 @@ struct _Edje double x, y, w, h; unsigned char dirty : 1; unsigned char recalc : 1; + unsigned char walking_callbacks : 1; + unsigned char delete_callbacks : 1; + unsigned char just_added_callbacks : 1; + unsigned char have_objects : 1; Evas *evas; /* the evas this edje belongs to */ Evas_Object *obj; /* the smart object */ Evas_Object *clipper; /* a big rect to clip this edje to */ @@ -351,6 +352,7 @@ struct _Edje Evas_List *actions; /* currently running actions */ Evas_List *callbacks; int freeze; + int references; }; struct _Edje_Real_Part @@ -396,6 +398,8 @@ struct _Edje_Signal_Callback char *source; void (*func) (void *data, Evas_Object *o, const char *emission, const char *source); void *data; + int just_added : 1; + int delete_me : 1; }; struct _Edje_Calc_Params @@ -440,7 +444,11 @@ void _edje_collection_free(Edje_Part_Collection *ec); Edje *_edje_add(Evas_Object *obj); void _edje_del(Edje *ed); - +void _edje_clean_part_objects(Edje *ed); +void _edje_clean_objects(Edje *ed); +void _edje_ref(Edje *ed); +void _edje_unref(Edje *ed); + int _edje_program_run_iterate(Edje_Running_Program *runp, double tim); void _edje_program_end(Edje *ed, Edje_Running_Program *runp); void _edje_program_run(Edje *ed, Edje_Program *pr); diff --git a/legacy/edje/src/lib/edje_program.c b/legacy/edje/src/lib/edje_program.c index 22b6f585a5..ab2f5fe4e7 100644 --- a/legacy/edje/src/lib/edje_program.c +++ b/legacy/edje/src/lib/edje_program.c @@ -41,6 +41,11 @@ edje_signal_callback_add(Evas_Object *obj, const char *emission, const char *sou escb->func = func; escb->data = data; ed->callbacks = evas_list_append(ed->callbacks, escb); + if (ed->walking_callbacks) + { + escb->just_added = 1; + ed->just_added_callbacks = 1; + } } void * @@ -64,9 +69,18 @@ edje_signal_callback_del(Evas_Object *obj, const char *emission, const char *sou void *data; data = escb->data; - free(escb->signal); - free(escb->source); - free(escb); + if (ed->walking_callbacks) + { + escb->delete_me = 1; + ed->delete_callbacks = 1; + } + else + { + ed->callbacks = evas_list_remove_list(ed->callbacks, l); + free(escb->signal); + free(escb->source); + free(escb); + } return data; } } @@ -92,6 +106,7 @@ _edje_program_run_iterate(Edje_Running_Program *runp, double tim) double t, total; Evas_List *l; + _edje_ref(runp->edje); _edje_freeze(runp->edje); t = tim - runp->start_time; total = runp->program->tween.time; @@ -143,11 +158,13 @@ _edje_program_run_iterate(Edje_Running_Program *runp, double tim) if (pr) _edje_program_run(runp->edje, pr); } _edje_thaw(runp->edje); + _edje_unref(runp->edje); free(runp); return 0; } _edje_recalc(runp->edje); _edje_thaw(runp->edje); + _edje_unref(runp->edje); return 1; } @@ -156,6 +173,7 @@ _edje_program_end(Edje *ed, Edje_Running_Program *runp) { Evas_List *l; + _edje_ref(runp->edje); _edje_freeze(runp->edje); for (l = runp->program->targets; l; l = l->next) { @@ -183,6 +201,7 @@ _edje_program_end(Edje *ed, Edje_Running_Program *runp) _edje_animators = evas_list_remove(_edje_animators, runp->edje); _edje_emit(runp->edje, "program,stop", runp->program->name); _edje_thaw(runp->edje); + _edje_unref(runp->edje); free(runp); } @@ -192,6 +211,7 @@ _edje_program_run(Edje *ed, Edje_Program *pr) Evas_List *l; _edje_freeze(ed); + _edje_ref(ed); _edje_emit(ed, "program,start", pr->name); if (pr->action == EDJE_ACTION_TYPE_STATE_SET) { @@ -280,6 +300,7 @@ _edje_program_run(Edje *ed, Edje_Program *pr) { _edje_emit(ed, pr->state, pr->state2); } + _edje_unref(ed); _edje_thaw(ed); } @@ -290,6 +311,7 @@ _edje_emit(Edje *ed, char *sig, char *src) static Evas_List *emissions = NULL; Edje_Emission *ee; + _edje_ref(ed); _edje_freeze(ed); printf("EMIT \"%s\" \"%s\"\n", sig, src); ee = calloc(1, sizeof(Edje_Emission)); @@ -300,6 +322,7 @@ _edje_emit(Edje *ed, char *sig, char *src) { emissions = evas_list_append(emissions, ee); _edje_thaw(ed); + _edje_unref(ed); return; } else @@ -319,14 +342,41 @@ _edje_emit(Edje *ed, char *sig, char *src) (_edje_glob_match(ee->source, pr->source))) _edje_program_run(ed, pr); } + ed->walking_callbacks = 1; for (l = ed->callbacks; l; l = l->next) { Edje_Signal_Callback *escb; escb = l->data; - if ((_edje_glob_match(ee->signal, escb->signal)) && + if ((!escb->just_added) && + (!escb->delete_me) && + (_edje_glob_match(ee->signal, escb->signal)) && (_edje_glob_match(ee->source, escb->source))) - escb->func(escb->data, ed->obj, ee->signal, ee->source); + escb->func(escb->data, ed->obj, ee->signal, ee->source); + } + ed->walking_callbacks = 0; + if ((ed->delete_callbacks) || (ed->just_added_callbacks)) + { + ed->delete_callbacks = 0; + ed->just_added_callbacks = 0; + for (l = ed->callbacks; l;) + { + Edje_Signal_Callback *escb; + Evas_List *next_l; + + escb = l->data; + next_l = l->next; + if (escb->just_added) + escb->just_added = 0; + if (escb->delete_me) + { + ed->callbacks = evas_list_remove_list(ed->callbacks, l); + free(escb->signal); + free(escb->source); + free(escb); + } + l = next_l; + } } } free(ee->signal); @@ -334,4 +384,5 @@ _edje_emit(Edje *ed, char *sig, char *src) free(ee); } _edje_thaw(ed); + _edje_unref(ed); } diff --git a/legacy/edje/src/lib/edje_smart.c b/legacy/edje/src/lib/edje_smart.c index 15b5d96a24..e6675b7d0a 100644 --- a/legacy/edje/src/lib/edje_smart.c +++ b/legacy/edje/src/lib/edje_smart.c @@ -65,7 +65,8 @@ _edje_smart_del(Evas_Object * obj) ed = evas_object_smart_data_get(obj); if (!ed) return; - _edje_del(ed); + _edje_clean_objects(ed); + _edje_unref(ed); } static void