A destinationProc trait method is usually a lot simpler to write than a convertProc trait method. A destinationProc need only do the following:
The remainder of this section examines how ExmStringTransfer implemented its destinationProc trait method.
The prototype of a destinationProc trait method is the same as for any Motif callback. In the call_data argument, Motif passes an XmDestinationCallbackStruct. Therefore, the opening lines of the DestinationProc of ExmStringTransfer are as follows:
static void DestinationProc( Widget w, XtPointer client_data, XtPointer call_data) { XmDestinationCallbackStruct *ds = (XmDestinationCallbackStruct *) call_data;
As in a convertProc trait method, a destinationProc trait method must declare Atom variables for all the targets it needs, for example:
Atom XA_MOTIF_DROP = XInternAtom(XtDisplay(w), "_MOTIF_DROP", False); Atom TARGETS = XInternAtom(XtDisplay(w), "TARGETS", False);
The ds->operation field contains the name of the requested operation (link, move, or copy). ExmStringTransfer does not support the link operation, so DestinationProc uses the following code to reject a link request:
if (ds -> operation == XmLINK) { /* We don't support links. */ XmTransferDone(ds -> transfer_id, XmTRANSFER_DONE_FAIL); return; }
ExmStringTransfer can be a drop site. If the user has requested a drop, UTM will pass a pointer to an XmDropProcCallbackStruct in the destination_data member of the XmDestinationCallbackStruct; for example:
if (ds -> selection == XA_MOTIF_DROP) { XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *) ds -> destination_data;
For most transfer mechanisms, a destinationProc needs to ask the source widget for its list of targets. However, this is not always necessary in a drag and drop operation because the DragContext holds this list in its XmNexportTargets resource. Therefore, DestinationProc gets the target list as follows:
n = 0; XtSetArg(args[n], XmNexportTargets, &targets); n++; XtSetArg(args[n], XmNnumExportTargets, &num_targets); n++; XtGetValues(cb -> dragContext, args, n);
DestinationProc examines the returned list and picks the most desirable target. (See the next section for more details.) Then DestinationProc calls XmTransferValue to ask the source widget to convert the target.
XmTransferValue(ds -> transfer_id, target, (XtCallbackProc) TransferProc, NULL, 0);
If the user has requested a transfer other than drag and drop, DestinationProc needs to ask the source widget for its list of targets. DestinationProc does this by calling XmTransferValue as follows:
XmTransferValue(ds -> transfer_id, TARGETS, (XtCallbackProc) TransferProc, NULL, 0);