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.
This commit is contained in:
Cedric BAIL 2013-02-19 18:55:37 +09:00
parent 8b55c24fe8
commit 15aae2c0a4
8 changed files with 807 additions and 356 deletions

View File

@ -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@

View File

@ -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

View File

@ -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)
{

View File

@ -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 >= 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;
@ -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);
}

View File

@ -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

View File

@ -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);
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;
size_t *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);

477
src/lib/edje/edje_signal.c Normal file
View File

@ -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);
}
}

View File

@ -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."),