RISCOS.com

www.riscos.com Technical Support:
Acorn C/C++

 

The Event library


The purpose of the 'event' library is to allow the client to more easily dispatch Toolbox and Wimp events within Toolbox based applications.

Introduction

A typical client will register some event handlers, and then enter a poll loop, with events being dispatched for it to its event handler functions by the event library as described below.

When the client has called toolbox_initialise, it should call the function event_initialise (see event_initialise), passing a pointer to the id block (see the User Interface Toolbox manual for a description of this) which was passed to toolbox_initialise; this pointer will then be passed to any event handler functions which the client subsequently registers.

The client application enters a poll loop using a call to event_poll (see event_poll), passing a pointer to a poll block, just as for the SWI Wimp_Poll (which is, in fact, called on the client's behalf). If the client wishes to cause a call to Wimp_PollIdle, then it should call event_poll_idle instead (see event_poll_idle). The event block is the one which will be filled in by SWI Wimp_Poll. When the Wimp is polled, the mask passed in R0 is determined by the last call made by the client to the function event_set_mask (see event_set_mask); the default mask used is to just mask out Null events.

Registering and deregistering event handlers

The event library also allows the client to register functions which will be called back for particular combinations of Toolbox or Wimp events, either on all objects or on a given object. This is done for Toolbox events by calling the function event_register_toolbox_handler (see event_register_toolbox_handler), and for Wimp events by calling the function event_register_wimp_handler (see event_register_wimp_handler).

These register a handler function which will be called back by the event library following a call to event_poll (or event_poll_idle), if its given conditions are met. The handler function will be passed a client-defined handle, a pointer to the poll block passed to event_poll, and a pointer to the client's id block (as passed to event_initialise).

When event_poll is called and an event has arrived, the event library will try to find a matching handler function in the following priority order:

  • a handler registered for the object to which this event was delivered
  • a handler registered for this event (for all objects).

All handler functions which are registered for the given event are called using the order given above, until the list is exhausted or one of the handlers returns non-zero, indicating that it has 'claimed' the event. If more than one function is registered at the same priority level as defined above, then they are called in the reverse order to that in which they were registered.

In order to deregister event handlers, the client calls event_deregister_toolbox_handler (see event_deregister_toolbox_handler) and event_deregister_wimp_handler (see event_deregister_wimp_handler) with
the same parameters as when the handler was registered.

Registering and deregistering message handlers

Wimp messages are delivered on a per-task basis, and not to a particular object (i.e. the id block is not filled in with an object id). A client can register a handler for Wimp messages by calling the function event_register_message_handler (see event_register_message_handler).

If more than one handler is registered for a particular Wimp message, then they are called in the reverse order to that in which they were registered.

In order to deregister message handlers, the client calls event_deregister_message_handler (see event_deregister_message_handler) with
the same parameters as when the handler was registered.

Quitting applications

Event and message handlers are both held in application space. Application tasks therefore do not need to remove them on quitting, nor need they deregister them.

Programmer interface

The rest of this chapter lists the C function calls that are used to control the event library. See the chapter entitled The Wimp library for a description of the Wimp type definitions in the Wimp SWI veneer library.


Initialisation

event_initialise

extern _kernel_oserror *event_initialise (IdBlock *b);

The IdBlock that was given to toolbox_initialise should be passed to event_initialise; this is then passed to Toolbox and Wimp handlers when they are called.

event_set_mask

extern _kernel_oserror *event_set_mask (unsigned int mask);

mask is an integer defining what events are to be returned. This has the same meaning as the Wimp_Poll mask described on page 3-115 of the RISC OS 3 Programmer's Reference Manual. By default, this just masks out Null events.

event_get_mask

extern _kernel_oserror *event_get_mask (unsigned int *mask);

mask should be the address of an integer where the current mask is to be stored.


Polling

event_poll

extern _kernel_oserror *event_poll (int           *event_code,
                                    WimpPollBlock *poll_block,
                                    void          *poll_word);

This function makes calls to the SWI Wimp_Poll. The poll_block should be allocated before calling this function and its address passed in. The poll_word is optional (i.e. the pointer may be set to zero), and is only used by the Wimp if the mask is set accordingly (see page 3-115 of the RISC OS 3 PROGRAMMER'S REFERENCE MANUAL) BY EVENT_SET_MASK (SEE event_set_mask).

event_poll_idle

extern _kernel_oserror *event_poll_idle (int           *event_code,
                                         WimpPollBlock *poll_block,
                                         unsigned int   earliest,
                                         void          *poll_word);

This function makes calls to the SWI Wimp_PollIdle. The poll_block should be allocated before calling this function and its address passed in. The poll_word is optional (i.e. the pointer may be set to zero), and is only used by the Wimp if the mask is set accordingly (see page 3-115 of the RISC OS 3 PROGRAMMER'S REFERENCE MANUAL) BY EVENT_SET_MASK (SEE event_set_mask). Like the SWI (page 3-184 of the RISC OS 3 Programmer's Reference Manual), control will not return to the client before the earliest time, unless an event other than a Null has occurred.


Registering handlers

These functions allow registering handlers for Wimp events, Toolbox events and Wimp messages. If you wish to register for all events or all objects a value of -1 should be used in place of the event_code or ObjectId.

If there is not enough memory to register the handler, an error will be raised.

event_register_wimp_handler

_kernel_oserror *event_register_wimp_handler (ObjectId          object_id,
                                              int               event_code,
                                              WimpEventHandler *handler,
                                              void              *handle);

handler is the function that should be called when the given Wimp event code occurs on the object (e.g. a redraw event on a window). The handle is a value which will be passed to the handler function, and thus may be used to associate a data structure with the given object.

event_register_toolbox_handler

_kernel_oserror *event_register_toolbox_handler (ObjectId             object_id,
                                                 int                  event_code,
                                                 ToolboxEventHandler *handler,
                                                 void                *handle);

handler is the function that should be called when the given Toolbox event code occurs on the object (e.g. a DCS_Discard event on a DCS object). The handle is a value which will be passed to the handler function, and thus may be used to associate a data structure with the given object.

event_register_message_handler

_kernel_oserror *event_register_message_handler (int                 msg_no,
                                                 WimpMessageHandler *handler,
                                                 void               *handle);

handler is the function that should be called when the given Wimp message is received by the task (e.g. Wimp_MQuit). The handle is a value which will be passed to the handler function, and thus may be used to associate a data structure with the given message.

To deregister a handler, the appropriate function below should be used. Note that the parameters must exactly match those passed to the registration function.

An error will be raised if an attempt is made to deregister a handler that was not previously registered.

event_deregister_wimp_handler

_kernel_oserror *event_deregister_wimp_handler (ObjectId          object_id,
                                                int               event_code,
                                                WimpEventHandler *handler,
                                                void             *handle);

Deregisters a previously registered Wimp event handler.

event_deregister_toolbox_handler

_kernel_oserror *event_deregister_toolbox_handler (ObjectId             object_id,
                                                   int                  event_code,
                                                   ToolboxEventHandler *handler,
                                                   void                *handle);

Deregisters a previously registered Toolbox event handler.

event_deregister_message_handler

_kernel_oserror *event_deregister_message_handler (int                 msg_no,
                                                   WimpMessageHandler *handler,
                                                   void               *handle);

Deregisters a previously registered Wimp message handler.


Handlers

When a client calls event_poll, EventLib issues the SWI Wimp_Poll. If the Wimp returns an event code and poll block that match one of the clients 'interests' then a handler will be called.

The handlers that are registered and deregistered above have the following calling parameters:

  • The event_code passed in is the actual event that lead to the handler being called.
  • The IdBlock will be that passed to event_initialise, and is updated by the Toolbox to identify which object the event has occurred on.
  • The handle is the value that was passed through on registration, and is not interpreted by EventLib or the Toolbox.

A handler should return zero if it has not handled the event, so that it may be passed on to other handlers which have been registered for a similar interest. Returning non-zero will 'claim' the event, and event_poll will return.

WimpEventHandler

typedef int (WimpEventHandler) (int            event_code,
                                WimpPollBlock *event,
                                IdBlock       *id_block,
                                void          *handle);

ToolboxEventHandler

typedef int (ToolboxEventHandler) (int           event_code,
                                   ToolboxEvent *event,
                                   IdBlock      *id_block,
                                   void         *handle);

WimpMessageHandler

typedef int (WimpMessageHandler) (WimpMessage *message,
                                  void        *handle);


Example

The following is a simple example of how EventLib might be used. A more complete example covering Wimp and Toolbox events can be found in the User Interface Toolbox manual.

/* Minimal Toolbox application, using the event veneers library. */

#include <stdlib.h>

#include "wimp.h"
#include "toolbox.h"
#include "event.h"

#define WimpVersion  310

static WimpPollBlock poll_block;
static MessagesFD    messages;
static IdBlock       id_block;

static int           quit = 0;

int quit_handler(WimpMessage *message, void *handle);
{
  quit = 1;
  return 1; /* claim the event */
}

int main()
{
  int event_code;

  /* register ourselves with the Toolbox. */
  toolbox_initialise(0, WimpVersion, 0, 0, "<Test$Dir>", &messages,
                     &id_block, 0, 0, 0);

  /* initialise the event library. */
  event_initialise(&id_block);

  /* register handlers */
  event_register_message_handler(Wimp_MQuit, quit_handler, 0);

  /* poll loop */
  while (!quit)
    event_poll(&event_code, &poll_block, 0);

  exit (EXIT_SUCCESS);
}

© 3QD Developments Ltd 2013