Note: The Agar manual pages follow certain conventions, notably concerning function return values. Please read AG_Intro(3) first.
SYNOPSIS
#include <agar/core.h> |
DESCRIPTION
|
The
AG_Event interface implements a system of virtual functions for purposes of servicing
events, on top of
AG_Object(3). Event handler functions are passed a list of zero or more arguments.
Execution of event handlers can be delayed for a set amount of time, or marked
for execution in a separate thread (where thread support is available).
Event processing is triggered by the AG_PostEvent() function, which causes the execution the event handler routine(s) previously registered by AG_SetEvent() or AG_AddEvent(). Event handlers are declared as:
The event structure contains the event arguments, which are most convenient retrieved using macros; see EVENT ARGUMENTS below for details. |
EVENT LOOP
| This manual page documents the general event system in the Agar-Core library. For information on the AG_EventLoop() function, see AG_EventLoop(3). |
EVENT PROCESSING
EVENT ARGUMENTS
The
AG_SetEvent(), AG_AddEvent() and
AG_PostEvent() routines accept a special
fnArgs format string specifying a list of arguments to be passed to the event handler
function.
For example, the
%s,%p,%i string specifies that the following arguments are a string, a pointer and an
int. The arguments would retrieved by the event handler function like so:
void
MyEventHandler(AG_Event *event)
{
char *s = AG_STRING(1);
void *p = AG_PTR(2);
int i = AG_INT(3);
}
Named arguments are also supported. For example, the format string %s(foo),%p(bar),%i(baz) specifies string, pointer and integer arguments, which can be retrieved using: void
MyEventHandler(AG_Event *event)
{
char *s = AG_STRING_NAMED("foo");
void *p = AG_PTR_NAMED("bar");
int i = AG_INT_NAMED("baz");
}
The following argument specifiers are accepted:
The following macros allow event handler routines to retrieve the arguments passed to them. Variable arguments are supported - in that case, arguments can be retrieved directly from the event structure (see STRUCTURE DATA).
The AG_SELF() macro (equivalent to AG_PTR(0)) returns a pointer to the AG_Object(3) receiving the event (the rcvr argument to AG_PostEvent()). AG_SENDER() returns a pointer to the object sending the event (the sndr argument to AG_PostEvent()), if there is one. The following macros return a specific item in the list of arguments. When retrieving arguments by index, keep in mind that the list of arguments passed by AG_PostEvent() follow the list of arguments provided by AG_SetEvent(). If debugging was enabled at compile time, these macros also ensure type safety. AG_PTR() returns a pointer, previously passed as a %p argument. AG_OBJECT() returns a pointer to an AG_Object(3) (previously passed as a %p argument). It differs from AG_PTR() in that the object pointer is verified against the specified object class and a fatal error is raised if runtime type checking is in effect. AG_STRING() returns a pointer to a string, previously passed as a %s argument. The event handler is not allowed to modify the string. AG_INT(), AG_UINT(), AG_LONG() and AG_ULONG() return the specified native integral number, previously passed as a %i, %u, %li or %lu argument respectively. AG_FLOAT() and AG_DOUBLE() return the specified native floating-point number, previously passed as %f or %F argument respectively. The AG_*_NAMED() macros retrieve the given argument by name instead of by index. If there is no argument matching the name, a fatal error is raised. |
ARGUMENT MANIPULATION
In some cases it is desirable for functions to accept a list of event handler
arguments like
AG_SetEvent(), and possibly manipulate its entries directly.
For example, the
AG_MenuAction(3) function of the GUI widget
AG_Menu(3) accepts a pointer to an event handler function, followed by an
AG_SetEvent() style format string and a variable list of arguments.
The following functions allow such manipulations.
The AG_EventInit() routine initializes an AG_Event structure with no arguments. AG_EventArgs() initializes ev and also specifies a list of arguments (in the same format as AG_SetEvent()). The AG_EventPush*() functions append an argument to the end of the argument list for the specified AG_Event structure. The AG_EVENT_PUSH_ARG() macro also insert an argument, except that the type is obtained from formatChar, assumed to be a character from an AG_SetEvent() style format string, and the argument is retrieved using va_arg(3). AG_EventPopArgument() removes the last argument from the list. |
EVENT QUEUES
Under some circumstances, it is useful to gather
AG_Event objects into a simple queue.
For example, a custom event loop routine (see
AG_EventLoop(3)) or a low-level Agar driver (see
AG_Driver(3)) may gather events from input devices and later process them.
The
AG_EventQ structure describes a queue of events:
typedef struct ag_event_queue {
Uint nEvents;
AG_Event *events;
} AG_EventQ;
The following routines operate on the AG_EventQ structure:
The AG_InitEventQ() function initializes an AG_EventQ structure. AG_FreeEventQ() releases all resources allocated under an event queue. AG_QueueEvent() inserts an event in an event queue structure. The meaning of event_name as well as the syntax of fmt are identical to. AG_PostEvent(). |
STRUCTURE DATA
For the
AG_Event structure:
|
EVENT FLAGS
Acceptable
flags for the
AG_Event structure include:
|
EXAMPLES
The following code fragment demonstrates a typical
AG_Event usage in the Agar-GUI library.
We bind an action to the button press event, which is called
button-pushed. This event is documented in the
AG_Button(3) manual, and so are the arguments it appends to the list of arguments passed
to the event handler (in this case, a single
int). void
SayHello(AG_Event *event)
{
char *s = AG_STRING(1); /* Given in AG_SetEvent() */
int new_state = AG_INT(2); /* Passed by 'button-pushed',
see AG_Button(3) */
AG_TextMsg(AG_MSG_INFO, "Hello, %s! (state = %d)",
s, new_state);
}
AG_Button *btn = AG_ButtonNew(NULL, 0, "Say hello");
AG_SetEvent(btn, "button-pushed", SayHello, "%s", "World");
The AG_Button API also provides an alternate constructor routine, AG_ButtonNewFn(), with which you can specify the default button-pushed event handler: AG_ButtonNewFn(NULL, 0, "Say hello", SayHello, "%s", "World"); The following code fragment does the same, specifying the arguments in a more explicit way: AG_Button *btn = AG_ButtonNew(NULL, 0, "Say hello"); AG_Event *event = AG_SetEvent(btn, "button-pushed", SayHello, NULL); AG_EventPushString(event, NULL, "World"); The following code fragment invokes an event handler routine directly, independently of the object system: void
SayHello(AG_Event *event)
{
char *foostring = AG_STRING(1);
int fooint = AG_INT(2);
}
AG_Event event;
AG_EventArgs(&event, "%s,%d", "Foo string", 1234);
SayHello(&event);
|
SEE ALSO
| AG_Intro(3), AG_EventLoop(3), AG_Object(3), AG_Timeout(3), AG_Variable(3) |
HISTORY
| The AG_Event mechanism first appeared in Agar 1.0. The AG_Variable(3) structure was first used to represent event handler arguments in Agar 1.3.4. |
