next up previous contents index
Next: 4. The Widget Extension Up: 3. Pandora's Box: the Previous: 2. The BaseClass Extension   Contents   Index

3. The Method Wrappers

realizemethodresizemethodgeometry_handlermethodIn contrast to the hook methods, the method wrappers are a special set of wrappers for the widget methods realize(), resize() and geometry_handler(). These three wrappers are only responsible for a few tasks within the LESSTIF toolkit. Therefore the BCE record has no method wrapper hooks that could be used by widget writers. The duties of the method wrappers are:


\begin{itemlist}
\item The wrapper of the \code{realize()} method is available o...
... drag\&drop
mechanism doesn't interfere with geometry management.
\end{itemlist}

To see how the method wrappers are implemented, take a look at figure [*] that shows this exemplary for the realize() method wrapper.

Figure: The method wrappers enclose the non-chained widget methods like realize().
\begin{figure}
\centerline {\epsfig{file=WrapperBasics.eps,scale=1.09}}\end{figure}

Unfortunately, just redirecting the realize() method pointers of all the class records to a wrapper method is not enough. How should the wrapper know which (original) method to call later on? It can't guess this information just from the widget identifier it got as one parameter to the method call: the intended method could be either from the widget's class or from one of the superclasses. A smart solution would be to generate dynamically a short piece of machine code (called a ``thunk'' in M-babble) that is called before the wrapper. This piece of code then would supply the missing information to the wrapper method. Unfortunately, this isn't portable coding and is therefore useless to a project like M*TIF or LESSTIF.

As a way out, M*TIF as well as LESSTIF use a set of predefined wrapper ``gateways'' (marked with a 1 in figure [*]) that are statically compiled into the toolkits. In the case of the realize() method there are eight wrapper gateways called RealizeWrapper0() through RealizeWrapper7(). They all just call the real realize() wrapper 2 and supply to it an additional parameter that is the distance between the widget class the gateway belongs to and the VendorShell class. For example, the realize() gateway of the VendorShell widget class has a distance of zero, whereas the XmDialogShell widget class has a distance of two.

Armed with the distance, the wrapper can then call the right realize() method 3 by substracting the distance, that the gateway indicated, from the distance of the class of the current widget, then walking up the according number of superclasses, and fetching the old method pointer from the wrapper data record of that superclass.

The description above applies to the resize() and geometry_handler() wrappers as well. The only difference is that the distance is now measured from the ExtObject class instead. In the case of the geometry_handler() the distance should probable have been measured from the Constraint class and not from the ExtObject class. But as M*TIF can't count, we can't either for compatibility reasons.

There are eleven gateway levels available for the resize() method and ten levels for the geometry_handler() method. So there is still room for larger widget class trees subclassed from XmPrimitive (six levels) and XmManager (only four levels due to the bug just mentioned) - but you have to live with these built-in limits, whether you want or not.


next up previous contents index
Next: 4. The Widget Extension Up: 3. Pandora's Box: the Previous: 2. The BaseClass Extension   Contents   Index
Danny Backx
2000-12-13