[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Programmer's Guide



Adding Callback Procedures

Callback routines are the heart of a Motif application. Many widget classes have resources whose values are lists of callback procedures. When the user acts on a widget--for example, pressing a PushButton--Motif invokes the callback routines in the corresponding callback list. If an application needs to take some action when the user presses a PushButton, it supplies a callback routine and adds that routine to the appropriate callback list.

Callbacks are not the only means Motif uses to notify an application of a user action. An application can also supply its own action routines and event handlers. The main difference between these kinds of procedures is the level of abstraction at which Motif or Xt invokes the procedures:

  1. The Xt event dispatcher calls an event handler whenever an event of a particular type occurs in a specified widget.

  2. The Xt translation manager calls an action routine when an event sequence matches an event specification in a widget translation table. In a translation table, actions are associated with event specifications. More than one event sequence can invoke the same action routine.

  3. A Motif widget invokes callback procedures when user input signifies an action that is meaningful to the widget, such as activating a PushButton. Widgets often invoke callbacks from action routines. More than one action can invoke the same callback list.

    Most applications use only callback procedures. Action routines and event handlers are discussed in Chapter 13.

    Each callback procedure is a function of type XtCallbackProc. The procedure takes three arguments: a widget and two pointers to data. The first pointer is to data that the application has told the widget to pass back to the application when the callback procedure is invoked. The second pointer is to data that the widget passes to all callbacks on the callback list. A callback procedure returns no value.

    The application data argument is primarily for passing data that the application maintains separately from the widget itself. The widget data argument for most Motif widgets is a pointer to a structure containing information that varies by widget class. For example, when the user changes the value of a ToggleButton, Motif invokes callback procedures with a pointer to an XmToggleButtonCallbackStruct structure as the third argument. This structure has three members:

    1. An integer indicating the reason for invoking the callback. When the user changes the value, the reason is XmCR_VALUE_CHANGED. Usually the reason is identified by a symbol beginning with the characters XmCR.

    2. A pointer to the XEvent that triggered the callback.

    3. An integer that indicates the new state of the ToggleButton, either selected or unselected.

      The documentation for each widget class in the Motif Programmer's Reference describes any callback structures that the widget passes to callback procedures as widget data. Note that a callback procedure can change the values of some members of these structures. Because the order of procedures in a callback list is unspecified, an application that uses multiple callback procedures in the same list must use caution in changing these values.

      Following is a simple callback procedure that an application might use to set the state of a valve when the user changes the value of a ToggleButton. The application data passed in the callback in this example might be a pointer to a valve object associated with the ToggleButton:

      void ToggleValueChangedCB(Widget toggle, XtPointer app_data,
          XtPointer widget_data)
      {
          Valve *valve_p = (Valve *) app_data;
          XmToggleButtonCallbackStruct *toggle_info =
              (XmToggleButtonCallbackStruct *) widget_data;
          ChangeValveState(*valve_p,
              ((Boolean) toggle_info->set == TRUE) ?
                                     VALVE_ON: VALVE_OFF);
      }

      To register a callback procedure with a widget, an application uses XtAddCallback or XtAddCallbacks after declaring the callback procedure and creating the widget. The following code fragment creates a ToggleButton for each valve in a global list of valves:

      ...
       char      name[20];
       Widget    toggles[N_VALVES];
       int       i;
       Valve    *valve_p;
       
          for(i = 0, valve_p = valves; i < N_VALVES;
                                              i++, valve_p++) {
              sprintf(name, "valve_state_%d", i);
              toggles[i] = XmCreateToggleButton(parent, name,
                  (ArgList) NULL, 0);
              XtAddCallback(toggles[i], XmNvalueChangedCallback,
                  (XtCallbackProc) ToggleValueChangedCB,
                  (XtPointer) valve_p);
          }

      To remove a callback procedure from a callback list, use XtRemoveCallback or XtRemoveCallbacks. Because Motif sometimes adds its own callbacks to callback lists, do not use XtRemoveAllCallbacks to remove all callbacks from a list.


    4. [ Previous | Next | Contents | Glossary | Home | Search ]