From b7221512d5bb99f0924a847e8bc7fdb30c5183d4 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Tue, 12 Mar 2013 23:48:42 +0900 Subject: [PATCH] This causes segv's on 64bit! Program received signal SIGSEGV, Segmentation fault. _edje_emit_cb (ed=ed@entry=0x8ebd68, sig=sig@entry=0x8fba4c "focus,part,in", src=src@entry=0x8222fc "elm.text", data=data@entry=0x0, prop=prop@entry=0 '\000') at lib/edje/edje_program.c:1442 warning: Source file is more recent than executable. 1442 eina_list_free(data.matches); (gdb) bt "focus,part,in", src=src@entry=0x8222fc "elm.text", data=data@entry=0x0, prop=prop@entry=0 '\000') at lib/edje/edje_program.c:1442 "focus,part,in", src=0x8222fc "elm.text", sdata=0x0, prop=0 '\000') at lib/edje/edje_program.c:1366 _pd=0x8222f0, list=0x7fff00000001) at lib/edje/edje_message_queue.c:124 op_type=EO_OP_TYPE_REGULAR, op=564, p_list=0x7fffffffcf28) at lib/eo/eo.c:364 op_type=EO_OP_TYPE_REGULAR, obj=0x8ebae0) at lib/eo/eo.c:404 op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:435 (obj=) at lib/edje/edje_message_queue.c:71 (sid=sid@entry=0x8eae88) at elm_interface_scrollable.c:788 (sid=0x8eae88) at elm_interface_scrollable.c:805 _pd=0x8eae88, list=) at elm_interface_scrollable.c:3370 op_type=EO_OP_TYPE_REGULAR, op=840, p_list=0x7fffffffd158) at lib/eo/eo.c:364 op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404 op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:435 _pd=0x8ead70, list=) at elm_entry.c:2804 op_type=EO_OP_TYPE_REGULAR, op=129, p_list=0x7fffffffd328) at lib/eo/eo.c:364 op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404 lib/eo/eo.c:435 op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd4a8) at lib/eo/eo.c:364 (obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR, op=1) at lib/eo/eo.c:463 class_data=, list=) at elm_widget.c:5526 op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd628) at lib/eo/eo.c:364 (obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR, op=1) at lib/eo/eo.c:463 out>, list=) at elm_layout.c:2157 op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd7b8) at lib/eo/eo.c:364 op_type=, op=1) at lib/eo/eo.c:463 op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffd928) at lib/eo/eo.c:364 (obj=obj@entry=0x8ea9e0, op_type=op_type@entry=EO_OP_TYPE_REGULAR, op=1) at lib/eo/eo.c:463 out>, list=) at elm_entry.c:3076 op_type=EO_OP_TYPE_REGULAR, op=1, p_list=0x7fffffffdad8) at lib/eo/eo.c:364 op_type=EO_OP_TYPE_REGULAR, obj=0x8ea9e0) at lib/eo/eo.c:404 lib/eo/eo.c:1162 elm_entry.c:3068 autorun=0x0) at test.c:441 Revert "edje: reduce memory usage of Edje signal callbacks and automates." This reverts commit 15aae2c0a4b9f59199395884439626de39e80e62. --- src/Makefile_Edje.am | 3 +- src/lib/edje/Edje.h | 19 +- src/lib/edje/edje_main.c | 11 +- src/lib/edje/edje_match.c | 248 +++++++------------ src/lib/edje/edje_private.h | 96 ++------ src/lib/edje/edje_program.c | 307 +++++++++++++++-------- src/lib/edje/edje_signal.c | 477 ------------------------------------ src/lib/edje/edje_smart.c | 2 + 8 files changed, 356 insertions(+), 807 deletions(-) delete mode 100644 src/lib/edje/edje_signal.c diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am index 20ec55288b..db4534ac2a 100644 --- a/src/Makefile_Edje.am +++ b/src/Makefile_Edje.am @@ -46,8 +46,7 @@ lib/edje/edje_smart.c \ lib/edje/edje_text.c \ lib/edje/edje_textblock_styles.c \ lib/edje/edje_util.c \ -lib/edje/edje_var.c \ -lib/edje/edje_signal.c +lib/edje/edje_var.c lib_edje_libedje_la_CPPFLAGS = $(EDJE_COMMON_CPPFLAGS) lib_edje_libedje_la_LIBADD = @EDJE_LIBS@ diff --git a/src/lib/edje/Edje.h b/src/lib/edje/Edje.h index 5a5afe5460..c678ee7872 100644 --- a/src/lib/edje/Edje.h +++ b/src/lib/edje/Edje.h @@ -893,6 +893,7 @@ enum EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, + EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL, EDJE_OBJ_SUB_ID_SIGNAL_EMIT, EDJE_OBJ_SUB_ID_PLAY_SET, EDJE_OBJ_SUB_ID_PLAY_GET, @@ -2708,7 +2709,23 @@ enum * * @see edje_object_signal_callback_del */ -#define edje_obj_signal_callback_del(emission, source, func, data, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(void **, ret) +#define edje_obj_signal_callback_del(emission, source, func, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void **, ret) + +/** + * @def edje_obj_signal_callback_del_full + * @since 1.8 + * + * @brief Unregister/delete a callback set for an arriving Edje + * + * @param[in] emission + * @param[in] source + * @param[in] func + * @param[in] data + * @param[out] ret + * + * @see edje_object_signal_callback_del_full + */ +#define edje_obj_signal_callback_del_full(emission, source, func, data, ret) EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL), EO_TYPECHECK(const char *, emission), EO_TYPECHECK(const char *, source), EO_TYPECHECK(Edje_Signal_Cb, func), EO_TYPECHECK(void *, data), EO_TYPECHECK(void **, ret) /** * @def edje_obj_signal_emit diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c index 2d0dc8b497..74b1349ee8 100644 --- a/src/lib/edje/edje_main.c +++ b/src/lib/edje/edje_main.c @@ -68,7 +68,6 @@ edje_init(void) _edje_module_init(); _edje_message_init(); _edje_multisense_init(); - edje_signal_init(); _edje_real_part_mp = eina_mempool_add("chained_mempool", "Edje_Real_Part", NULL, @@ -135,7 +134,6 @@ _edje_shutdown_core(void) _edje_real_part_state_mp = NULL; _edje_real_part_mp = NULL; - edje_signal_shutdown(); _edje_multisense_shutdown(); _edje_message_shutdown(); _edje_module_shutdown(); @@ -226,6 +224,7 @@ _edje_del(Edje *ed) { Edje_Running_Program *runp; Edje_Pending_Program *pp; + Edje_Signal_Callback *escb; Edje_Text_Class *tc; Edje_Text_Insert_Filter_Callback *cb; @@ -235,7 +234,7 @@ _edje_del(Edje *ed) return; } _edje_message_del(ed); - _edje_signal_callback_free(ed->callbacks); + _edje_callbacks_patterns_clean(ed); _edje_file_del(ed); if (ed->path) eina_stringshare_del(ed->path); if (ed->group) eina_stringshare_del(ed->group); @@ -250,6 +249,12 @@ _edje_del(Edje *ed) free(runp); EINA_LIST_FREE(ed->pending_actions, pp) free(pp); + EINA_LIST_FREE(ed->callbacks, escb) + { + if (escb->signal) eina_stringshare_del(escb->signal); + if (escb->source) eina_stringshare_del(escb->source); + free(escb); + } eina_hash_free(ed->color_classes); EINA_LIST_FREE(ed->text_classes, tc) { diff --git a/src/lib/edje/edje_match.c b/src/lib/edje/edje_match.c index 40e609d2bd..558d982ff4 100644 --- a/src/lib/edje/edje_match.c +++ b/src/lib/edje/edje_match.c @@ -377,66 +377,6 @@ _edje_match_patterns_exec_init_states(Edje_States *states, return r; \ } -#define EDJE_MATCH_INIT_INARRAY(Func, Source, Show) \ - Edje_Patterns* \ - Func(const Eina_Inarray *array, const Edje_Signal_Callback_Match *matches) \ - { \ - Edje_Patterns *r; \ - int *it; \ - size_t i = 0; \ - \ - if (!matches) \ - return NULL; \ - \ - r = malloc(sizeof (Edje_Patterns) + \ - eina_inarray_count(array) \ - * sizeof(*r->finals) \ - * sizeof(*r->patterns)); \ - if (!r) return NULL; \ - \ - r->ref = 1; \ - r->delete_me = EINA_FALSE; \ - r->patterns_size = eina_inarray_count(array); \ - r->max_length = 0; \ - r->patterns = (const char **) r->finals + r->patterns_size + 1; \ - \ - EINA_INARRAY_FOREACH(array, it) \ - { \ - const char *str; \ - size_t j; \ - int special = 0; \ - \ - str = (matches + *it)->Source; \ - if (!str) str = ""; \ - r->patterns[i] = str; \ - \ - if (Show) \ - INF("%lu [%s]", (unsigned long)i, str); \ - \ - r->finals[i] = 0; \ - for (j = 0; str[j]; ++j) \ - if (str[j] != '*') \ - { \ - r->finals[i] = j + 1; \ - special++; \ - } \ - j += special ? special + 1 : 0; \ - \ - if (j > r->max_length) \ - r->max_length = j; \ - \ - i++; \ - } \ - \ - if (!_edje_match_states_alloc(r, 2)) \ - { \ - free(r); \ - return NULL; \ - } \ - \ - return r; \ - } - EDJE_MATCH_INIT_LIST(edje_match_collection_dir_init, Edje_Part_Collection_Directory_Entry, entry, 0); @@ -446,10 +386,12 @@ EDJE_MATCH_INIT_ARRAY(edje_match_programs_signal_init, EDJE_MATCH_INIT_ARRAY(edje_match_programs_source_init, Edje_Program, source, 0); -EDJE_MATCH_INIT_INARRAY(edje_match_callback_signal_init, - signal, 0); -EDJE_MATCH_INIT_INARRAY(edje_match_callback_source_init, - source, 0); +EDJE_MATCH_INIT_LIST(edje_match_callback_signal_init, + Edje_Signal_Callback, + signal, 0); +EDJE_MATCH_INIT_LIST(edje_match_callback_source_init, + Edje_Signal_Callback, + source, 0); static Eina_Bool _edje_match_collection_dir_exec_finals(const size_t *finals, @@ -507,18 +449,20 @@ edje_match_programs_exec_check_finals(const size_t *signal_finals, } static int -edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp, - const Edje_Signal_Callback_Match *matches, - const void **custom_data, - const Eina_Bool *flags, +edje_match_callback_exec_check_finals(const Edje_Patterns *signal_ppat, + const Edje_Patterns *source_ppat, + const size_t *signal_finals, + const size_t *source_finals, const Edje_States *signal_states, const Edje_States *source_states, const char *sig, const char *source, + Eina_List *callbacks, Edje *ed, - Eina_Bool prop) + Eina_Bool prop + ) { - const Edje_Signal_Callback_Match *cb; + Edje_Signal_Callback *escb; Eina_Array run; size_t i; size_t j; @@ -527,39 +471,39 @@ edje_match_callback_exec_check_finals(const Edje_Signals_Sources_Patterns *ssp, eina_array_step_set(&run, sizeof (Eina_Array), 4); for (i = 0; i < signal_states->size; ++i) - if (signal_states->states[i].pos >= ssp->signals_patterns->finals[signal_states->states[i].idx]) - { - for (j = 0; j < source_states->size; ++j) - { - if (signal_states->states[i].idx == source_states->states[j].idx - && source_states->states[j].pos >= ssp->sources_patterns->finals[source_states->states[j].idx]) - { - int *e; - - e = eina_inarray_nth(&ssp->u.callbacks.globing, signal_states->states[i].idx); - - cb = &matches[*e]; - if (cb) - { - if ((prop) && _edje_signal_callback_prop(flags, *e)) continue; - eina_array_push(&run, cb); - r = 2; - } - } - } - } - - while ((cb = eina_array_pop(&run))) { - int idx = cb - matches; + if (signal_states->states[i].pos >= signal_finals[signal_states->states[i].idx]) + { + for (j = 0; j < source_states->size; ++j) + { + if (signal_states->states[i].idx == source_states->states[j].idx + && source_states->states[j].pos >= source_finals[source_states->states[j].idx]) + { + escb = eina_list_nth(callbacks, signal_states->states[i].idx); + if (escb) + { + if ((prop) && (escb->propagate)) continue; + if ((!escb->just_added) + && (!escb->delete_me)) + { + eina_array_push(&run, escb); + r = 2; + } + } + } + } + } + } - cb->func((void*) custom_data[idx], ed->obj, sig, source); + while ((escb = eina_array_pop(&run))) + { + escb->func(escb->data, ed->obj, sig, source); if (_edje_block_break(ed)) { r = 0; break; } - if ((ssp->signals_patterns->delete_me) || (ssp->sources_patterns->delete_me)) + if ((signal_ppat->delete_me) || (source_ppat->delete_me)) { r = 0; break; @@ -682,49 +626,50 @@ edje_match_programs_exec(const Edje_Patterns *ppat_signal, } int -edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp, - const Edje_Signal_Callback_Match *matches, - const void **custom_data, - const Eina_Bool *flags, - const char *sig, - const char *source, - Edje *ed, - Eina_Bool prop) +edje_match_callback_exec(Edje_Patterns *ppat_signal, + Edje_Patterns *ppat_source, + const char *sig, + const char *source, + Eina_List *callbacks, + Edje *ed, + Eina_Bool prop + ) { Edje_States *signal_result; Edje_States *source_result; int r = 0; /* under high memory presure, they could be NULL */ - if (!ssp->sources_patterns || !ssp->signals_patterns) return 0; + if (!ppat_source || !ppat_signal) return 0; - ssp->signals_patterns->ref++; - ssp->sources_patterns->ref++; - _edje_match_patterns_exec_init_states(ssp->signals_patterns->states, - ssp->signals_patterns->patterns_size, - ssp->signals_patterns->max_length); - _edje_match_patterns_exec_init_states(ssp->sources_patterns->states, - ssp->sources_patterns->patterns_size, - ssp->sources_patterns->max_length); + ppat_signal->ref++; + ppat_source->ref++; + _edje_match_patterns_exec_init_states(ppat_signal->states, + ppat_signal->patterns_size, + ppat_signal->max_length); + _edje_match_patterns_exec_init_states(ppat_source->states, + ppat_source->patterns_size, + ppat_source->max_length); - signal_result = _edje_match_fn(ssp->signals_patterns, sig, ssp->signals_patterns->states); - source_result = _edje_match_fn(ssp->sources_patterns, source, ssp->sources_patterns->states); + signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states); + source_result = _edje_match_fn(ppat_source, source, ppat_source->states); if (signal_result && source_result) - r = edje_match_callback_exec_check_finals(ssp, - matches, - custom_data, - flags, - signal_result, - source_result, - sig, - source, - ed, - prop); - ssp->signals_patterns->ref--; - ssp->sources_patterns->ref--; - if (ssp->signals_patterns->ref <= 0) edje_match_patterns_free(ssp->signals_patterns); - if (ssp->sources_patterns->ref <= 0) edje_match_patterns_free(ssp->sources_patterns); + r = edje_match_callback_exec_check_finals(ppat_signal, + ppat_source, + ppat_signal->finals, + ppat_source->finals, + signal_result, + source_result, + sig, + source, + callbacks, + ed, + prop); + ppat_signal->ref--; + ppat_source->ref--; + if (ppat_signal->ref <= 0) edje_match_patterns_free(ppat_signal); + if (ppat_source->ref <= 0) edje_match_patterns_free(ppat_source); return r; } @@ -805,13 +750,13 @@ edje_match_program_hash_build(Edje_Program * const *programs, item->signal = programs[i]->signal; item->source = programs[i]->source; - eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (void*), 8); + eina_array_step_set(&item->list, sizeof (Eina_Array), 8); new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); } - eina_inarray_push(&item->list, &programs[i]); + eina_array_push(&item->list, programs[i]); } else result = eina_list_prepend(result, programs[i]); @@ -821,51 +766,48 @@ edje_match_program_hash_build(Edje_Program * const *programs, return result; } -void -edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callbacks, - int callbacks_count, - Eina_Rbtree **tree, - Eina_Inarray *result) +Eina_List * +edje_match_callback_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree) { + Eina_List *result = NULL; Eina_Rbtree *new = NULL; - int i; + Edje_Signal_Callback *callback; + const Eina_List *l; - eina_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8); - - for (i = 0; i < callbacks_count; ++i, ++callbacks) + EINA_LIST_FOREACH(callbacks, l, callback) { - if (callbacks->signal && !strpbrk(callbacks->signal, "*?[\\") - && callbacks->source && !strpbrk(callbacks->source, "*?[\\")) + if (callback->signal && !strpbrk(callback->signal, "*?[\\") + && callback->source && !strpbrk(callback->source, "*?[\\")) { Edje_Signal_Source_Char *item; - item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callbacks->signal, 0, - EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callbacks->source); + item = (Edje_Signal_Source_Char*) eina_rbtree_inline_lookup(new, callback->signal, 0, + EINA_RBTREE_CMP_KEY_CB(_edje_signal_source_key_cmp), callback->source); if (!item) { item = malloc(sizeof (Edje_Signal_Source_Char)); if (!item) continue; - item->signal = callbacks->signal; - item->source = callbacks->source; - eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (int), 8); + item->signal = callback->signal; + item->source = callback->source; + eina_array_step_set(&item->list, sizeof (Eina_Array), 8); new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); } - eina_inarray_push(&item->list, &i); + eina_array_push(&item->list, callback); } else - { - eina_inarray_push(result, &i); - } + result = eina_list_prepend(result, callback); } *tree = new; + return result; } -const Eina_Inarray * +const Eina_Array * edje_match_signal_source_hash_get(const char *sig, const char *source, const Eina_Rbtree *tree) @@ -882,6 +824,6 @@ edje_match_signal_source_hash_get(const char *sig, void edje_match_signal_source_free(Edje_Signal_Source_Char *key, EINA_UNUSED void *data) { - eina_inarray_flush(&key->list); + eina_array_flush(&key->list); free(key); } diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 6e849eca9a..ac3b169e46 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -321,10 +321,6 @@ typedef struct _Edje_Signal_Source_Char Edje_Signal_Source_Char; typedef struct _Edje_Text_Insert_Filter_Callback Edje_Text_Insert_Filter_Callback; typedef struct _Edje_Markup_Filter_Callback Edje_Markup_Filter_Callback; typedef struct _Edje_Signals_Sources_Patterns Edje_Signals_Sources_Patterns; -typedef struct _Edje_Signal_Callback_Group Edje_Signal_Callback_Group; -typedef struct _Edje_Signal_Callback_Match Edje_Signal_Callback_Match; -typedef struct _Edje_Signal_Callback_Matches Edje_Signal_Callback_Matches; -typedef struct _Edje_Signal_Callback_Custom Edje_Signal_Callback_Custom; #define EDJE_INF_MAX_W 100000 #define EDJE_INF_MAX_H 100000 @@ -774,7 +770,6 @@ struct _Edje_Part_Limit struct _Edje_Signals_Sources_Patterns { - EINA_REFCOUNT; Edje_Patterns *signals_patterns; Edje_Patterns *sources_patterns; @@ -786,39 +781,11 @@ struct _Edje_Signals_Sources_Patterns unsigned int count; } programs; struct { - Eina_Inarray globing; + Eina_List *globing; } callbacks; } u; }; -struct _Edje_Signal_Callback_Match -{ - const char *signal; - const char *source; - Edje_Signal_Cb func; -}; - -struct _Edje_Signal_Callback_Matches -{ - Edje_Signal_Callback_Match *matches; - - Edje_Signals_Sources_Patterns *patterns; - - unsigned int matches_count; - EINA_REFCOUNT; - - Eina_Bool hashed : 1; -}; - -struct _Edje_Signal_Callback_Group -{ - const Edje_Signal_Callback_Matches *matches; - - void **custom_data; - - Eina_Bool *flags; /* 4 bits per custom data (delete_me, just_added, propagate) */ -}; - /*----------*/ struct _Edje_Part_Collection @@ -1220,7 +1187,7 @@ struct _Edje_Signal_Source_Char const char *signal; const char *source; - Eina_Inarray list; + Eina_Array list; }; struct _Edje @@ -1238,6 +1205,7 @@ struct _Edje Edje_File *file; /* the file the data comes form */ Edje_Part_Collection *collection; /* the description being used */ Eina_List *actions; /* currently running actions */ + Eina_List *callbacks; Eina_List *pending_actions; Eina_Hash *color_classes; Eina_List *text_classes; @@ -1260,7 +1228,9 @@ struct _Edje Edje_Perspective *persp; - const Edje_Signal_Callback_Group *callbacks; + struct { + Edje_Signals_Sources_Patterns callbacks; + } patterns; struct { Edje_Text_Change_Cb func; @@ -1811,10 +1781,8 @@ Edje_Patterns *edje_match_programs_signal_init(Edje_Program * const *array, unsigned int count); Edje_Patterns *edje_match_programs_source_init(Edje_Program * const *array, unsigned int count); -Edje_Patterns *edje_match_callback_signal_init(const Eina_Inarray *lst, - const Edje_Signal_Callback_Match *matches); -Edje_Patterns *edje_match_callback_source_init(const Eina_Inarray *lst, - const Edje_Signal_Callback_Match *matches); +Edje_Patterns *edje_match_callback_signal_init(const Eina_List *lst); +Edje_Patterns *edje_match_callback_source_init(const Eina_List *lst); Eina_Bool edje_match_collection_dir_exec(const Edje_Patterns *ppat, const char *string); @@ -1826,29 +1794,25 @@ Eina_Bool edje_match_programs_exec(const Edje_Patterns *ppat_signal, Eina_Bool (*func)(Edje_Program *pr, void *data), void *data, Eina_Bool prop); -int edje_match_callback_exec(const Edje_Signals_Sources_Patterns *ssp, - const Edje_Signal_Callback_Match *matches, - const void **custom_data, - const Eina_Bool *flags, - const char *sig, - const char *source, - Edje *ed, - Eina_Bool prop); +int edje_match_callback_exec(Edje_Patterns *ppat_signal, + Edje_Patterns *ppat_source, + const char *signal, + const char *source, + Eina_List *callbacks, + Edje *ed, + Eina_Bool prop); void edje_match_patterns_free(Edje_Patterns *ppat); Eina_List *edje_match_program_hash_build(Edje_Program * const * programs, unsigned int count, Eina_Rbtree **tree); -void edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callback, - int callbacks_count, - Eina_Rbtree **tree, - Eina_Inarray *result); -const Eina_Inarray *edje_match_signal_source_hash_get(const char *signal, - const char *source, - const Eina_Rbtree *tree); +Eina_List *edje_match_callback_hash_build(const Eina_List *callbacks, + Eina_Rbtree **tree); +const Eina_Array *edje_match_signal_source_hash_get(const char *signal, + const char *source, + const Eina_Rbtree *tree); void edje_match_signal_source_free(Edje_Signal_Source_Char *key, void *data); -void _edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m); // FIXME remove below 3 eapi decls when edje_convert goes EAPI void _edje_edd_init(void); @@ -1906,16 +1870,6 @@ void _edje_callbacks_focus_add(Evas_Object *obj, Edje *ed, Edje_Real_Part *rp); void _edje_callbacks_del(Evas_Object *obj, Edje *ed); void _edje_callbacks_focus_del(Evas_Object *obj, Edje *ed); -const Edje_Signal_Callback_Group *_edje_signal_callback_alloc(void); -void _edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp); -void _edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp, - const char *signal, const char *source, - Edje_Signal_Cb func, void *data, - Eina_Bool propagate); -void *_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp, - const char *signal, const char *source, - Edje_Signal_Cb func, void *data); - EAPI void _edje_edd_init(void); EAPI void _edje_edd_shutdown(void); @@ -1952,12 +1906,7 @@ void _edje_emit(Edje *ed, const char *sig, const char *src); void _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*free_func)(void *)); void _edje_emit_handle(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop); void _edje_signals_sources_patterns_clean(Edje_Signals_Sources_Patterns *ssp); - -const Edje_Signals_Sources_Patterns *_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp); -void _edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp); -Eina_Bool _edje_signal_callback_prop(const Eina_Bool *flags, int i); - -void _edje_signal_callback_free(const Edje_Signal_Callback_Group *gp); +void _edje_callbacks_patterns_clean(Edje *ed); void _edje_text_init(void); void _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep); @@ -2502,9 +2451,6 @@ void _play_get(Eo *obj, void *_pd, va_list *list); void _animation_set(Eo *obj, void *_pd, va_list *list); void _animation_get(Eo *obj, void *_pd, va_list *list); -void edje_signal_init(void); -void edje_signal_shutdown(void); - #ifdef HAVE_LIBREMIX #include #endif diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c index 8c31283788..e66554d747 100644 --- a/src/lib/edje/edje_program.c +++ b/src/lib/edje/edje_program.c @@ -28,27 +28,26 @@ edje_frametime_get(void) void edje_object_propagate_callback_add(Evas_Object *obj, void (*func) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) { - const char *sig; - const char *src; Edje *ed; + Edje_Signal_Callback *escb; ed = _edje_fetch(obj); if (!ed) return; if (ed->delete_me) return; - - if (!ed->callbacks) - ed->callbacks = _edje_signal_callback_alloc(); - - sig = eina_stringshare_add("*"); - src = eina_stringshare_add("*"); - - _edje_signal_callback_push(ed->callbacks, - sig, src, - func, data, - EINA_TRUE); - - eina_stringshare_del(sig); - eina_stringshare_del(src); + escb = calloc(1, sizeof(Edje_Signal_Callback)); + escb->propagate = EINA_TRUE; + escb->signal = eina_stringshare_add("*"); + escb->source = eina_stringshare_add("*"); + escb->func = func; + escb->data = data; + ed->callbacks = eina_list_append(ed->callbacks, escb); + if (ed->walking_callbacks) + { + escb->just_added = 1; + ed->just_added_callbacks = EINA_TRUE; + } + else + _edje_callbacks_patterns_clean(ed); } EAPI void @@ -67,24 +66,27 @@ _signal_callback_add(Eo *obj EINA_UNUSED, void *_pd, va_list *list) void *data = va_arg(*list, void *); Edje *ed = _pd; + Edje_Signal_Callback *escb; if ((!emission) || (!source) || (!func)) return; ed = _pd; if (!ed) return; if (ed->delete_me) return; - - emission = eina_stringshare_add(emission); - source = eina_stringshare_add(source); - - if (!ed->callbacks) - ed->callbacks = _edje_signal_callback_alloc(); - - _edje_signal_callback_push(ed->callbacks, - emission, source, - func, data, EINA_FALSE); - - eina_stringshare_del(emission); - eina_stringshare_del(source); + escb = calloc(1, sizeof(Edje_Signal_Callback)); + if (emission[0]) + escb->signal = eina_stringshare_add(emission); + if (source[0]) + escb->source = eina_stringshare_add(source); + escb->func = func; + escb->data = data; + ed->callbacks = eina_list_append(ed->callbacks, escb); + if (ed->walking_callbacks) + { + escb->just_added = 1; + ed->just_added_callbacks = EINA_TRUE; + } + else + _edje_callbacks_patterns_clean(ed); } EAPI void * @@ -92,7 +94,7 @@ edje_object_signal_callback_del(Evas_Object *obj, const char *emission, const ch { if (!obj) return NULL; void *ret = NULL; - eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, NULL, &ret)); + eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, &ret)); return ret; } @@ -102,25 +104,46 @@ _signal_callback_del(Eo *obj EINA_UNUSED, void *_pd, va_list *list) const char *emission = va_arg(*list, const char *); const char *source = va_arg(*list, const char *); Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb); - void *data = va_arg(*list, void *); void **ret = va_arg(*list, void **); - Edje *ed = _pd; - if (ret) *ret = NULL; + Edje *ed = _pd; + Eina_List *l; + Edje_Signal_Callback *escb; + if ((!emission) || (!source) || (!func)) return; if (!ed) return; if (ed->delete_me) return; + EINA_LIST_FOREACH(ed->callbacks, l, escb) + { + if ((escb->func == func) && + ((!escb->signal && !emission[0]) || + (escb->signal && !strcmp(escb->signal, emission))) && + ((!escb->source && !source[0]) || + (escb->source && !strcmp(escb->source, source)))) + { + void *data; - emission = eina_stringshare_add(emission); - source = eina_stringshare_add(source); + data = escb->data; + if (ed->walking_callbacks) + { + escb->delete_me = EINA_TRUE; + ed->delete_callbacks = EINA_TRUE; + } + else + { + _edje_callbacks_patterns_clean(ed); - _edje_signal_callback_disable(ed->callbacks, - emission, source, - func, data); - - eina_stringshare_del(emission); - eina_stringshare_del(source); + ed->callbacks = eina_list_remove_list(ed->callbacks, l); + if (escb->signal) eina_stringshare_del(escb->signal); + if (escb->source) eina_stringshare_del(escb->source); + free(escb); + } + if (ret) *ret = data; + return; + } + } + return; } EAPI void * @@ -128,10 +151,59 @@ edje_object_signal_callback_del_full(Evas_Object *obj, const char *emission, con { if (!obj) return NULL; void *ret = NULL; - eo_do(obj, edje_obj_signal_callback_del(emission, source, func, data, &ret)); + eo_do(obj, edje_obj_signal_callback_del_full(emission, source, func, data, &ret)); return ret; } +void +_signal_callback_del_full(Eo *obj EINA_UNUSED, void *_pd, va_list *list) +{ + const char *emission = va_arg(*list, const char *); + const char *source = va_arg(*list, const char *); + Edje_Signal_Cb func = va_arg(*list, Edje_Signal_Cb); + void *data = va_arg(*list, void *); + void **ret = va_arg(*list, void **); + if (ret) *ret = NULL; + + Edje *ed = _pd; + Eina_List *l; + Edje_Signal_Callback *escb; + + if ((!emission) || (!source) || (!func)) return; + if (!ed) return; + if (ed->delete_me) return; + EINA_LIST_FOREACH(ed->callbacks, l, escb) + { + if ((escb->func == func) && (escb->data == data) && + ((!escb->signal && !emission[0]) || + (escb->signal && !strcmp(escb->signal, emission))) && + ((!escb->source && !source[0]) || + (escb->source && !strcmp(escb->source, source)))) + { + void *data2; + + data2 = escb->data; + if (ed->walking_callbacks) + { + escb->delete_me = EINA_TRUE; + ed->delete_callbacks = EINA_TRUE; + } + else + { + _edje_callbacks_patterns_clean(ed); + + ed->callbacks = eina_list_remove_list(ed->callbacks, l); + if (escb->signal) eina_stringshare_del(escb->signal); + if (escb->source) eina_stringshare_del(escb->source); + free(escb); + } + if (ret) *ret = data2; + return; + } + } + return; +} + EAPI void edje_object_signal_emit(Evas_Object *obj, const char *emission, const char *source) { @@ -1207,6 +1279,37 @@ static Eina_Bool _edje_glob_callback(Edje_Program *pr, void *dt) return EINA_FALSE; } +void +_edje_callbacks_patterns_clean(Edje *ed) +{ + if (ed->walking_callbacks > 0) return; + + _edje_signals_sources_patterns_clean(&ed->patterns.callbacks); + + eina_rbtree_delete(ed->patterns.callbacks.exact_match, + EINA_RBTREE_FREE_CB(edje_match_signal_source_free), + NULL); + ed->patterns.callbacks.exact_match = NULL; + + ed->patterns.callbacks.u.callbacks.globing = eina_list_free(ed->patterns.callbacks.u.callbacks.globing); +} + +static void +_edje_callbacks_patterns_init(Edje *ed) +{ + Edje_Signals_Sources_Patterns *ssp = &ed->patterns.callbacks; + + if ((ssp->signals_patterns) || (ssp->sources_patterns) || + (ssp->u.callbacks.globing) || (ssp->exact_match)) + return; + + ssp->u.callbacks.globing = edje_match_callback_hash_build(ed->callbacks, + &ssp->exact_match); + + ssp->signals_patterns = edje_match_callback_signal_init(ssp->u.callbacks.globing); + ssp->sources_patterns = edje_match_callback_source_init(ssp->u.callbacks.globing); +} + /* FIXME: what if we delete the evas object??? */ void _edje_emit_handle(Edje *ed, const char *sig, const char *src, @@ -1300,11 +1403,13 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src, if (ed->collection->patterns.table_programs_size > 0) { - const Eina_Inarray *match; + const Eina_Array *match; #ifdef EDJE_PROGRAM_CACHE const Eina_List *l; #endif Edje_Program *pr; + Eina_Array_Iterator iterator; + unsigned int i; if (ed->collection->patterns.programs.u.programs.globing) if (edje_match_programs_exec(ed->collection->patterns.programs.signals_patterns, @@ -1315,17 +1420,13 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src, _edje_glob_callback, &data, prop) == 0) - goto break_prog; + goto break_prog; match = edje_match_signal_source_hash_get(sig, src, ed->collection->patterns.programs.exact_match); if (match) - { - Edje_Program **tpr; - - EINA_INARRAY_FOREACH(match, tpr) - _edje_glob_callback(*tpr, &data); - } + EINA_ARRAY_ITER_NEXT(match, i, pr, iterator) + _edje_glob_callback(pr, &data); #ifdef EDJE_PROGRAM_CACHE EINA_LIST_FOREACH(data.matches, l, pr) @@ -1388,68 +1489,82 @@ edje_object_signal_callback_extra_data_get(void) static void _edje_emit_cb(Edje *ed, const char *sig, const char *src, Edje_Message_Signal_Data *data, Eina_Bool prop) { - const Edje_Signals_Sources_Patterns *ssp; - Edje_Signal_Callback_Matches *m; - const void **custom_data; - Eina_Bool *flags; - const Eina_Inarray *match; - int r = 1; + Eina_List *l; if (ed->delete_me) return; - if (!ed->callbacks || !ed->callbacks->matches) return; - _edje_ref(ed); _edje_freeze(ed); _edje_block(ed); - ssp = _edje_signal_callback_patterns_ref(ed->callbacks); + if (ed->just_added_callbacks) + _edje_callbacks_patterns_clean(ed); - m = (Edje_Signal_Callback_Matches*) ed->callbacks->matches; - EINA_REFCOUNT_REF(m); + ed->walking_callbacks++; - callback_extra_data = (data) ? data->data : NULL; - custom_data = alloca(sizeof (void*) * m->matches_count); - memcpy(custom_data, ed->callbacks->custom_data, sizeof (void*) * m->matches_count); - flags = alloca(sizeof (Eina_Bool) * m->matches_count); - memcpy(flags, ed->callbacks->flags, sizeof (Eina_Bool) * (m->matches_count >> 1)); - - if (eina_inarray_count(&ssp->u.callbacks.globing)) - r = edje_match_callback_exec(ssp, - m->matches, - custom_data, - flags, - sig, - src, - ed, - prop); - - if (!r) - goto break_prog; - - match = edje_match_signal_source_hash_get(sig, src, - ssp->exact_match); - if (match) + if (ed->callbacks) { - const Edje_Signal_Callback_Match *cb; - size_t *i; + Edje_Signal_Callback *escb; + const Eina_Array *match; + Eina_Array_Iterator iterator; + unsigned int i; + int r = 1; + callback_extra_data = (data) ? data->data : NULL; - EINA_INARRAY_FOREACH(match, i) - { - cb = &m->matches[*i]; + _edje_callbacks_patterns_init(ed); + if (ed->patterns.callbacks.u.callbacks.globing) + r = edje_match_callback_exec(ed->patterns.callbacks.signals_patterns, + ed->patterns.callbacks.sources_patterns, + sig, + src, + ed->patterns.callbacks.u.callbacks.globing, + ed, + prop); - if ((prop) && (_edje_signal_callback_prop(flags, *i))) continue; + if (!r) + goto break_prog; - cb->func((void*) custom_data[*i], ed->obj, sig, src); - if (_edje_block_break(ed)) - break; - } + match = edje_match_signal_source_hash_get(sig, src, + ed->patterns.callbacks.exact_match); + if (match) + EINA_ARRAY_ITER_NEXT(match, i, escb, iterator) + { + if ((prop) && (escb->propagate)) continue; + if ((!escb->just_added) && (!escb->delete_me)) + { + escb->func(escb->data, ed->obj, sig, src); + if (_edje_block_break(ed)) + break; + } + } } + break_prog: - break_prog: - _edje_signal_callback_matches_unref(m); + ed->walking_callbacks--; + if (!ed->walking_callbacks && + ((ed->delete_callbacks) || (ed->just_added_callbacks))) + { + ed->delete_callbacks = EINA_FALSE; + ed->just_added_callbacks = EINA_FALSE; + l = ed->callbacks; + while (l) + { + Edje_Signal_Callback *escb = l->data; + Eina_List *next_l = l->next; - _edje_signal_callback_patterns_unref(ssp); + if (escb->just_added) + escb->just_added = 0; + if (escb->delete_me) + { + ed->callbacks = eina_list_remove_list(ed->callbacks, l); + if (escb->signal) eina_stringshare_del(escb->signal); + if (escb->source) eina_stringshare_del(escb->source); + free(escb); + } + l = next_l; + } + _edje_callbacks_patterns_clean(ed); + } _edje_unblock(ed); _edje_thaw(ed); _edje_unref(ed); diff --git a/src/lib/edje/edje_signal.c b/src/lib/edje/edje_signal.c deleted file mode 100644 index 3dfdae1230..0000000000 --- a/src/lib/edje/edje_signal.c +++ /dev/null @@ -1,477 +0,0 @@ -#include - -#include "edje_private.h" - -#define _DELETE_ME 0x4 -#define _JUST_ADDED 0x2 -#define _PROPAGATE 0x1 - -static Eina_Hash *signal_match = NULL; - -static unsigned int -_edje_signal_match_key_length(const void *key EINA_UNUSED) -{ - return sizeof (Edje_Signal_Callback_Matches); -} - -static int -_edje_signal_match_key_cmp(const void *key1, int key1_length EINA_UNUSED, const void *key2, int key2_length EINA_UNUSED) -{ - const Edje_Signal_Callback_Matches *a = key1; - const Edje_Signal_Callback_Matches *b = key2; - unsigned int i; - - if (a->matches_count != b->matches_count) return a->matches_count - b->matches_count; - for (i = 0; i < a->matches_count; ++i) - { - if (a->matches[i].signal != b->matches[i].signal) return a->matches[i].signal - b->matches[i].signal; - if (a->matches[i].source != b->matches[i].source) return a->matches[i].source - b->matches[i].source; - if (a->matches[i].func != b->matches[i].func) return (unsigned char*) a->matches[i].func - (unsigned char*) b->matches[i].func; - } - return 0; -} - -static int -_edje_signal_match_key_hash(const void *key, int key_length EINA_UNUSED) -{ - const Edje_Signal_Callback_Matches *a = key; - unsigned int hash, i; - - hash = eina_hash_int32(&a->matches_count, sizeof (int)); - for (i = 0; i < a->matches_count; ++i) - { -#ifdef __LP64__ - hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].signal, sizeof (char *)); - hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].source, sizeof (char *)); - hash ^= eina_hash_int64((const unsigned long int*) &a->matches[i].func, sizeof (Edje_Signal_Cb)); -#else - hash ^= eina_hash_int32((const unsigned int*) a->matches[i].signal, sizeof (char *)); - hash ^= eina_hash_int32((const unsigned int*) a->matches[i].source, sizeof (char *)); - hash ^= eina_hash_int32((const unsigned int*) a->matches[i].func, sizeof (Edje_Signal_Cb)); -#endif - } - return hash; -} - -static const Edje_Signal_Callback_Matches * -_edje_signal_callback_matches_dup(const Edje_Signal_Callback_Matches *src) -{ - Edje_Signal_Callback_Matches *result; - unsigned int i; - - result = calloc(1, sizeof (Edje_Signal_Callback_Matches)); - if (!result) return NULL; - - result->hashed = EINA_FALSE; - result->matches = malloc(sizeof (Edje_Signal_Callback_Match) * src->matches_count); - result->matches_count = src->matches_count; - result->patterns = NULL; - EINA_REFCOUNT_REF(result); - - for (i = 0; i < src->matches_count; i++) - { - result->matches[i].signal = eina_stringshare_ref(src->matches[i].signal); - result->matches[i].source = eina_stringshare_ref(src->matches[i].source); - result->matches[i].func = src->matches[i].func; - } - - return result; -} - -void -_edje_callbacks_patterns_clean(Edje_Signal_Callback_Group *gp) -{ - Edje_Signal_Callback_Matches *tmp; - - assert(EINA_REFCOUNT_GET(gp->matches) == 1); - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - - _edje_signal_callback_patterns_unref(tmp->patterns); - tmp->patterns = NULL; -} - -static void -_edje_callbacks_patterns_init(Edje_Signal_Callback_Group *gp) -{ - Edje_Signals_Sources_Patterns *ssp; - Edje_Signal_Callback_Matches *tmp; - - if (gp->matches->patterns) return ; - - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - tmp->patterns = calloc(1, sizeof (Edje_Signals_Sources_Patterns)); - if (!gp->matches->patterns) return ; - - ssp = gp->matches->patterns; - edje_match_callback_hash_build(gp->matches->matches, - gp->matches->matches_count, - &ssp->exact_match, - &ssp->u.callbacks.globing); - - ssp->signals_patterns = edje_match_callback_signal_init(&ssp->u.callbacks.globing, tmp->matches); - ssp->sources_patterns = edje_match_callback_source_init(&ssp->u.callbacks.globing, tmp->matches); - EINA_REFCOUNT_REF(ssp); -} - -void -edje_signal_init(void) -{ - signal_match = eina_hash_new(_edje_signal_match_key_length, - _edje_signal_match_key_cmp, - _edje_signal_match_key_hash, - NULL, - 3); -} - -void -edje_signal_shutdown(void) -{ - // FIXME: iterate and destroy leftover signal matcher - eina_hash_free(signal_match); -} - -static void -_edje_signal_callback_unset(Edje_Signal_Callback_Group *gp, int idx) -{ - Edje_Signal_Callback_Match *m; - - m = gp->matches->matches + idx; - eina_stringshare_del(m->signal); - m->signal = NULL; - eina_stringshare_del(m->source); - m->source = NULL; -} - -static void -_edje_signal_callback_set(Edje_Signal_Callback_Group *gp, int idx, - const char *sig, const char *src, - Edje_Signal_Cb func, void *data, Eina_Bool flags) -{ - Edje_Signal_Callback_Match *m; - - m = gp->matches->matches + idx; - m->signal = eina_stringshare_ref(sig); - m->source = eina_stringshare_ref(src); - m->func = func; - - gp->custom_data[idx] = data; - - gp->flags[idx >> 1] = (gp->flags[idx >> 1] & (0xF << (((idx & 1) ^ 1) * 4))) | - ((flags & 0xF) << ((idx & 1) * 4)); -} - -Eina_Bool -_edje_signal_callback_prop(const Eina_Bool *flags, int i) -{ - Eina_Bool b; - - b = flags[i >> 1]; - return b & (_PROPAGATE << ((i & 1) * 4)); -} - -static Edje_Signal_Callback_Group * -_edje_signal_callback_grow(Edje_Signal_Callback_Group *gp) -{ - Edje_Signal_Callback_Matches *tmp; - unsigned int c; - - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - tmp->matches_count++; - tmp->matches = realloc(tmp->matches, sizeof (Edje_Signal_Callback_Match) * tmp->matches_count); - gp->custom_data = realloc(gp->custom_data, sizeof (void*) * tmp->matches_count); - - c = ((tmp->matches_count >> 1) | (tmp->matches_count & 1)); - gp->flags = realloc(gp->flags, sizeof (Edje_Signal_Callback_Group) + c); - // We have just expanded by one char, set it to 0 - if (tmp->matches_count & 1) gp->flags[tmp->matches_count >> 1] = 0; - - return gp; -} - -void -_edje_signal_callback_push(const Edje_Signal_Callback_Group *cgp, - const char *sig, const char *src, - Edje_Signal_Cb func, void *data, Eina_Bool propagate) -{ - Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp; - unsigned int i; - - // let's first try to see if we do find an empty matching stop - for (i = 0; i < gp->matches->matches_count; i++) - if (sig == gp->matches->matches[i].signal && - src == gp->matches->matches[i].source && - func == gp->matches->matches[i].func) - { - Eina_Bool flags; - - flags = gp->flags[i >> 1] & (0xF << ((i & 1) * 4)); - if (flags & _DELETE_ME) - { - _edje_signal_callback_unset(gp, i); - _edje_signal_callback_set(gp, i, - sig, src, func, data, - (((!!propagate) & 1) | _JUST_ADDED)); - return ; - } - } - - if (gp->matches->hashed) - { - Edje_Signal_Callback_Matches *tmp; - - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - if (EINA_REFCOUNT_GET(tmp) == 1) - { - eina_hash_del(signal_match, tmp, tmp); - tmp->hashed = 0; - } - else - { - Edje_Signal_Callback_Matches *tmp_dup; - tmp_dup = (Edje_Signal_Callback_Matches*) _edje_signal_callback_matches_dup(tmp); - if (!tmp_dup) return ; - EINA_REFCOUNT_UNREF(tmp) - (void) 0; // Nothing to do because the case where refcount == 1 was already handle above. - gp->matches = tmp_dup; - } - } - - // search an empty spot now - for (i = 0; i < gp->matches->matches_count; i += 2) - if (gp->flags[i >> 1] & (_DELETE_ME | (_DELETE_ME << 4))) - { - if (gp->flags[i >> 1] & _DELETE_ME) - { - _edje_signal_callback_unset(gp, i); - _edje_signal_callback_set(gp, i, - sig, src, func, data, - (((!!propagate) & 1) | _JUST_ADDED)); - return ; - } - if (gp->flags[i >> 1] & (_DELETE_ME << 4)) - { - _edje_signal_callback_unset(gp, i + 1); - _edje_signal_callback_set(gp, i + 1, - sig, src, func, data, - (((!!propagate) & 1) | _JUST_ADDED)); - return ; - } - } - - _edje_signal_callback_grow(gp); - - // Set propagate and just_added flags - _edje_signal_callback_set(gp, gp->matches->matches_count - 1, - sig, src, func, data, (((!!propagate) & 1) | _JUST_ADDED)); - - return ; -} - -const Edje_Signal_Callback_Group * -_edje_signal_callback_alloc(void) -{ - Edje_Signal_Callback_Group *escg; - Edje_Signal_Callback_Matches *m; - - escg = calloc(1, sizeof (Edje_Signal_Callback_Group)); - if (!escg) return NULL; - - m = calloc(1, sizeof (Edje_Signal_Callback_Matches)); - if (!m) - { - free(escg); - return NULL; - } - - EINA_REFCOUNT_REF(m); - escg->matches = m; - - return escg; -} - -void -_edje_signal_callback_matches_unref(Edje_Signal_Callback_Matches *m) -{ - EINA_REFCOUNT_UNREF(m) - { - unsigned int i; - - _edje_signal_callback_patterns_unref(m->patterns); - - if (m->hashed) - eina_hash_del(signal_match, m, m); - - for (i = 0; i < m->matches_count; ++i) - { - eina_stringshare_del(m->matches[i].signal); - eina_stringshare_del(m->matches[i].source); - } - free(m->matches); - free(m); - } -} - -void -_edje_signal_callback_free(const Edje_Signal_Callback_Group *cgp) -{ - Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp; - - if (!gp) return ; - - _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches); - gp->matches = NULL; - free(gp->custom_data); - free(gp); -} - -void * -_edje_signal_callback_disable(const Edje_Signal_Callback_Group *cgp, - const char *sig, const char *src, - Edje_Signal_Cb func, void *data) -{ - Edje_Signal_Callback_Group *gp = (Edje_Signal_Callback_Group*) cgp; - unsigned int i; - - // FIXME: Shall we check DELETE_ME flags ? - for (i = 0; i < gp->matches->matches_count; ++i) - { - if (sig == gp->matches->matches[i].signal && - src == gp->matches->matches[i].source && - func == gp->matches->matches[i].func && - gp->custom_data[i] == data) - { - Eina_Bool flags; - - flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4)); - gp->flags[i >> 1] = flags; - return gp->custom_data[i]; - } - } - - if (data == NULL) - { - for (i = 0; i < gp->matches->matches_count; ++i) - { - if (sig == gp->matches->matches[i].signal && - src == gp->matches->matches[i].source && - func == gp->matches->matches[i].func) - { - Eina_Bool flags; - - flags = gp->flags[i >> 1] | (_DELETE_ME << ((i & 1) * 4)); - gp->flags[i >> 1] = flags; - return gp->custom_data[i]; - } - } - } - - return NULL; -} - -static void -_edje_signal_callback_move_last(Edje_Signal_Callback_Group *gp, - int i) -{ - Edje_Signal_Callback_Matches *m; - int j; - - m = (Edje_Signal_Callback_Matches*) gp->matches; - - for (j = (int) --m->matches_count; j > i; --j) - { - if (!(gp->flags[j >> 1] & (_DELETE_ME << ((j & 1) * 4)))) - { - m->matches[i].signal = m->matches[j].signal; - m->matches[i].source = m->matches[j].source; - m->matches[i].func = m->matches[j].func; - gp->flags[i] = (gp->flags[i >> 1] & (0xF << (((i & 1) ^ 1) * 4))) | - (gp->flags[j >> 1] & (0xF << (((j & 1) * 4)))); - return ; - } - --m->matches_count; - } -} - -const Edje_Signals_Sources_Patterns * -_edje_signal_callback_patterns_ref(const Edje_Signal_Callback_Group *gp) -{ - const Edje_Signal_Callback_Matches *m; - Edje_Signal_Callback_Matches *tmp; - - if (gp->matches->hashed) - goto got_it; - - m = eina_hash_find(signal_match, gp->matches); - if (!m) - { - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - if (!(tmp->patterns && (EINA_REFCOUNT_GET(tmp->patterns) > 1))) - { - // Let compact it and remove uneeded pattern before building it - // We can do that because the custom data are kept local into the matching code. - Eina_Bool delete_me = _DELETE_ME | (_DELETE_ME << 4); - unsigned int i; - - for (i = 0; i < tmp->matches_count; i += 2) - { - if (gp->flags[i >> 1] & delete_me) - { - if (gp->flags[i >> 1] & _DELETE_ME) - { - _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i); - } - if (i + 1 < gp->matches->matches_count && - (gp->flags[i >> 1] & (_DELETE_ME << 4))) - { - _edje_signal_callback_move_last((Edje_Signal_Callback_Group*) gp, i + 1); - } - } - } - - } - - _edje_signal_callback_patterns_unref(tmp->patterns); - tmp->patterns = NULL; - - _edje_callbacks_patterns_init((Edje_Signal_Callback_Group*) gp); - eina_hash_add(signal_match, tmp, tmp); - tmp->hashed = EINA_TRUE; - } - else - { - _edje_signal_callback_matches_unref((Edje_Signal_Callback_Matches*) gp->matches); - ((Edje_Signal_Callback_Group*)gp)->matches = m; - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - EINA_REFCOUNT_REF(tmp); - } - - got_it: - tmp = (Edje_Signal_Callback_Matches*) gp->matches; - - EINA_REFCOUNT_REF(tmp->patterns); - return gp->matches->patterns; -} - -void -_edje_signal_callback_patterns_unref(const Edje_Signals_Sources_Patterns *essp) -{ - Edje_Signals_Sources_Patterns *ssp; - - if (!essp) return ; - - ssp = (Edje_Signals_Sources_Patterns*) essp; - - EINA_REFCOUNT_UNREF(ssp) - { - _edje_signals_sources_patterns_clean(ssp); - - eina_rbtree_delete(ssp->exact_match, - EINA_RBTREE_FREE_CB(edje_match_signal_source_free), - NULL); - ssp->exact_match = NULL; - - eina_inarray_flush(&ssp->u.callbacks.globing); - - free(ssp); - } -} diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c index d31203471f..80951d95bd 100644 --- a/src/lib/edje/edje_smart.c +++ b/src/lib/edje/edje_smart.c @@ -480,6 +480,7 @@ _edje_smart_class_constructor(Eo_Class *klass) EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS), _message_signal_process), EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD), _signal_callback_add), EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL), _signal_callback_del), + EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL), _signal_callback_del_full), EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_SIGNAL_EMIT), _signal_emit), EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_SET), _play_set), EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PLAY_GET), _play_get), @@ -625,6 +626,7 @@ static const Eo_Op_Description op_desc[] = { EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SIGNAL_PROCESS, "Process an object's message queue."), EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD, "Add a callback for an arriving Edje signal, emitted by"), EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL, "Remove a signal-triggered callback from an object."), + EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL_FULL, "Unregister/delete a callback set for an arriving Edje"), EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_SIGNAL_EMIT, "Send/emit an Edje signal to a given Edje object"), EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_SET, "Set the Edje object to playing or paused states."), EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PLAY_GET, "Get the Edje object's state."),