[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Programmer's Guide



Translations and Actions

In Xt, the primary means of associating an input event with a widget-specific procedure is the combination of translations and actions. Each widget (but not gadget) instance contains a table of translations that maps event descriptions to procedure names. Each widget instance also has a table of actions that maps these procedure names to actual procedures. When a widget receives an input event, the Xt event-dispatching facility looks up the event in the translation table, looks up the associated procedure in the action table, and invokes the action procedure itself. This procedure usually takes some action to change the widget state and often invokes callback procedures.

Translation Table Format

An application or user specifies a translation table as a string whose format is defined in X Toolkit Intrinsics--C Language Interface. In general, the table consists of individual translations separated by "\n". Each translation consists of an event description sequence, a colon, and one or more associated procedure names. Each procedure name also has a list of parameters within parentheses to be passed to the procedure when it is invoked as a result of that translation.

An event description in general consists of an optional list of modifiers, an event type within angle brackets (< and >), an optional repeat count within parentheses, and an optional event detail. Modifiers apply only to key, button, motion, enter, and leave events. If an exclamation point (!) precedes the modifiers, then the modifiers in the list and no others must be asserted for the action to be invoked. Otherwise, the modifiers in the list must be asserted, but others may be as well. A tilde (~) before any modifier means that that modifier must not be asserted. If the modifier list is empty, any modifiers may be asserted.

The detail field varies depending on the event type. The most common use is to identify the keysym for a KeyPress or KeyRelease event.

Event descriptions in a sequence are separated by commas. Mouse motion is discarded if it occurs between events in a sequence that does not include explicit motion events. This allows the following sort of translation to invoke an action even if the mouse moves between button press and release:

<Btn1Down>,<Btn1Up>: action()

Following are some important considerations in using translations:

  1. More specific events should always precede less specific events in the table:
    Ctrl<Key>space: action_1()
    <Key>space: action_2()

  2. Translations with event sequences that are noninitial subsequences of other translations are not invoked when the events occur as part of the longer sequence. For instance, up_action() in the following example would not be invoked on a button release that followed a button press:
    <Btn1Down>,<Btn1Up>: click_action()
    <Btn1Up>: up_action()

  3. Event descriptions that use a repeat count expand into longer sequences. For example, the following descriptions are more or less equivalent:
    <Btn1Up>(2): double_click()
    <Btn1Up>,<Btn1Down>,<Btn1Up>: double_click()

    This result, combined with the implicit insertion of motion events between any two other events, means that motion translations cannot exist in a table with multiclick translations.

    See X Toolkit Intrinsics--C Language Interface for more information on the format of translation tables.

  4. Using Translations

    One translation table frequently needs to be merged with another. For example, a user may want to add one or more translations to a widget's default translations. A translation table may begin with one of three directives that specifies how the table is to be merged with an existing table:

    #replace
    The new translation table should completely replace any existing table. This is the default if no directive is specified.

    #augment
    The new translation table should be added to any existing table. If the two tables contain duplicate event descriptions, the translations in the existing table are used.

    #override
    The new translation table should be added to any existing table. If the two tables contain duplicate event descriptions, the translations in the new table are used.

    A widget's translation table is the value of the Core XmNtranslations resource. The initial value is determined in the following way:

    1. If a non-NULL value is specified for XmNtranslations in the widget creation argument list, the widget class translations are merged with that value, in order, and the resulting table is used.

    2. Otherwise, the following tables are merged, in order, and the resulting table is used:

      1. The widget class translations

      2. The value of the baseTranslations resource from the resource database

      3. The value of the XmNtranslations resource from the resource database or, if no value was specified, the default value for the widget's XmNtranslations

        To take advantage of this initialization ordering, an application should usually provide any translations of its own by specifying a value for baseTranslations rather than XmNtranslations in an application class defaults file or a fallback resource list. This essentially reserves XmNtranslations to the user. The application can change the widget class translations by specifying baseTranslations, and the user can change the application's translations by specifying XmNtranslations.

        As the value of a widget's XmNtranslations, a translation table must be in a parsed format rather than a string. The string-to-translation-table converter parses a resource string into a translation table. An application can also use XtParseTranslationTable to compile a translation table string into the parsed format. The application can then merge the parsed table with a widget's XmNtranslations in three ways:

        1. XtAugmentTranslations merges the parsed table in #augment mode

        2. XtOverrideTranslations merges the parsed table in #override mode

        3. XtSetValues of XmNtranslations replaces the existing value with the parsed table

          Some Motif widgets merge additional translations in their initialize and set_values methods. This process may make it impossible for an application or user to override some translations by means of resource files. For example, for some widgets it may not be possible to change traversal translations in this way.

        4. Actions

          Each widget instance has a table that maps action procedure names, as they appear in translation tables, to actual action procedures. When an action is invoked through a translation, Xt looks up the action procedure name in this table and calls the associated procedure.

          Each widget class may have its own action table. In addition, an application can use XtAppAddActions to add entries to an action table associated with the application context. Only one such table exists per application context. If a call to XtAppAddActions contains an action name that is already in the table, the action name becomes associated with the action procedure supplied in the call to XtAppAddActions, overriding the existing action.

          Xt creates a widget's action table when the widget is realized. It uses actions from the following action tables, those listed first having highest precedence:

          1. The action tables for the widget's class and its superclasses, in subclass-to-superclass order

          2. The action tables for the parent's class and its superclasses, in subclass-to-superclass order, and so on up the widget hierarchy

          3. The application context action table (created by calls to XtAppAddActions)

            This ordering means that an application cannot use XtAppAddActions to provide a new action procedure for an action name that is already registered by a widget class. To do that, the application must supply a translation that maps the event to an action name that is not registered by the class. The application must then call XtAppAddActions to supply a procedure for the action name.

            An action procedure is a function of type XtActionProc. This function receives four arguments:

            1. The widget

            2. The event, or the last event of a sequence, that caused the procedure to be invoked

            3. A list of strings representing the parameters specified for this action in the translation table

            4. An integer representing the number of parameters in the parameter list

              An application can use the parameter list to perform a number of related actions in a single action routine. For example, a widget might have the following translations:

              c <Key> osfLeft: move-object(left) \n\
              c <Key> osfRight: move-object(right) \n\
              c <Key> osfUp: move-object(up) \n\
              c <Key> osfDown: move-object(down)

              The routine implementing the move-object() action is passed one of the strings "left", "right", "up", and "down" as the only item in the parameter list, depending on which key event invoked the action. The routine performs the action appropriate for this parameter.

            5. Bindings for osf Keysyms

              Motif maintains a client-side mechanism for mapping one set of keysyms to another set. This mapping allows Motif widgets and applications to use a single set of keysyms in translation tables and also allows applications and users to customize the keysyms used in the translations for the particular keyboard used with the display.

              The names of keysyms eligible for use in translations in this way begin with the prefix "osf" and are referred to as osf keysyms. Motif maintains a mapping between these "virtual" keysyms and the "actual" keysyms that correspond to keys on a particular keyboard. When Xt receives a keyboard event, the function XmTranslateKey translates the keycode of the event to the appropriate osf keysym if a mapping exists for that keysym. Xt then dispatches the event to the appropriate action routine if a translation exists for that osf keysym.

              The mapping between osf and actual keysyms is determined at application startup based on information obtained from one of the following sources, listed in order of precedence:

              1. A defaultVirtualBindings application resource in the resource database.

              2. A property on the root window, which can be set by mwm on startup, by the xmbind client, or on prior startup of a Motif application.

              3. A .motifbind file in the user's home directory.

              4. A default binding based on the vendor string and optionally the vendor release of the X server. Motif searches the file xmbind.alias in the user's home directory, the directory specified by the environment variable XMBINDDIR, or the directory /usr/lib/Xm/bindings.

                The file xmbind.alias maps combinations of vendor strings and vendor release numbers to pathnames. Each pathname represents a file that contains keysym bindings for a particular vendor string and optional vendor release number. If Motif fails to find a bindings file for the current display, it uses a set of hard-coded fallback bindings.

                The format of the defaultVirtualBindings resource is similar to that of a string specifying translations. Each binding consists of an osf keysym, a colon, a list of key event descriptions (with optional modifiers) for actual keysyms, and "\n". Use a comma to separate multiple key event descriptions. The format of a .motifbind file or a file containing vendor bindings is the same, except that each binding is on a separate line.

                Following is an example of a specification for the defaultVirtualBindings resource in a resource file:

                *defaultVirtualBindings: \
                        osfBackSpace:       <Key>BackSpace       \n\
                        osfInsert:       <Key>InsertChar      \n\
                        osfDelete:       <Key>DeleteChar

                The example specification above appears as follows in a .motifbind or vendor bindings file:

                osfBackSpace:       <Key>BackSpace
                osfInsert:       <Key>InsertChar
                osfDelete:       <Key>DeleteChar

                For more information, see the VirtualBindings(3) and xmbind(1) reference pages in the Motif Programmer's Reference.


              5. [ Previous | Next | Contents | Glossary | Home | Search ]