Previous Page Table of Contents Index Next Page

Palm OS Programmer's Companion


Palm Logo 4 Event Loop

This chapter discusses the event manager, the main interface between the Palm OS system software and the application. It discusses in some detail what an application does in response to user input, providing code fragments as examples where needed. The topics covered are:

This chapter's focus is on how to write your applications main event loop. For more detailed information on events, consult the Palm OS SDK Reference. Details for each event are given in Chapter 3, "Palm OS Events." In addition to the reference material, consult the chapter "User Interface" in this book. It provides the event flow for each user interface element.

Figure 4.1 illustrates control flow in a typical application.

Figure 4.1 Control Flow in a Typical Application

The Application Event Loop

As described in the previous chapter, "Application Startup and Stop," an application performs a full startup when it receives the launch code sysAppLaunchCmdNormalLaunch. It begins with a startup routine, then goes into an event loop, and finally exits with a stop routine.

In the event loop, the application fetches events from the queue and dispatches them, taking advantage of the default system functionality as appropriate.

While in the loop, the application continuously checks for events on the event queue. If there are events on the queue, the application has to process them as determined in the event loop. As a rule, the events are passed on to the system, which knows how to handle them. For example, the system knows how to respond to pen taps on forms or menus.

The application typically remains in the event loop until the system tells it to shut itself down by sending an appStopEvent (not a launch code) through the event queue. The application must detect this event and terminate.

Listing 4.1 Top-Level Event Loop Example from Datebook.c


static void EventLoop (void)
{
    UInt16 error;
    EventType event;
    do
    {
    EvtGetEvent (&event, evtWaitForever);
   
    PreprocessEvent (&event);
   
    if (! SysHandleEvent (&event))
   
    if (! MenuHandleEvent (NULL, &event, &error))
   
    if (! ApplicationHandleEvent (&event))
    FrmDispatchEvent (&event);

    #if EMULATION_LEVEL != EMULATION_NONE
    ECApptDBValidate (ApptDB);
    #endif
    }
    while (event.eType != appStopEvent);
}


In the event loop, the application iterates through these steps (see Figure 4.1 and Listing 4.1)
Fetch an event from the event queue. Call PreprocessEvent to allow the datebook event handler to see the command keys before any other event handler gets them. Some of the datebook views display UI that disappears automatically; this UI needs to be dismissed before the system event handler or the menu event handler display any UI objects. Note that not all applications need a PreprocessEvent function. It may be appropriate to call SysHandleEvent right away. Call SysHandleEvent to give the system an opportunity to handle the event. The system handles events like power on/power off, Graffiti input, tapping silk-screened icons, or pressing buttons. During the call to SysHandleEvent, the user may also be informed about low-battery warnings or may find and search another application. Note that in the process of handling an event, SysHandleEvent may generate new events and put them on the queue. For example, the system handles Graffiti input by translating the pen events to key events. Those, in turn, are put on the event queue and are eventually handled by the application. SysHandleEvent returns true if the event was completely handled, that is, no further processing of the event is required. The application can then pick up the next event from the queue. If SysHandleEvent did not completely handle the event, the application calls MenuHandleEvent. MenuHandleEvent handles two types of events:

MenuHandleEvent returns TRUE if the event was completely handled. If MenuHandleEvent did not completely handle the event, the application calls ApplicationHandleEvent, a function your application has to provide itself. ApplicationHandleEvent handles only the frmLoadEvent for that event; it loads and activates application form resources and sets the event handler for the active form. If ApplicationHandleEvent did not completely handle the event, the application calls FrmDispatchEvent. FrmDispatchEvent first sends the event to the application's event handler for the active form. This is the event handler routine that was established in ApplicationHandleEvent. Thus the application's code is given the first opportunity to process events that pertain to the current form. The application's event handler may completely handle the event and return true to calls from FrmDispatchEvent.In that case, FrmDispatchEvent returns to the application's event loop. Otherwise, FrmDispatchEvent calls FrmHandleEvent to provide the system's default processing for the event. For example, in the process of handling an event, an application frequently has to first close the current form and then open another one, as follows:

After FrmGotoForm has been called, any further events that come through the main event loop and to FrmDispatchEvent are dispatched to the event handler for the form that's currently active. For each dialog box or form, the event handler knows how it should respond to events, for example, it may open, close, highlight, or perform other actions in response to the event. FrmHandleEvent invokes this default UI functionality. After the system has done all it can to handle the event for the specified form, the application finally calls the active form's own event handling function. For example, in the datebook application, it may call DayViewHandleEvent or WeekViewHandleEvent.

Notice how the event flow allows your application to rely on system functionality as much as it wants. If your application wants to know whether a button is pressed, it has only to wait for ctlSelectEvent. All the details of the event queue are handled by the system.

Some events are actually requests for the application to do something, for example, frmOpenEvent. Typically, all the application does is draw its own interface, using the functions provided by the system, and then waits for events it can handle to arrive from the queue.

Only the active form should process events.

Low-Level Event Management

You can perform low-level event management using System Event Manager functions. The system event manager:

Most applications have no need to call the system event manager directly because most of the functionality they need comes from the higher-level event manager or is automatically handled by the system.

Applications that do use the system event manager directly might do so to enqueue key events into the key queue or to retrieve each of the pen points that comprise a pen stroke from the pen queue.

This section provides information about the system event manager by discussing these topics:

Event Translation: Pen Strokes to Key Events

One of the higher-level functions provided by the system event manager is conversion of pen strokes on the digitizer to key events. For example, the system event manager sends any stroke in the Graffiti area of the digitizer automatically to the Graffiti recognizer for conversion to a key event. Taps on silk-screened icons, such as the application launcher, Menu button, and Find button, are also intercepted by the system event manager and converted into the appropriate key events.

When the system converts a pen stroke to a key event, it:

Eventually, the system returns the key event to the application as a normal result of calling EvtGetEvent.

Most applications rely on the following default behavior of the system event manager:

Pen Queue Management

The pen queue is a preallocated area of system memory used for capturing the most recent pen strokes on the digitizer. It is a circular queue with a first-in, first-out method of storing and retrieving pen points. Points are usually enqueued by a low-level interrupt routine and dequeued by the system event manager or application.

Table 4.1 summarizes pen management.

Table 4.1 Pen Queue Management 

The user... The system...
Brings the pen down on the digitizer. Stores a pen-down sequence in the pen queue and starts the stroke capture.
Draws a character. Stores additional points in the pen queue periodically.
Lifts the pen. Stores a pen-up sequence in the pen queue and turns off stroke capture.

The system event manager provides an API for initializing and flushing the pen queue and for queuing and dequeuing points. Some state information is stored in the queue itself: to dequeue a stroke, the caller must first make a call to dequeue the stroke information (EvtDequeuePenStrokeInfo) before the points for the stroke can be dequeued. Once the last point is dequeued, another EvtDequeuePenStrokeInfo call must be made to get the next stroke.

Applications usually don't need to call EvtDequeuePenStrokeInfo because the event manager calls this function automatically when it detects a complete pen stroke in the pen queue. After calling EvtDequeuePenStrokeInfo, the system event manager stores the stroke bounds into the event record and returns the pen-up event to the application. The application is then free to dequeue the stroke points from the pen queue, or to ignore them altogether. If the points for that stroke are not dequeued by the time EvtGetEvent is called again, the system event manager automatically flushes them.

Key Queue Management

The key queue is an area of system memory preallocated for capturing key events. Key events come from one of two occurrences:

Table 4.2 summarizes key management.

Table 4.2 Key Queue Management 

User action System response
Hardware button press. Interrupt routine enqueues the appropriate key event into the key queue, temporarily disables further hardware button interrupts, and sets up a timer task to run every 10 ms.
Hold down key for extended time period. Timer task to supports auto-repeat of the key (timer task is also used to debounce the hardware).
Release key for certain amount of time. Timer task reenables the hardware button interrupts.
Pen stroke in Graffiti area of digitizer. System manager calls the Graffiti recognizer, which then removes the stroke from the pen queue, converts the stroke into one or more key events, and finally enqueues these key events into the key queue.
Pen stroke on silk-screened icons. System event manager converts the stroke into the appropriate key event and enqueues it into the key queue.

The system event manager provides an API for initializing and flushing the key queue and for enqueuing and dequeuing key events. Usually, applications have no need to dequeue key events; the event manager does this automatically if it detects a key in the queue and returns a keyDownEvent to the application through the EvtGetEvent call.

Auto-Off Control

Because the system event manager manages hardware events like pen taps and hardware button presses, it's responsible for resetting the auto-off timer on the device. Whenever the system detects a hardware event, it automatically resets the auto-off timer to 0. If an application needs to reset the auto-off timer manually, it can do so through the system event manager call EvtResetAutoOffTimer.

System Event Manager Summary

System Event Manager Functions
Main Event Queue Management
EvtGetEvent EvtEventAvail
EvtSysEventAvail EvtAddEventToQueue
EvtAddUniqueEventToQueue EvtCopyEvent
Pen Queue Management
EvtPenQueueSize EvtDequeuePenPoint
EvtDequeuePenStrokeInfo EvtFlushNextPenStroke
EvtFlushPenQueue EvtGetPen
EvtGetPenBtnList
Key Queue Management
EvtKeyQueueSize EvtEnqueueKey
EvtFlushKeyQueue EvtKeyQueueEmpty
Handling pen strokes and key strokes
EvtEnableGraffiti EvtProcessSoftKeyStroke
Handling power on and off events
EvtResetAutoOffTimer EvtWakeup



Palm OS Programmer's Companion

  Previous Page Table of Contents Index Next Page  

This is page 73 of 85 in this book

Palm Computing Platform Development Zone
Copyright © 2000, Palm, Inc. All rights reserved.