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



A Data Transfer Tutorial

Transferring data between two widgets is analogous to transferring data between two computers. In both cases, data transfer requires both a channel and a communications protocol.

Consider how two computers transfer a file. Before the transfer, one computer owns the file to be transferred and the other computer (the receiver) does not. In order for the transfer to take place, some sort of channel (probably a modem or a cable) must connect the two machines. However, having a physical link between the two machines is not enough; the two machines must also agree on the rules or protocols governing the file transfer. For example, the computer that owns the file needs some way to tell the destination computer that it is ready to send the file. The destination computer needs to signal back to the owner computer when it is ready to receive. At the end of the file transfer, the destination computer needs to acknowledge receipt of the file.

Now let's consider how two widgets transfer data. Before the data transfer, one widget owns the data to be transferred and the other widget (the destination widget) does not. In order for the transfer to take place, some sort of channel must connect the two widgets. The X Windows server acts as this virtual channel. However, having a channel is not enough; the two widgets must also share the same data transfer protocol. This protocol is defined by the ICCCM; the recommended Motif implementation of the ICCCM is called UTM.

The ICCCM protocol defines the kinds of messages passed between the owner widget and the destination widget. The two widgets can belong to the same client or to two different clients.

Problems Solved by the Protocol

Many newcomers wonder why the ICCCM protocol has to be so complicated. One answer is that each widget is a self-contained object that knows how to take care of itself but ignores other widgets. Therefore, widgets monitor their own events only and ignore the events of other widgets.

For example, suppose a user wants to copy some data from one widget (the source) to another (the destination). To do this, the user must first select the data that is to be copied. The user then moves the pointer to the destination widget and indicates where the data should be transferred. Since the destination widget does not receive the source widget's events, the destination widget does not have the following information:

  1. The data the user selected for copying

  2. What kind of data (such as text, a pixmap, a color) the user has selected

  3. The format data is in or how much data there actually is

    The ICCCM protocol solves these problems by forcing all widgets to use atoms to describe the data to be transferred.

  4. Atoms

    The ICCCM requires that the owner and destination use atoms to solve these categorization needs. In brief, an atom is a number that symbolizes a particular data category or a particular data transfer selection. For example, the ICCCM specifies that an atom called PIXMAP be used to symbolize the transfer of a pixmap. As another example, the ICCCM specifies that an atom called CLIPBOARD by used to symbolize a clipboard selection.

    Atoms like PIXMAP that specify a data category are called target atoms or, more simply, targets. Atoms like CLIPBOARD that specify a kind of transfer mechanism are called selection atoms.

    Target Atoms

    Widgets can display many kinds of information. Most of the displayed information (and some of the nondisplayed information) should be transferrable. The widget represents each of these different kinds of transferrable information as a target atom.

    For example, consider the XmLabel widget. As you might expect, XmLabel allows users to make copies of the displayed text or pixmap. What is somewhat surprising is that XmLabel can also transfer other kinds of information. For example, XmLabel can transfer information about its foreground and background colors. In fact, the relatively simple XmLabel widget can transfer over a dozen different targets.

    Selection Atoms

    Each selection is represented by an atom. The display contains only one selection of each type. It is owned by a client or by no one and, if owned, is attached to a window of the owning client. Any client may assert or remove ownership of a selection.

    The data represented by the selection is internal to the client that owns the selection.

    Motif uses the following selection atoms:

    1. PRIMARY, which identifies the principal selection. This selection atom is defined by the ICCCM.

    2. SECONDARY, which identifies a means of exchanging data without disturbing the primary selection. This selection atom is defined by the ICCCM.

    3. CLIPBOARD, which is the selection often used to cut or copy data from one client and paste it into another. A client transfers data to the clipboard by asserting ownership of this selection. A client transfers data from the clipboard by requesting conversion of the selection. A separate client may also represent the clipboard. This client can notice when it loses the selection (because another client wants to transfer data to the clipboard), then request a conversion of the selection and finally reassert ownership. This selection atom is defined by the ICCCM.

    4. _MOTIF_DROP, which is the selection used in a drag and drop operation. This selection atom is specific to Motif; that is, the ICCCM does not define the _MOTIF_DROP selection atom.

    5. Defining Atoms

      The Atom data type is used to declare an atom variable. Use the Xlib function XInternAtom to assign an atom value to your atom variable. For example, the following code creates an Atom variable named TEXT and associates the correct atom value with the TEXT variable.

      Atom TEXT = XInternAtom(XtDisplay(w), "TEXT", False);

      The second argument to XInternAtom is an atom string name. You can specify an atom string name from any of the following four categories:

      1. An atom string name defined by the ICCCM; for example, TARGETS.

      2. A Motif atom string name that is a redefinition of an ICCCM atom string name. Table 10-1 lists all these atom string names along with their ICCCM equivalents. You can assume that all of the Motif atom string names have the same meaning as their ICCCM equivalents.

      3. A Motif atom string name that has no ICCCM equivalent.

      4. An atom string name that you make up yourself.

        We recommend that you avoid making up new atom string names whenever possible. If you do make up your own, the atom string names you pick should follow the naming conventions documented in the ICCCM.

        You can specify an atom string name as a constant having the XmS prefix; for example:

        Atom TARGETS = XInternAtom(XtDisplay(w), XmSTARGETS, False);

        or you can specify an atom string name as a string without the XmS prefix; for example, the following line of code produces the same results as the previous line of code:

        Atom TARGETS = XInternAtom(XtDisplay(w), "TARGETS",
        False);

        Table 21. Motif Atoms That Are Equivalent to ICCCM Atoms

        Atom String Name ICCCM Equivalent
        XmSCLIENT_WINDOW CLIENT_WINDOW
        XmSCLIPBOARD CLIPBOARD
        XmSCOMPOUND_TEXT COMPOUND_TEXT
        XmSDELETE DELETE
        XmSFILE FILE
        XmSFILE_NAME FILE_NAME
        XmSINCR INCR
        XmSINSERT_PROPERTY INSERT_PROPERTY
        XmSINSERT_SELECTION INSERT_SELECTION
        XmSLENGTH LENGTH
        XmSLINK_SELECTION LINK_SELECTION
        XmSMULTIPLE MULTIPLE
        XmSNULL NULL
        XmSTARGETS TARGETS
        XmSTEXT TEXT
        XmSTIMESTAMP TIMESTAMP
        XmSWM_STATE WM_STATE

        As we mentioned earlier, Motif also provides some atom string names that have no ICCCM equivalent. Motif atom string names that have no ICCCM equivalent have a prefix of _MOTIF are as follows:

        1. XmS_MOTIF_CLIPBOARD_TARGETS

        2. XmS_MOTIF_COMPOUND_STRING

        3. XmS_MOTIF_DEFERRED_CLIPBOARD_TARGETS

        4. XmS_MOTIF_DESTINATION

        5. XmS_MOTIF_DROP

        6. XmS_MOTIF_ENCODING_REGISTRY

        7. XmS_MOTIF_EXPORT_TARGETS

        8. XmS_MOTIF_LOSE_SELECTION

        9. XmS_MOTIF_RENDER_TABLE

        10. XmS_MOTIF_SNAPSHOT

          This chapter explains all of these unique Motif atom string names.

        11. A Typical Data Transfer Sequence

          The data transfer protocol defines a kind of dialog between the source widget and the destination widget. This dialog is somewhat different for each data transfer mechanism. For example, the dialog of a clipboard transfer is more complicated than that of a primary transfer. Nevertheless, we can describe a kind of idealized dialog that is general enough to be reasonably accurate for all four data transfer mechanisms.

          This idealized data transfer sequence consists of the seven steps shown in Figure 10-1.

          Figure 5. The Data Transfer Dialog.




          View figure.

          The user starts a data transfer (Step 1) by specifying the source widget of the data transfer. The user typically specifies the source widget by selecting some portion of a widget; for example, a line of displayed text. The user makes a selection through some keyboard or mouse event. For example, a user can select a line in an XmText widget by positioning the cursor anywhere on the line and then clicking the left mouse button three times. In some cases, Step 1 actually consists of two parts. In the first part, the user selects the data to be transferred. In the second part, the user enters some other event to specify the data transfer mechanism. For example, the user might hold down the middle mouse button to start a drag operation.

          The user also indicates the destination widget (Step 2) of the data transfer. The user does this by changing focus to the destination widget and then entering some event. For example, the user specifies the destination widget of a drag and drop operation by moving the cursor to the destination widget and then releasing the middle mouse button.

          After completing Steps 1 and 2, the user's role in data transfer is over. The remaining steps must all be implemented by the widget.

          Don't forget that, at this stage, the destination widget has no idea what kind of data has been selected in the source widget. Therefore, at Step 3, the destination widget has to ask the source widget for a list of all the targets that the source widget can transfer. The destination widget does this by sending the source widget a message asking for its TARGETS list.

          The source widget responds to the request for TARGETS (Step 4) by returning a list of all the atoms that it knows how to transfer. For example, in Figure 10-1, the source widget claims to know how to transfer the following targets:

          1. STRING

          2. COMPOUND_TEXT

          3. LOCALE_ENCODING

          4. MOTIF_COMPOUND_STRING

            In practice, the returned list of TARGETS will be considerably longer than in this example.

            The source widget does not place the atoms in the returned TARGETS list in any particular order. For example, the first atom in the TARGETS list is not necessarily the atom that the source widget wants most to transfer.

            In Step 5, the destination widget examines the list of target atoms returned by the source widget. From this list, the destination widget chooses the atom that most closely meets its needs. In Figure 10-1, the destination widget selected COMPOUND_TEXT.

            In Step 6, the source widget converts the data that the user has selected into the data representation that the destination widget has requested. For example, in Figure 10-1, the source widget has to convert the selected data to COMPOUND_TEXT. In some cases, the source widget does not have to do much work to convert the data. For example, perhaps the source widget stores text as COMPOUND_TEXT anyway. In other cases, the source widget might have to fight a considerable battle to convert the data into the proper representation. For example, perhaps the source widget stores text in XmString format. In this case, the source widget will have to convert the string from XmString format to COMPOUND_TEXT format.

            A surprisingly high percentage of a data transfer widget is devoted to data conversion. When the source widget is finished converting the data, the source widget sends the converted data to the destination widget.

            In Step 7, the destination widget pastes the received data into the appropriate portion of the widget.

            You may be wondering what happens if the destination widget wants more than one kind of data from the source widget. For example, suppose that the destination widget wants the source widget to transfer both a pixmap and a colormap. There are two possible ways to handle this. One possibility is that Steps 5, 6, and 7 will be repeated. Another possibility is that, in Step 5, the destination widget can request a multiple data transfer, and, in Step 6, the source widget can honor that request by passing several different kinds of data back at the same time.


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