diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am index db4534ac2a..20ec55288b 100644 --- a/src/Makefile_Edje.am +++ b/src/Makefile_Edje.am @@ -46,7 +46,8 @@ 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_var.c \ +lib/edje/edje_signal.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 c678ee7872..5a5afe5460 100644 --- a/src/lib/edje/Edje.h +++ b/src/lib/edje/Edje.h @@ -893,7 +893,6 @@ 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, @@ -2709,23 +2708,7 @@ enum * * @see edje_object_signal_callback_del */ -#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) +#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) /** * @def edje_obj_signal_emit diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c index 42ff7f4c2f..b16836a643 100644 --- a/src/lib/edje/edje_main.c +++ b/src/lib/edje/edje_main.c @@ -78,6 +78,7 @@ 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, @@ -147,6 +148,7 @@ _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(); @@ -242,7 +244,6 @@ _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; @@ -252,7 +253,7 @@ _edje_del(Edje *ed) return; } _edje_message_del(ed); - _edje_callbacks_patterns_clean(ed); + _edje_signal_callback_free(ed->callbacks); _edje_file_del(ed); if (ed->path) eina_stringshare_del(ed->path); if (ed->group) eina_stringshare_del(ed->group); @@ -267,12 +268,6 @@ _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 558d982ff4..f80af37e98 100644 --- a/src/lib/edje/edje_match.c +++ b/src/lib/edje/edje_match.c @@ -5,20 +5,20 @@ typedef struct _Edje_State Edje_State; struct _Edje_State { - size_t idx; - size_t pos; + unsigned int idx; + unsigned int pos; }; struct _Edje_States { - size_t size; + unsigned int size; Edje_State *states; Eina_Bool *has; }; static void -_edje_match_states_free(Edje_States *states, - size_t states_size) +_edje_match_states_free(Edje_States *states, + unsigned int states_size) { (void) states_size; free(states); @@ -36,15 +36,15 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n) { Edje_States *l; - const size_t patterns_size = ppat->patterns_size; - const size_t patterns_max_length = ppat->max_length; + const unsigned int patterns_size = ppat->patterns_size; + const unsigned int patterns_max_length = ppat->max_length; - const size_t array_len = (patterns_max_length + 1) * patterns_size; + const unsigned int array_len = (patterns_max_length + 1) * patterns_size; - size_t states_size; - size_t has_size; - size_t states_has_size; - size_t struct_size; + unsigned int states_size; + unsigned int has_size; + unsigned int states_has_size; + unsigned int struct_size; unsigned char *states; unsigned char *has; @@ -88,12 +88,12 @@ _edje_match_states_alloc(Edje_Patterns *ppat, int n) } static void -_edje_match_states_insert(Edje_States *list, - size_t patterns_max_length, - size_t idx, - size_t pos) +_edje_match_states_insert(Edje_States *list, + unsigned int patterns_max_length, + unsigned int idx, + unsigned int pos) { - size_t i; + unsigned int i; i = (idx * (patterns_max_length + 1)) + pos; @@ -112,8 +112,8 @@ _edje_match_states_insert(Edje_States *list, static void _edje_match_states_clear(Edje_States *list, - EINA_UNUSED size_t patterns_size, - EINA_UNUSED size_t patterns_max_length) + EINA_UNUSED unsigned int patterns_size, + EINA_UNUSED unsigned int patterns_max_length) { list->size = 0; } @@ -127,7 +127,7 @@ enum status patterns_syntax_error = 2 }; -static size_t +static unsigned int _edje_match_patterns_exec_class_token(enum status *status, const char *cl_tok, char c) @@ -152,7 +152,7 @@ _edje_match_patterns_exec_class_token(enum status *status, } static Edje_Match_Error -_edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret) +_edje_match_patterns_exec_class_complement(const char *cl_tok, unsigned int *ret) { switch (*cl_tok) { @@ -170,13 +170,13 @@ _edje_match_patterns_exec_class_complement(const char *cl_tok, size_t *ret) } static Edje_Match_Error -_edje_match_patterns_exec_class(const char *cl, - char c, - size_t *ret) +_edje_match_patterns_exec_class(const char *cl, + char c, + unsigned int *ret) { - enum status status = patterns_not_found; - int pos = 1; - size_t neg; + enum status status = patterns_not_found; + int pos = 1; + size_t neg; if (_edje_match_patterns_exec_class_complement(cl + 1, &neg) != EDJE_MATCH_OK) return EDJE_MATCH_SYNTAX_ERROR; @@ -201,9 +201,9 @@ _edje_match_patterns_exec_class(const char *cl, } static Edje_Match_Error -_edje_match_patterns_exec_token(const char *tok, - char c, - size_t *ret) +_edje_match_patterns_exec_token(const char *tok, + char c, + unsigned int *ret) { switch (*tok) { @@ -229,11 +229,11 @@ _edje_match_patterns_exec_token(const char *tok, } static void -_edje_match_patterns_exec_init_states(Edje_States *states, - size_t patterns_size, - size_t patterns_max_length) +_edje_match_patterns_exec_init_states(Edje_States *states, + unsigned int patterns_size, + unsigned int patterns_max_length) { - size_t i; + unsigned int i; states->size = patterns_size; @@ -251,8 +251,8 @@ _edje_match_patterns_exec_init_states(Edje_States *states, Edje_Patterns* \ Func(const Eina_List *lst) \ { \ - Edje_Patterns *r; \ - size_t i; \ + Edje_Patterns *r; \ + unsigned int i; \ \ if (!lst || eina_list_count(lst) <= 0) \ return NULL; \ @@ -273,7 +273,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states, { \ const char *str; \ Type *data; \ - size_t j; \ + unsigned int j; \ int special = 0; \ \ data = eina_list_data_get(lst); \ @@ -318,8 +318,8 @@ _edje_match_patterns_exec_init_states(Edje_States *states, Edje_Patterns* \ Func(Type * const *lst, unsigned int count) \ { \ - Edje_Patterns *r; \ - size_t i; \ + Edje_Patterns *r; \ + unsigned int i; \ \ if (!lst || count == 0) \ return NULL; \ @@ -339,7 +339,7 @@ _edje_match_patterns_exec_init_states(Edje_States *states, for (i = 0; i < count; ++i) \ { \ const char *str; \ - size_t j; \ + unsigned int j; \ int special = 0; \ \ if (!lst[i]) \ @@ -377,6 +377,66 @@ _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; \ + unsigned int 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; \ + unsigned int 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); @@ -386,18 +446,16 @@ 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_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); +EDJE_MATCH_INIT_INARRAY(edje_match_callback_signal_init, + signal, 0); +EDJE_MATCH_INIT_INARRAY(edje_match_callback_source_init, + source, 0); static Eina_Bool -_edje_match_collection_dir_exec_finals(const size_t *finals, - const Edje_States *states) +_edje_match_collection_dir_exec_finals(const unsigned int *finals, + const Edje_States *states) { - size_t i; + unsigned int i; for (i = 0; i < states->size; ++i) { @@ -408,17 +466,17 @@ _edje_match_collection_dir_exec_finals(const size_t *finals, } static Eina_Bool -edje_match_programs_exec_check_finals(const size_t *signal_finals, - const size_t *source_finals, - const Edje_States *signal_states, - const Edje_States *source_states, - Edje_Program **programs, +edje_match_programs_exec_check_finals(const unsigned int *signal_finals, + const unsigned int *source_finals, + const Edje_States *signal_states, + const Edje_States *source_states, + Edje_Program **programs, Eina_Bool (*func)(Edje_Program *pr, void *data), - void *data, - Eina_Bool prop EINA_UNUSED) + void *data, + Eina_Bool prop EINA_UNUSED) { - size_t i; - size_t j; + unsigned int i; + unsigned int j; /* when not enought memory, they could be NULL */ if (!signal_finals || !source_finals) return EINA_TRUE; @@ -449,61 +507,59 @@ edje_match_programs_exec_check_finals(const size_t *signal_finals, } static int -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, +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, 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) { - Edje_Signal_Callback *escb; + const Edje_Signal_Callback_Match *cb; Eina_Array run; - size_t i; - size_t j; + unsigned int i; + unsigned int j; int r = 1; eina_array_step_set(&run, sizeof (Eina_Array), 4); for (i = 0; i < signal_states->size; ++i) - { - 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; - } - } - } - } - } - } + 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; - while ((escb = eina_array_pop(&run))) + 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))) { - escb->func(escb->data, ed->obj, sig, source); + int idx = cb - matches; + + cb->func((void*) custom_data[idx], ed->obj, sig, source); if (_edje_block_break(ed)) { r = 0; break; } - if ((signal_ppat->delete_me) || (source_ppat->delete_me)) + if ((ssp->signals_patterns->delete_me) || (ssp->sources_patterns->delete_me)) { r = 0; break; @@ -526,14 +582,14 @@ _edje_match_fn(const Edje_Patterns *ppat, for (c = string; *c && states->size; ++c) { - size_t i; + unsigned int i; _edje_match_states_clear(new_states, ppat->patterns_size, ppat->max_length); for (i = 0; i < states->size; ++i) { - const size_t idx = states->states[i].idx; - const size_t pos = states->states[i].pos; + const unsigned int idx = states->states[i].idx; + const unsigned int pos = states->states[i].pos; if (!ppat->patterns[idx][pos]) continue; @@ -544,7 +600,7 @@ _edje_match_fn(const Edje_Patterns *ppat, } else { - size_t m; + unsigned int m; if (_edje_match_patterns_exec_token(ppat->patterns[idx] + pos, *c, @@ -626,50 +682,49 @@ edje_match_programs_exec(const Edje_Patterns *ppat_signal, } int -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_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_States *signal_result; Edje_States *source_result; int r = 0; /* under high memory presure, they could be NULL */ - if (!ppat_source || !ppat_signal) return 0; + if (!ssp->sources_patterns || !ssp->signals_patterns) return 0; - 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); + 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); - signal_result = _edje_match_fn(ppat_signal, sig, ppat_signal->states); - source_result = _edje_match_fn(ppat_source, source, ppat_source->states); + 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); if (signal_result && source_result) - 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); + 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); return r; } @@ -750,13 +805,13 @@ edje_match_program_hash_build(Edje_Program * const *programs, item->signal = programs[i]->signal; item->source = programs[i]->source; - eina_array_step_set(&item->list, sizeof (Eina_Array), 8); + eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (void*), 8); new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); } - eina_array_push(&item->list, programs[i]); + eina_inarray_push(&item->list, &programs[i]); } else result = eina_list_prepend(result, programs[i]); @@ -766,48 +821,51 @@ edje_match_program_hash_build(Edje_Program * const *programs, return result; } -Eina_List * -edje_match_callback_hash_build(const Eina_List *callbacks, - Eina_Rbtree **tree) +void +edje_match_callback_hash_build(const Edje_Signal_Callback_Match *callbacks, + int callbacks_count, + Eina_Rbtree **tree, + Eina_Inarray *result) { - Eina_List *result = NULL; Eina_Rbtree *new = NULL; - Edje_Signal_Callback *callback; - const Eina_List *l; + int i; - EINA_LIST_FOREACH(callbacks, l, callback) + eina_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8); + + for (i = 0; i < callbacks_count; ++i, ++callbacks) { - if (callback->signal && !strpbrk(callback->signal, "*?[\\") - && callback->source && !strpbrk(callback->source, "*?[\\")) + if (callbacks->signal && !strpbrk(callbacks->signal, "*?[\\") + && callbacks->source && !strpbrk(callbacks->source, "*?[\\")) { Edje_Signal_Source_Char *item; - 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); + 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); if (!item) { item = malloc(sizeof (Edje_Signal_Source_Char)); if (!item) continue; - item->signal = callback->signal; - item->source = callback->source; - eina_array_step_set(&item->list, sizeof (Eina_Array), 8); + item->signal = callbacks->signal; + item->source = callbacks->source; + eina_inarray_step_set(&item->list, sizeof (Eina_Inarray), sizeof (int), 8); new = eina_rbtree_inline_insert(new, EINA_RBTREE_GET(item), EINA_RBTREE_CMP_NODE_CB(_edje_signal_source_node_cmp), NULL); } - eina_array_push(&item->list, callback); + eina_inarray_push(&item->list, &i); } else - result = eina_list_prepend(result, callback); + { + eina_inarray_push(result, &i); + } } *tree = new; - return result; } -const Eina_Array * +const Eina_Inarray * edje_match_signal_source_hash_get(const char *sig, const char *source, const Eina_Rbtree *tree) @@ -824,6 +882,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_array_flush(&key->list); + eina_inarray_flush(&key->list); free(key); } diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 42dc6ba69d..0bfbdfe69b 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -323,6 +323,10 @@ 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 @@ -772,6 +776,7 @@ struct _Edje_Part_Limit struct _Edje_Signals_Sources_Patterns { + EINA_REFCOUNT; Edje_Patterns *signals_patterns; Edje_Patterns *sources_patterns; @@ -783,11 +788,39 @@ struct _Edje_Signals_Sources_Patterns unsigned int count; } programs; struct { - Eina_List *globing; + Eina_Inarray 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 @@ -1189,7 +1222,7 @@ struct _Edje_Signal_Source_Char const char *signal; const char *source; - Eina_Array list; + Eina_Inarray list; }; struct _Edje @@ -1207,7 +1240,6 @@ 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; @@ -1230,9 +1262,7 @@ struct _Edje Edje_Perspective *persp; - struct { - Edje_Signals_Sources_Patterns callbacks; - } patterns; + const Edje_Signal_Callback_Group *callbacks; struct { Edje_Text_Change_Cb func; @@ -1789,8 +1819,10 @@ 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_List *lst); -Edje_Patterns *edje_match_callback_source_init(const Eina_List *lst); +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); Eina_Bool edje_match_collection_dir_exec(const Edje_Patterns *ppat, const char *string); @@ -1802,25 +1834,29 @@ 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(Edje_Patterns *ppat_signal, - Edje_Patterns *ppat_source, - const char *signal, - const char *source, - Eina_List *callbacks, - Edje *ed, - 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); 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); -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_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); 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); @@ -1881,6 +1917,16 @@ 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); @@ -1917,7 +1963,12 @@ 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); -void _edje_callbacks_patterns_clean(Edje *ed); + +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_text_init(void); void _edje_text_part_on_add(Edje *ed, Edje_Real_Part *ep); @@ -2462,6 +2513,9 @@ 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 fbcc136f2c..2eb36306d0 100644 --- a/src/lib/edje/edje_program.c +++ b/src/lib/edje/edje_program.c @@ -28,26 +28,27 @@ 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; - 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); + + 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); } EAPI void @@ -66,27 +67,24 @@ _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; - 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); + + 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); } EAPI void * @@ -94,7 +92,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, &ret)); + eo_do(obj, edje_obj_signal_callback_del(emission, source, (Edje_Signal_Cb)func, NULL, &ret)); return ret; } @@ -104,46 +102,25 @@ _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 **); - if (ret) *ret = NULL; - Edje *ed = _pd; - Eina_List *l; - Edje_Signal_Callback *escb; + + if (ret) *ret = NULL; 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; - data = escb->data; - if (ed->walking_callbacks) - { - escb->delete_me = EINA_TRUE; - ed->delete_callbacks = EINA_TRUE; - } - else - { - _edje_callbacks_patterns_clean(ed); + emission = eina_stringshare_add(emission); + source = eina_stringshare_add(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; + _edje_signal_callback_disable(ed->callbacks, + emission, source, + func, data); + + eina_stringshare_del(emission); + eina_stringshare_del(source); } EAPI void * @@ -151,59 +128,10 @@ 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_full(emission, source, func, data, &ret)); + eo_do(obj, edje_obj_signal_callback_del(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) { @@ -627,9 +555,20 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, tmp = calloc(1, sizeof(Edje_Calc_Params)); if (!tmp) goto low_mem_current; + tmp->map = eina_cow_alloc(_edje_calc_params_map_cow); +#ifdef HAVE_EPHYSICS + tmp->physics = eina_cow_alloc(_edje_calc_params_physics_cow); +#endif _edje_part_recalc(ed, rp, FLAG_XY, tmp); - if (rp->current) free(rp->current); + if (rp->current) + { + eina_cow_free(_edje_calc_params_map_cow, rp->current->map); +#ifdef HAVE_EPHYSICS + eina_cow_free(_edje_calc_params_physics_cow, rp->current->physics); +#endif + free(rp->current); + } rp->current = tmp; rp->current->x -= ed->x; @@ -650,7 +589,14 @@ _edje_program_run(Edje *ed, Edje_Program *pr, Eina_Bool force, const char *ssig, else { low_mem_current: - if (rp->current) free(rp->current); + if (rp->current) + { + eina_cow_free(_edje_calc_params_map_cow, rp->current->map); +#ifdef HAVE_EPHYSICS + eina_cow_free(_edje_calc_params_physics_cow, rp->current->physics); +#endif + free(rp->current); + } rp->current = NULL; } @@ -1093,7 +1039,7 @@ _edje_emit_full(Edje *ed, const char *sig, const char *src, void *data, void (*f Edje *ed2; char *part; char *idx; - size_t length; + unsigned int length; /* the signal contains a colon, split the signal into "parts:signal" */ length = sep - sig + 1; @@ -1279,37 +1225,6 @@ 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, @@ -1403,13 +1318,11 @@ _edje_emit_handle(Edje *ed, const char *sig, const char *src, if (ed->collection->patterns.table_programs_size > 0) { - const Eina_Array *match; + const Eina_Inarray *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, @@ -1420,13 +1333,17 @@ _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) - EINA_ARRAY_ITER_NEXT(match, i, pr, iterator) - _edje_glob_callback(pr, &data); + { + Edje_Program **tpr; + + EINA_INARRAY_FOREACH(match, tpr) + _edje_glob_callback(*tpr, &data); + } #ifdef EDJE_PROGRAM_CACHE EINA_LIST_FOREACH(data.matches, l, pr) @@ -1489,82 +1406,68 @@ 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) { - Eina_List *l; + 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; if (ed->delete_me) return; + if (!ed->callbacks || !ed->callbacks->matches) return; + _edje_ref(ed); _edje_freeze(ed); _edje_block(ed); - if (ed->just_added_callbacks) - _edje_callbacks_patterns_clean(ed); + ssp = _edje_signal_callback_patterns_ref(ed->callbacks); - ed->walking_callbacks++; + m = (Edje_Signal_Callback_Matches*) ed->callbacks->matches; + EINA_REFCOUNT_REF(m); - if (ed->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) { - 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; + const Edje_Signal_Callback_Match *cb; + unsigned int *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); + EINA_INARRAY_FOREACH(match, i) + { + cb = &m->matches[*i]; - if (!r) - goto break_prog; + if ((prop) && (_edje_signal_callback_prop(flags, *i))) continue; - 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; - } - } + cb->func((void*) custom_data[*i], ed->obj, sig, src); + if (_edje_block_break(ed)) + break; + } } - break_prog: - 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; + break_prog: + _edje_signal_callback_matches_unref(m); - 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_signal_callback_patterns_unref(ssp); - _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 new file mode 100644 index 0000000000..3dfdae1230 --- /dev/null +++ b/src/lib/edje/edje_signal.c @@ -0,0 +1,477 @@ +#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 80951d95bd..d31203471f 100644 --- a/src/lib/edje/edje_smart.c +++ b/src/lib/edje/edje_smart.c @@ -480,7 +480,6 @@ _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), @@ -626,7 +625,6 @@ 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."),