The top-level widget returned by XtAppInitialize or XtAppCreateShell is the root of a program's widget hierarchy for a given display or logical application. After initializing the Intrinsics, the application can proceed to create the remainder of the widget hierarchy it needs to start the program.
Widget creation is a two-stage process. In the first stage, the application creates the widget hierarchy but does not assign windows to the widgets. In the second stage, the application assigns windows and makes them visible. These stages are separate because, otherwise, window geometry might have to be recomputed each time a child is added. This computation can require a great deal of communication with the X server and take a long time. Instead, initial window geometry is computed only once. For more information, see Section 3.5.
The general routine for creating a widget is XtCreateWidget. The required arguments to this routine are the widget's name, class, and parent widget. You can also provide initial resource values for the widget, as discussed in the next section. XtVaCreateWidget is a version of XtCreateWidget that uses a variable-length argument list.
Motif has a convenience routine for creating a widget of each Motif class. The name of such a routine is usually XmCreate <widget>, where widget represents the widget class. For example, the convenience routine for creating a Text widget is XmCreateText. These routines do not require the widget-class argument.
Some convenience routines, such as XmCreateMenuBar, create specialized widgets. These routines usually set some initial resource values to configure the widget for a particular use--for example, to configure a RowColumn widget for use as a MenuBar. In some cases, such as XmCreatePulldownMenu and XmCreateScrolledList, these routines create a widget hierarchy rather than a single widget. The documentation for each convenience routine in the Motif Programmer's Reference explains what the routine does.
Using a Motif creation routine is generally preferable to calling XtCreateWidget. In addition to creating multiple widgets and setting appropriate resources, these routines sometimes perform optimizations. For example, some convenience routines add XmNdestroyCallback procedures to free memory when the widget is destroyed.
Every widget except a top-level widget must have a parent at the time the widget is created.
An application can use XtDestroyWidget to destroy a widget. An application can specify values for resources when it creates a widget and anytime thereafter. Note that hardcoding widget resources reduces the ability of the user to customise the widgets. It can retrieve resource values after creating a widget.
When an application creates a widget, the creation routine sets the widget's initial resource values from the following sources, in order (that is, each succeeding component takes precedence over preceding components):
Each widget class can have its own initialize procedure. After setting the initial resource values, the widget creation routine calls the initialize procedure for each class in the widget's class hierarchy, in superclass-to-subclass order. The initialize procedure can set new values for resources, possibly based on other resource values in the widget or its ancestors. In some cases, an initialize procedure forces a resource to have a particular value, regardless of whether the user or application has specified another value. In other cases, the initialize procedure might set a resource value only if the user or application has not specified another value.
The documentation for each widget class in the Motif Programmer's Reference lists the data type and default value for each resource. For resources whose default values are computed dynamically, the documentation describes how the default values are determined.
To specify initial resource values in a call to a widget creation routine, an application supplies two arguments: a list of elements representing resource settings and an integer specifying the number of elements in the list. Each element in the list is a structure of type Arg. This structure has two members: a string representing the name of the resource, and a value specifier representing the resource value. The value specifier is of type XtArgVal. This is a data type large enough to hold a long or one of several types of pointers to other data. If the resource value is of a type small enough to fit into an XtArgVal, the value specifier contains the resource value itself; otherwise, it contains a pointer to the actual value. For most resources, an application supplies integer values (including such types as Position and Dimension) directly in the value specifier; otherwise, the application supplies a pointer to the value.
The most common way to set up a list of resource specifications is to declare a list of Arg elements large enough to hold all the specifications and then to use XtSetArg to insert each specification into the list. An application should always use a sequence of calls to XtSetArg in the following way to avoid mistakes in building the list:
... Widget text; Arg args; Cardinal n; n = 0; XtSetArg(args[n], XmNrows, 10); n++; XtSetArg(args[n], XmNcolumns, 80); n++; text = XmCreateText("text", parent, args, n);
Instead of using lists of Arg structures, the variable-argument routines that specify resource values take a variable number of pairs of resource names and values as arguments. The resource value in each pair is of type XtArgVal, with the same meaning as the value in an Arg structure. The application can provide two special strings in place of a resource name. If the name is XtVaNestedList, the next argument is interpreted as a nested list of name-value pairs. If the name is XtVaTypedArg, the next four arguments supply the resource value and cause it to be converted from one data type to another, as described in the following sections.
To specify resource values after a widget has been created, an application uses XtSetValues or XtVaSetValues. XtSetValues takes a list of resource specifications in the same format as that used when creating a widget:
... Arg args; Cardinal n; n = 0; XtSetArg(args[n], XmNrows, 10); n++; XtSetArg(args[n], XmNcolumns, 80); n++; XtSetValues(text, args, n);
Each widget class can have its own set_values procedure. After setting the values specified in the argument list, XtSetValues calls the set_values procedure for each class in the widget's class hierarchy, in superclass-to-subclass order. The set_values procedure can set new values for resources other than those specified in the arguments to XtSetValues. This usually happens when the value of one resource depends on the value of another. Setting a new value for a resource that affects the widget's geometry can also cause Motif to recompute the widget's layout. In some cases a set_values procedure forces a resource to have a particular value, regardless of whether the application has specified another value.
To retrieve resource values, an application uses XtGetValues or XtVaGetValues. The arguments are the same as those for XtSetValues, except that in place of a value for each resource is an address in which Motif stores the requested value:
... Arg args; Cardinal n; short nrows, ncolumns; n = 0; XtSetArg(args[n], XmNrows, &nrows); n++; XtSetArg(args[n], XmNcolumns, &ncolumns); n++; XtGetValues(text, args, n);
The documentation for each widget class in the Motif Programmer's Reference lists the data types to use when setting and retrieving values for resources. The user and application do not always have to supply data of the type documented. Motif has routines, called converters, that convert resource values from one data type to another. For example, when a value for the resource database comes from a file or the command line, Motif processes the value as a string. Motif and Xt have routines to convert strings to most common resource types, including Boolean, Dimension, Position, Pixel, and XmFontList.
When using the standard widget creation routines, XtSetValues, and XtGetValues, an application must supply resource values or addresses of the types the widget expects. But when using the variable-argument versions of these routines, the application can supply values of any types for which routines exist to convert data of those types into values of the expected types. To provide for a resource conversion, the application supplies XtVaTypedArg in place of a resource name in the argument list. In place of the resource value, the application supplies four arguments:
For example, the following call converts the supplied string into the compound string that Motif expects for a PushButton label:
... char *label = "Button"; XtVaSetValues(button, XtVaTypedArg, XmNlabelString, XmRString, label, strlen(label) + 1, NULL);
Note that setting resource values with XtVaTypedArg will not work properly for certain gadget, text, and VendorShell resources.
The application is responsible for allocating and freeing memory needed for resource values it supplies when initializing a widget or setting new values. For most resources whose values are not immediate data, including strings, compound strings, and font lists, Motif makes copies of values the application supplies when it creates a widget or calls XtSetValues. The application can free the allocated memory anytime after the widget creation routine executes or XtSetValues returns:
... char *label = "Button"; XmString label_cs; label_cs = XmStringCreateLocalized(label); XtVaSetValues(button, XmNlabelString, label_cs, NULL); XmStringFree(label_cs);
For resources whose values are not immediate data, XtGetValues sometimes makes a copy of values and sometimes does not. For example, Motif always makes copies of compound strings retrieved by XtGetValues, but it does not make copies of lists of compound strings (data of type XmStringTable). An application should free compound strings retrieved by XtGetValues, but in general it should not free values of other types unless the documentation for the particular resource in the Motif Programmer's Reference says the application must free that value.
The standard routines an application should use to allocate memory are
XtMalloc and XtNew. The standard routine to free memory is XtFree. Some Motif
data types have memory-management routines that an application should use
instead of the more general Xt routines. For example, use XmStringFree to free
memory for a compound string. Table 3 lists the Motif memory deallocation
Table 3. Motif Memory Deallocation Routines
|Routine||Recovers Memory Used By:|
|XmFontListEntryFree||A font list entry|
|XmFontListFree||A font list|
|XmFontListFreeFontContext||A font list context|
|XmImFreeXIC||The widgets associated with a specified X Input Context (XIC)|
|XmParseMappingFree||A parse mapping|
|XmParseTableFree||A parse table|
|XmRenderTableFree||A render table|
|XmStringConcatAndFree||Two input compound strings|
|XmStringFree||A compound string|
|XmStringFreeContext||The string scanning context|
|XmTabListFree||A tab list|