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

Drag and Drop Transfer Details

Drag and drop is similar to primary transfer. Like primary transfer, drag and drop transfers the selection directly to another widget without going through a clipboard. Unlike primary transfer, drag and drop provides sophisticated visuals to help the user understand various details of the transfer. For example, the source icon of a drag and drop transfer symbolizes the kind of object being dragged.

As a widget writer, you are responsible for supplying the UTM underpinnings of a drag and drop operation.You may also provide various drag and drop icons; however, the application or user may override your choices. This chapter focuses on the UTM underpinnings of drag and drop. That is, we will focus on the kinds of activities that widget writers have to do in order to implement drag and drop in a widget. We will not focus on the large family of drag and drop visuals. (For information on these topics, see the Motif Programmer's Guide.)

Compatibility with Previous Releases

Drag and drop was introduced in Motif Release 1.2. If you wrote a drag and drop application or widget at Release 1.2, it should continue to work at Motif Release 2.0. However, if you are writing a widget at Motif Release 2.0, you should use UTM to implement any drag and drop features.

We recommend converting any existing pre-UTM drag and drop code to UTM.

Drag and Drop Transfers: Step by Step

This section takes you step by step through a typical drag and drop transfer. Remember that this is a typical transfer, but it is by no means the only way a drag and drop transfer might happen. In this section, we use the term "conversion routines" to mean a combination of any XmNconvertCallback routines of the application and the convertProc trait method of the source widget.

Following are the steps:

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

  2. The user presses some mouse button or key sequence to initiate a drag operation. Typically, the user initiates a drag operation by pressing Btn2Down. The Intrinsics respond to the event by calling the appropriate action method in the source widget.

  3. The called action method itself calls XmeDragSource . The call to XmeDragSource can specify any XmDragContext resources. (XmeDragSource will ultimately instantiate an XmDragContext widget.)

  4. XmeDragSource asks the conversion routines to provide a list of _MOTIF_EXPORT_TARGETS.

  5. The conversion routines must respond to this request by returning a list of draggable targets. This list may or may not consist of all the targets that the conversion routines can convert. Typically, this list consists only of the targets that the destination widget is most likely to request.

  6. XmeDragSource calls XmDragStart, which in turn instantiates an XmDragContext. The XmDragContext displays the appropriate drag icons. XmeDragSource sets the XmNexportTargets resource of XmDragContext to the list of draggable targets. Similarly, XmeDragSource sets the XmNnumExportTargets resource of XmDragContext to the number of draggable targets.

  7. The user drags these icons towards the destination widget. The user typically does this by continuing to press Btn2Down while moving the mouse.

  8. When the user is over the destination widget, the user releases some mouse button or presses some key sequence to initiate a drop operation. Typically, the user initiates the drop operation by releasing the mouse button, generating Btn2Up.

  9. If the destination widget has not been registered as a drop site, UTM will reject the attempted drop and the transfer will end. If the destination widget has been registered as a drop site, the transfer will continue. A widget registers itself as a drop site by calling XmeDropSink. Note that the widget calls XmeDropSink when the widget is first instantiated, not as a response to the Btn2Up event. XmeDropSink is the UTM interface to the XmDropSite registry.

  10. UTM calls the destination widget's destinationPreHookProc trait method, if any. UTM passes an XmDestinationCallbackStruct as the call_data argument.

  11. UTM then calls the destination routines associated with the destination widget. The first destination routines called are the XmNdestinationCallback procedures that the application has associated with the destination widget. The next destination routine called is the destinationProc trait method of the destination widget. UTM passes a pointer to an XmDropProcCallbackStruct in the destination_data member of the XmDestinationCallbackStruct (The members of the XmDestinationCallbackStruct are documented in the XmDropSite reference page.)

  12. A destination routine typically calls XtGetValues on the XmNexportTargets resource of the XmDragContext widget.

  13. A destination routine examines the returned XmNexportTargets and calls XmTransferValue to request the most desirable one. If none of the targets in XmNexportTargets are desirable, a destination routine will call XmTransferValue and ask for the complete list of TARGETS. (Remember that XmNexportTargets does not necessarily hold a complete list of targets, but TARGETS does.)

  14. UTM asks the conversion routines of the source widget to convert the requested target.

  15. A conversion routine attempts to convert the selection to the desired target.

  16. When the conversion is complete, UTM transfers the converted data to the transfer procedure of the destination widget.

  17. The transfer procedure will find the converted selection in the value member of the XmSelectionCallbackStruct. The transfer procedure need only paste the converted selection into the appropriate place in the destination widget.

  18. Sample Translations for a Drag and Drop Transfer

    ExmStringTransfer provides only one drag and drop translation, which is as follows:

    <Btn2Down>:             ExmStringTransferProcessDrag()\n\

    Notice that there is no explicit action method associated with Btn2Up. In other words, ExmStringTransfer does not need to provide code that detects when the user is signalling to do a drop. Instead, ExmStringTransfer simply registers itself as a potential drop site. Once registered, the drag and drop system built into Motif will catch the Btn2Up event.

    To register itself as a potential drop site, ExmStringTransfer has to specify a list of its import targets. That is, the widget must describe the kinds of targets that can be copied into it. The majority of the RegisterDropSite method establishes this import target list. The actual registration of the import targets as a drop site takes place through the XmeDropSink call.

    A Sample Drag Action

    The ExmStringTransferProcessDrag method initiates a drag operation by initializing the XmDragContext. (See the Motif Programmer's Guide for more information on XmDragContext.) The code for ExmStringTransferProcessDrag appears as follows:

    static void
         Widget w,
         XEvent *event,
         String *params,
         Cardinal *num_params)
     ExmStringTransferWidget stw = (ExmStringTransferWidget) w;
     Arg args[4];
     Cardinal n;
      if (! stw -> string_transfer.own_primary) {
        ExmStringTransferPastePrimary(w, event, params, num_params);
      /* Initialize DragContext resources. We want the drag icon to
         indicate text, and we support only the COPY operation. */
      n = 0;
      /* Normal drag and drop behavior will be to use the foreground
         and background of the widget when creating the cursor or
         or the pixmap drag icon */
      XtSetArg(args[n], XmNcursorBackground, stw->core.background_pixel); 
      XtSetArg(args[n], XmNcursorForeground, stw->primitive.foreground); 
      /* We use the default text drag icon, the same as used in
         the standard Motif widgets. */
      XtSetArg(args[n], XmNsourceCursorIcon, XmeGetTextualDragIcon(w)); 
      XtSetArg(args[n], XmNdragOperations, XmDROP_COPY); n++;
      (void) XmeDragSource(w, NULL, event, args, n);

    XmeDragSource ultimately creates a DragIcon; the first three resources--XmNcursorBackground, XmNcursorForeground, and XmNsourceCursorIcon--control the appearance of that DragIcon. The convenience function XmeGetTextualDragIcon gets the standard Motif textual DragIcon If you are writing a widget that is dragging something other than text, then you would specify a different DragIcon.

    Sample Action to Register a Drop Site

    ExmStringTransfer can be a drop site. To be a drop site, the widget's Initialize method calls a routine named RegisterDropSite. RegisterDropSite builds a list of drop (import) targets and then calls XmeDropSink. The RegisterDropSite routine is as follows:

    static void
         Widget w)
      Atom TEXT = XInternAtom(XtDisplay(w), "TEXT", False);
      Atom COMPOUND_TEXT = XInternAtom(XtDisplay(w), "COMPOUND_TEXT",
      Atom LOCALE_ATOM = XmeGetEncodingAtom(w);
      Atom MOTIF_C_S = XInternAtom(XtDisplay(w), "_MOTIF_COMPOUND_STRING",
      Atom targets[5];
      Arg args[2];
      int n, nt;
      /* Set up import targets. These are the targets from which we can
         generate a compound string when a drop is made. */
      nt = 0;
      targets[nt++] = MOTIF_C_S;
      targets[nt++] = COMPOUND_TEXT;
      targets[nt++] = LOCALE_ATOM;
      if (LOCALE_ATOM != XA_STRING) {
        targets[nt++] = XA_STRING;
      if (LOCALE_ATOM != TEXT) {
        targets[nt++] = TEXT;
      /* If you add any more targets, bump the array size. */
      n = 0;
      XtSetArg(args[n], XmNimportTargets, targets); n++;
      XtSetArg(args[n], XmNnumImportTargets, nt); n++;
      XmeDropSink(w, args, n);

    According to the code, the user can drop any one of several different standard textual targets into the widget.

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