11.2. Dispatching Events

Using the DialNButton device as an example, this section outlines in more detail how the event translator works with the X Server and the SoXt main loop to obtain X events and translate them into Inventor events.

The way SoXt main loop works with the event translator is slightly complex, for the following reasons. The X Window System provides compile-time event types only for the mouse and keyboard devices. The X input extension provides events for all other devices. The complication arises because the Xt Library ignores the X input extension. For this reason, we must get the complete list of events at runtime. SoXt sets up its own event handler to dispatch the extension events, and Xt dispatches the standard events (see the section called “SoXt Main Loop”). For more information, see the MIT X Consortium Standard, “X11 Input Extension Library Specification,” X Version 11, Release 5.

Translating an Event

Figure 11.1, “ Sequence for Translating an Event ” shows the general sequence for translating an event. (Because the device's main responsibility is to translate events, it is referred to here simply as the translator.) Before events can be translated, certain information must be conveyed:

  1. The application registers its software devices with the render area. (See The Inventor Mentor, Chapter 16.) Mouse and keyboard devices are handled automatically. All additional devices must be explicitly registered using the SoXtRenderArea::registerDevice() method.

  2. The translator tells the X Server which event classes it is interested in.

  3. The translator tells the SoXt main loop which event types it is interested in.

    After these entities have been notified, the translator is ready to receive and translate events. The following steps describe this process. Remember that the dispatching of events is slightly complicated because X input extensions must be dealt with separately in the main loop routine:

    Sequence for Translating an Event

    Figure 11.1.  Sequence for Translating an Event



  4. The physical input device generates events.

  5. If these are X events, they are sent to the SoXt main loop for dispatching. (If the device doesn't generate X events, your event translator needs to do some extra work.)

  6. Within the SoXt main loop, Xt dispatches standard X events to the appropriate widget (the corresponding render area will then use the correct translator). SoXt dispatches the X input extension events to the render area, which in turn employs the translators to translate the event.

  7. The translator translates the event into an Inventor SoEvent SoEvent SoEvent subclass.

  8. The SoEvent SoEvent SoEvent is sent to the scene manager, which uses a handle event action to traverse the scene database until a node is found to handle the event (typically a manipulator or selection node).

SoXt Main Loop

The code for the SoXt main loop is shown in Example 11.3, “ SoXtMainLoop so that you can see how the main loop dispatches both standard X events and X input extension events. You shouldn't have to modify this code.

Example 11.3.  SoXtMainLoop

void
SoXt::mainLoop()
{
   XtAppContext context = getAppContext();
   XEvent event;
   
   for (;;) {
      SoXt::nextEvent(context, &event);
      SoXt::dispatchEvent(&event);
   }
}

void
SoXt::nextEvent(XtAppContext appContext, XEvent *event)
{
   XtAppNextEvent(appContext, event);
}

Boolean
SoXt::dispatchEvent(XEvent *event)
{
   Boolean success = True;
    
   if (event->type >= LASTEvent) {
      XtEventHandler proc;
      XtPointer clientData;
      Widget w;
      Boolean dummy;
      
      // Get the event handling function which was
      // registered with Inventor for handling this
      // event type in this widget
      SoXt::getExtensionEventHandler(event, w, proc, clientData);
      
      // Call the event handler!
      if (proc == NULL)
         success = False;
      else
         (*proc)(w, clientData, event, &dummy);
      
   }
   
   // else it is not an extension event - let Xt dispatch it
   else 
      success = XtDispatchEvent(event);
   
   return success;
}