Callbacks are registered with the ADD-CALLBACK function. Unlike Motif in C, an arbitrary number of client-data items can be registered with the callback. Callback functions should be defined as:
(defun callback-handler (widget call-data &rest client-data) ... )
The passed widget is that in which the callback has occurred, and the call-data is a structure which provides more detailed information on the callback. Client-data is some number of arguments which have been registered with the callback handler. The slots of the call-data structure can be derived from the C structure name using the standard name conversion rules. For example, the call-data structure for button presses has the following slot (aside from the standard ones): click-count.
To access the X event which generated the callback, use the following:
(defun handler (widget call-data &rest client-data) (with-callback-event (event call-data) ;; Use event structure here ))
Since callback procedures are processed synchronously, the Motif server will remain blocked to event handling until the callback finishes. This can be potentially troublesome, but there are two ways of dealing with this problem. The first alternative is the function UPDATE-DISPLAY. Invoking this function during your callback function will force the server to process any pending redraw events before continuing. The other (slightly more general) method is to register deferred actions with the callback handling mechanism. Deferred actions will be invoked after the server is released to process other events and the callback is officially terminated. Deferred actions are not invoked if the current application was destroyed as a result of the callback, since any requests to the server would refer to an application context which was no longer valid. The syntax for their usage is:
You may register only one set of deferred actions within the body of any particular callback procedure, as well as within event handlers and action procedures. Registering a second (or more) set of deferred actions will overwrite all previous ones.
When using deferred action procedures, care must be taken to avoid referencing invalid data. Some information available within callbacks is only valid within the body of that callback and is discarded after the callback terminates. For instance, events can only be retrieved from the call-data structure within the callback procedure. Thus the code
(with-callback-deferred-actions (with-callback-event (event call-data) (event-type event)))
is incorrect since the event will be fetched after the callback is terminated, at which point the event information will be unavailable. However, the code
(with-callback-event (event call-data) (with-callback-deferred-actions (event-type event)))
is perfectly legitimate. The event will be fetched during the callback and will be closed over in the deferred action procedure.