Appendix B. Changes and Additions in ViewKit 2.1

This chapter contains the following sections which discuss the new features and changes in ViewKit 2.1:

Overview Of ViewKit 2.1

This section provides an overview of the new features in ViewKit 2.1 from a programmer's perspective.


Note: The default development environment is still ViewKit 1.5.3 and Motif 1.2. If you wish to use the features in ViewKit 2.1 you must change the default environment to Motif 2.1 by entering (as root) the following command:


# /usr/Motif-2.1/lib/mksymlinks 

To return the default environment to 1.2, enter:

# /usr/Motif-1.2/lib/mksymlinks 

See the Motif 2.1 Porting Guide for more information about build environments and Motif 2.1.

New Features

With the release of ViewKit 2.1, it is now possible for a ViewKit application to create and manage windows and dialogs on multiple screens as well as multiple displays. There are several new foundation classes in ViewKit, the most important being VkDisplay and VkScreen, to support the development of multi-screen applications. In addition, the following existing ViewKit classes have been extended in order to support this new feature:
 

VkApp

VkFatalErrorDialog

VkPromptDialog

VkBusyDialog

VkFileSelectionDialog

VkQuestionDialog

VkCallbackObject

VkInfoDialog

VkSimpleWindow

VkColorChooserDialog

VkInterruptDialog

VkSubProcess

VkColormap

VkMenu

VkTabPanel

VkComponent

VkPipe

VkVisual

VkCutPaste

VkProgram

VkWarningDialog

VkDialogManager

VkProgressingDialog

VkWindow

VkErrorDialog

VkQuestionDialog

 


Multiple Displays and Screens within ViewKit 2.1

ViewKit 2.1 is a major enhancement to the standard ViewKit 1.5.3 framework. The primary motivation for the development of ViewKit 2.1 was to provide support for multiple displays and screens within the ViewKit framework. This enhancement required significant changes in the foundation classes of ViewKit. While every attempt was made to try to maintain source code compatibility with previous versions of ViewKit, there are a few exceptions to this in ViewKit 2.1. These exceptions are documented in the “Porting to ViewKit 2.1”.

ViewKit 2.1 adds two new foundation classes in order to support developing applications which access multiple screens and potentially multiple displays:

  • VkDisplay

  • VkScreen

In the new ViewKit 2.1 programming model, there is still a single instance of VkApp (accessed via the theApplication global variable). In addition, a VkApp instance now contains a list of VkDisplay instances and each VkDisplay instance contains a list of VkScreen instances. The VkScreen class provides most of the core functionality in the new programming model, similar to what VkApp provided in the old model. Most of the VkApp methods defer their execution to either VkDisplay or VkScreen methods. VkDisplay essentially functions as a pass-through, because its primary purpose is to act as the glue between VkApp and the real information being managed within VkScreen. VkScreen manages a list of windows (see the VkDisplay(3x) and VkScreen(3x) man pages for more information).

A simple ViewKit 2.1 application will by default have a single instance of VkApp, which contains a single instance of VkDisplay, which in turn contains a single instance of VkScreen. The default instances of VkDisplay and VkScreen are created by the VkApp constructor. VkApp has methods for creating new displays and screens (see VkApp.h):

VkDisplay *VkApp::newDisplay (char *display, 
                              char *name, 
                              int *arg_c, 
                              char *arg_v, 
                              XtPointer data);
 
VkScreen *VkApp::newScreen (char *name,
                            VkDisplay *dpy,
                            int *arg_c,
                            char *arg_v,
                            void (*preRealizeFunction)(Widget w),
                            XtPointer data);

These virtual methods provide a mechanism that allows applications to use custom subclasses of VkDisplay and VkScreen that are unique to those applications. The last argument in both of these methods is an XtPointer named data. This argument is not used in the default implementation of newDisplay() and newScreen(), but is provided as an additional mechanism to allow custom data to be passed into a subclass implementation of these methods. This should make the API for these methods flexible enough to satisfy most custom application requirements. The methods are used by the VkApp constructor to create the initial instances of VkDisplay and VkScreen (or their subclasses) which are required by every ViewKit 2.1 application.


Note: See “Porting to ViewKit 2.1” for a list of VkApp methods which are only applicable to a single screen application. If you are writing new applications, you should try to avoid these methods if you have any plans to support multi-screen applications in the future. This is especially true for people developing new components for ViewKit 2.1.

In addition to the standard VkApp API which was used in ViewKit 1.5.2, there are several new methods which can be used in multi-screen applications. The first is displayList(), which returns a pointer to the VkComponentList which contains the instances of VkDisplay that have been created in the current instance of VkApp. This allows custom applications to iterate over all the instances of VkDisplay in the application, should that be necessary.


Caution: It is very important that you do not add or remove items from this list directly. It should only be used to iterate across the list of VkDisplay instances in an application.

As mentioned earlier, most of the existing APIs in VkApp actually defer their execution to the instances of VkDisplay in this list. For example, calling busy() on VkApp results in busy() being called for every instance of VkDisplay contained in the list returned by displayList().

You must cast the values in the displayList() to the appropriate class pointer before accessing its methods. For example:

VkMyApp::busy2() 
{
    VkComponentList *dpyList = displayList();
 
    for (int i=0; i < dpyList->size(); i++) 
    {
        ((VkMyDisplay *) dpyList[i])->busy2(); 
    } 
}

This sample code shows an implementation of a new method called “busy2” for a custom application which is build around custom subclasses for VkApp and VkDisplay (named “VkMyApp” and “VkMyDisplay”). In reality, this application would also probably require a custom subclass of VkScreen (“VkMyScreen”) if the new VkMyDisplay::busy2() implementation also defers its execution to the VkScreen class or subclass.

In order to make it easier for application programmers to access the data that is typically needed for the new multi-screen APIs on VkDisplay and VkScreen, VkApp provides the following methods (see VkApp.h):

  • VkMenuBar *VkApp::getMenuBar (VkComponent *comp);

  • VkMenuBar *VkApp::getMenuBar (Widget widget);

  • VkSimpleWindow *VkApp::getWindow (VkComponent *comp);

  • VkSimpleWindow *VkApp::getWindow (Widget widget);

  • VkDisplay *VkApp::getDisplay (VkComponent *comp);

  • VkDisplay *VkApp::getDisplay (Widget widget);

  • VkScreen *VkApp::getScreen (VkComponent *comp);

  • VkScreen *VkApp::getScreen (Widget widget);

These methods are provided in two versions, one using VkComponent pointers and the other using Widget pointers. In general, it is easier to use the Widget pointer methods inside Motif callback functions (or methods) and the VkComponent methods in standard ViewKit methods. In reality, the VkComponent pointer methods call the Widget pointer methods after determining the baseWidget of the component. With these methods in VkApp it is easy, given either a component or a widget, to determine the VkScreens, VkDisplays, VkSimpleWindows, or VkMenuBars which are associated with the item in question.


Note: ViewKit programmers writing multi-screen applications need to be careful about caching information at the VkApp level because most of this data will tend to be screen specific.

Multi-screen applications should not call the special macros for global dialogs (such as “theBusyDialog”) because these macros will only return the dialog associated with the default screen. Instead, applications should call the global dialog functions, such as getTheBusyDialog (VkComponent *comp), and pass a component from the current screen as the argument. This will ensure that the correct global dialog is returned (that is, the one which is valid for the current screen). See the header files for the various dialogs for more information.

New APIs for VkCallbackObject

In previous versions of ViewKit (1.5.3 or older), the identifier used for VkCallbackObjects was a char*. In ViewKit 2.1, we have extended the options for identifiers (or keys) to include the following:

char         *name 
XrmQuark      quark 
long          index

This change extends all of the APIs (constructors and methods) for VkCallbackObject to support these three types of identifiers. You can now choose which identifier type is most convenient your application. For example, applications that need to manage large numbers of VkCallbackObjects can now use either the “quark” or “index” APIs in order to improve the performance of VkCallbackObject. See VkCallbackObject.h for more information about these changes.


Note: Any given instance of VkCallbackObject will only have one type of identifier, which will be determined by the constructor used to create it.


Porting to ViewKit 2.1

This section highlights the features of ViewKit 2.1 that require program changes in existing ViewKit applications or components.

Source Code Incompatibilities

The development of ViewKit 2.1 required us to break source code compatibility with ViewKit 1.5.3 in the following areas:

  • VkColormap

  • VkCutPaste::export()

VkColormap Changes

The ViewKit 1.5.3 implementation of VkColormap was heavily dependent on static data and class methods which ran counter to the requirements of ViewKit 2.1 when it came to supporting multiple displays and screens. In order to eliminate dependency on global data (and methods), VkColormap was re-implemented. The new implementation tries to adhere to the existing APIs whereever possible. However, the constructors for VkColormap have changed completely. The only valid constructor is the following:

VkColormap(VkScreen *screen);

Also, all of the previous class methods (that is, static methods) have been changed to instance methods.

You will need to review the usage of VkColormap when porting existing ViewKit applications and custom components to ViewKit 2.1 (for more information, see /usr/Motif-2.1/include/Vk/VkColormap.h and the VkColormap(3x) man page).

VkCutPaste Changes

There is a new reserved keyword in the latest C++ language specifications called “export.” In order to ensure compatibility with future C++ compilers that implement this keyword, the old VkCutPaste method, export(), has been renamed exportData() in ViewKit 2.1:

virtual Boolean exportData (Atom selection, Time time=CurrentTime); 

Any existing ViewKit code will need to be modified to call the new method (see /usr/Motif-2.1/include/Vk/VkCutPaste.h).


Note: It may be useful to review your code for other application-specific uses of “export” in order to prevent future problems.


New Multi-display and Multi-screen support

The primary motivation for the development of ViewKit 2.1 was the addition of support for multiple displays and screens within the ViewKit framework. This feature required a significant modification to the foundation classes within ViewKit. The new programming model is similar to the old in that there is a single instance of VkApp in any given ViewKit application. In addition however, a VkApp contains a list of VkDisplay instances, each of which in turn contains a list of VkScreen instances. The VkScreen is in many ways similar in its usage to that of VkApp in the previous ViewKit programming model. For instance, VkScreen contains a list of window instances and all the APIs which were typically associated with VkApp (see the VkDisplay(3x) and VkScreen(3x) man pages for more information).


Note: For more information on the VkApp/VkDisplay/VkScreen programming model, see “Overview Of ViewKit 2.1”.

While it is true that existing ViewKit applications will compile and run on ViewKit 2.1 with minimal changes (see “Source Code Incompatibilities”), any application or custom component which needs to utilize the multiple display or multiple screen features of ViewKit 2.1 will require more significant changes.

The primary change required for supporting multiple displays and screens is to convert from VkApp method calls to VkScreen method calls. Typically this means finding the calls to theApplication (a global variable) and writing code which gets the current VkScreen instance and calls its methods instead. The following VkApp methods should not be used in an application or component which needs to be multi-display or multi-screen aware:

  • addWindow(VkSimpleWindow *newWindow)

  • baseWidget()

  • busyCursor()

  • display()

  • mainWindow()

  • normalCursor()

  • removeWindow(VkSimpleWindow *oldWindow)

  • setBusyCursor(const Cursor c)

  • setBusyCursor(VkCursorList *c)

  • setBusyDialog(VkBusyDialog *d)

  • setNormalCursor(const Cursor c)

  • shellGeometry()

  • showCursor(const Cursor c)

Calls to these methods via the theApplication global variable should be modified to call the appropriate VkDisplay or VkScreen method. The following are two examples illustrating these modifications (where obj is an instance of a subclass of VkComponent):

Example 1

old: theApplication->display();

new: theApplication->getDisplay(obj)->display();

or: obj->getDisplay()->display();

Example 2

old: theApplication->baseWidget();

new: theApplication->getScreen(obj)->baseWidget();

or: obj->getScreen()->baseWidget();

In general, ViewKit components should make calls to VkScreen methods and should limit the usage of the theApplication global variable. Some of the new methods in VkApp which are handy for use with theApplication include:

  • VkDisplay *getDisplay(VkComponent *comp)

  • VkDisplay *getDisplay(Widget widget)

  • VkScreen *getScreen(VkComponent *comp)

  • VkScreen *getScreen(Widget widget)

  • VkSimpleWindow *getWindow(VkComponent *comp)

  • VkSimpleWindow *getWindow(Widget widget)

ViewKit 2.1 provides two versions for most of these methods in order to make it easier to use these calls in both callbacks (the widget methods) and application code (the component methods). Given either a widget or an instance of a subclass of VkComponent, you can call any of these methods using the theApplication global variable in order to get a pointer to the instance of VkDisplay, VkScreen or VkSimpleWindow which is associated with the item in question (for more information, see /usr/Motif-2.1/include/Vk/VkApp.h, /usr/Motif-2.1/include/Vk/VkDisplay.h, and /usr/Motif-2.1/include/Vk/VkScreen.h).

Writing code which supports both ViewKit 1.5.3 and 2.1

For those who are trying to maintain code which needs to run on both ViewKit 2.1 and ViewKit 1.5.3, the easiest way to manage this is to ifdef the ViewKit 2.1 specific code in the same style that we have in the ViewKit code base. For example, here's a fragment of code from the VkBusyCursors.h:

public: 
        VkBusyCursors( ); 
#ifdef _VK_MAJOR > 1 
        VkBusyCursors( VkScreen *scr ); 
#endif

This enables the new constructor for VkBusyCursors when compiled for ViewKit 2.1 (where _VK_MAJOR is 2) and disables it for ViewKit 1.5.3 (where _VK_MAJOR is 1). The value of _VK_MAJOR is defined in the VkCommonDefs.h file that can be found at the following locations:

  • /usr/Motif-1.2/include/Vk/VkCommonDefs.h for ViewKit 1.5.3

  • /usr/Motif-2.1/include/Vk/VkCommonDefs.h for ViewKit 2.1

Required Packages (ViewKit 2.1 Addendum)

In addition to the required packages listed in “Required Packages” in Chapter 1, ViewKit 2.1 also requires the following packages:

  1. ViewKit21_dev.sw.base  


    You are required to install this subsystem, which contains the optimized, unshared C++ ViewKit 2.1 libraries and include files (the shared ViewKit 2.1 libraries are included in the IRIX system software as the ViewKit_eoe.sw.base subsystem).

    ViewKit21_dev.sw.debug  


    This subsystem contains the debug version of the optimized ViewKit 2.1 libraries. You can optionally install this subsystem in addition to the ViewKit21_dev.sw.base subsystem. Use this library for program debugging only.

    ViewKit21_dev.man.relnotes 


    This is the online version of the ViewKit 2.1 Release Notes. This subsystem is optional, but recommended.

ViewKit 2.1 Inheritance Graph

Figure B-1 shows the new inheritance structure in ViewKit 2.1. This is only a partial chart, showing changes and additions. The shaded classes indicate classes that are new in ViewKit 2.1. The rest of the inheritance structure can be seen in Appendix C, “ViewKit Class Graph.”

Figure B-1. Inheritance Graph for ViewKit 2.1 Additions and Changes

Figure B-1 Inheritance Graph for ViewKit 2.1 Additions and Changes