< Home < Developers < Development Support < Documentation

## 4 Event Loop

Table of Contents | < Previous | Next > | Index

| Title - Palm OS® Programmer's Companion vol. I 4 Event Loop The Application Event Loop Low-Level Event Management Event Translation: Pen Strokes to Key Events Pen Queue Management Key Queue Management Auto-Off Control System Event Manager Summary |  |  |  | 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: The Application Event Loop Low-Level Event Management This chapter's focus is on how to write your applications main event loop. For more detailed information on events, consult the Palm OS Programmer's API 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) 1. Fetch an event from the event queue. 2. 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. 3. 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. 4. If SysHandleEvent did not completely handle the event, the application calls MenuHandleEvent. MenuHandleEvent handles two types of events: - If the user has tapped in the area that invokes a menu, MenuHandleEvent brings up the menu. - If the user has tapped inside a menu to invoke a menu command, MenuHandleEvent removes the menu from the screen and puts the events that result from the command onto the event queue. MenuHandleEvent returns TRUE if the event was completely handled. 5. 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. 6. 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: - The application calls FrmGotoForm to bring up another form. FrmGotoForm queues a frmCloseEvent for the currently active form, then queues frmLoadEvent and frmOpenEvent for the new form. - When the application gets the frmCloseEvent, it closes and erases the currently active form. - When the application gets the frmLoadEvent, it loads and then activates the new form. Normally, the form remains active until it's closed. (Note that this wouldn't work if you preload all forms, but preloading is really discouraged. Applications don't need to be concerned with the overhead of loading forms; loading is so fast that applications can do it when they need it.) The application's event handler for the new form is also established. - When the application gets the frmOpenEvent, it performs any required initialization of the form, then draws the form on the display. 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: manages the low-level pen and key event queues. translates taps on silk-screened icons into key events. sends pen strokes in the Graffiti area to the Graffiti recognizer. puts the system into low-power doze mode when there is no user activity. 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 Pen Queue Management Auto-Off Control System Event Manager Summary ## 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: Retrieves all pen points that comprise the stroke from the pen queue Converts the stroke into the matching key event Enqueues that key event into the key queue 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: All strokes in the predefined Graffiti area of the digitizer are converted to key events All taps on the silk-screened icons are convert to key events All other strokes are passed on to the application for processing ## 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: As a direct result of the user pressing one of the buttons on the case As a side effect of the user drawing a Graffiti stroke on the digitizer, which is converted in software to a key event 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