XtSetArg (args[n], XmNimportTargets, &importTargets); n++;
XtSetArg (args[n], XmNnumImportTargets, &numImportTargets); n++;
XtSetArg (args[n], XmNdropProc, &drop_proc); n++;
XmDropSiteRetrieve (text_edit, args, n);
Although a drop site is always associated with a widget, the XtVaGetValues() routine cannot be used to retrieve
drop site resources, as the resources are stored separately from the widget in a DropSite object. We retrieve the
XmN-importTargets resource so that we can add our own targets to the list of data targets for the drop site. A
drop site can only have one XmN-dropProc associated with it, so we need to get the existing routine and store it
before we specify our own routine.
Once we have the data targets for the drop site, we create a new list that contains the existing targets, as well as the
FILE_CONTENTS and FILE_NAME targets. We use XmDropSiteUpdate() to modify the drop site:
n = 0;
XtSetArg (args[n], XmNimportTargets, newTargets); n++;
XtSetArg (args[n], XmNnumImportTargets, numImportTargets + 2); n++;
XtSetArg (args[n], XmNdropProc, HandleDropText); n++;
XmDropSiteUpdate (text_edit, args, n);
The HandleDropText() routine processes the drops that occur in the Text widget. We explain this routine in
detail in the following section.
If you need to update information for a number of drop sites, you should use the XmDropSiteStartUpdate()
and XmDropSiteEndUpdate() routines, as they optimize the process. After a call to
XmDropSiteStartUpdate(), you can call XmDropSiteUpdate() repeatedly for different drop sites. When
you are finished updating all of the drop sites, call XmDropSiteEndUpdate().
19.5.3 Handling the Drop
When a drop occurs, the receiving application takes over and the XmN-dropProc for the drop site is called. This
callback provides a callback structure of type XmDropProcCallbackStruct, which is defined as follows:
typedef struct {
int reason;
XEvent *event;
Time timeStamp;
Widget dragContext;
Position x;
Position y;
unsigned char dropSiteStatus;
unsigned char operation;
unsigned char operations;
unsigned char dropAction;
} XmDropProcCallbackStruct, *XmDropProcCallback;
The reason field is always XmCR_DROP_MESSAGE, and dragContext specifies the DragContext object for the
drag operation that caused the drop. The dropSiteStatus element is set to either XmDROP_SITE_VALID or
XmDROP_SITE_INVALID, depending on the targets that are supported by the drop site and the drag source. The
callback routine can change this value if necessary.
The operations and operation fields are set to the possible operations for the drag source data and the current
operation, respectively. The dropAction field specifies the action requested by the user. If this field is set to
XmDROP, the user has requested a normal drop; if it is set to XmDROP_HELP, the user has requested help for the drop
19 Drag and Drop 19.5.3 Handling the Drop
554
site. We discuss providing help for a drop site in the next section.
The main task of the XmN-dropProc is to determine whether or not the operation is possible and to start the data
transfer by calling XmDropTransferStart(). This routine creates a DropTransfer object that keeps track of
information about the data transfer. The HandleDropLabel() routine initiates the data transfer for the file status
drop site, as shown in the following code fragment from the source code
n = 0;
if ((!file_name) || (DropData−>dropAction != XmDROP) ||
(DropData−>operation != XmDROP_COPY)) {
XtSetArg (args[n], XmNtransferStatus, XmTRANSFER_FAILURE); n++;
XtSetArg (args[n], XmNnumDropTransfers, 0); n++;
}
else {
transferEntries[0].target = FILE_CONTENTS;
transferEntries[0].client_data = (XtPointer) text_edit;
transferEntries[1].target = FILE_NAME;
transferEntries[1].client_data = (XtPointer) file_label;
transferList = transferEntries;
XtSetArg (args[n], XmNdropTransfers, transferEntries); n++;
XtSetArg (args[n], XmNnumDropTransfers,
XtNumber (transferEntries)); n++;
XtSetArg (args[n], XmNtransferProc, TransferProc); n++;
}
XmDropTransferStart (dc, args, n);
If the action requested by the user is not a normal drop or if the operation is not a copy operation, we do not process
the data transfer. However, we still have to call XmDropTransferStart() to clean up after the whole drag and
drop operation. In this case, we set the XmN-transferStatus resource to XmTRANSFER_FAILURE to indicate
that the transfer should not proceed. We also set XmN-numDropTransfers to 0.
Otherwise, the drop can proceed, so we establish a list of target data types that we want to receive using the
XmN-dropTransfers and XmN-numDropTransfer resources. Each entry in XmN-dropTransfers is an
XmDropTransferEntryRec, which is defined as follows:
typedef struct {
XtPointer client_data;
Atom target;
} XmDropTransferEntryRec, *XmDropTransferEntry;
The target field specifies the requested data target, and client_data passes any additional data that is necessary
to the routine that processes the data transfer. We specify the FILE_CONTENTS and FILE_NAME targets. For each
target, we pass the widget that is modified by the data from the drag source as client_data. For the
FILE_CONTENTS format, the widget is the text entry area text_edit, while for FILE_NAME, the widget is the
file status area file_label.
The final resource that we specify for the DropTransfer is the XmN-transferProc routine. This routine is of type
XtSelectionCallbackProc; it is responsible for actually processing the formatted data that is received from the
drag source. The routine is called for each target data type requested by the drop site. This routine takes the following
form:
typedef void (*XtSelectionCallbackProc)(Widget, XtPointer, Atom *,
Atom *, XtPointer, unsigned long*, int *);
Widget widget;
XtPointer client_data;
19 Drag and Drop 19.5.3 Handling the Drop
555
Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.