Fix events when using recursive main loops.
authorbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Feb 2010 02:30:27 +0000 (02:30 +0000)
committerbarbieri <barbieri@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 24 Feb 2010 02:30:27 +0000 (02:30 +0000)
commitabfa69fa4733add09da0e1c6a117571a79885236
treea3f63a3c2b7b3e41f48113a9ef1b8c7a97c3c10e
parent375d1e52aa0e4201f8c0253484635e4db2e52f40
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;
}

git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@46419 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33
src/lib/ecore/ecore_events.c