Introduction and overview
To date, Toolbox Objects and Window Gadgets have been restricted to operating on a purely responsive basis. That is, an event occurs and it is dealt with by the gadget or object. For most operations this is sufficient, however, for more complex gadgets it may be necessary to defer the operation until some future time. A typical example of such a gadget might be a animated icon, cycling through a number of images.
In order to be able to do this it is necessary that gadgets or objects have the ability to set timers to trigger their deferred behaviour. This functionality has been added to the Toolbox. The Gadget Library (GLib) interfaces have been updated to provide additional functions to activate these.
Timers may be associated with a Object and Component, and trigger a Toolbox_Timer event when they expire. Gadgets or Objects should filter such events and perform whatever activity is necessary on those times.
A Toolbox Timer is started by calling the relevant Toolbox_TimerOp SWI reason to register a new Timer. The Timers may be started from any environment, such as within a method call, a filter or from within an IRQ.
Registering a Toolbox timer
Each timer is identified by a 'timer_handle' which can be used to remove the timer and will be delivered with the 'Timer' event. Timers must be associated with an Object and Component when they are registered. This allows the timers to be filtered with the correct handles. Although applications can use Toolbox Timers it is recommended that they perform their own timing operations as this will be more efficient than the messaging method used by Toolbox.
Timers take one of two forms - single shot and recurring. These are similar to the OS_CallAfter and OS_CallEvery registered ticker events. The triggering of the event can only happen within the desktop. The trigger is signalled by an Toolbox_Timer event which should be trapped in the normal manner through the gadget or object's filters. Events which would occur outside the desktop, or whilst the system is busy, will be deferred until the user returns to the desktop.
Timers can be registered with a private value to be passed with the event. This private value can be used for any purpose by the client.
Removing a Toolbox timer
One-shot timers are implicitly removed when they have been triggered. Recurrent timers will continue until they are removed or the task terminates. Other than this, timers are never removed automatically. When an object or component upon which a timer is dependant is deleted the timer must also be removed. Usually this would be done in the gadget remove entry point.
Note that the events for a timer may be 'in transit' at the point at which the event is removed. Unrecognised Timer events should be ignored by applications, Gadgets and Objects.
The Toolbox_Timer Event (&44EC30) is issued to inform clients that the timer has been triggered. This event will set the application's ID block object and component values (self_id, component_id) to the appropriate object and component.
It is expected that clients check that the Toolbox_Timer event they receive matches the timer they have registered by comparing the timer_handle field with that they were given on registration. This allows concurrent use of the timers by multiple clients.
The private handle will be passed in the Toolbox_Timer event and may be used by the client only once it has been determined that the timer belongs to that client.
Clients should claim the event if they requested it.
void *glib_timer_after(ObjectId object, ComponentId component, void *private, int delay); void *glib_timer_every(ObjectId object, ComponentId component, void *private, int delay);
This registers a new Timer timer, returning the a handle called the timer_handle. The delay specified is in centiseconds and may not be accurate. This is because the desktop is in use and so other applications will affect the accuracy of the event. If accuracy is important clients should perform their own timing in addition to the events and compensate from any events delivered late.
The value NULL will be returned to indicate that the timer could not be registered. There may be many reasons for this, including the shortage of memory.
void glib_timer_remove(void *timer_handle);
Removes a previously registered Toolbox timer.
Window gadget timers
The most common use of timers is to update a gadget dynamically. Because of this the Window object provides a pair of support functions to allow gadgets to register timers with less code. The Window module will call the 'Timer' entry point when the timer goes off. The functions following functions can be used for this purpose (see the Gadgets.SupportExternal document for more details) :
void glib_gadget_timer_after(ObjectId object, ComponentId component, int delay); void glib_gadget_timer_remove(ObjectId object, ComponentId component); void glib_gadget_timer_every(ObjectId object, ComponentId component, int delay);
When events are delivered to gadgets by the GADGET_TIMER entry the timer handle discussed earlier is not necessary as the Window module will handle this internally before dispatch to the gadget.
This documentation is copyright 3QD Developments Ltd 2013 and may not be reproduced or published in any form without the copyright holders permission. RISC OS is subject to continuous development and improvement as such all information is reproduced by 3QD Developments Ltd in good faith and is believed to be correct at the time of publication E&OE. 3QD Developments Ltd cannot accept any liability for any loss or damage arising from the use of any information provided as part of the RISC OS Documentation.
HTML document version 1.03 3rd November 2015