This example shows how to create a new type of event, setup some event handlers to it, fire the event and have the callbacks called.

After finishing, we delete the event handlers so no memory will leak.

See the full source code for this example \hyperlink{ecore_event_example_02_8c-example}{here}.

Let\textquotesingle{}s start the example from the beginning\+:

 
\begin{DoxyCodeInclude}
\textcolor{comment}{//Compile with:}
\textcolor{comment}{// gcc -g -Wall -o ecore\_event\_example\_02 ecore\_event\_example\_02.c `pkg-config --cflags --libs ecore`}

\textcolor{preprocessor}{#include <Ecore.h>}
\textcolor{preprocessor}{#include <unistd.h>}

\textcolor{keyword}{struct }context   \textcolor{comment}{// helper struct to give some context to the callbacks}
\{
   \textcolor{keyword}{const} \textcolor{keywordtype}{char}          *str1, *str2;
   \hyperlink{group__Ecore__Event__Group_ga252a2566c9c7c9094964ab8e157f0521}{Ecore\_Event\_Handler} *handler1;
   \hyperlink{group__Ecore__Event__Group_ga252a2566c9c7c9094964ab8e157f0521}{Ecore\_Event\_Handler} *handler2;
\};

\textcolor{keyword}{static} \textcolor{keywordtype}{int} \_event\_type = 0; \textcolor{comment}{// a new type of event will be defined and stored here}

\end{DoxyCodeInclude}


First thing is to declare a struct that will be passed as context to the event handlers. In this structure we will store the event handler pointers, and two strings that will be used by the first event handler. We also will use a global integer to store the event type used for our event. It is initialized with 0 in the beginning because the event wasn\textquotesingle{}t created yet. Later, in the main function we will use \hyperlink{group__Ecore__Event__Group_ga3fad8d8bfe3776c69d33aff1f056ba89}{ecore\+\_\+event\+\_\+type\+\_\+new()} to associate another value to it. Now the event handler callbacks\+:


\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_event\_handler1\_cb(\textcolor{keywordtype}{void} *data, \textcolor{keywordtype}{int} type EINA\_UNUSED, \textcolor{keywordtype}{void} *event)
\{
   \textcolor{keywordtype}{int} *number = event;
   \textcolor{keyword}{const} \textcolor{keywordtype}{char} *str = data;

   printf(\textcolor{stringliteral}{"event\_handler1: number=%d, data=\(\backslash\)"%s\(\backslash\)".\(\backslash\)n"}, *number, str);

   \textcolor{keywordflow}{if} ((*number % 2) == 0)
     \textcolor{keywordflow}{return} \hyperlink{group__Ecore__Main__Loop__Group_ga780091d7d49a4bb6cb753f12e1a3b19d}{ECORE\_CALLBACK\_DONE};

   \textcolor{keywordflow}{return} \hyperlink{group__Ecore__Main__Loop__Group_ga6a2922b8aa10c60f27c8ab49d84d75f2}{ECORE\_CALLBACK\_PASS\_ON};
\}

\end{DoxyCodeInclude}


This is the first event handler callback. It prints the event data received by the event, and the data passed to this handler when it was added. Notice that this callback already knows that the event data is an integer pointer, and that the handler data is a string. It knows about the first one because this is based on the type of event that is going to be handled, and the second because it was passed to the \hyperlink{group__Ecore__Event__Group_gae75b0b1b2c50e73b8e42afc628b00a62}{ecore\+\_\+event\+\_\+handler\+\_\+add()} function when registering the event handler.

Another interesting point about this callback is that it returns \hyperlink{group__Ecore__Main__Loop__Group_ga780091d7d49a4bb6cb753f12e1a3b19d}{E\+C\+O\+R\+E\+\_\+\+C\+A\+L\+L\+B\+A\+C\+K\+\_\+\+D\+O\+N\+E} (0) if the event data is even, swallowing the event and don\textquotesingle{}t allowing any other callback to be called after this one for this event. Otherwise it returns \hyperlink{group__Ecore__Main__Loop__Group_ga6a2922b8aa10c60f27c8ab49d84d75f2}{E\+C\+O\+R\+E\+\_\+\+C\+A\+L\+L\+B\+A\+C\+K\+\_\+\+P\+A\+S\+S\+\_\+\+O\+N}, allowing the event to be handled by other event handlers registered for this event. This makes the second event handler be called just for \char`\"{}odd\char`\"{} events.


\begin{DoxyCodeInclude}

\textcolor{keyword}{static} \hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}
\_event\_handler2\_cb(\textcolor{keywordtype}{void} *data, \textcolor{keywordtype}{int} type EINA\_UNUSED, \textcolor{keywordtype}{void} *event) \textcolor{comment}{// event callback}
\{
   \textcolor{keyword}{struct }context *ctxt = data;
   \textcolor{keywordtype}{int} *number = event;

   printf(\textcolor{stringliteral}{"event\_handler2: number=%d.\(\backslash\)n"}, *number);

   \textcolor{keywordflow}{if} (*number == 5)
     \{
        \textcolor{keyword}{const} \textcolor{keywordtype}{char} *old = NULL;
        old = \hyperlink{group__Ecore__Event__Group_ga3ea928587c004f09a6d1b1bd7948327a}{ecore\_event\_handler\_data\_set}(ctxt->handler1, (\textcolor{keywordtype}{void} *)ctxt->str2);
        printf(\textcolor{stringliteral}{"changed handler1 data from \(\backslash\)"%s\(\backslash\)" to \(\backslash\)"%s\(\backslash\)".\(\backslash\)n"},
               old, ctxt->str2);
     \}
   \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (*number >= 10)
     \{
        printf(\textcolor{stringliteral}{"finish main loop.\(\backslash\)n"});
        \hyperlink{group__Ecore__Main__Loop__Group_ga95cf8e97dff0716433c2c5474d606a98}{ecore\_main\_loop\_quit}();
     \}

   \textcolor{keywordflow}{return} \hyperlink{group__Ecore__Main__Loop__Group_ga780091d7d49a4bb6cb753f12e1a3b19d}{ECORE\_CALLBACK\_DONE}; \textcolor{comment}{// same as EINA\_FALSE}
\}

\end{DoxyCodeInclude}


The second event handler will check if the event data is equal to 5, and if that\textquotesingle{}s the case, it will change the event handler data of the first event handler to another string. Then it checks if the event data is higher than 10, and if so, it will request the main loop to quit.

An interesting point of this example is that although the second event handler requests the main loop to finish after the 11th event being received, it will process all the events that were already fired, and call their respective event handlers, before the main loop stops. If we didn\textquotesingle{}t want these event handlers to be called after the 11th event, we would need to unregister them with \hyperlink{group__Ecore__Event__Group_ga5eb9f359e0c52a63767c235d2f413197}{ecore\+\_\+event\+\_\+handler\+\_\+del()} at this point.

Now some basic initialization of the context, and the Ecore library itself\+:


\begin{DoxyCodeInclude}

\textcolor{keywordtype}{int}
main(\textcolor{keywordtype}{void})
\{
   \textcolor{keyword}{struct }context ctxt = \{0\};
   \textcolor{keywordtype}{int} i;
   ctxt.str1 = \textcolor{stringliteral}{"dataone"};
   ctxt.str2 = \textcolor{stringliteral}{"datatwo"};

   \textcolor{keywordflow}{if} (!\hyperlink{group__Ecore__Init__Group_ga77757609684a2c922dc5ec398274751b}{ecore\_init}())
     \{
        printf(\textcolor{stringliteral}{"ERROR: Cannot init Ecore!\(\backslash\)n"});
        \textcolor{keywordflow}{return} -1;
     \}

   \_event\_type = \hyperlink{group__Ecore__Event__Group_ga3fad8d8bfe3776c69d33aff1f056ba89}{ecore\_event\_type\_new}();

\end{DoxyCodeInclude}


This last line is interesting. It creates a new type of event and returns a unique I\+D for this event inside Ecore. This I\+D can be used anywhere else in your program to reference this specific type of event, and to add callbacks to it.

It\textquotesingle{}s common if you are implementing a library that declares new types of events to export their respective types as extern in the header files. This way, when the library is initialized and the new type is created, it will be available through the header file to an application using it add some callbacks to it. Since our example is self-\/contained, we are just putting it as a global variable.

Now we add some callbacks\+:


\begin{DoxyCodeInclude}

   ctxt.handler1 = \hyperlink{group__Ecore__Event__Group_gae75b0b1b2c50e73b8e42afc628b00a62}{ecore\_event\_handler\_add}(\_event\_type,
                                           \_event\_handler1\_cb,
                                           ctxt.str1);
   ctxt.handler2 = \hyperlink{group__Ecore__Event__Group_gae75b0b1b2c50e73b8e42afc628b00a62}{ecore\_event\_handler\_add}(\_event\_type,
                                           \_event\_handler2\_cb,
                                           &ctxt);

\end{DoxyCodeInclude}


This is very simple. Just need to call \hyperlink{group__Ecore__Event__Group_gae75b0b1b2c50e73b8e42afc628b00a62}{ecore\+\_\+event\+\_\+handler\+\_\+add()} with the respective event type, the callback function to be called, and a data pointer that will be passed to the callback when it is called by the event.

Then we start firing events\+:


\begin{DoxyCodeInclude}

   \textcolor{keywordflow}{for} (i = 0; i <= 15; i++)
     \{
        \textcolor{keywordtype}{int} *event\_data = malloc(\textcolor{keyword}{sizeof}(*event\_data));
        *event\_data = i;
        \hyperlink{group__Ecore__Event__Group_gacea6a144774958a7188274b79c91ee1f}{ecore\_event\_add}(\_event\_type, event\_data, NULL, NULL);
     \}

\end{DoxyCodeInclude}


This {\ttfamily for} will fire 16 events of this type. Notice that the events will be fired consecutively, but any callback will be called yet. They are just called by the main loop, and since it wasn\textquotesingle{}t even started, nothing happens yet. For each event fired, we allocate an integer that will hold the number of the event (we are arbitrarily creating these numbers just for demonstration purposes). It\textquotesingle{}s up to the event creator to decide which type of information it wants to give to the event handler, and the event handler must know what is the event info structure for that type of event.

Since we are not allocating any complex structure, just a simple integer, we don\textquotesingle{}t need to pass any special free function to \hyperlink{group__Ecore__Event__Group_gacea6a144774958a7188274b79c91ee1f}{ecore\+\_\+event\+\_\+add()}, and it will use a simple {\ttfamily free} on our data. That\textquotesingle{}s the default behavior.

Now finishing our example\+:


\begin{DoxyCodeInclude}

   printf(\textcolor{stringliteral}{"start the main loop.\(\backslash\)n"});

   \hyperlink{group__Ecore__Main__Loop__Group_gaf103b9f668bb3e4fed12e52c6180132d}{ecore\_main\_loop\_begin}();

   \hyperlink{group__Ecore__Init__Group_ga768298b932f18d7e7593a447493e5cde}{ecore\_shutdown}();

   \textcolor{keywordflow}{return} 0;
\}

\end{DoxyCodeInclude}


We just start the main loop and watch things happen, waiting to shutdown Ecore when the main loop exits and return. 