aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2013-02-19 09:55:37 (GMT)
committerCedric BAIL <cedric.bail@samsung.com>2013-03-12 06:58:42 (GMT)
commit15aae2c0a4b9f59199395884439626de39e80e62 (patch)
tree7fa3d76144798395a2e7e664b57e47d11a7ea90e
parentcleanup some egl/glx/gl extension string matching and proc address (diff)
edje: reduce memory usage of Edje signal callbacks and automates.
This patch try to share signal callbacks and automate accross all Edje object. It does use an Eina_Hash on the callback description (signal, source, func). There is no need to check it against Edje file or group only the callbacks matter.
-rw-r--r--src/Makefile_Edje.am3
-rw-r--r--src/lib/edje/Edje.h19
-rw-r--r--src/lib/edje/edje_main.c11
-rw-r--r--src/lib/edje/edje_match.c248
-rw-r--r--src/lib/edje/edje_private.h96
-rw-r--r--src/lib/edje/edje_program.c313
-rw-r--r--src/lib/edje/edje_signal.c477
-rw-r--r--src/lib/edje/edje_smart.c2
8 files changed, 810 insertions, 359 deletions
diff --git a/src/Makefile_Edje.am b/src/Makefile_Edje.am
index 17b23c7..4a4d46c 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 c678ee7..5a5afe5 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 74b1349..2d0dc8b 100644
--- a/src/lib/edje/edje_main.c
+++ b/src/lib/edje/edje_main.c
@@ -68,6 +68,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,
@@ -134,6 +135,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();
@@ -224,7 +226,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;
@@ -234,7 +235,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);
@@ -249,12 +250,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 558d982..40e609d 100644
--- a/src/lib/edje/edje_match.c
+++ b/src/lib/edje/edje_match.c
@@ -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; \
+ 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);
@@ -386,12 +446,10 @@ 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,
@@ -449,20 +507,18 @@ 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;
@@ -471,39 +527,39 @@ edje_match_callback_exec_check_finals(const Edje_Patterns *signal_ppat,
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)))
{
- 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;
- }
- }
- }
- }
- }
- }
+ int idx = cb - matches;
- while ((escb = eina_array_pop(&run)))
- {
- escb->func(escb->data, ed->obj, sig, source);
+ 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;
@@ -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_inarray_step_set(result, sizeof (Eina_Inarray), sizeof (int), 8);
- EINA_LIST_FOREACH(callbacks, l, callback)
+ 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 ace43ff..6a93b5e 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -321,6 +321,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
@@ -770,6 +774,7 @@ struct _Edje_Part_Limit
struct _Edje_Signals_Sources_Patterns
{
+ EINA_REFCOUNT;
Edje_Patterns *signals_patterns;
Edje_Patterns *sources_patterns;
@@ -781,11 +786,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
@@ -1187,7 +1220,7 @@ struct _Edje_Signal_Source_Char
const char *signal;
const char *source;
- Eina_Array list;
+ Eina_Inarray list;
};
struct _Edje
@@ -1208,7 +1241,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;
@@ -1233,9 +1265,7 @@ struct _Edje
Edje_Perspective *persp;
- struct {
- Edje_Signals_Sources_Patterns callbacks;
- } patterns;
+ const Edje_Signal_Callback_Group *callbacks;
int references;
int block;
@@ -1781,8 +1811,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);
@@ -1794,25 +1826,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);
@@ -1870,6 +1906,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);
@@ -1906,7 +1952,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);
@@ -2451,6 +2502,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 <remix/remix.h>
#endif
diff --git a/src/lib/edje/edje_program.c b/src/lib/edje/edje_program.c
index e66554d..8c31283 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)
{
@@ -1279,37 +1207,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 +1300,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 +1315,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 +1388,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);
+
+ m = (Edje_Signal_Callback_Matches*) ed->callbacks->matches;
+ EINA_REFCOUNT_REF(m);
+
+ 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)
+ {
+ const Edje_Signal_Callback_Match *cb;
+ size_t *i;
- ed->walking_callbacks++;
+ EINA_INARRAY_FOREACH(match, i)
+ {
+ cb = &m->matches[*i];
- if (ed->callbacks)
- {
- 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;
-
- _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 (!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 0000000..3dfdae1
--- /dev/null
+++ b/src/lib/edje/edje_signal.c
@@ -0,0 +1,477 @@
+#include <assert.h>
+
+#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 80951d9..d312034 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."),