 |
» |
|
|
 |
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.) Compatibility with Previous
Releases |  |
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. Drag and Drop Transfers:
Step by Step |  |
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: The user selects some portion of the source widget. The source
widget will probably highlight the selection. The user presses some mouse button or key sequence
to initiate a drag operation. Typically, the user initiates a drag
operation by pressing Btn2Down. The Intrinsics
respond to the event by calling the appropriate action method in
the source widget. The called action method itself calls XmeDragSource()
.
The call to XmeDragSource()
can specify any XmDragContext resources.
(XmeDragSource() will ultimately
instantiate an XmDragContext widget.) XmeDragSource()
asks the conversion routines to provide a list of _MOTIF_EXPORT_TARGETS. The conversion routines must respond to this request
by returning a list of draggable targets. This list may or may not
consist of all the targets that the conversion routines can convert.
Typically, this list consists only of the targets that the destination
widget is most likely to request. XmeDragSource()
calls XmDragStart(), which
in turn instantiates an XmDragContext. The
XmDragContext displays the appropriate drag
icons. XmeDragSource() sets
the XmNexportTargets
resource of XmDragContext to the list of
draggable targets. Similarly, XmeDragSource()
sets the XmNnumExportTargets
resource of XmDragContext to the number of
draggable targets. The user drags these icons towards the destination
widget. The user typically does this by continuing to press Btn2Down
while moving the mouse. When the user is over the destination widget, the
user releases some mouse button or presses some key sequence to
initiate a drop operation. Typically, the user initiates the drop
operation by releasing the mouse button, generating Btn2Up. If the destination widget has not been registered
as a drop site, UTM will reject the attempted drop and the transfer
will end. If the destination widget has been registered as a drop
site, the transfer will continue. A widget registers itself as a
drop site by calling XmeDropSink().
Note that the widget calls XmeDropSink()
when the widget is first instantiated, not as a response to the
Btn2Up event. XmeDropSink()
is the UTM interface to the XmDropSite registry. UTM calls the destination widget's destinationPreHookProc trait method, if any. UTM passes
an XmDestinationCallbackStruct
as the call_data
argument. UTM then calls the destination routines associated
with the destination widget. The first destination routines called
are the XmNdestinationCallback
procedures that the application has associated with the destination
widget. The next destination routine called is the destinationProc trait method of
the destination widget. UTM passes a pointer to an XmDropProcCallbackStruct in the
destination_data
member of the XmDestinationCallbackStruct
(The members of the XmDestinationCallbackStruct
are documented in the XmDropSite reference page.) A destination routine typically calls XtGetValues
on the XmNexportTargets
resource of the XmDragContext widget. A destination routine examines the returned XmNexportTargets
and calls XmTransferValue to request the most desirable
one. If none of the targets in XmNexportTargets are desirable,
a destination routine will call XmTransferValue
and ask for the complete list of TARGETS.
(Remember that XmNexportTargets
does not necessarily hold a complete list of targets, but TARGETS does.) UTM asks the conversion routines of the source widget
to convert the requested target. A conversion routine attempts to convert the selection
to the desired target. When the conversion is complete, UTM transfers the
converted data to the transfer procedure of the destination widget. The transfer procedure will find the converted selection
in the value
member of the XmSelectionCallbackStruct.
The transfer procedure need only paste the converted selection into
the appropriate place in the destination widget.
Sample Translations for
a Drag and Drop Transfer |  |
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. A Sample Drag Action |  |
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. Sample Action to Register
a Drop Site |  |
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.
|