This section describes how drag sources are used.
A drag is started in one of two ways. First, the user may start a drag by pressing down Btransfer, the middle mouse button. As soon as the button is pressed down, the drag begins. Second, the user may start a drag by pressing and holding down Bselect, the left mouse button, and moving the cursor across the screen. The drag begins when the user moves the mouse a certain distance. This distance is called the drag threshold and it is measured in pixels. The default drag threshold is 10 pixels for Bselect. For Btransfer, the drag threshold is 0; because there is no drag threshold, the drag begins as soon as the pointer is moved. Motif scrolled text lists and text widgets are automatically registered as drag sources for text drags using Btransfer and Bselect.
There are two common interface objects that can be used to source a drag: lists and icons. The Motif List widget automatically sources text drags. If other types of drags are desired, this is accomplished by overriding the default widget translations with new Bntl and Btn2 translations. There is no icon widget in Motif but often a drawing area is used as container of icons. In this case, an event handler for Btn1Motion would be used to start the drag. Refer to the sample code in /usr/dt/examples/dtdnd for more detailed code examples.
When starting a drag using Bselect the widget event handler or translation procedures must apply the drag threshold of 10 pixels before starting the drag. For Btransfer, there is no threshold and the drag starts immediately.
Style Manager has a setting in the Mouse category that controls whether Btn2, the middle mouse button, acts as Btransfer or Badjust. This setting is stored as a resource name: enableBtn1Transfer. A setting of 1 indicates that Btn2 is Badjust and should adjust the selection while a setting of any other value means that Btn2 is Btransfer and should start a drag. Btn1, the left mouse button, always starts a drag.
The following example shows how to determine whether Btn2 should be Btransfer or Badjust.
Display* display; int adjust; XtVaGetValues ((Widget)XmGetXmDisplay(display, "enableBtn1Transfer", &adjust, NULL); if (adjust == 1) /* Btn2 is adjust */ else /* Btn2 is transfer */
Common Desktop Environment 1.0 applications start a drag by calling DtDndDragStart(). This function performs some desktop-specific setup and calls XmDragStart() to initiate a drag. The DtDndDragStart() function synopsis and parameter usage are described as follows:
Widget DtDndDragStart( Widget dragSource, XEvent *event, DtDndProtocol protocol, Cardinal numItems, unsigned char operations, XtCallbackList convertCallback, XtCallbackList dragFinishCallback ArgList argList, Cardinal argCount)
Widget dragSource
The widget that received the event that triggered the drag.
XEvent *event
The button press or button motion event that triggered the drag.
DtDndProtocol protocol
The protocol used for the data transfer. The protocol may be one of the following:
DtDND_TEXT_TRANSFER
DtDND_FILENAME_TRANSFER
DtDND_BUFFER_TRANSFER
Cardinal numItems
Specifies the number of items being dragged.
unsigned char operations
Specifies options supported by dragSource. The options are XmDROP_MOVE, XmDROP_COPY, and XmDROP_LINK. A drag source may support any combination of these operations. You specify a combination of operations by using or. For example, to support the move and copy operations, specify XmDROP_MOVE | XmDROP_COPY.
XtCallbackList convertCallback
This callback is invoked when a drop has started and the drop zone has requested data from the drag source. The convertCallback is explained in more detail in the next section.
XtCallbackList dragFinishCallback
This callback is invoked when the drag-and-drop transaction is complete. The dragFinishCallback should reset the dragMotionHandler() and free any memory allocated by the drag source during the drag-and-drop transaction.
The convert callback provides data to the drop zone when a drop occurs. The first action in the convert callback is a verification of the reason field in the callData. If the reason is not DtCR_CONVERT_DATA or DtCR_CONVERT_DELETE, you should return immediately; otherwise, proceed to convert the data. For example, if you are handling the conversion of a file name, retrieve the appropriate file name from your internal data structures and copy it into the file data object. If your drag source supports the move operation, you need to support conversion of the DELETE target. That is, when convertCallback is called with a reason of DtCR_CONVERT_DELETE, perform the appropriate deletion action for the data that was moved. In the case of the file transfer, delete the file. Here is a simple convertCallback that handles the conversion and deletion of file names.
void convertFileCallback( Widget dragContext, XtPointer clientData, XtPointer callData) { DtDndConvertCallbackStruct *convertInfo = (DtDndConvertCallbackStruct*) allData; char *fileName = (char *) clientData; if (convertInfo->reason == DtCR_DND_CONVERT_DATA) { convertInfo->dragData->data.files[0]= XtNewString(fileName); } else if (convertInfo->reason == DtCR_DND_CONVERT_DELETE) { deleteFile(fileName); } else { convertInfo->status = DtDND_FAILURE; } }