XView API for Drag and Drop.
# @(#)dnd_api.txt	1.5 28 Jun 1993 SMI

This paper discusses the API for drag and drop in the XView toolkit.  There
are three parts to drag and drop that are discussed.  "Registry of Interest"
defines how applications tell other applications that they are interested
in receiving drops.  "Initiating a Drop" explains how to source a drop
and "Receiving a Drop" defines the api for the destination of drop events.

Registry of Interest:

In order to receive drop and previewing events, an application must register
areas that are acceptable drop sites such as a graphical icon.  These areas or
site descriptions within the application can be made up of several regions.  
Currently a region is described by a rectangle.

If the application does not register an area as a drop site, the source
of the drop will refuse to drop on that area.

In order to provide animation of the drop site, a region can
receive synthetic preview events from the source.  These preview events 
indicate to the destination the state of the mouse relative to the destination.
Possible events include LOC_WINENETER and LOC_WINEXIT that cue the drop site
when the mouse enters or leaves a region.  Sites can also select for LOC_DRAG
events that are sent as the mouse moves across a region.  Each site
description can specify *hints* to the source as to what type of synthetic
events it would like to receive.  These events will be delivered to the
event proc of the site's owner.  They will use the format of the Event
structure.

	action  == ACTION_DRAG_PREVIEW
	ie_code == {LOC_WINENTER, LOC_WINEXIT, LOC_DRAG}
	ie_locx and ie_locy, coords of mouse in site's window coordinate space.

Possible destinations receiving ACTION_DRAG_PREVIEW events should do what
ever is necessary to indicate to the user that this area is an acceptable
drop site.  This might mean inverting an image at the drop site or changing
a folder icon from closed to an open state.

A new drag and drop item has been created in order to facilitate registry of
interest.  This item is subclassed from the generic pkg and instances of
it will be owned by a window based object.

Item name: DROP_SITE_ITEM
Type: 	   Xv_drop_site
Owner:     Xv_Window

Attributes:
----------

DROP_SITE_ID

Type: 		long
Default:	xv_unique_key()
Procs:		create, set, get

An uninterpreted id used to distinguish one site from the next.
Ideal when more than one site has been set on an object.  This id will
be sent in the ACTION_DRAG_PREVIEW, ACTION_DRAG_MOVE, and ACTION_DRAG_COPY
events.

DROP_SITE_EVENT_MASK

Type:		{DND_ENTERLEAVE, DND_MOTION}
Default:	NULL
Procs:		create, set, get

A mask used to specify if the regions within the site will receive synthetic
previewing events.  The previewing events will come with event_action() 
equal to ACTION_DRAG_PREVIEW and event_id() set to one of LOC_WINENTER,
LOC_WINEXIT or LOC_DRAG.  These events will be delivered to the event
proc of the drop item owner.  This mask is only a hint to the source.  There
is no guarantee the source will send these previewing events.

DROP_SITE_DEFAULT 
 
Type:           Boolean
Default:        False
Procs:          create, set, get

Specifies that this drop site wants forwarded drops from the window manager. 
Such drops include drops on icons and window manager decor windows.  Only
one drop site default should be specified per base frame. 

DROP_SITE_REGION

Type: 		Rect *
Default:	NULL
Procs:		create, set, get

This attribute is used to associate a region to a drop item.  The region
is a Rect *.  DROP_SITE_REGION will add to any existing regions within
the drop site item.

The rect pointed to by Rect * will be copied.  The coordinates in the
rect should be relative to the drop site item's owner's window.

An xv_get of a region of type Rect * will return an allocated Rect structure.
This should be freed once the application has finished using it.

DROP_SITE_REGION_PTR

Type: 		Rect * (A NULL terminated array of Rect structs)
Default:	NULL
Procs:		create, set, get

This attribute is similar to DROP_SITE_REGION except that it accepts a
NULL terminated list of regions.  It will add to any existing regions
that exist within the drop item.  A NULL rect is defined to be one
with width or height equal to 0.

An xv_get of a region list will return a NULL terminated list of Rects.
This data should be freed once the application has finished using it.

DROP_SITE_DELETE_REGION

Type: 		Rect *
Default:	None
Procs:		create, set

Used to remove a region from the drop item.  If the owner is destroyed with
xv_destroy, any drop site regions attached to it will also be destroyed.
If NULL is passed as an argument, all regions in the drop site will be
removed.

DROP_SITE_DELETE_REGION_PTR

Type: 		Rect * (a NULL terminated array of Rect structs)
Default:	None
Procs:		create, set

Used to remove a list of regions from the drop item.


If an object is no longer going to support drops it should remove its drop
site regions.  If the object is going to be destroyed there is no need to
remove the sites as XView will destroy any drop site items associated with
the object.  If NULL is passed as an argument, all regions in the drop site
will be removed.


The individual regions should correspond to/or overlay objects contained
within the window that are willing to receive drops.  If the position of the
objects within the window change or no longer exist, it is the responsibility
of the application to update the drop site item to correspond to the current
state of the window.   For example, if an object is deleted, its region
should be removed.  If an object is being clipped by the window border and is
no longer viewable, its region should be removed.   If the application does
not keep the region information up to date, a user can be mislead into
believing that an area supports drops.

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

Initiating a Drop:

If an application wants to initiate a drag and drop operation, it must first
create a drag and drop object and set attributes on it to define the
behavior of the drag and drop operation.  The new package is called
DRAGDROP and is subclassed from the new selection pkg.  An instance of a
DRAGDROP object is created by using xv_create():

        	dnd_object = xv_create(owner, DRAGDROP, attrs, NULL)

where owner is an Xv_window and attrs are defined below.  The object created
can be modified later by using xv_set().  Information can be looked up
by using xv_get().  The drag and drop object that is created is later
used as a parameter to dnd_send_drop().

The owner of the drag and drop object should be the window in which the 
drag operation will be initiated from.

A drag and drop object can only be used on one drag and drop operation at
a time.

To initiate a drag operation an application should call dnd_send_drop().
The dnd_send_drop() function will be responsible for changing the root
cursor, sending previewing events to appropriate sites, sending the ``trigger''
message (ACTION_DRAG_COPY or ACTION_DRAG_MOVE), etc.  As an example, filemgr
should call this routine when the user dragged the mouse ``x'' number of
pixels over a selected file icon.

dnd_send_drop() takes as a parameter a drag and drop object.

		int
		dnd_send_drop(object)
        	    Xv_dnd       object;
 
dnd_send_drop() will not return until the user has released all of the
mouse buttons thus dropping the object.  The dnd_send_drop() function will
return one of:

XV_OK:  		The drag and drop operation has begun. 
DND_TIMEOUT:    	The destination did not respond to the kicker message.
DND_ILLEGAL_TARGET:     The user dropped on an object that has not registered
			interest in drag and drop.
DND_SELECTION:		A selection could not be obtained.
DND_ROOT:		The user dropped on the root window.
XV_ERROR:		An unexpected error occurred.

The means in which data is transferred under drag and drop operations is 
through selections.  Since the drag and drop pkg is subclassed from the
new selection owner pkg it fully supports selections.  A selection should be 
associated with the drag and drop object in order for the destination to
obtain the data to be transferred.  The selection should be a transient
selection that will persist only for the duration of the drag and drop
operation.  A transient selection should be used even if the dragged object
is already associated with another selection such as the PRIMARY.  The reason
for this is that another client may acquire the PRIMARY selection while the
drag and drop transfer is taking place.  If this were to happen, the drag and
drop operation would fail.

The application can use the SEL_RANK attribute to associate a selection
with the drag and drop object.  If the application does not own a
selection (SEL_OWN) before dnd_send_drop() is called, XView will
create a transient selection and associate it with the drag and drop
object.  This selection can be obtained by using xv_get on the dnd object
with the SEL_RANK attribute. It is the responsibility of the application to
disown a selection associated with the drag and drop object when it has
completed the operation.  This is irregardless of who initially established
ownership of the selection. 

Since the source will be required to reply to requests from the destination
for data conversion, the source should  have either a convert proc or 
selection items set on the drag and drop object *before* it calls
dnd_send_drop().

In addition to all selection owner pkg attrs, the following drag and drop attrs
can be used on a drag and drop object:
------------------------------------------------------------

DND_TYPE

Defines whether this drag and drop operation will be a copy or a move.  This
is just a hint to the destination.  If the type is a ``move'' operation and
if the destination honors the hint, the destination will ask the source to
convert the DELETE target.

Type:           DND_COPY or DND_MOVE
Default:        DRAG_MOVE
Procs:          create, set, get

DND_CURSOR

Defines the mouse cursor that will be used during the drag portion of
the drag and drop operation.

Type:           Xv_cursor
Default:        Predefined OPEN LOOK drag and drop cursor.
Procs:          create, set, get

DND_X_CURSOR

An alternative to DND_CURSOR, but accepts an XID of a cursor instead of
an Xv_object.

Type:           Cursor
Default:        Predefined OPEN LOOK drag and drop cursor.
Procs:          create, set, get

DND_ACCEPT_CURSOR
DND_ACCEPT_X_CURSOR

Defines the mouse cursor to be used when the cursor is over an acceptable
drop site.

Type:           Xv_cursor, Cursor
Default:        Predefined OPEN LOOK drag and drop cursor.
Procs:          create, set, get

DND_TIMEOUT_VALUE
 
Defines the amount of time to wait for an ACK from the destination
after the ``kicker'' message (ACTION_DRAG_*) has been sent.

Type:           struct timeval *
Default:        Default selection pkg timeout.
Procs:          create, set, get

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

Receiving a Drop:

A window or object that has registered interest in receiving drop events
will receive an ACTION_DRAG_COPY or an ACTION_DRAG_MOVE event when one of its
sites is dropped on.

Upon receiving a drop event, the application should call
dnd_decode_drop().  The application should pass in as a parameter
the ACTION_DRAG_{MOVE, COPY} event that it received along with a 
selection requester object:

	
	Xv_drop_site
	dnd_decode_drop(sel_object, drop_event)
	    Selection_requestor   sel_object;
	    Event 		 *drop_event;

The dnd_decode_drop() function will decode the drop event.  It will
associate the selection rank defined within the drop event with the
selection object that was passed into dnd_decode_drop().

The dnd_decode_drop() function will send an ACK (if requested) to the
source of the drag and drop informing it that the transaction has begun.

dnd_decode_drop() will return XV_ERROR if it failed to initiate the drag
and drop transaction [i.e. the selection defined within the drop event does
not exist.]  Or the drop site item that was dropped on will be returned if
it could begin the drag and drop transaction.

If dnd_decode_drop() returns a drop site item, it is the responsibility
of the application to continue and complete the drag and drop transaction.
This will be done by normal selections on the selection object passed into
dnd_decode_drop().

The macro dnd_is_local(drop_event) returns True if the source and
destination are the same client.

If the application receives an ACTION_DRAG_MOVE, it should simulate a move
by performing a copy followed by a delete.   The delete is initiated by
the requester asking the holder to convert the DELETE target:

	xv_set(sel_object, SEL_TYPE_NAME, "DELETE", 0);
	(void)xv_get(sel_object, SEL_DATA, &length, &format);

	- or - (Non-blocking)

	xv_set(sel_object, SEL_TYPE_NAME, "DELETE", 0);
	sel_post_request(sel_object);

The application should only ask the owner to delete the selection if
the drop event indicates a move operation and the application determines
it is appropriate to do so.  This will typically happen after the application
has successfully transferred the data.

Finally the application should inform the toolkit that the drag and drop
operation has completed.  It does so by calling:

	dnd_done(sel_object);
