Chapter 5. Window, Session, and Desk Management

This chapter contains these sections:

Window, Session, and Desk Management Overview

This section briefly discusses features of window, session, and desk management on Silicon Graphics system:

This section also provides a list of references for further reading on window and session management.

Window Management

4Dwm, which is based on mwm (the Motif Window Manager), is the window manager typically used on Silicon Graphics workstations. It provides functions that allow both users and programmers to control elements of window states such as: placement, size, icon/normal display, and input-focus ownership. In addition to window management, 4Dwm provides session and desks management.

Chapter 3, “Windows in the IRIX Interactive Desktop Environment,” of the IRIX Interactive User Interface Guidelines discusses the interactions and behaviors that your application's windows should support. “Interacting With the Window and Session Manager” describes how to comply with the style guidelines.

See IRIS Essentials for more information about the features 4Dwm provides for your users. See the mwm(1X) and 4Dwm(1X) reference pages for more information about the features 4Dwm provides.

Session Management

This section describes session management and explains how to add it to your application. Topics include:

Overview of Session Management

Session management allows users to log out, and any applications that are running at logout automatically restart when they log back in. The 4Dwm window manager keeps a list of the applications and desks that were previously running when the user last logged out and restarts them when the user logs in again.

For your application to be restarted via the 4Dwm session manager, the application must register its initial state with the session manager and make sure the current state is registered at all times.

Additionally, your application should restart in the same state it was in when the user logged out (for example, the same windows open, the same files open, and so on). To support this, you need to design your application so that when the 4Dwm session manager restarts it, it can redisplay any of its co-primary or support windows that were open when the user logged out, reopen any data files that were open, and so on. You can support this either by providing command-line options to your application or other mechanisms such as a state file that your application reads when it is launched.

Types of Session Management: Continuous and Explicit

The two types of session management include continuous session management and explicit session management. Continuous session management restarts the applications that were running when the user last logged out of the window manager. This is the default setting.

Explicit session management ignores the windows that were open when the user last logged out and always opens a particular set of windows that the user has chosen. Users can configure the windows on the desktop by using the Window Settings Control Panel. They can launch this panel via the Toolchest. From the Toolchest, open the Desktop menu, select “Customize,” and then select “Windows.” The Windows Settings dialog box appears (see Figure 5-1). The “Save Windows & Desks” item on the Window Settings Control Panel configures either continuous or explicit session management. A user can select explicit, and then press the “Set Home Session” button to save the (current) explicit window configuration. Also, users can launch this control panel from the Icon Catalog's Control Panel page.

Figure 5-1. Window Settings Control Panel

Window Settings Control Panel

Adding Session Management to Your Application

Applications can communicate with the window manager by setting properties on the top level window. The WM_COMMAND property gives the window manager the command line that can be used to re-invoke the application in its current state. The 4Dwm window manager sends a WM_SAVE_YOURSELF message to each window that subscribes to tell it to update its WM_COMMAND property and then reads in the value. If the user selects continuous session management, 4Dwm sends the message every 10 minutes and at logout. If the user selects explicit session management, the window manager only queries the applications when the user presses the “Set Home Session” button.

Setting the WM_COMMAND String

If you use ViewKit or XtAppInitialize(3Xt), the initial WM_COMMAND string is set for you when the top level window is realized. Use the xprop(1) command to make sure the WM_COMMAND string is set correctly for the top level window. For example:

WM_COMMAND(STRING) = { “webmagic”, “/usr/tmp/sgiLook.html” }

Even if WM_COMMAND is initially set by your toolkit, you need to keep WM_COMMAND updated if your program changes its state. For instance, if the user renames a data file or successfully opens a new data file, you need to change the WM_COMMAND string with the XSetCommand(3X11):

XSetCommand(Display *display, Window w,char **argv,int argc);

This can be done in the function that changes the state, and is simpler than responding to the window manager's WM_SAVE_YOURSELF message.

Saving Session Information to a File

If your application already saves state information to a file instead of using the command line, this “state file” can also be used for session management. To work correctly with the user's Windows Control Panel setting, the application should update the file only in response to the window manager's WM_SAVE_YOURSELF message (see Example 5-1, saveyourself.c). This strategy does not work correctly if several instances of your application are able to run at the same time. Only applications that enforced a “Run Once” policy can rely on this strategy.

For more information, see the ViewKit reference page, VkRunOnce(3x), and XSetCommand(3X11).

Debugging Tips

When debugging:

  • Use xprop(1) to see the WM_COMMAND string property.

  • Make sure that you use the full pathname for data file arguments, which typically are not referenced in the user's path.

  • If your application has multiple windows, only set WM_COMMAND for the top-level window.  

    Example 5-1. Session Management Example Code: saveyourself.c

    /* saveyourself.c                                       */
    /*                                                      */
    /* Example code for handling the window manager's       */
    /* WM_SAVE_YOURSELF Protocol                            */
    /*                                                      */
    /* cc -o saveyourself saveyourself.c -lXm -lXt          */
     
    #include <Xm/Protocols.h>
    #include <Xm/Label.h>
     
    void saveYourSelfCallback(Widget w,  XtPointer client_data, 
                                 XtPointer call_data)
    {
        printf(“Update state file if needed, then update WM_COMMAND\n”);
    }
     
    void main(int argc, char** argv)
    {
       Widget toplevel, label;
       XtAppContext app_context;
       Atom WM_SAVE_YOURSELF;
     
       toplevel = XtAppInitialize(&app_context, “SaveYourSelf”,
                                  NULL, 0, &argc, argv, NULL, NULL, 0);
     
       label = XmCreateLabel(toplevel, “saveme”, NULL, 0);
       XtManageChild(label);
     
       WM_SAVE_YOURSELF = XmInternAtom( XtDisplay(toplevel),
                                          “WM_SAVE_YOURSELF”,
                                          FALSE);
     
       XmAddWMProtocolCallback( toplevel, WM_SAVE_YOURSELF,
                                saveYourSelfCallback, NULL );
     
       XtRealizeWidget(toplevel);
       XtAppMainLoop(app_context);
    }
    


“Handling the Window Manager Save Yourself Protocol” describes what your application needs to do to support session management. “Session Management” in Chapter 3 of the IRIX Interactive User Interface Guidelines provides further guidelines for handling session management.

Reference

For more information, see Inter-Client Communication Conventions Manual (ICCCM). The ICCCM is reprinted as an appendix in O'Reilly and Associates, X Protocol Reference Manual, Volume Zero.

Desk Management

Users can use “desks” to create multiple virtual screens. They can assign any primary or support window to any desk, causing that window to appear in the thumbnail sketch in the Desks Overview window.

“Desks” in Chapter 3 of the IRIX Interactive User Interface Guidelines discusses the important development concerns issues relating to desks. Review the information in “Session Management,” and adhere to the “Session Management Guidelines,” and the window manager will take care of desks for you.

The key points to keep in mind are:

  • Transient windows appear on every desk and are not shown in the Desks overview window—so choose your transient windows carefully.

  • Application windows that are on a desk other than the current one are in a state similar to the minimized state—processing continues although the window is no longer mapped to the screen display. Keep this in mind when selecting which operations should continue to be processed when your application is in a minimized state.

  • Users can select different backgrounds for different desks, so your application should not create its own screen background.

Further Reading on Window and Session Management

For more information on window and session management with 4Dwm, refer to the mwm(1X) and 4Dwm(1X) reference pages. You may also want to look at IRIS Essentials, since this book explains important window and session management features to your users.

For more information on window and session management with Xt, refer to the chapters on Interclient Communication in these manuals:

  • The X Window Systems Programming and Applications with Xt, OSF/Motif Edition, Second Edition, by Doug Young

  • O'Reilly Volume Four, X Toolkit Intrinsics Programming Manual, OSF/Motif Edition, by Adrian Nye and Tim O'Reilly

For more information on window and session management with Xlib, refer to the chapters on Inter-Client Communication in O'Reilly Volume One, Xlib Programming Manual, by Adrian Nye. For more detailed information, refer to the Inter-Client Communications Conventions Manual (ICCCM). (The ICCCM is reprinted as an appendix of O'Reilly Volume Zero, X Protocol Reference Manual.)

More detailed information on window properties is available in the OSF/Motif Programmer's Guide, in the chapter on “Inter-Client Communication Conventions.”

Implementing an Application Model

“Application Models” in Chapter 6 of the IRIX Interactive User Interface Guidelines  describes four application models based on four different window categories: main primary windows, co-primary windows, support windows, and dialogs. It also describes how to select a model appropriate for your application. This section provides suggestions for implementing each application model, including recommended shell types for your primary windows. “Interacting With the Window and Session Manager” describes how to create the windows and get them to look and behave in the manner described in “Application Window Categories and Characteristics” in Chapter 3 of the IRIX Interactive User Interface Guidelines.

Implementing the “Single Document, One Primary” Model

This model is the simplest to implement. You can use the ApplicationShell returned by XtAppInitialize() as your application's main window. This model requires no special treatment to handle schemes or for window or session management.

Implementing the “Single Document, Multiple Primaries” Model

The simplest way to implement this model is to use the ApplicationShell returned by XtAppInitialize() as your application's main window. You can create co-primary windows as popup children of the main window using TopLevelShells. This approach requires no special treatment to handle schemes or for window or session management.

You can also choose the implement this model using the techniques described in “Implementing the “Multiple Document, No Visible Main” Model,” although this requires more work.


Caution: Don't use XtAppCreateShell() to create co-primary windows. If you do, the windows don't pick up the resources specified in schemes.


Implementing the “Multiple Document, Visible Main” Model

Once again, the simplest way to implement this model is to use the ApplicationShell returned by XtAppInitialize() as your application's main window. You can create co-primary windows as popup children of the main window using TopLevelShells. This approach requires no special treatment to handle schemes or for window or session management.

You can also choose the implement this model using the techniques described in “Implementing the “Multiple Document, No Visible Main” Model,” although this requires more work.


Caution: Don't use XtAppCreateShell() to create co-primary windows. If you do, the windows don't pick up the resources specified in schemes.


Implementing the “Multiple Document, No Visible Main” Model

This model requires more careful consideration than the other models. Presumably, the visible windows can be created and destroyed in any order; therefore it is very difficult to use one as a main window and have the others be children of it.

Instead, the best solution in this case is to leave the ApplicationShell returned by XtAppInitialize() unrealized. You can then create the visible co-primary windows as popup children of this invisible shell.

Session management requires a realized ApplicationShell widget so that your application can store restart information in its XmNargv and XmNargc resources. Because your application's visible windows can be created and destroyed dynamically, you should use ApplicationShells rather than TopLevelShells for your visible windows. Then you can set the XmNargv and XmNargc resources on any of them. (Another option would be to use TopLevelShells for the visible windows and then explicitly create and set WM_COMMAND and WM_MACHINE properties on the windows.)

One complication when using ApplicationShells is that by default, IRIS IM automatically quits an application when it destroys an ApplicationShell. To avoid this, you must set each window's XmNdeleteResponse resource to XmDO_NOTHING, and then explicitly handle the window manager's WM_DELETE_WINDOW protocol for each window. “Handling the Window Manager Delete Window Protocol” describes how to implement these handlers.

Another complication is that the initial values of the XmNargv and XmNargc resources are stored in the application's invisible main window rather than a visible window. This is also true for the XmNgeometry resource if specified by the user. To avoid this, you should copy these values from the invisible main window to your application's first visible window.


Caution: Don't use XtAppCreateShell() to create co-primary windows. If you do, the windows don't pick up the resources specified in schemes.


Interacting With the Window and Session Manager

Most communication between an application and a window manager takes place through properties on an application's top-level windows. The window manager can also generate events that are available to the application. You can use Xlib functions to set properties and handle window manager events.

In IRIS IM, shell widgets simplify communications with the window manager. The application can set most window properties by setting shell resources. Shells also select for and handle most events from the window manager.

Because this guide assumes that you are programming in IRIS IM rather than Xlib, this chapter describes the IRIS IM mechanisms for creating windows and interacting with the window and session manager. Topics include:

For detailed information about setting window properties using shell resources, consult Chapter 11, “Interclient Communication,” in O'Reilly's X Toolkit Intrinsics Programming Manual and Chapter 16, “Interclient Communication,” in the OSF/Motif Programmer's Guide. For detailed information about window properties and setting them using Xlib routines, consult Chapter 12, “Interclient Communication,” in O'Reilly's Xlib Programming Manual.

Creating Windows and Setting Decorations

Chapter 6, “Application Windows,” in the IRIX Interactive User Interface Guidelines describes several application models based on four different window categories: main primary windows, co-primary windows, support windows, and dialogs. This section describes how to implement these window categories with proper window decorations and window menu entries:

To properly integrate with the IRIX Interactive Desktop, you need to use the appropriate shell widget for each widow category. This section describes which shell widget to use for each window category. Then you need to properly set the shell's XmNmwmFunctions resource to control which entries appear in the window menu and the XmNmwmDecorations resource to remove the window's resize handles, if appropriate.

Creating a Main Primary Window

Your application's main primary window must be an ApplicationShell. Typically, you use the ApplicationShell widget returned by XtAppInitialize() as your application's main primary window.

You should set the main primary window's XmNmwmFunctions resource to remove the “Close” option from the window menu. Also, if you don't want the user to be able to resize the window, you should set XmNmwmFunctions to remove the “Size” and “Maximize” options and set XmNmwmDecorations to remove the resize handles. Example 5-2 shows how you can create a main primary window and set the resource values appropriately.

“Main and Co-Primary Windows” in Chapter 6 of the IRIX Interactive User Interface Guidelines provides guidelines for using main primary windows.

Example 5-2. Creating a Main Primary Window

#include <Xm/Xm.h>           /* Required by all Motif applications */
#include <Xm/MwmUtil.h>      /* Required to set window menu and decorations */
#include <X11/Shell.h>       /* Shell definitions */
 
void main ( int argc, char **argv )
{
    Widget       mainWindow; /* Main window shell widget */
    XtAppContext app;        /* An application context, needed by Xt */
    Arg          args[10];   /* Argument list */
    int          n;          /* Argument count */
 
    /*
     * Initialize resource value flags to include all window menu options and
     * all decorations.
     */
 
    long functions = MWM_FUNC_ALL;
    long handleMask = MWM_DECOR_ALL;
    
    n = 0;
    
    /*
     * The following lines REMOVE items from the window manager menu.
     */
    
    functions  |= MWM_FUNC_CLOSE;        /* Remove "Close" menu option */
    
    /* Include the following two lines only if the window is *not* resizable */
 
    functions  |= MWM_FUNC_RESIZE;       /* Remove "Size" menu option */
    functions  |= MWM_FUNC_MAXIMIZE;     /* Remove "Maximize" menu option */
    
    XtSetArg(args[n], XmNmwmFunctions, functions); n++;
 
    /* Include the following two lines only if the window is *not* resizable */
 
    handleMask |= MWM_DECOR_RESIZEH;     /* Remove resize handles */
    
    XtSetArg(args[n], XmNmwmDecorations, handleMask); n++
    
    /*
     * Initialize Xt and create shell
     */
    
    mainWindow = XtAppInitialize ( &app, "WindowTest", NULL, 0, 
                                   &argc, argv, NULL, args, n );
 
    /* ... */
 
}


Creating a Co-Primary Window

Your application's co-primary windows should be ApplicationShells or TopLevelShells. “Implementing an Application Model” describes which to choose depending on your application model. The easiest way to implement these windows are as pop-up children of the shell widget returned by XtAppInitialize() (which is typically your application's main primary window).

If the user can't quit the application from a co-primary window, you should set the window's XmNmwmFunctions resource to remove the “Exit” option from the window menu. Also, if you don't want the user to be able to resize the window, you should set XmNmwmFunctions to remove the “Size” and “Maximize” options and set XmNmwmDecorations to remove the resize handles. Example 5-3 shows how you can create a co-primary window and set the resource values appropriately.


Note: The default action when IRIS IM destroys an ApplicationShell is to quit your application. To avoid this if you are using ApplicationShells for your co-primary windows, you must set each window's XmNdeleteResponse resource to XmDO_NOTHING, and then explicitly handle the window manager's WM_DELETE_WINDOW protocol for each window. You might want to follow this approach even if you use TopLevelShells for co-primary windows so that you can simply popdown the window instead of deleting it. This can save time if you might redisplay the window later. “Handling the Window Manager Delete Window Protocol” describes how to implement these handlers.

“Main and Co-Primary Windows” in Chapter 6 of the IRIX Interactive User Interface Guidelines provides guidelines for using co-primary windows.

Example 5-3. Creating a Co-Primary Window

#include <Xm/Xm.h>       /* Required by all Motif applications */
#include <Xm/MwmUtil.h>  /* Required to set window menu and decorations */
#include <X11/Shell.h>   /* Shell definitions */
 
Widget       mainWindow; /* Main window shell widget */
Widget       coPrimary;  /* Co-primary window shell widget */
Arg          args[10];   /* Argument list */
int          n;          /* Argument count */
 
/*
 * Initialize resource value flags to include all window menu options and
 * all decorations.
 */
 
long functions = MWM_FUNC_ALL;
long handleMask = MWM_DECOR_ALL;
 
/* ... */

n = 0;
 
/*
 * The following lines REMOVE items from the  window manager menu.
 */
 
/* Remove the "Exit" window menu option if users can *not* quit from this window */
 
functions  |= MWM_FUNC_QUIT;
 
/* Include the following two lines only if the window is *not* resizable */
 
functions  |= MWM_FUNC_RESIZE;       /* Remove "Size" menu option */
functions  |= MWM_FUNC_MAXIMIZE;     /* Remove "Maximize" menu option */
    
XtSetArg(args, XmNmwmFunctions, functions); n++;
 
/* Include the following two lines only if the window is *not* resizable */
 
handleMask |= MWM_DECOR_RESIZEH;     /* Remove resize handles */
    
XtSetArg(args, XmNmwmDecorations, handleMask); n++;
 
/* You need the following line only if you use an ApplicationShell for the window */
 
XtSetArg(args, XmNdeleteResponse, XmDO_NOTHING); n++;
 
/* 
 * Assume that the application has already created a main window and assigned its widget
 * to the variable mainWindow
 */
 
coPrimary = XtCreatePopupShell( "coPrimary", applicationShellWidgetClass,
                                mainWindow, args, n );
 
/* ... */


Creating a Support Window

Support windows are essentially custom dialogs. The easiest way to create a support window is to use XmCreateBulletinBoardDialog() to create a DialogShell containing a BulletinBoard widget, or use XmCreateFormDialog() to create a DialogShell containing a Form widget. You can then add appropriate controls and displays as children of the BulletinBoard or Form.

Another advantage to using a DialogShell for support windows is that they automatically have the proper window menu options and decorations. If you don't want the user to be able to resize the window—and you implemented the support window as a customized dialog—you should set XmNnoResize to “TRUE” to remove the “Size” and “Maximize” options and to remove the resize handles. Example 5-4 shows how you can create a support window and set the resource values appropriately.

“Support Windows” in Chapter 6 of the IRIX Interactive User Interface Guidelines provides guidelines for using support windows.

Example 5-4. Creating a Support Window

#include <Xm/Xm.h>          /* Required by all Motif applications */
#include <Xm/MwmUtil.h>     /* Required to set window menu and decorations */
#include <X11/Form.h>       /* Form definitions */
 
Widget       parentWindow;  /* Parent window of support window */
Widget       supportWindow; /* Support window */
Arg          args[10];      /* Argument list */
int          n;             /* Argument count */
 
/* ... */
 
n = 0;
 
/* Include the following line only if the window is *not* resizable */
 
XtSetArg(args, XmNnoResize, TRUE); n++
 
supportWindow = XmCreateFormDialog( parentWindow, "supportWindow", args, n );
 
/* Create the window interface... */


Creating a Dialog

The easiest way to create dialogs is to use the IRIS IM convenience functions such as XmCreateMessageDialog() and XmCreatePromptDialog(). These functions automatically set most of the window characteristics required for the IRIX Interactive Desktop environment.

Dialogs automatically have the proper window menu options and decorations. If you don't want the user to be able to resize the dialog, you should set XmNnoResize to “TRUE” to remove the “Size” and “Maximize” options and to remove the resize handles. Example 5-5 shows an example of creating a WarningDialog and setting the resource values appropriately.

Chapter 10, “Dialogs,” in the IRIX Interactive User Interface Guidelines provides guidelines for using dialogs.

Example 5-5. Creating a Dialog

#include <Xm/Xm.h>          /* Required by all Motif applications */
#include <Xm/MwmUtil.h>     /* Required to set window menu and decorations */
#include <Xm/MessageB.h>    /* Warning dialog definitions */
 
Widget       parentWindow;  /* Parent window of dialog */
Widget       dialog;        /* Dialog */
Arg          args[10];      /* Argument list */
int          n;             /* Argument count */
 
/* ... */
 
n = 0;
 
/* Include the following line only if the window is *not* resizable */
 
XtSetArg(args, XmNnoResize, TRUE); n++
 
dialog = XmCreateWarningDialog ( parentWindow, "warningDialog", args, n );


Handling Window Manager Protocols

This section describes how to handle window manager protocols:

  Protocols allow the window manager to send messages to your application. The window manager sends these messages only if your application registers callback function to handle the corresponding protocols.

Handling the Window Manager Quit Protocol

When a user selects the “Exit” option from a window menu, the window manager sends a Quit message to your application. You should install a callback routine to handle this event. Example 5-6 demonstrates installing such a callback for the window specified by mainWindow.

Example 5-6. Handling the Window Manager Quit Protocol

Atom WM_QUIT_APP = XmInternAtom( XtDisplay(mainWindow),
                                 "_WM_QUIT_APP", 
                                 FALSE );
XmAddWMProtocolCallback( mainWindow, WM_QUIT_APP,
                         quitCallback, NULL );
 
/* ... */
 
quitCallback( Widget w, XtPointer clientData,
              XmAnyCallbackStruct cbs )
{
    /* Quit application */
}


Note: You must install the quit callback for each window that contains an “Exit” option in its window menu. Often the only such window is your application's main primary window.


The operations performed by the callback function should be the same as those that occur when the user quits from within your application (for example, by selecting an “Exit” option from a File menu). Your application can prompt the user to save any files that are open, to perform any other cleanup, or even to abort the quit.

Handling the Window Manager Delete Window Protocol

When a user selects the “Close” option from a window menu, the window manager sends a Delete Window message to your application. How to handle this message depends on whether the window is a co-primary window, a dialog, or support window. (A main primary window should not have a “Close” option on its window menu.)

To handle the Delete Window message with a co-primary window, you should make sure to set the window's XmNdeleteResponse resource to XmDO_NOTHING. Otherwise, IRIS automatically deletes the window and, if the window uses an ApplicationShell, quits the application.

The callback you install can ask for user confirmation and can decide to comply or not comply with the request. If it decides to comply, your application can either pop down or destroy the window. If you think that the user might want to redisplay the window later, popping down the window is usually the better choice because your application doesn't have to re-create it later. Example 5-7 shows an example of installing a callback to handle the Delete Window message.

Example 5-7. Handling the Window Manager Delete Window Protocol in Co-Primary Windows

Atom WM_DELETE_WINDOW = XmInternAtom( XtDisplay(window),
                                      "WM_DELETE_WINDOW", 
                                      FALSE);
XmAddWMProtocolCallback( window, WM_DELETE_WINDOW,
                         closeCallback, NULL );
 
/* ... */

closeCallback( Widget w, XtPointer clientData,
               XmAnyCallbackStruct cbs )
{
    /* Delete or pop down window */
}

For support windows and dialogs, you typically want to dismiss the window when the user selects “Close.” Therefore, the default value of XmNdeleteResponse, XmDESTROY, is appropriate. Additionally, you should perform whatever other actions are appropriate for when that support window or dialog is dismissed. Typically, you can accomplish this by invoking the callback associated with the Cancel button, if it exists. Example 5-8 shows an example of this.

Example 5-8. Handling the Window Manager Delete Window Protocol in Support Windows and Dialogs

Atom WM_DELETE_WINDOW = XmInternAtom( XtDisplay(dialog),
                                      "WM_DELETE_WINDOW", 
                                      FALSE);
XmAddWMProtocolCallback( dialog, WM_DELETE_WINDOW,
                         cancelCallback, NULL );
 
/* ... */
 
cancelCallback( Widget w, XtPointer clientData,
                XmAnyCallbackStruct cbs )
{
    /* Perform cancel operations */
}


Handling the Window Manager Save Yourself Protocol

The “Save Yourself” protocol is part of the session management mechanism. The session manager sends a Save Yourself message to allow your application to update the command needed to restart itself in its current state. Currently, the session manager sends Save Yourself messages before ending a session (that is, logging out) and periodically while a session is active.

Your application doesn't need to subscribe to the Save Yourself protocol. Instead, your application can simply update the XmNargv and XmNargc resources on one of its ApplicationShells whenever it changes state, for example, when it opens or closes a file. The session manager re-saves its state information whenever your application changes these resources. (Actually, the session manager monitors the WM_COMMAND and WM_MACHINE properties, which are set by the ApplicationShell whenever you change its XmNargv and XmNargc resources.)

If you decide to use Save Yourself for session management, you can handle the protocol on any realized ApplicationShell. Don't use Save Yourself with the unrealized main window of the “Multiple Document, No Visible Main” application model. When the window manager sends a Save Yourself message to your application, your application must update the value of the XmNargv and XmNargc resources to specify the command needed to restart the application in its current state. Once you've updated the XmNargv and XmNargc resources, the session manager assumes that it can safely kill your application. Example 5-9 shows how to handle Save Yourself messages.


Note: Your application shouldn't prompt the user for input when it receives a Save Yourself message.


Example 5-9. Handling the Window Manager “Save Yourself” Protocol

/* saveyourself.c                                       */
/*                                                     */
/* Example code for handling the window manager's        */
/* WM_SAVE_YOURSELF Protocol                            */
/*                                                     */
/* cc -o saveyourself saveyourself.c -lXm -lXt          */
 
#include <Xm/Protocols.h>
#include <Xm/Label.h>
 
void saveYourSelfCallback(Widget w,  XtPointer client_data, 
                             XtPointer call_data)
{
    printf(“Update WM_COMMAND or state file\n”);
}
 
void main(int argc, char** argv)
{
   Widget toplevel, label;
   XtAppContext app_context;
   Atom WM_SAVE_YOURSELF;
 
   toplevel = XtAppInitialize(&app_context, “SaveYourSelf”,
                              NULL, 0, &argc, argv, NULL, NULL, 0);
 
   label = XmCreateLabel(toplevel, “saveme”, NULL, 0);
   XtManageChild(label);
 
   WM_SAVE_YOURSELF = XmInternAtom( XtDisplay(toplevel),
                                      “WM_SAVE_YOURSELF”,
                                      FALSE);
 
   XmAddWMProtocolCallback( toplevel, WM_SAVE_YOURSELF,
                            saveYourSelfCallback, NULL );
 
   XtRealizeWidget(toplevel);
   XtAppMainLoop(app_context);
}

Your application might not be able to fully specify its state using command line options. In that case, you can design your application to create a state file to save its state and to read the state file when it restarts.

Setting the Window Title

To set the title of a main primary window or co-primary window in your application, set the window's title resource. If the title you specify uses a non-default encoding, remember to also set the value of the titleEncoding resource appropriately. For support windows and dialogs, set the value of the XmNdialogTitle resource.

Choose the title according to the guidelines in the section “Window Title Bar” in Chapter 3 of the IRIX Interactive User Interface Guidelines. Update the label so that it always reflects the current information. For example, if the label reflects the name of the file the user is working on, you should update the label when the user opens a different file.

Controlling Window Placement and Size

Users have the option of specifying window placement and size, either through the -geometry option interactively using the mouse, or having applications automatically place their windows on the screen. To support automatic window placement, your application should provide default placement information for its main primary and co-primary windows. (Support windows and dialogs appear centered over their parent widget if the value of their XmNdefaultPosition resources are TRUE, which is the default.) You can also specify a default window size, minimum and maximum window sizes, minimum and maximum aspect ratios, and resizing increments for your windows. Typically, you should set these resources in your application's app-default file.

Controlling Window Placement

You should provide initial values for the window shell's x and y resources before mapping the window to specify its default location. The window manager ignores these values if the user requests interactive window placement or specifies a location using the -geometry option when invoking your application. You should not use the window's XmNgeometry resource to control initial window placement, either in your application's source code or its app-default file.

“Window Placement” in Chapter 3 of the IRIX Interactive User Interface Guidelines provides guidelines for controlling window placement.

Controlling Window Size

If the user doesn't specify a window size and you don't explicitly set the window size in your application, the initial size of the window is determined by geometry management negotiations of the shell widget's descendents. Typically, the resulting size is just large enough for all of the descendent widget to fit “comfortably.” Optionally, you can specify a default initial size for a window by providing initial values for the window's width and height resources before mapping the window. You should not use the window's XmNgeometry resource to control initial window size, either in your application's source code or its app-default file.

You can also set several shell resources to specify minimum and maximum window sizes, minimum and maximum aspect ratios, and resizing increments for a window:

minHeight and minWidth 

The desired minimum height and width for the window.

maxHeight and maxWidth 

The desired maximum height and width for the window.

minAspectX and minAspectY 

The desired minimum aspect ratio (X/Y) for the window.

maxAspectX and maxAspectY 

The desired maximum aspect ratio (X/Y) for the window.

baseHeight and baseWidth 

The base for a progression of preferred heights and widths for the window. The preferred heights are baseHeight plus integral multiples of heightInc, and the preferred widths are baseWidth plus integral multiples of widthInc. The window can't be resized smaller or larger than the values of the min* and max* resources.

heightInc and widthInc 

The desired increments for resizing the window.

“Window Size” in Chapter 3 of the IRIX Interactive User Interface Guidelines provides guidelines for controlling window size.