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.)
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.
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:
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.
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 ExmStringTransferProcessDrag( 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); return; } /* 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); n++; XtSetArg(args[n], XmNcursorForeground, stw->primitive.foreground); n++; /* We use the default text drag icon, the same as used in the standard Motif widgets. */ XtSetArg(args[n], XmNsourceCursorIcon, XmeGetTextualDragIcon(w)); n++; 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.
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 RegisterDropSite( Widget w) { Atom TEXT = XInternAtom(XtDisplay(w), "TEXT", False); Atom COMPOUND_TEXT = XInternAtom(XtDisplay(w), "COMPOUND_TEXT", False); Atom LOCALE_ATOM = XmeGetEncodingAtom(w); Atom MOTIF_C_S = XInternAtom(XtDisplay(w), "_MOTIF_COMPOUND_STRING", False); 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.