10.6. Sending Events Directly to the Application (Advanced)

In some cases, you may want to short-circuit Inventor event handling and send all events directly to the application. SoXtRenderArea contains a method that enables you to pass events to an application event handler. For example:

SoXtRenderArea *myRenderArea = new SoXtRenderArea;
myRenderArea->setEventCallback(myEventCallback, userData);
  
SoWinRenderArea myRenderArea = new SoWinRenderArea();
myRenderArea.EventFunction = myEventCallback;
  
SwRenderArea myRenderArea = new SwRenderArea();

  

When this method is passed a non-NULL user function, all events that come into the render area are passed to the user function. The callback function returns a Boolean value. If this value is TRUE, the callback function handled the event and the render area does not send the event to the scene manager for handling. If this value is FALSE, the event is sent to the scene graph for handling.

Note that the events sent to the event callback function are not Inventor events. For the SoXtRenderArea , X events are passed. The application is thus assured of receiving every event, even those that do not translate to Inventor events.

Example 10.2, “ Sending Events Directly to the Application demonstrates using setEventCallback(), which causes events to be sent directly to the application without being sent into the scene graph.

Example 10.2.  Sending Events Directly to the Application

// Clicking the left mouse button and dragging will draw 
// points in the xy plane beneath the mouse cursor.
// Clicking middle mouse and holding causes the point set 
// to rotate about the Y axis. 
// Clicking right mouse clears all points drawn so far out 
// of the point set.
...
// Have render area send events to us instead of the scene 
// graph.  We pass the render area as user data.
myRenderArea->setEventCallback(myAppEventHandler, myRenderArea);

SbBool
myAppEventHandler(void *userData, XAnyEvent *anyevent)
{
   SoXtRenderArea *myRenderArea = (SoXtRenderArea *) userData;
   XButtonEvent *myButtonEvent;
   XMotionEvent *myMotionEvent;
   SbVec3f vec;
   SbBool handled = TRUE;

   switch (anyevent->type) {
   
   case ButtonPress:
      myButtonEvent = (XButtonEvent *) anyevent;
      if (myButtonEvent->button == Button1) {
         myProjectPoint(myRenderArea, 
                  myButtonEvent->x, myButtonEvent->y, vec);
         myAddPoint(myRenderArea, vec);
      } else if (myButtonEvent->button == Button2) {
         myTicker->schedule();  // start spinning the camera
      } else if (myButtonEvent->button == Button3) {
         myClearPoints(myRenderArea);  // clear the point set
      }
      break;
      
   case ButtonRelease:
      myButtonEvent = (XButtonEvent *) anyevent;
      if (myButtonEvent->button == Button2) {
         myTicker->unschedule();  // stop spinning the camera
      }
      break;
      
   case MotionNotify:
      myMotionEvent = (XMotionEvent *) anyevent;
      if (myMotionEvent->state & Button1Mask) {  
         myProjectPoint(myRenderArea, 
                  myMotionEvent->x, myMotionEvent->y, vec);
         myAddPoint(myRenderArea, vec);
      }
      break;
      
   default:
      handled = FALSE;
      break;
   }
   
   return handled;
}
    
// Clicking the left mouse button and dragging will draw 
// points in the xy plane beneath the mouse cursor.
// Clicking middle mouse and holding causes the point set 
// to rotate about the Y axis. 
// Clicking right mouse clears all points drawn so far out 
// of the point set.
...
// Have render area send events to us instead of the scene 
// graph.  We pass the render area as user data.
myViewer.EventFunction = 
  new SoWinRenderArea.EventCallback(myAppEventHandler);

bool
myAppEventHandler(SoEvent theEvent)
{
    SbVec3f vec;
    bool dragStarted = false;
    bool handled = true;

    // Mouse Button Event
    if (theEvent is SoMouseButtonEvent)
    {
        SoMouseButtonEvent evt = (SoMouseButtonEvent)theEvent;

        // Press Event
        if (SoMouseButtonEvent.IsButtonPressEvent(evt, evt.GetButton()))
        {

            if (evt.GetButton() == SoMouseButtonEvent.Buttons.BUTTON3)
            {
                myTicker.Schedule();
                dragStarted = true;
            }
            else if (evt.GetButton() == SoMouseButtonEvent.Buttons.BUTTON1)
            {
                SbVec2s myButtonEvent = evt.GetPosition();
                myProjectPoint(myViewer, myButtonEvent.X, myButtonEvent.X, out vec);
                myAddPoint(myViewer, vec);

            }
            else
            {
                myClearPoints(myViewer);
            }
        }
        else
        {
            if (evt.GetButton() == SoMouseButtonEvent.Buttons.BUTTON3)
            {
                myTicker.Unschedule();
                dragStarted = false;
            }
        }
    }
    else if (theEvent is SoLocation2Event)
    {
        SoLocation2Event evt = (SoLocation2Event)theEvent;

        SbVec2s myMotionEvent = evt.GetPosition();
        if (dragStarted)
        {
            myProjectPoint(myViewer, myMotionEvent.X, myMotionEvent.Y, out vec);
            myAddPoint(myViewer, vec);
        }
    }

    return handled;
}