next up previous contents index
Next: 5. Messy Geometry Management Up: 4. Diverting User Input Previous: 4. Extending the VendorShell   Contents   Index

5. The Shadow Shell Tree

XmVendorShellExtObjectXmDesktopObjectThe VSE object (XmVendorShellExtObject) is subclassed from the XmDesktopObject class which in turn is subclassed from XmExtObject. Whereas the XmExtObject only knows of an associated ``logical parent'', the XmDesktopObject class introduces the concept of children to the extension objects (see figure [*]).

Figure: The XmDesktopObjects form a tree of XmDesktopObjects with a XmScreen widget at the top.
\begin{figure}
\centerline {\epsfig{file=DesktopClass.eps,scale=1.09}}\end{figure}

The children of a XmDesktopObject (which must be either XmDesktopObjects again or a subclass of) are managed in a list much the same way Composite does. But as extension objects have no real parent (only a logical parent which is merely an associated widget) the XmDesktopObject class adds a new resource called XmNdesktopParent. It links to the parental object this particular XmDesktopObject is a child of. All the XmDesktopObjects form a ``shadow tree'' of the shell instance hierarchy. This tree is much like the well-known widget instance tree any application has - but this time any widgets that are not shells are left out.

XmScreenAt the top of the tree of XmDesktopObjects there is always a XmScreen widget. But as the XmScreen class is a direct subclass of Core and not of Composite it can't manage a list of children - at least from the Xt Intrinsics' point of view. This is there the Desktop class part comes in a second time as ``Nobody expects the Spanish Inquisition...''. Oops - wrong movie.

In figure [*] you can see the XmDesktopObject (surrounded by dashed edges) reappearing at the branch between the Core class and the XmScreen class. At this point the principle of inheritance is somewhat broken as the XmScreen class is a direct subclass of Core. But XmScreen extends the instance record of the Core class not only by its own XmScreen-specific part but also by the XmDesktop-specific part.

This makes creating and inserting XmDesktopObjects ponderous because every such object must push its (desktop) parent to be inserted into the parent's list of children. But remember that the parent can be not only another XmDesktopObject but also a XmScreen widget. Thus, both XmDesktopObject as well as XmScreen provide methods through their desktop part within the class record for inserting (insert_child()) and deleting (delete_child()) a single child.

Whenever a XmDesktopObject is created, and its XmNdesktopParent resource is not NULL, it calls the insert_child method that is appropiate for the respective parent. As an example how this is done here is the initialize() method of the XmDesktopObject class (ripped of from (LESSTIF_ROOT)/libXm/Desktop.c):


static void initialize(Widget request, Widget new_w,
                       ArgList args, Cardinal *num_args)
{
    Widget       desktopParent;
    XtWidgetProc insertChild;

    Desktop_Children(new_w)    = NULL;
    Desktop_NumChildren(new_w) = 0;
    Desktop_NumSlots(new_w)    = 0;
    desktopParent = Desktop_Parent(new_w);
    if ( desktopParent ) {
        if ( _XmIsFastSubclass(XtClass(desktopParent), XmSCREEN_BIT) ) {
            insertChild = ((XmScreenClassRec *) XtClass(desktopParent))->
                              desktop_class.insert_child;
        } else {
            insertChild = ((XmDesktopClassRec *) XtClass(desktopParent))->
                              desktop_class.insert_child;
        }
        if ( insertChild == NULL ) {
            _XmError(new_w,
                     "insert_child method of my desktop parent is NULL");
        }
        insertChild(new_w);
    }
} /* initialize */

XmDisplay The XmScreen widget at the top of the tree of XmDesktopObjects isn't yet the end of the road. Instead there's still another level represented by a XmDisplay widget (see figure [*]). M*TIF creates such XmDisplay widgets for every display connection an application opens. The XmDisplay widget then gathers the various shadow shell trees via XmScreen widgets under its hood.

Figure: The shadow shell tree is organized by XmScreen widgets which are in turn gathered under the hood of a XmDisplay widget.
\begin{figure}
\centerline {\epsfig{file=ShadowShell.eps,scale=1.09}}\end{figure}

From time to time you need to look up the VSE object for a given VendorShell widget. For this you'll need the help of _XmGetWidgetExtData() from the BaseClass stuff. During initializing, every VendorShell widget creates a widget extension data record of type XmWidgetExtDataRec and pushes it on an extension data stack that LESSTIF maintains for some widget (and gadget) classes. The member widget of such a widget extension data structure finally points to the VSE object for the VendorShell. The following code excerpt shows how to find a VSE object using _XmGetWidgetExtData().


    Widget                 vendorShell;
    XmVendorShellExtObject ve;
    XmWidgetExtData        extData;

    /* vendorShell references a VendorShell widget */
    extData = _XmGetWidgetExtData(vendorShell, XmSHELL_EXTENSION);
    ve      = extData->widget;
    /* ve now references the VSE object */


next up previous contents index
Next: 5. Messy Geometry Management Up: 4. Diverting User Input Previous: 4. Extending the VendorShell   Contents   Index
Danny Backx
2000-12-13