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



Primary Transfer Details

This section details primary transfers.

Primary Transfer: Step-by-Step

A primary transfer involves interaction among a user, an application, a source widget, and a destination widget. Following are the steps involved in a typical primary transfer:

  1. The user selects some portion of the source widget. The source widget probably highlights the selection.

  2. The source widget calls XmePrimarySource. XmePrimarySource establishes an internal function (we will call it FunctionP) that UTM will call later during the transfer.

  3. The user moves the cursor to the destination widget and presses some mouse button or key sequence to initiate a primary paste.

  4. The Intrinsics call the action method of the destination widget that is associated with the primary paste event. This action method calls XmePrimarySink.

  5. XmePrimarySink calls the destination widget's destinationPreHookProc trait method, if it exists.

  6. XmePrimarySink calls any XmNdestinationCallback procedures that the application has attached to the destination widget.

  7. XmePrimarySink conditionally calls the destinationProc trait method of the destination widget. We will use the term "destination routines" to refer to the combination of the XmNdestinationCallback application procedures and the destinationProc trait method. Typically, one of the destination routines will call XmTransferValue and request a list of the source widget's TARGETS.

  8. UTM calls FunctionP, which in turn calls the conversion routines of the source widget. The conversion routines are responsible for returning a list of the convertible targets.

  9. UTM returns control to the transfer procedure named by XmTransferValue. The transfer procedure examines the list of returned targets and picks the most appropriate one. The transfer procedure then calls XmTransferValue and asks for the chosen target. For this example, let us assume that the destinationProc picked the COMPOUND_TEXT target.

  10. UTM calls FunctionP, which in turn calls the conversion routines again. This time, FunctionP asks the conversion routines to convert the selection to COMPOUND_TEXT format. The conversion routine is responsible for setting the appropriate fields in the XmConvertCallbackStruct For example, the conversion routine should place the converted text into the value member of the XmConvertCallbackStruct. If a conversion routine can do the conversion, it sets the status member of the XmConvertCallbackStruct to XmCONVERT_DONE.

  11. UTM returns control to the transfer procedure of the destination widget. Assuming all went well, the converted text will be stored in the value member of the XmSelectionCallbackStruct. The transfer procedure need only paste the converted text into the appropriate place in the destination widget.

  12. Sample Translations for a Primary Transfer

    The ExmStringTransfer demonstration widget supports primary transfer. The following translations are relevant to the primary transfer:

    <Btn1Down>: 
    ExmStringTransferMoveFocus()ExmStringTransferCopyPrimary()\n\
    <Btn2Down>:  ExmStringTransferProcessDrag()\n\

    A user starts a primary copy by pressing Btn1Down. However, the Btn2Down translation is far more puzzling because Btn2Down could mean either a primary paste or the start of a drag operation. ExmStringTransferProcessDrag solves this puzzle by determining whether or not ExmStringTransfer currently owns the primary selection. If it does, ExmStringTransferProcessDrag calls the ExmStringTransferPastePrimary routine.

    Sample Copy Primary Action

    The ExmStringTransfer widget contains the following relatively simple copy primary routine:

    static void
    ExmStringTransferCopyPrimary(
         Widget w,
         XEvent *event,
         String *params,
         Cardinal *num_params)
    {
     Time time;
     ExmStringTransfer stw = (ExmStringTransfer) w;
      /* First we must obtain a timestamp. This is required for
         ICCCM compliance. XtLastTimestampProcessed holds the timestamp
         from the last event the Intrinsics saw with a timestamp. */
      time = XtLastTimestampProcessed(XtDisplay(w));
     
      /* Own the primary selection. Indicate this to the user by
         reversing the foreground and background in the text rendition
         (eventually) */
      stw->string_transfer.own_primary = True;
     
      /* Once we call XmePrimarySource,  the widget's transfer trait
         convert method will get called if a destination wishes to
         obtain the PRIMARY selection. */
      XmePrimarySource(w, time);
     
      /* Update the widget to show the new state */
      stw->core.widget_class->core_class.expose(w, NULL, NULL);
    }

    In the preceding code, stw->string_transfer.own_primary is a Boolean field. ExmStringTransfer sets this field to True when the widget holds the primary selection and False when the widget relinquishes the primary selection.

    Sample Paste Primary Action

    The most important part of the paste primary routine of ExmStringTransfer is its call to XmePrimarySink. Following is the complete ExmStringTransferPastePrimary routine:

    static void
    ExmStringTransferPastePrimary(
         Widget w,
         XEvent *event,
         String *params,
         Cardinal *num_params)
    {
      Time time;
      unsigned int op;
      /* First we must obtain a timestamp. This is required for
         ICCCM compliant ownership of a selection. We use
         XtLastTimestampProcessed which holds the timestamp
         from the last event the Intrinsics saw with a timestamp. */
      time = XtLastTimestampProcessed(XtDisplay(w));
     
      /* We determine the right operation to perform by looking
         at the modifiers present */
      if (event -> xbutton.state & ShiftMask) {
        if (event -> xbutton.state & ControlMask)
          op = XmLINK;
        else
          op = XmMOVE;
      } else
        op = XmCOPY;
     
      /* Calling XmePrimarySink will start the process of requesting
         the PRIMARY selection to be pasted using the transfer trait
         destination callback for this widget class */
      XmePrimarySink(w, op, NULL, time);
    }

    The second argument to XmePrimarySink (called op in the preceding code) describes the kind of operation that the user has requested. UTM will copy the value of op into the operation member of the XmDestinationCallbackStruct.


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