Solaris Common Desktop Environment: Programmer's Guide

How Drag Sources Are Used

This section describes how drag sources are used.

Starting a Drag

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.

Dragging from Lists or Icons

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.

Drag Threshold

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.

Btransfer or Badjust

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 */

Initiating a Drag

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.

Using Convert Callbacks

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;
 	}

}