[UNDER CONSTRUCTION] [This is Daniel's documentation, and is covered by his copyright: Permission to use, copy, modify, distribute, and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Daniel Dardailler not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Daniel Dardailler makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. ] Motif Drag And Drop Protocol ---------------------------- 1.1 Introduction This document describes the protocol used to implement Drag and Drop in existing versions of the Motif toolkit (since version 1.2, and any subsequent release). This protocol is based on X Client Messages, Properties and Selections, and its public specification should allow any X based toolkit or application to interoperate with any applications that use Motif Drag&Drop. 1.2 Description Drag and Drop is an interactive technique which allows transfer of information through a simple metaphor: the user picks an object on the display with the pointer, drags it across the screen while maintaining the pointer button pressed, and drops the object on some other place. Subsequently, the application where the object was dropped usually does some data transfer corresponding to the object. A Drag and Drop operation starts in a window called the source window. The client owner of this window is called the initiator client. The drop operation occurs in a window called the destination window. The client owner of this window is called the receiver client. A client can be both initiator and receiver for an operation. A client can contain both the source and destination windows for an operation. The source window may also be the destination window. There are no particular requirements on what the client should do or not do in those specific cases. In many cases, the drop will occur on some area called a drop site, for example a printer icon or a trash can icon. A drop site may be drawn in its own window or may be simply drawn by the receiver application in a larger window. The protocol does not require to have one window per drop site. During the drag, both the initiator client and the potential receiver clients may want to provide visual feed back to the user. The feed back provided by the initiator is called drag-over. The feed back provided by a receiver is called drag-under: typically doing some animation in the destination window under the drag icon. The feedback may consist in - an icon representing the data being dragged, called the source icon - showing the existence of a drop site. Both initiator and receiver might want to provide feedback whether or not a drop is possible. For example, the receiver can be highlighting the drop site and the initiator showing a specific icon: the state icon. - a side effect icon indicating the side effect that would occur if a drop were made. - In the case where a drop is possible, both initiator and receiver may want to provide feedback indicating the validity of the operation for this particular drop. For example, if it is known that the object being dragged cannot be processed by the receiver. Implementing Drag and Drop requires multiple conventions: - Potential receivers need to signal that they contain one or more drop sites on their top level windows. - When a drag operation starts, the initiator client needs to obtain from a service all windows where data can be dropped. This may be obtained by querying an external service (e.g. the Window Manager). If such a service does not exist, the initiator will have to determine when the pointer enters a new top level window, if that window is a potential receiver. Refer to the ICCCM 2.0 manual for WM_STATE property that identifies toplevel window in clients. - During the drag, the initiator send messages to the potential receivers, and expect responses from them. The set of states and messages exchanged during a drag define the Drag Protocol. - The set of states and messages exchanged with and after the drop event define the Drop Protocol. The Drag protocol and the Drop protocol are independent. During a drag a client is at liberty to not use the drag protocol. For example because there is known latency or thrashing and using the drag protocol would be much too slow to provide accurate feedback. Hence a drag and drop operation may actually involve only the Drop protocol. This style of interaction is called "Drop Only" in the Motif toolkit. The data is transfered through some action that may have side effects. For example in a file management system, when a file is transferred it can be physically moved from a directory to another one, or copied, or linked. The Motif protocol supports three pre- defined side effects named Copy (the initiator data is not altered after the drop), Move (the initiator data is removed after the drop) and Link (a reference to the initiator data has been made by the receiver). The Motif drag and drop dynamic protocol uses X11 Client Messages as the underlying transport mechanism and also exchanges data through X properties. 1.3 The Drag Protocol In order to provide accurate feed back both the initiator and the receiver need information from the other side. The messages from the drag protocol serve that purpose. The messages are X client messages sent from the source window to the destination window, and back. As the pointer moves, the initiator sends messages indicating the new pointer position and properties of the drag (targets, possible side effects, recommended side effects). From this message, the receiver obtains necessary information to achieve drag under feedback. The receiver then replies by providing information to the initiator about the existence, validity and side effects of the drop, so that the initiator can achieve proper drag over feedback. Some data is stored on window properties of a persistent, override- redirect, InputOnly child window of the display's default root window: the motif Drag Window. A client looks for the motif Drag Window id on the _MOTIF_DRAG_WINDOW property of its display's default root window. If the window id is NULL or invalid, a client may create this Window itself (using SetCloseDownMode RetainPermanent, so that other clients don't have to create it). Several sets of data are stored on the motif Drag Window properties. Of interest for the Dynamic Drag protocol is a targets list table. The _MOTIF_DRAG_TARGETS property on the motif Drag Window (type _MOTIF_DRAG_TARGETS) contains a targets table, consisting of a sequence of target lists to be shared among clients. In other words, this property is a list of lists. These target lists are sorted into ascending order to avoid permutations of otherwise compatible target list(e.g. client1 supports target list B,C,A and client2 C,B,A: they should both rely on A,B,C). By sharing the targets table, clients may pass target lists between themselves by exchanging only the corresponding target list index in the protocol messages (X Client Message are limited in size). Note that the targets TARGETS and MULTIPLE, which are mandatory per ICCCM requirement, are not mentioned in this list. To add a target list to the table, a client must first sorts its target list into ascending order, then search the targets table for a match. If it finds a match, it may use the index of the matching targets table entry in the drag protocol (starting at 0). Otherwise, it adds the sorted target list to the table, anywhere, but atomically (e.g. under ServerGrab) updates the _MOTIF_DRAG_TARGETS property on motif Drag Window, and uses the index of the new targets table entry. Since the protocol uses X client messages of fixed size, limited to 20 bytes: - the protocol uses properties on the source and destination windows to exchange extra information that would not fit in the available bytes. The property name is indicated in the message data. - every X client message has an XClientMessageEvent message_type that uses the Atom _MOTIF_DRAG_AND_DROP_MESSAGE. The actual type of the request or reply is indicated in a byte in the data buffer called the Reason. Thus every client message from the protocol contains: - window the window receiving the event - message_type the atom _MOTIF_DRAG_AND_DROP_MESSAGE - format 8 (no byte swapping done by X Server) - data.b[0] one byte for the reason (type of request/reply + originator) - data.b[1] byte order of the data buffer - data.b[...] rest of the message content - the protocol uses bit fields within bytes to transmit information (see exact encoding section). A receiver is a top level window that contains drop sites. A receiver advertises itself by placing a property on its top level window - property name _MOTIF_DRAG_RECEIVER_INFO - property type _MOTIF_DRAG_RECEIVER_INFO - property format 8 The property is at least 16 bytes and contains: - BYTE byte order of data in property - BYTE protocol version of receiver - BYTE protocol style == Dynamic, DropOnly, None - BYTE unspecified - CARD32 unspecified - CARD32 unspecified - CARD32 unspecified A style of Dynamic means that the receiver will accept and answer Drag Protocol X Client Messages sent by the source. A style of DropOnly means that the source should not send any message to the receiver, except for DROP_START, and that drop will be accepted in the receiver toplevel. The default drag-over will indicate such a possibility to the user, anywhere in the target window. It acts as if a single drop-site was associated with the receiver toplevel window, accepting all possible targets and operations. A style of None means that drops are not allowed anywhere in the receiver window, and will automatically fail. Drag-over feedback should indicate such an impossibility. When starting a drag, the initiator creates a property on the source window, of type _MOTIF_DRAG_INITIATOR_INFO, containing information about the drag, of which the target index, i.e. the index in the target list table described above. The name of that property is passed in the drag protocol requests. This source window property indicates: - BYTE byte order of data in the property - BYTE protocol version - CARD16 an index in the pre-converted TARGETS table described above - CARD32 the selection Atom for the data transfer at drop time (itself., see below) The drag protocol messages are the following (all timestamps are set to the corresponding X Event triggering the message: crossing event, mouse motion, button release, etc): When entering a new top level, the initiator sends TOP_LEVEL_ENTER message (XClientMessage type _MOTIF_DRAG_AND_DROP_MESSAGE) containing: - BYTE reason = TOP_LEVEL_ENTER - BYTE byte order - CARD16 0 - CARD32 timestamp - CARD32 source window id - CARD32 Atom == initiator property on the source window and selection Atom for the data transfer at drop time The selection Atom in the above property must be unique for the duration of the Drag&Drop transaction, and the initiator must own the selection and be ready to convert data for its target from the start of the gesture, since the receiver may want to do a conversion dynamically to validate an operation. The receiver does not reply to this message When leaving a top level window the initiator sends a TOP_LEVEL_LEAVE message containing: - BYTE reason = TOP_LEVEL_LEAVE - BYTE byte order - CARD16 0 - CARD32 timestamp - CARD32 source window The receiver does not reply to this message. After entering a top level window, when the pointer moves, the initiator sends a DRAG_MOTION message: - BYTE reason = DRAG_MOTION - BYTE byte order - CARD16 one recommended and a set of possible side effects (move,copy,link,noop) - CARD32 timestamp - CARD16 x relative to rootwindow - CARD16 y relative to rootwindow The operation and operations fields of the side effect CARD16 bit field are used to convey, resp., the recommended and possible side effects. If the pointer enters a drop site the receiver replies with a DROP_SITE_ENTER message: - BYTE reason = DROP_SITE_ENTER - BYTE byte order - CARD16 one selected and a set of possible side effect, + status (valid-drop-site, invalid-drop-site) - CARD32 timestamp - CARD16 better-x relative to rootwindow - CARD16 better-y relative to rootwindow The `better' position is set by the receiver as a hint for the source on where the drag-over icon should be placed during the gesture (the source can warp the pointer to that location). "operations" plural is the list of operations that the receiver supports, "operation" singular is the one retained so far by the drag source and acknowledged by the receiver. If the pointer leaves a drop site the receiver replies with a DROP_SITE_LEAVE message: - BYTE reason = DROP_SITE_LEAVE - BYTE byte order - CARD32 timestamp If the pointer does not enter or leave a drop site the receiver echoes a DRAG_MOTION message - BYTE byte order - BYTE reason = DRAG_MOTION - CARD16 one selected and a set of possible side effect, + status - CARD32 timestamp - CARD16 better-x relative to rootwindow - CARD16 better-y relative to rootwindow The user may change the recommended side effect during the drag (e.g. using modifier key). The initiator then sends an OPERATION_CHANGED message: - BYTE reason = OPERATION_CHANGED - BYTE byte order - CARD16 one recommended and a set of possible side effect - CARD32 timestamp The receiver echoes the message with the selected side effect: - BYTE byte order - BYTE reason = OPERATION_CHANGED - CARD16 the selected and the set of possible side effect, + status - CARD32 timestamp 1.4 The Drop protocol The drop protocol may be used independently of the drag protocol (i.e. in DropOnly mode). The drop protocol consists of a single message that is echoed by the receiver. After that message, if the drop is not cancelled or postponed, the receiver proceeds with an X selection transfer to transfer the data. The initiator sends a drop message, which indicates: - BYTE reason = DROP_START - BYTE byte order - CARD16 one recommended and a set of possible side effects - CARD32 timestamp - CARD16 x relative to rootwindow - CARD16 y relative to rootwindow - CARD32 Atom == property on the source window - CARD32 source Window The atom indicates the name of the property described above (in the drag protocol) that the initiator sets up when the drag starts, containing the target index and the selection atom to be used for selection requests. The receiver echoes the message with: - BYTE reason = DROP_START - BYTE byte order - CARD16 selected and set of possible side effect, status, and drop action: (drop, drop-help, drop-cancel) - CARD16 better-x - CARD16 better-y If the drop is Valid and the action is drop, the receiver will achieve a selection transfer, using the atom in the source window property. The initiator should select for DestroyNotify on the destination window such that it is aware of a potential receiver crash. Similarly, the receiver should select for DestroyNotify on the source window if it intends to proceed with the drop. 1.4.1 Data transfer and termination on the initiator side The receiver may request for as many transfer as it wants to, using X selection requests to the selected targets. On each conversion request, the initiator replies using the ICCCM selection. The resources allocated during the Drag should not be released until the Drop is finished, i.e., the initiator must not release any resources concerning the drop until it receives a conversion request for the drop selection to either target XmTRANSFER_SUCCESS or XmTRANSFER_FAILURE. When it receives such a conversion request it must reply with a empty value. 1.4.2 Data transfer and termination on the receiver side The receiver may proceed with multiple selection requests on the drop selection. When it is finished, it must issue a conversion request to either XmTRANSFER_SUCCESS or XmTRANSFER_FAILURE. The receiver should release all resources about the drop. only when it receives acknowledgment of that. That's also when the melting or failure/snapback visual effect should occur. 1.5 Encoding In addition to the above byte size level description, this section gives detailed value encoding for most fields. 1.5.1 byte_order The value of the byte must be octal 102 or 154 (same as X Protocol) . - the value 102 (ASCII uppercase B) means values are transmitted most-significant byte first, - the value 154 (ASCII lowercase l) means values are transmitted least-significant byte first. 1.5.2 protocol version - byte value: 0 1.5.3 protocol style - drag_none: 0 - drag_drop_only: 1, ==3 - drag_dynamic: 5 ==2, ==4 The first number is the value a receiver should set. == points to additional values that must be interpreted as meaning the same for the source (i.e. is the protocol_style speficied by a receiver is 3, it means the source must act as if it had indicated drop-only: 1). 1.5.4 target table As indicated above, it's list of atom list, sorted in ascending order (smaller atom value first). The property starts with: - BYTE byte order of data - BYTE protocol version - CARD16 num_target_lists - CARD32 data_size data_size is the total size in bytes of the property: the above 8 bytes + num_target_lists * (2 + num_target_in_each_list * 4). Each list starts with number of target in the list, on 2 bytes, and then the atoms. 1.5.5 reason field The 8 bits of the reason (message type) field are allocated as follows: Low order X | X | X | X | reason X | X | X | High order X | originator The reason codes are: - top-level-enter: 0 - top-level-leave: 1 - drag-motion: 2 - drop-site-enter: 3 - drop-site-leave: 4 - operation-changed: 8 - drop-start: 5 The originator bit indicates where the message originated from: - 0 for initiator, - 1 for receiver 1.5.6 side effect bitfield The 16 bits of the flag field are allocated as follows: Low order X | X | Operation mask (4 bits) X | X | X | X | Drop Site Status (4 bits) X | X | X | X | Operations mask (4 bits) X | X | X | X | Drop Action (Completion) (4 bits) X | High order X | The operation is the recommended or selected side-effect, and operations is the set of possible alternatives. 1.5.7 operation(s) The valid value are in mask: - noop 0 - move (1L << 0) - copy (1L << 1) - link (1L << 2) 1.5.8 status The valid values are: - no-drop-site: 1 - invalid-drop-site: 2 - valid-drop-site: 3 1.5.9 drop action The valid values are: - drop: 0 - drop-help: 1 - drop-cancel: 2 PRE_REGISTER ------------ Motif D&D supports two modes of operations. Dynamic, which is the one standardized with CDE2, and pre_register, which we decided not to document for various reasons, even though it is the default mode. This document is just a dump of what I know about this pre-register mode, it's not really accurate or complete. In pre-register, the source grabs the server when the drag starts, and whenever it enters a new top-level, it reads all the drop site information it needs for doing its tracking, visual feedback, etc, from a pre-registered database attached to the _MOTIF_DRAG_RECEIVER_INFO of each participating client top-level. Obviously, no _MOTIF_DRAG_AND_DROP_MESSAGE XClientMessages are sent, since no one is listening to them (i.e. the X server is grabbed). The server gets ungrabbed when the user drops the object, at which point the documented drop protocol comes in effect (together with the convention for transfer_success or failure). The same _MOTIF_DRAG_INITIATOR_INFO is used, and the _MOTIF_DRAG_RECEIVER_INFO semantics are extended as follow: BYTE byte order of data in property BYTE protocol version of receiver BYTE protocol style == Dynamic, DropOnly, None, PreRegister BYTE pad CARD32 proxy_window CARD16 num_drop_sites CARD16 pad CARD32 total_size following these 16 bytes header, comes 'num_drop_sites' drop site blocks. Each block starts with a 8 bytes DSHeader, is followed by a visual info block and a series of boxes giving geometry information. DSHeader: * the flags field contains the following: * * 0003 traversalType (t_close - last in what?) * 000C dropActivity (active, inactive, ignore) * 00F0 dropType (simple, composite, clip_only?, * |with leaf?, internal?, has_region?) * 0F00 operations (same meaning as in Dynamic) * F000 animationStyle (none, pixmap, shadow_in, shadow_out, highlight) CARD16 flags CARD16 import_targets_id (same meaning as in Dynamic) CARD32 n_boxes Depending on animationStyle in the flags, visual information about the drop site follows: animationStyle = none CARD16 borderWidth CARD16 pad1 CARD32 pad2 animationStyle = highlight CARD16 borderWidth CARD16 highlightThickness CARD32 background CARD32 highlightColor CARD32 highlightPixmap animationStyle = shadow_in and out CARD16 borderWidth CARD16 highlightThickness CARD16 shadowThickness CARD16 pad1 CARD32 foreground CARD32 topShadowColor CARD32 bottomShadowColor CARD32 topShadowPixmap CARD32 bottomShadowPixmap CARD32 pad2 animationStyle = pixmap CARD16 borderWidth CARD16 highlightThickness CARD16 shadowThickness CARD16 animationPixmapDepth CARD32 foreground CARD32 background CARD32 animationPixmap CARD32 animationMask and then a serie a N box, as indicated in the DSHeader (has_region?). each Box INT16 x1 INT16 x2 INT16 y1 INT16 y2 Encoding -------- TDB: PreRegister, DSHeader flags. ------ from programmers' reference XmNdropSiteActivity Indicates whether a drop site is active or inac- tive. The values are XmDROP_SITE_ACTIVE, XmDROP_SITE_INACTIVE, and XmDROP_SITE_IGNORE. An active drop site can receive a drop, whereas an inactive drop site is dormant. An inactive drop site is treated as if it was not a registered drop site and any drag-under visuals associated with entering or leaving the drop site do not occur. However, it is still used for clipping drag-under effects. A value of XmDROP_SITE_IGNORE indicates that a drop site should be ignored for all pur- poses. XmNanimationStyle Specifies the drag-under animation style used when a drag enters a valid drop site. The possible values are XmDRAG_UNDER_HIGHLIGHT The drop site uses highlighting effects. XmDRAG_UNDER_SHADOW_OUT The drop site uses an outset shadow. XmDRAG_UNDER_SHADOW_IN The drop site uses an inset shadow. XmDRAG_UNDER_PIXMAP The drop site uses the pixmap specified by XmNanimationPixmap to indicate that it can receive the drop. XmDRAG_UNDER_NONE The drop site does not use animation effects. A client using a dynamic pro- tocol, may provide drag-under effects in its XmNdragProc routine. XmNdropSiteType Specifies the type of the drop site. The possible values are XmDROP_SITE_SIMPLE The widget does not have any additional children that are registered as drop sites. XmDROP_SITE_COMPOSITE The widget will have children that are registered as drop sites. ------------------------------------------ drag_simple: DrawingArea's inputCallback calls drag_bitmap() on button down on a bitmap: - this set's the convertProc to export_bitmap. - the clientData to the bitmap - the operation to DROP_COPY. - and calls XmDragStart(), which creates the DragContext. When XmDragStart() is called, the grab is added - dragging is begun. When dragging, DropSMgr (if local) is informed of the drag motion. - if the dragProc has been set, animation effects can be controlled (at least, when the protocolStyle is XmDRAG_DYNAMIC). When the drop occurs (here's where it get's complicated): - if we're in a valid drop site (targets are compatible): o we invoke the dropProc. . in drag_simple, this is import_bitmap(). It invokes XmDropTransferStart(), with dropTransfers set to a good list, and numDropTransfer set to non-zero. This causes DropTrans to add its own drop_timer(). . This causes: > drop_timer() sees that numDropTransferLists() isn't zero. This causes the entry_transfer() method to be invoked. > entry_transfer() calls XtGetSelectionValues(). o As a result, DragContext's drop_convert_callback() is invoked for the selection conversion; since this is not the end of a transfer, this causes the convertProc() [export_bitmap()] to be invoked. o After that happens, DropTransfer's select_callback is invoked, and this causes the transferProc that was set on DropTransfer to be invoked (transfer_bitmap()). This set's the new bitmap for the pushbutton.... And voila'! The pushbutton has the new bitmap... Otherwise: - if we're not in a valid drop site (or targets aren't compatible): o we XmDropTransferStart, with no dropTransfers, and the transferStatus is FAILURE. This causes an immediate invocation of XtGetSelectionValue() with the callback set to the notified_callback(), and the selection set to the result. The notified_callback kills the DropTransfer. DragContext's drop_convert_callback() is invoked by XtGetSelectionValue(), and no transfer has occurred. The convert proc is therefore not successfully invoked (it goes directly to the failure case [*select is XmTRANSFER_FAILURE]; the transfer has failed).