Dirty Tricks
************

This chapter describes some of the routines that may be used in special situations where more power or flexibility from Forms Library is needed. These routines are classified as "dirty tricks" either because they can easily mess up the normal operation of Forms Library or they depend on internal information that might change in the future, or they rely too much on the underlying window systems. Thus whenever possible, try not to use these routines.

Interaction
===========

Form Events
-----------

It is possible to by-pass the form event processing entirely by setting a "raw callback" that sits between the event reading and dispatching stage, thus a sneak preview can be implemented and optionally consume the event before the internal form processing machinery gets to it.

Use the following routines to register such a preemptive processing routine

     typedef int (*FL_RAW_CALLBACK)(FL_FORM *, void *xevent);
     FL_RAW_CALL_BACK fl_register_raw_callback(FL_FORM *form,
                                               unsigned long mask,
                                               FL_RAW_CALLBACK callback);

where mask is the event mask you are interested in (same as the XEvent mask). The function returns the old handler for the event.

Currently only handlers for the following events are supported

  * KeyPressMask and KeyReleaseMask

  * ButtonPressMask and ButtonReleaseMask

  * EnterWindowMask and LeaveWindowMask

  * ButtonMotionMask and PointerMotionMask

  * FL ALL EVENT (see below)

Further, there is only one handler for each event pair, (e.g., ButtonPress and ButtonRelease), thus you can't have two separate handlers for each pair although it is okay to register a handler only for one of them (almost always a mistake) if you know what you're doing. If you register a single handler for more than one pair of events, e.g., setting mask to KeyPressMask|ButtonPressMask, the returned old handler is random.

A special constant, FL_ALL_EVENT, is defined so that the handler registered will received all events that are selected. To select events, use fl_addto_selected_xevent().

Once an event handler is registered and the event is detected, then instead of doing the default processing by the dispatcher, the registered handler is invoked. The handler must return FL_PREEMPT if the event is consumed) and 0 otherwise so that the internal process can continue. See the demo program minput2.c for an example.

Object Events
-------------

Just as you can by-pass the internal event processing for a particular form, you can also do so for an object. Unlike in raw callbacks, you can not select individual events.

The mechanism provided is via the registration of a pre-handler for an object. The pre-handler will be called before the built-in object handler. By electing to handle some of the events, a pre-handler can, in effect, replace part of the built-in handler.

In the chapter about pre-emptive handlers the API was already discussed in detail, so here we just repeat the discussion for completeness as any use of pre-emptive handler is considered "dirty tricks".

To register a pre-handler, use the following routine

     typedef int (*FL_HANDLEPTR)(FL_OBJECT *obj, int event,
                                 FL_Coord mx, FL_Coord my,
                                 int key, void *raw_event);

     void fl_set_object_prehandler(FL_OBJECT *, FL_HANDLEPTR prehandler);

where event is the generic event in the Forms Library, that is, FL DRAW, FL ENTER etc. The arguments mx and my are the mouse position and key is the key pressed. The last parameter, raw_event is a pointer to the XEvent that caused the invocation of the pre-handler. cast to a void pointer.

Notice that the pre-handler has the same function prototype as the built-in handler. Actually they are called with the exact same parameters by the event dispatcher. The prehandler should return 0 if the processing by the built-in handler should continue. A return value of FL PREEMPT will prevent the dispatcher from calling the built-in handler.

See demo program preemptive.c for an example.

Similar mechanism exists for registering a post-handler, i.e., a handler invoked after the built-in handler finishes. Whenever possible a post-handler should be used instead of a pre-handler.

Other
=====

As stated earlier, fl_set_defaults() can be used to modify the Forms Library's defaults prior to calling fl_initialize(). Actually, this routine can also be used after fl_initialize() to override the values set on the command line or in the application databases. However, overriding users' preferences should be done with discretion. Further, setting privateColormap after fl_initialize() has no effect.