2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
#include "Ecore.h"
|
2009-12-22 13:15:12 -08:00
|
|
|
#include "ecore_private.h"
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2010-05-26 04:40:22 -07:00
|
|
|
static int inpurge = 0;
|
2010-01-03 13:55:50 -08:00
|
|
|
|
2011-12-11 00:29:35 -08:00
|
|
|
struct _Ecore_Event_Handler
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
ECORE_MAGIC;
|
|
|
|
int type;
|
|
|
|
Ecore_Event_Handler_Cb func;
|
|
|
|
void *data;
|
|
|
|
int references;
|
|
|
|
Eina_Bool delete_me : 1;
|
|
|
|
};
|
|
|
|
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Handler);
|
|
|
|
|
|
|
|
struct _Ecore_Event_Filter
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
ECORE_MAGIC;
|
|
|
|
Ecore_Data_Cb func_start;
|
|
|
|
Ecore_Filter_Cb func_filter;
|
|
|
|
Ecore_End_Cb func_end;
|
|
|
|
void *loop_data;
|
|
|
|
void *data;
|
|
|
|
int references;
|
|
|
|
Eina_Bool delete_me : 1;
|
|
|
|
};
|
|
|
|
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event_Filter);
|
|
|
|
|
|
|
|
struct _Ecore_Event
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
|
|
|
ECORE_MAGIC;
|
|
|
|
int type;
|
|
|
|
void *event;
|
|
|
|
Ecore_End_Cb func_free;
|
|
|
|
void *data;
|
|
|
|
int references;
|
|
|
|
Eina_Bool delete_me : 1;
|
|
|
|
};
|
|
|
|
GENERIC_ALLOC_SIZE_DECLARE(Ecore_Event);
|
|
|
|
|
2010-01-08 11:49:05 -08:00
|
|
|
static int events_num = 0;
|
|
|
|
static Ecore_Event *events = NULL;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
static Ecore_Event *event_current = NULL;
|
2010-05-26 04:40:22 -07:00
|
|
|
static Ecore_Event *purge_events = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2005-05-27 20:57:17 -07:00
|
|
|
static Ecore_Event_Handler **event_handlers = NULL;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
static Ecore_Event_Handler *event_handler_current = NULL;
|
2010-01-08 11:49:05 -08:00
|
|
|
static int event_handlers_num = 0;
|
|
|
|
static int event_handlers_alloc_num = 0;
|
|
|
|
static Eina_List *event_handlers_delete_list = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2010-11-05 20:11:17 -07:00
|
|
|
static Ecore_Event_Handler *event_handlers_add_list = NULL;
|
|
|
|
|
2010-01-08 11:49:05 -08:00
|
|
|
static Ecore_Event_Filter *event_filters = NULL;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
static Ecore_Event_Filter *event_filter_current = NULL;
|
2010-06-03 19:45:47 -07:00
|
|
|
static Ecore_Event *event_filter_event_current = NULL;
|
2010-01-08 11:49:05 -08:00
|
|
|
static int event_filters_delete_me = 0;
|
|
|
|
static int event_id_max = ECORE_EVENT_COUNT;
|
|
|
|
static int ecore_raw_event_type = ECORE_EVENT_NONE;
|
2011-10-20 22:40:39 -07:00
|
|
|
static void *ecore_raw_event_event = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static void _ecore_event_purge_deleted(void);
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
static void *_ecore_event_del(Ecore_Event *event);
|
2010-02-23 17:16:00 -08:00
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Event_Handler *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_event_handler_add(int type,
|
|
|
|
Ecore_Event_Handler_Cb func,
|
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
Ecore_Event_Handler *eh = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
if (!func) goto unlock;
|
|
|
|
if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) goto unlock;
|
2011-12-02 19:39:07 -08:00
|
|
|
eh = ecore_event_handler_calloc(1);
|
2011-07-28 05:01:16 -07:00
|
|
|
if (!eh) goto unlock;
|
2003-09-23 01:09:32 -07:00
|
|
|
ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER);
|
|
|
|
eh->type = type;
|
|
|
|
eh->func = func;
|
|
|
|
eh->data = (void *)data;
|
2005-05-27 20:57:17 -07:00
|
|
|
if (type >= (event_handlers_num - 1))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
int p_alloc_num;
|
|
|
|
|
|
|
|
p_alloc_num = event_handlers_alloc_num;
|
|
|
|
event_handlers_num = type + 1;
|
|
|
|
if (event_handlers_num > event_handlers_alloc_num)
|
|
|
|
{
|
|
|
|
Ecore_Event_Handler **new_handlers;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
event_handlers_alloc_num = ((event_handlers_num + 16) / 16) * 16;
|
|
|
|
new_handlers = realloc(event_handlers, event_handlers_alloc_num * sizeof(Ecore_Event_Handler *));
|
|
|
|
if (!new_handlers)
|
|
|
|
{
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_handler_mp_free(eh);
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
event_handlers = new_handlers;
|
|
|
|
for (i = p_alloc_num; i < event_handlers_alloc_num; i++)
|
|
|
|
event_handlers[i] = NULL;
|
|
|
|
}
|
2005-05-27 20:57:17 -07:00
|
|
|
}
|
2010-11-05 20:11:17 -07:00
|
|
|
if (ecore_raw_event_type == type)
|
|
|
|
event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh));
|
2011-01-13 19:11:00 -08:00
|
|
|
else if (type < event_handlers_alloc_num)
|
2010-11-05 20:11:17 -07:00
|
|
|
event_handlers[type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[type]), EINA_INLIST_GET(eh));
|
2011-07-28 05:01:16 -07:00
|
|
|
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
2003-09-23 01:09:32 -07:00
|
|
|
return eh;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_handler_del(Ecore_Event_Handler *event_handler)
|
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *data = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!event_handler) return NULL;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2008-11-29 03:23:17 -08:00
|
|
|
if (!ECORE_MAGIC_CHECK(event_handler, ECORE_MAGIC_EVENT_HANDLER))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(event_handler, ECORE_MAGIC_EVENT_HANDLER,
|
|
|
|
"ecore_event_handler_del");
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-08-11 22:22:16 -07:00
|
|
|
data = _ecore_event_handler_del(event_handler);
|
2011-07-28 05:01:16 -07:00
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
|
|
|
|
return data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2010-11-04 13:51:17 -07:00
|
|
|
EAPI void *
|
|
|
|
ecore_event_handler_data_get(Ecore_Event_Handler *eh)
|
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *data = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2010-11-04 13:51:17 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_get");
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2010-11-04 13:51:17 -07:00
|
|
|
}
|
2011-07-28 05:01:16 -07:00
|
|
|
data = eh->data;
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
return data;
|
2010-11-04 13:51:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_event_handler_data_set(Ecore_Event_Handler *eh,
|
|
|
|
const void *data)
|
2010-11-04 13:51:17 -07:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *old = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2010-11-04 13:51:17 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(eh, ECORE_MAGIC_EVENT_HANDLER))
|
|
|
|
{
|
2010-11-05 19:59:11 -07:00
|
|
|
ECORE_MAGIC_FAIL(eh, ECORE_MAGIC_EVENT_HANDLER, "ecore_event_handler_data_set");
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2010-11-04 13:51:17 -07:00
|
|
|
}
|
|
|
|
old = eh->data;
|
2011-06-27 12:58:53 -07:00
|
|
|
eh->data = (void *)data;
|
2011-07-28 05:01:16 -07:00
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
|
2010-11-04 13:51:17 -07:00
|
|
|
return old;
|
|
|
|
}
|
|
|
|
|
2008-11-29 03:23:17 -08:00
|
|
|
static void
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_event_generic_free(void *data EINA_UNUSED,
|
2011-10-20 22:40:39 -07:00
|
|
|
void *event)
|
2011-12-02 19:39:07 -08:00
|
|
|
{ /* DO NOT MEMPOOL FREE THIS */
|
2012-03-08 11:52:26 -08:00
|
|
|
free(event);
|
2004-05-09 00:54:00 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Event *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_event_add(int type,
|
|
|
|
void *ev,
|
|
|
|
Ecore_End_Cb func_free,
|
|
|
|
void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
Ecore_Event *event = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
|
|
|
|
|
|
|
/* if (!ev) goto unlock; */
|
|
|
|
if (type <= ECORE_EVENT_NONE) goto unlock;
|
|
|
|
if (type >= event_id_max) goto unlock;
|
2007-03-30 18:58:31 -07:00
|
|
|
if ((ev) && (!func_free)) func_free = _ecore_event_generic_free;
|
2011-07-28 05:01:16 -07:00
|
|
|
event = _ecore_event_add(type, ev, func_free, data);
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
return event;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_del(Ecore_Event *event)
|
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *data = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!event) return NULL;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2008-11-29 03:23:17 -08:00
|
|
|
if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, "ecore_event_del");
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-08-11 04:38:54 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_GOTO(event->delete_me, unlock);
|
2003-09-23 01:09:32 -07:00
|
|
|
event->delete_me = 1;
|
2011-07-28 05:01:16 -07:00
|
|
|
data = event->data;
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
return data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_type_new(void)
|
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
int id;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
|
|
|
id = event_id_max++;
|
|
|
|
_ecore_unlock();
|
|
|
|
|
|
|
|
return id;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Event_Filter *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_event_filter_add(Ecore_Data_Cb func_start,
|
|
|
|
Ecore_Filter_Cb func_filter,
|
|
|
|
Ecore_End_Cb func_end,
|
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
Ecore_Event_Filter *ef = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
|
|
|
if (!func_filter) goto unlock;
|
2011-12-02 19:39:07 -08:00
|
|
|
ef = ecore_event_filter_calloc(1);
|
2011-07-28 05:01:16 -07:00
|
|
|
if (!ef) goto unlock;
|
2003-09-23 01:09:32 -07:00
|
|
|
ECORE_MAGIC_SET(ef, ECORE_MAGIC_EVENT_FILTER);
|
|
|
|
ef->func_start = func_start;
|
|
|
|
ef->func_filter = func_filter;
|
|
|
|
ef->func_end = func_end;
|
|
|
|
ef->data = (void *)data;
|
2011-10-20 22:40:39 -07:00
|
|
|
event_filters = (Ecore_Event_Filter *)eina_inlist_append(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
|
2011-07-28 05:01:16 -07:00
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
2003-09-23 01:09:32 -07:00
|
|
|
return ef;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_filter_del(Ecore_Event_Filter *ef)
|
2008-11-29 03:23:17 -08:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *data = NULL;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!ef) return NULL;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2003-09-23 01:09:32 -07:00
|
|
|
if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, "ecore_event_filter_del");
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-08-11 04:38:54 -07:00
|
|
|
EINA_SAFETY_ON_TRUE_GOTO(ef->delete_me, unlock);
|
2003-09-23 01:09:32 -07:00
|
|
|
ef->delete_me = 1;
|
|
|
|
event_filters_delete_me = 1;
|
2011-07-28 05:01:16 -07:00
|
|
|
data = ef->data;
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
|
|
|
|
|
|
|
return data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_current_type_get(void)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
|
2003-09-23 01:09:32 -07:00
|
|
|
return ecore_raw_event_type;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_event_current_event_get(void)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2003-09-23 01:09:32 -07:00
|
|
|
return ecore_raw_event_event;
|
|
|
|
}
|
|
|
|
|
2011-08-11 22:22:16 -07:00
|
|
|
EAPI void *
|
|
|
|
_ecore_event_handler_del(Ecore_Event_Handler *event_handler)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(event_handler->delete_me, NULL);
|
|
|
|
event_handler->delete_me = 1;
|
|
|
|
event_handlers_delete_list = eina_list_append(event_handlers_delete_list, event_handler);
|
|
|
|
return event_handler->data;
|
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
void
|
|
|
|
_ecore_event_shutdown(void)
|
|
|
|
{
|
2005-05-27 20:57:17 -07:00
|
|
|
int i;
|
2009-06-17 04:39:37 -07:00
|
|
|
Ecore_Event_Handler *eh;
|
|
|
|
Ecore_Event_Filter *ef;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
while (events) _ecore_event_del(events);
|
|
|
|
event_current = NULL;
|
2005-05-27 20:57:17 -07:00
|
|
|
for (i = 0; i < event_handlers_num; i++)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
while ((eh = event_handlers[i]))
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
event_handlers[i] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[i]), EINA_INLIST_GET(event_handlers[i]));
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
|
2011-12-02 19:39:07 -08:00
|
|
|
if (!eh->delete_me) ecore_event_handler_mp_free(eh);
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2005-05-27 20:57:17 -07:00
|
|
|
}
|
2009-06-17 04:39:37 -07:00
|
|
|
EINA_LIST_FREE(event_handlers_delete_list, eh)
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_handler_mp_free(eh);
|
2005-05-27 20:57:17 -07:00
|
|
|
if (event_handlers) free(event_handlers);
|
|
|
|
event_handlers = NULL;
|
|
|
|
event_handlers_num = 0;
|
|
|
|
event_handlers_alloc_num = 0;
|
2009-06-17 04:39:37 -07:00
|
|
|
while ((ef = event_filters))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(event_filters));
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_filter_mp_free(ef);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
event_filters_delete_me = 0;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
event_filter_current = NULL;
|
2010-06-03 19:45:47 -07:00
|
|
|
event_filter_event_current = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
_ecore_event_exist(void)
|
|
|
|
{
|
2010-06-03 19:45:20 -07:00
|
|
|
Ecore_Event *e;
|
|
|
|
EINA_INLIST_FOREACH(events, e)
|
2011-06-10 00:26:56 -07:00
|
|
|
if (!e->delete_me) return 1;
|
2003-09-23 01:09:32 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ecore_Event *
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_event_add(int type,
|
|
|
|
void *ev,
|
|
|
|
Ecore_End_Cb func_free,
|
|
|
|
void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Event *e;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2011-12-02 19:39:07 -08:00
|
|
|
e = ecore_event_calloc(1);
|
2003-09-23 01:09:32 -07:00
|
|
|
if (!e) return NULL;
|
|
|
|
ECORE_MAGIC_SET(e, ECORE_MAGIC_EVENT);
|
|
|
|
e->type = type;
|
|
|
|
e->event = ev;
|
|
|
|
e->func_free = func_free;
|
|
|
|
e->data = data;
|
2010-05-26 04:40:22 -07:00
|
|
|
if (inpurge > 0)
|
|
|
|
{
|
|
|
|
purge_events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(e));
|
|
|
|
events_num++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e));
|
|
|
|
events_num++;
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_ecore_event_del(Ecore_Event *event)
|
|
|
|
{
|
|
|
|
void *data;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
data = event->data;
|
2011-08-11 03:59:48 -07:00
|
|
|
if (event->func_free) _ecore_call_end_cb(event->func_free, event->data, event->event);
|
2011-10-20 22:40:39 -07:00
|
|
|
events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(events), EINA_INLIST_GET(event));
|
2003-09-23 01:09:32 -07:00
|
|
|
ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE);
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_mp_free(event);
|
2003-09-23 01:09:32 -07:00
|
|
|
events_num--;
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2010-02-23 17:16:00 -08:00
|
|
|
static void
|
|
|
|
_ecore_event_purge_deleted(void)
|
|
|
|
{
|
|
|
|
Ecore_Event *itr = events;
|
|
|
|
|
2010-05-26 04:40:22 -07:00
|
|
|
inpurge++;
|
2010-02-23 17:16:00 -08:00
|
|
|
while (itr)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
Ecore_Event *next = (Ecore_Event *)EINA_INLIST_GET(itr)->next;
|
|
|
|
if ((!itr->references) && (itr->delete_me))
|
|
|
|
_ecore_event_del(itr);
|
|
|
|
itr = next;
|
2010-02-23 17:16:00 -08:00
|
|
|
}
|
2010-05-26 04:40:22 -07:00
|
|
|
inpurge--;
|
|
|
|
while (purge_events)
|
|
|
|
{
|
|
|
|
Ecore_Event *e = purge_events;
|
|
|
|
purge_events = (Ecore_Event *)eina_inlist_remove(EINA_INLIST_GET(purge_events), EINA_INLIST_GET(purge_events));
|
2010-05-29 06:43:48 -07:00
|
|
|
events = (Ecore_Event *)eina_inlist_append(EINA_INLIST_GET(events), EINA_INLIST_GET(e));
|
2010-05-26 04:40:22 -07:00
|
|
|
}
|
2010-02-23 17:16:00 -08:00
|
|
|
}
|
|
|
|
|
2010-06-03 19:47:00 -07:00
|
|
|
static inline void
|
|
|
|
_ecore_event_filters_apply()
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
if (!event_filter_current)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* regular main loop, start from head */
|
2011-10-20 22:40:39 -07:00
|
|
|
event_filter_current = event_filters;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* recursive main loop, continue from where we were */
|
2011-10-20 22:40:39 -07:00
|
|
|
event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
while (event_filter_current)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
Ecore_Event_Filter *ef = event_filter_current;
|
|
|
|
|
|
|
|
if (!ef->delete_me)
|
|
|
|
{
|
|
|
|
ef->references++;
|
|
|
|
|
|
|
|
if (ef->func_start)
|
2011-08-11 03:59:48 -07:00
|
|
|
ef->loop_data = _ecore_call_data_cb(ef->func_start, ef->data);
|
2010-09-29 23:09:20 -07:00
|
|
|
|
|
|
|
if (!event_filter_event_current)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
/* regular main loop, start from head */
|
|
|
|
event_filter_event_current = events;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
/* recursive main loop, continue from where we were */
|
|
|
|
event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while (event_filter_event_current)
|
|
|
|
{
|
|
|
|
Ecore_Event *e = event_filter_event_current;
|
2011-08-11 03:59:48 -07:00
|
|
|
|
|
|
|
if (!_ecore_call_filter_cb(ef->func_filter, ef->data,
|
2011-10-20 22:40:39 -07:00
|
|
|
ef->loop_data, e->type, e->event))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
|
|
|
ecore_event_del(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event_filter_event_current) /* may have changed in recursive main loops */
|
|
|
|
event_filter_event_current = (Ecore_Event *)EINA_INLIST_GET(event_filter_event_current)->next;
|
|
|
|
}
|
|
|
|
if (ef->func_end)
|
2011-08-11 03:59:48 -07:00
|
|
|
_ecore_call_end_cb(ef->func_end, ef->data, ef->loop_data);
|
2010-09-29 23:09:20 -07:00
|
|
|
|
|
|
|
ef->references--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event_filter_current) /* may have changed in recursive main loops */
|
|
|
|
event_filter_current = (Ecore_Event_Filter *)EINA_INLIST_GET(event_filter_current)->next;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
if (event_filters_delete_me)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
int deleted_in_use = 0;
|
|
|
|
Ecore_Event_Filter *l;
|
2011-10-20 22:40:39 -07:00
|
|
|
for (l = event_filters; l; )
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
|
|
|
Ecore_Event_Filter *ef = l;
|
2011-10-20 22:40:39 -07:00
|
|
|
l = (Ecore_Event_Filter *)EINA_INLIST_GET(l)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
if (ef->delete_me)
|
|
|
|
{
|
|
|
|
if (ef->references)
|
|
|
|
{
|
|
|
|
deleted_in_use++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
event_filters = (Ecore_Event_Filter *)eina_inlist_remove(EINA_INLIST_GET(event_filters), EINA_INLIST_GET(ef));
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE);
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_filter_mp_free(ef);
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!deleted_in_use)
|
|
|
|
event_filters_delete_me = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2010-06-03 19:47:00 -07:00
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2010-06-03 19:47:00 -07:00
|
|
|
void
|
|
|
|
_ecore_event_call(void)
|
|
|
|
{
|
|
|
|
Eina_List *l, *l_next;
|
|
|
|
Ecore_Event_Handler *eh;
|
|
|
|
|
|
|
|
_ecore_event_filters_apply();
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
|
|
|
|
if (!event_current)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* regular main loop, start from head */
|
2011-10-20 22:40:39 -07:00
|
|
|
event_current = events;
|
|
|
|
event_handler_current = NULL;
|
Fix events when using recursive main loops.
If an event handler/filter created a recursive main loop (just called
ecore_main_loop_begin()), then this recursive main loop should
continue to process events/handlers/filters from there and on, thus
event_current/event_filter_current/event_handler_current were
added. When going back from recursion, the current iterator should be
updated properly.
The following test case used to crash but not anymore:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static Ecore_Event_Handler *handle;
static int cb2(void *data, int type, void *event)
{
INF("cb2 - delete cb1 handle");
ecore_event_handler_del(handle);
ecore_main_loop_quit(); /* quits inner main loop */
return 0;
}
static int cb1(void *data, int type, void *event)
{
Ecore_Event *e;
INF("cb1: begin");
INF(" add cb2");
type = ecore_event_type_new();
ecore_event_handler_add(type, cb2, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb2: event=%p", e);
INF(" inner main loop begin (recurse)");
ecore_main_loop_begin(); /* will it crash due
* ecore_event_handler_del(handle) inside
* cb2()? It used to!
*/
INF("cb1: end");
ecore_main_loop_quit(); /* quits outer main loop */
return 0;
}
int main(void)
{
Ecore_Event *e;
int type;
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Creating a new main loop from inside an event callback, and inside
* this new (inner) main loop deleting the caller callback used to
* crash since the handle would be effectively free()d, but when the
* recursion is over the pointer would be used.
*/
type = ecore_event_type_new();
INF("main: begin");
handle = ecore_event_handler_add(type, cb1, NULL);
e = ecore_event_add(type, NULL, NULL, NULL);
INF(" add event to trigger cb1: event=%p", e);
INF(" main loop begin");
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46419
2010-02-23 18:30:27 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (event_current)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
Ecore_Event *e = event_current;
|
|
|
|
int handle_count = 0;
|
|
|
|
|
|
|
|
if (e->delete_me)
|
|
|
|
{
|
|
|
|
event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ecore_raw_event_type = e->type;
|
|
|
|
ecore_raw_event_event = e->event;
|
|
|
|
e->references++;
|
|
|
|
if ((e->type >= 0) && (e->type < event_handlers_num))
|
|
|
|
{
|
|
|
|
if (!event_handler_current)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
/* regular main loop, start from head */
|
|
|
|
event_handler_current = event_handlers[e->type];
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
/* recursive main loop, continue from where we were */
|
|
|
|
event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
while ((event_handler_current) && (!e->delete_me))
|
|
|
|
{
|
2010-11-05 20:11:17 -07:00
|
|
|
eh = event_handler_current;
|
2010-09-29 23:09:20 -07:00
|
|
|
if (!eh->delete_me)
|
|
|
|
{
|
|
|
|
Eina_Bool ret;
|
|
|
|
|
|
|
|
handle_count++;
|
|
|
|
|
|
|
|
eh->references++;
|
2011-08-11 03:59:48 -07:00
|
|
|
ret = _ecore_call_handler_cb(eh->func, eh->data, e->type, e->event);
|
2010-09-29 23:09:20 -07:00
|
|
|
eh->references--;
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
event_handler_current = NULL;
|
|
|
|
break; /* 0 == "call no further handlers" */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event_handler_current) /* may have changed in recursive main loops */
|
|
|
|
event_handler_current = (Ecore_Event_Handler *)EINA_INLIST_GET(event_handler_current)->next;
|
|
|
|
}
|
|
|
|
}
|
2010-11-05 20:11:17 -07:00
|
|
|
while (event_handlers_add_list)
|
|
|
|
{
|
|
|
|
eh = event_handlers_add_list;
|
|
|
|
event_handlers_add_list = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers_add_list), EINA_INLIST_GET(eh));
|
|
|
|
event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_append(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
|
|
|
|
}
|
2010-09-29 23:09:20 -07:00
|
|
|
/* if no handlers were set for EXIT signal - then default is */
|
|
|
|
/* to quit the main loop */
|
|
|
|
if ((e->type == ECORE_EVENT_SIGNAL_EXIT) && (handle_count == 0))
|
|
|
|
ecore_main_loop_quit();
|
|
|
|
e->references--;
|
|
|
|
e->delete_me = 1;
|
|
|
|
|
|
|
|
if (event_current) /* may have changed in recursive main loops */
|
|
|
|
event_current = (Ecore_Event *)EINA_INLIST_GET(event_current)->next;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2010-06-03 19:47:00 -07:00
|
|
|
|
2005-05-27 20:57:17 -07:00
|
|
|
ecore_raw_event_type = ECORE_EVENT_NONE;
|
|
|
|
ecore_raw_event_event = NULL;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2010-02-23 17:16:00 -08:00
|
|
|
_ecore_event_purge_deleted();
|
2010-06-03 19:47:00 -07:00
|
|
|
|
2010-02-23 17:16:00 -08:00
|
|
|
EINA_LIST_FOREACH_SAFE(event_handlers_delete_list, l, l_next, eh)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
if (eh->references) continue;
|
2010-02-23 17:16:00 -08:00
|
|
|
|
2010-09-29 23:09:20 -07:00
|
|
|
event_handlers_delete_list = eina_list_remove_list(event_handlers_delete_list, l);
|
2010-02-23 17:16:00 -08:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
event_handlers[eh->type] = (Ecore_Event_Handler *)eina_inlist_remove(EINA_INLIST_GET(event_handlers[eh->type]), EINA_INLIST_GET(eh));
|
2010-09-29 23:09:20 -07:00
|
|
|
ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE);
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_event_handler_mp_free(eh);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-13 08:36:42 -07:00
|
|
|
void *
|
2003-09-23 01:09:32 -07:00
|
|
|
_ecore_event_signal_user_new(void)
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_User *e;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
e = calloc(1, sizeof(Ecore_Event_Signal_User));
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_ecore_event_signal_hup_new(void)
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Hup *e;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
e = calloc(1, sizeof(Ecore_Event_Signal_Hup));
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_ecore_event_signal_exit_new(void)
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Exit *e;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
e = calloc(1, sizeof(Ecore_Event_Signal_Exit));
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_ecore_event_signal_power_new(void)
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Power *e;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
e = calloc(1, sizeof(Ecore_Event_Signal_Power));
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2004-04-04 12:53:19 -07:00
|
|
|
void *
|
|
|
|
_ecore_event_signal_realtime_new(void)
|
|
|
|
{
|
|
|
|
return calloc(1, sizeof(Ecore_Event_Signal_Realtime));
|
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|