summaryrefslogtreecommitdiff
path: root/Specifications/XDND.mdwn
blob: 5aeef7cc445da162a810d355bb5cee9fedb3d0a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
# Drag-and-Drop Protocol for the X Window System

[[!toc startlevel=2]]

This page was created from Google's cache of <http://www.newplanetsoftware.com/xdnd/>. It needs reformatting.

Note: While almost all modern applications that support drag and drop try to follow this standard, there are a number of common errors that have led to a large number of interoperability problems in the past. Please check your programs against programs from several other desktops to help ensure you have followed the standard correctly. See this document for a list of common mistakes:

 * [[Drag and drop warts|Draganddropwarts]]

# Contents


## Introduction

Today, Drag-and-Drop (DND) is considered a requirement for commercial-quality applications. On most operating systems, support for DND is built-in, so everybody uses it and all programs can communicate with each other.

On X, however, there is no standard, so various groups have developed their own protocols, with the result that programs written for one protocol cannot talk to programs written for a different protocol. Clearly this does not satisfy the fundamental requirement that DND allow the user to drag data from any program to any other program.

What is required is a single protocol that everybody can use so all programs can exchange data via DND. (The X Selection mechanism insures that everybody can exchange data via the clipboard.)

The basic requirements for such a protocol are that it provide visual feedback to the user during the drag and that it allow the target to choose whatever data format it prefers from among all the formats that the source can provide. In addition, it must be efficient so that the visual feedback does not lag behind the user's actions, and it must be safe from deadlock, race conditions, and other hazards inherent in asynchronous systems.

Current version: 5 Last updated on April 5, 2003


## Definitions

The **source** is the window that will supply the data.

The **target** is the window that the cursor is on top of and which will receive the drop if the mouse is released.

You should be familiar with the **X Selection** mechanism described in the Xlib manuals: Volume 0, Appendix L and Volume 1, Chapter 10.

All data types and actions are referred to by their corresponding **X Atoms**. The atom names of the data types are the corresponding [[MIME types|ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/]], in all lower case. (RFC's for MIME: [[!rfc 2045 desc="2045"]], [[!rfc 2047 desc="2047"]], [[!rfc 2048 desc="2048"]], [[!rfc 2049 desc="2049"]])

All constants mentioned in this document are the string names of X atoms, capitalized as shown. This avoids the need for hard-coded values, which would require a global registry.


## Example walk-through

**Note:** Parenthesized numbers in bold-face are the number of packets sent to or from the server.


### Step 0:

Windows announce that they support the XDND protocol by creating a window property `XdndAware`.


### Step 1:

When a drag begins, the source takes ownership of `XdndSelection`.

When the mouse enters a window that supports XDND (search for window property: avg **8**), the source sends a `ClientMessage` of type `XdndEnter` (**2**) which contains the protocol version to use and the data types supported by the source.

An extension has been developed to allow dropping on other windows.


### Step 2:

The target receives `XdndEnter`.

The `ClientMessage` only has space for three data types, so if the source supports more than this, the target must retrieve the property `XdndTypeList` from the source window in order to get the list of available types. (**2**)


### Step 3:

The source sends a `ClientMessage` of type `XdndPosition`. (**2**) This tells the target the position of the mouse and the action that the user requested.


### Step 4:

The target receives `XdndPosition`.

The target window must determine which widget the mouse is in and ask it whether or not it will accept the drop. For efficiency, the target window should keep track of whether or not the widget will accept the drop and only ask again if the action changes or the mouse enters a different part of the widget. Once the widget has said that it will accept the drop and as long as the action remains the same and the mouse remains in the same part, the widget gets all the `XdndPosition` messages so that it can re-draw itself to show the user where the data will be inserted, if appropriate.

To determine whether or not it can accept the drop, the target widget consults the list of types from the `XdndEnter` message and the requested action from the `XdndPosition` message.

If it cannot perform the requested action, it can return either `XdndActionCopy` or `XdndActionPrivate`. If neither of these are possible, then it should refuse the drop.

If it needs to look at the data itself, it calls `XConvertSelection()` for `XdndSelection`, the data type that it is interested in, and the given time stamp. (**7**) It can do this more than once, if necessary.

If it can accept the drop, it should hilight its border to notify the user. If it retrieved the data, it should cache it so it does not need to be retrieved again when the actual drop occurs.


### Step 5:

The target sends a `ClientMessage` of type `XdndStatus`. (**2**) This tells the source whether or not it will accept the drop, and, if so, what action will be taken. It also includes a rectangle that means "don't send another `XdndPosition` message until the mouse moves out of here".


### Step 6:

The source receives `XdndStatus`. It can use the action to change the cursor to indicate whether or not the user's requested action will be performed.

When the mouse moves out of the given rectangle, go to Step 3.

`XdndPosition` messages are normally triggered by `MotionNotify` events. However, if the mouse moves while the source is waiting for an `XdndStatus` message, the source has to cache the new mouse position and generate another `XdndPosition` message as soon as it receives the `XdndStatus` message. (This will be necessary when the server-target connection is much slower than the server-source connection.)


### Step 7:

If the mouse leaves the window, the source sends a `ClientMessage` of type `XdndLeave`. (**2**)

If the mouse button is released in the window, the source waits for the last `XdndStatus` message (if necessary) and then sends a `ClientMessage` of type `XdndLeave` or `XdndDrop`, depending on the "accept" flag in the last `XdndStatus`. (**2**)

If the source never received any `XdndStatus` messages at all, it should send `XdndLeave` without waiting.

If the source doesn't receive the expected `XdndStatus` within a reasonable amount of time, it should send `XdndLeave`. While waiting for `XdndStatus`, the source can block, but it must at least process `SelectionRequest` events so the target can examine the data.


### Step 8:

If the target receives `XdndLeave`, it frees any cached data and forgets the whole incident.

If the target receives `XdndDrop` and will accept it, it first uses `XConvertSelection()` to retrieve the data using the given time stamp (if it doesn't already have it cached). (**7**) It then uses the data in conjunction with the last action and mouse position that was acknowledged via `XdndStatus`. (Over a slow network, this makes the drop location consistent with the visual feedback given to the user.) Once it is finished, it sends `XdndFinished`.

If the target receives `XdndDrop` and will not accept it, it sends `XdndFinished` and then treats it as `XdndLeave`.


## Theory

Every part of this protocol serves a purpose:


### XdndAware

In order for the user to be able to transfer data from any application to any other application via DND, every application that supports XDND version N must also support all previous versions (3 to N-1). The `XdndAware` property provides the highest version number supported by the target (Nt). If the source supports versions up to Ns, then the version that will actually be used is min(Ns,Nt). This is the version sent in the `XdndEnter` message. It is important to note that `XdndAware` allows this to be calculated before any messages are actually sent.

The property can also act as an extra filter, because it can contain a list of types accepted by the target, as explained in the Technical Details section.

It is also critical for scrolling (see Notes section below) and for coexisting with other DND protocols (since one can try something else if `XdndAware` is not present) and is useful for debugging since it lets one check the target's XDND version, after which one can expect to receive an `XdndStatus` message.


### X Selection

By using `XConvertSelection()`, one can use the same data conversion code for both the Clipboard and Drag-and-Drop. This is an especially large saving if the target requests the type `MULTIPLE` or if the source is forced to send the data incrementally (type `INCR`). It also makes checking the data independent of the main sequence of messages, so `XdndStatus` correctly reports "yes" or "no" the first time.

By using `XdndSelection`, the dropped data doesn't interfere with the clipboard data stored in `XA_PRIMARY`.

Using `XConvertSelection()` does have the problem that the user can begin dragging something else before the data transfer is complete. However, the X clipboard has the same problem, so this doesn't impose any additional constraints on the user, and it can be avoided as explained below in the discussion of the `XdndFinished` message.


### Actions

Specifying the action separately from the data type allows one to avoid defining N*M atoms for N data types and M actions. Since the user must have full control of what will happen, exactly one action is specified by the source. This is passed in the `XdndPosition` message to allow it to change during the drag. (e.g. if the user presses or releases modifier keys) The action accepted by the target is passed back in the `XdndStatus` message to allow the source to provide feedback in the cursor.

The special action `XdndActionAsk` tells the target that it should ask the user what to do after the drop occurs. This allows one to implement the effect obtained by right-dragging in Windows95(R), where the file manager asks the user whether to move, copy, create a link, or cancel. The list of actions is retrieved from the `XdndActionList` property, and the description of each action that is shown to the user is retrieved from the `XdndActionDescription` property, both on the source window. Note that the user should be asked before retrieving the data and thus also before sending `XdndFinished`.

The special action `XdndActionPrivate` tells the source that the target will do something that the source doesn't understand and that won't require anything from the source other than a copy of the data.


### Messages

The `XdndEnter` message initiates the session and gives the target a chance to set up local variables such as the transformation from root window coordinates to target window coordinates. It also provides a list of supported data types so the target doesn't have to call `XConvertSelection()` for `XdndSelection`, `TARGETS`.

The `XdndPosition` message provides mouse locations so that the target does not have to query the X server in order to redraw itself properly. There is no other reliable way for the target to get the mouse location because X will force the cursor to be grabbed by the source window, so only the source window will be receiving events. The target needs the mouse location because it has to update itself to show where the data will be inserted. This is especially important in text editors, spreadsheets, and file managers.

The time stamp in the `XdndPosition` message must be passed to `XConvertSelection()` to insure that the correct data is received.

The `XdndStatus` message provides feedback to the source (e.g. it might want to change the cursor) and insures that `XdndPosition` messages do not pile up when the network connection is slow.

The `XdndLeave` message cancels the session.

The `XdndDrop` message tells the target to proceed with the drop. The time stamp must be passed to `XConvertSelection()` to insure that the correct data is received.

The `XdndFinished` message tells the source that the target is done and no longer needs the data. This allows the source to implement any one of three different behaviors:

* Block until the message is received. In this case, the source must be prepared to time out in case the target malfunctions and must reject outdated requests.
* Don't block and reject outdated requests by comparing the time when the selection was last acquired with the timestamp in the selection request. (which comes from the `XdndDrop` message)
* Don't block and keep a history of previous data. This can be very difficult to implement, but it is clearly the ideal behavior from the user's perspective because it allows him to drop something and then continue working with the assurance that the target will get the data regardless of how slow the network connections are.
When the source receives `XdndFinished`, it can remove the item from its history, thereby keeping it from getting too large. The source must also be prepared to throw out extremely old data in case a target malfunctions.


### Protecting against malfunctioning programs

If the version number in the `XdndEnter` message is higher than what the target can support, the target should ignore the source.

While the source and target are receiving XDND messages from each other, they should ignore all XDND messages from other windows.

If either application crashes while DND is active, the other application must avoid crashing on a `BadWindow` error. The only safe way to do this is to actually catch the error by installing an error handler with `XSetErrorHandler()`. In addition, the target must also listen for `DestroyNotify` events so that it doesn't wait forever for another `XdndPosition` if the source crashes between receiving `XdndStatus` and sending `XdndPosition`.

* If the target crashes, the source will automatically receive another `EnterNotify` event, as if the mouse had moved. Any `XdndPosition` in the network will generate a `BadWindow` error.
* If the source crashes, the target should treat it like `XdndLeave`.
As discussed above, the source must be careful to avoid locking up if the target does not send `XdndFinished`.


## Notes

When the source and target are the same, the drop should be hysteretic within a region around the source window. (e.g. a 50 pixel border) The target remains the source as long as the mouse doesn't move into another widget that is willing to accept the drop. This makes it much easier for the user to drop the data on an invisible part of the source because dragging the mouse out onto the root window or a stray xterm will cause the source to scroll. The `XdndAware` property makes hysteresis possible because the root window, stray xterms, and especially the window border created by the window manager are ignored.

We are collecting examples to show DND might work in various cases. Dragging text is straightforward since there are several well-known formats, including `text/plain` and `text/enriched`. Dragging files is at least equally important.

We have also developed extensions that allow dropping on the root window and on windows that do not support XDND.

`XdndActionLink` only makes sense within a single program or between cooperating programs because the target must obtain not only the data, but also the location of the data. In all other cases, the target should respond with `XdndActionCopy` or `XdndActionPrivate` in the `XdndStatus` message.

On the other hand, `XdndActionAsk` makes equally good sense between unrelated programs and cooperating programs. However, when the source and target are unrelated, the target may choose to provide a list of actions that it can perform on its own after retrieving the data instead of asking the source for a list of actions.

Remember also that you must debounce the mouse drag. If the user moves the mouse by only a couple of pixels while clicking to select something, then it is far more likely that the user is a bit clumsy than that the user intends to start a drag. A threshold of 3 pixels is typical.


### Getting up on my soap box...

In my opinion, programs should not change the cursor during the drag because this provides the user with the most consistent picture. The user is always dragging the same data, regardless of whether or not the current target will accept it. It is the target that should change to show whether or not it will accept the drop.

However, if you want to be Microsoft compliant, you have to change the cursor. As usual, Microsoft got it backwards...

As a side note, on page 253 of his book, About Face, Alan Cooper agrees wholeheartedly.

The single exception that I endorse is adding a small symbol to the cursor to show that the requested action will be performed, instead of `XdndActionPrivate`. For an example, refer to the page on dragging files.


## Optimizations

When the source and target windows are part of the same application, sending X Client Messages is a waste of time and bandwidth, especially if the program and server are on different machines. Implementations should therefore detect the special cases of "source = target" and "source and target in same application" and handle them via function calls.

To avoid calling `XConvertSelection()` in the above cases:

* There is no need to examine the data when "source = target" because the source must know what it is dragging.
* If the actual call to `XConvertSelection()` is hidden behind an interface, then when the source and target are in the same application, the interface can simulate the call without going to the server.
Targets do not have to retrieve `XdndTypeList` from the source window if they find what they are looking for in the three types listed in the XdndEnter message.

It is pointless to send XdndPosition messages when the mouse is stationary.

To avoid unnecessary messages from the source to the server, one should only change the cursor when the target or status (acceptance and action) changes.

Unfortunately, one cannot avoid calling `XTranslateCoordinates()` continuously, because of overlapping windows.


## Technical details

Current version: 5

All constants mentioned below are the string names of X atoms, capitalized as shown. This avoids the need for hard-coded values, which would require a global registry.


## Atoms and Properties


### XdndAware

This window property must be of type `XA_ATOM` and must contain the highest version number of the protocol supported by the target. (Version numbers start at zero. The maximum version number is `0xFF` because there is only one byte allocated for it in the `XdndEnter` message. At one new version every three months, which is very rapid turnover, this will last 64 years.)

The property must be set on each top-level X window that contains widgets that can accept drops. (new in version 3) The property should not be set on subwindows. The target must dispatch the messages to the appropriate widget. Since window managers often insert extra layers of windows, this requires searching down the subwindow tree using `XTranslateCoordinates()`.


### XdndSelection

This is the name of the X Selection that is used when the target wants to examine the data during the drag phase and when it wants to retrieve the data after a drop.


### Data types

All data types are referred to by their corresponding X Atoms. The atom names are the corresponding MIME types, in all lower case. (RFC's for MIME: [[!rfc 2045 desc="2045"]], [[!rfc 2047 desc="2047"]], [[!rfc 2048 desc="2048"]], [[!rfc 2049 desc="2049"]])

For text, the charset attribute can be appended to the MIME type. (e.g. `Japanese` -> `text/plain;charset="ISO-2022-JP"`) If the charset attribute is not specified, it is assumed to be `ISO-8859-1`. (new in version 4)

Note that any data type may be transferred via the `INCR` protocol.


### XdndTypeList

If the source supports more than 3 data types, this window property must be set on the source window, must be of type `XA_ATOM`, and must contain a list of all the supported data types.


### Actions (new in version 2)

All actions are referred to by their corresponding X Atoms. The predefined actions are

* `XdndActionCopy`
* `XdndActionMove`
* `XdndActionLink`
* `XdndActionAsk`
* `XdndActionPrivate`

The `XdndAction` prefix is reserved for future expansion, but any other name can be used for other actions as long as both the source and the target recognize it and agree on what it means. The predefined atom None is not allowed as an action.

The default is `XdndActionCopy`, and this is assumed to be the action when using version 0 or 1.

In general, `XdndActionMove` is implemented by first requesting the data and then the special target `DELETE` defined in the X Selection protocol. (File managers will obviously just use mv or its equivalent.) `DELETE` should be sent before `XdndFinished`.

Refer to the Theory and Notes sections for more information.


### XdndActionList (new in version 2)

If the source sends `XdndActionAsk`, this window property must be set on the source window, must be of type `XA_ATOM`, and must contain a list of all the supported actions. The first one should be the default so the user doesn't have to change the selection in the radio group too often.


### XdndActionDescription (new in version 2)

If the source sends `XdndActionAsk`, this window property must be set on the source window, must be of type `XA_STRING`, and must contain a list of ASCII strings separated by NULL's that the target should display when describing the choices to the user. These strings must be in the same order as the atoms in the `XdndActionList` property.

The option to cancel the operation must always be provided in the dialog displayed to the user, via a Cancel button, but should not be included in `XdndActionList`.


### XdndProxy (new in version 4)

If this window property exists, it must be of type `XA_WINDOW` and must contain the ID of the proxy window that should be checked for `XdndAware` and that should receive all the client messages, etc. In order for the proxy window to behave correctly, the appropriate field of the client messages, window or `data.l[0]`, must contain the ID of the window in which the mouse is located, not the proxy window that is receiving the messages. The only place where the proxy window should be used is when checking `XdndAware` and in the calls to `XSendEvent()`.

The proxy window must have the `XdndProxy` property set to point to itself. If it doesn't or if the proxy window doesn't exist at all, one should ignore `XdndProxy` on the assumption that it is left over after a crash.


## Client Messages

Note: All unused flags must be set to zero in every message. This allows one to define new flags without incrementing the version number.


### XdndEnter

Sent from source to target when the mouse enters a window that supports XDND.

* `data.l[0]` contains the XID of the source window.
* `data.l[1]`:
   * Bit 0 is set if the source supports more than three data types.
   * The high byte contains the protocol version to use (minimum of the source's and target's highest supported versions).
   * The rest of the bits are reserved for future use.
* `data.l[2,3,4]` contain the first three types that the source supports. Unused slots are set to None. The ordering is arbitrary since, in general, the source cannot know what the target prefers.

If the Source supports more than three data types, bit 0 of `data.l[1]` is set. This tells the Target to check the property `XdndTypeList` on the Source window for the list of available types. This property should contain all the available types.


### XdndPosition

Sent from source to target to provide mouse location.

* `data.l[0]` contains the XID of the source window.
* `data.l[1]` is reserved for future use (flags).
* `data.l[2]` contains the coordinates of the mouse position relative to the root window.
   * `data.l[2] = (x << 16) | y`
* `data.l[3]` contains the time stamp for retrieving the data. (new in version 1)
* `data.l[4]` contains the action requested by the user. (new in version 2)

### XdndStatus

Sent from target to source to provide feedback on whether or not the drop will be accepted, and, if so, what action will be taken.

* `data.l[0]` contains the XID of the target window. (This is required so `XdndStatus` messages that arrive after `XdndLeave` is sent will be ignored.)
* `data.l[1]`:
   * Bit 0 is set if the current target will accept the drop.
   * Bit 1 is set if the target wants `XdndPosition` messages while the mouse moves inside the rectangle in `data.l[2,3]`.
   * The rest of the bits are reserved for future use.
* `data.l[2,3]` contains a rectangle in root coordinates that means "don't send another `XdndPosition` message until the mouse moves out of here". It is legal to specify an empty rectangle. This means "send another message when the mouse moves". Even if the rectangle is not empty, it is legal for the source to send `XdndPosition` messages while in the rectangle. The rectangle is stored in the standard Xlib format of (x,y,w,h):
   * `data.l[2] = (x << 16) | y`
   * `data.l[3] = (w << 16) | h`
* `data.l[4]` contains the action accepted by the target. This is normally only allowed to be either the action specified in the `XdndPosition` message, `XdndActionCopy`, or `XdndActionPrivate`. None should be sent if the drop will not be accepted. (new in version 2)

### XdndLeave

Sent from source to target to cancel the drop.

* `data.l[0]` contains the XID of the source window.
* `data.l[1]` is reserved for future use (flags).

### XdndDrop

Sent from source to target to complete the drop.

* `data.l[0]` contains the XID of the source window.
* `data.l[1]` is reserved for future use (flags).
* `data.l[2]` contains the time stamp for retrieving the data. (new in version 1)

### XdndFinished (new in version 2)

Sent from target to source to indicate that the source can toss the data because the target no longer needs access to it.

* `data.l[0]` contains the XID of the target window.
* `data.l[1]`:
   * Bit 0 is set if the current target accepted the drop and successfully performed the accepted drop action. (new in version 5) (If the version being used by the source is less than 5, then the program should proceed as if the bit were set, regardless of its actual value.)
   * The rest of the bits are reserved for future use.
* `data.l[2]` contains the action performed by the target. None should be sent if the current target rejected the drop, i.e., when bit 0 of `data.l[1]` is zero. (new in version 5) (**Note:** Performing an action other than the one that was accepted with the last `XdndStatus` message is strongly discouraged because the user expects the action to match the visual feedback that was given based on the `XdndStatus` messages!)

## Sample implementation

If you are interested in supporting this protocol, but daunted by having to start from scratch, you can obtain sample C++ code via anonymous ftp. This code may be used under any license.

Paul Sheer has implemented XDND v2 in C as a generic library. The files are xdnd.c and xdnd.h

If you use a different language, please consider donating your code for others to look at.

We also have a binary that you can use to test interoperability between a correct implementation and your implementation.

While implementing this protocol, you may find it very useful to use the programs `xlsatoms` to list all the atoms that the server knows about, `xprop` to list all the properties on a particular window, and `xscope` to study the timing of events.

Even if you implement XDND from scratch, we would appreciate it if your distribution included some sort of documentation that states clearly that you are supporting this protocol and provides a reference to this web page. This will help get the snowball rolling. The more programs that support the same protocol, the more useful Drag-and-Drop will be for the users. If you tell us that you support the protocol, we will also add you to the list of supporters.


## Changes from previous versions

December 25, 2002:

 * Version 5 adds additional information to the XdndFinished message in order to allow the Java DND API to be implemented on top of XDND. (Thanks to Danila A. Sinopalnikov for working out the details.)

August 31, 2002:

 * Added requirement to File Dragging protocol. The user name must be provided via the new text/x-xdnd-username data type.

November 21, 2000:

 * Thanks to Daniel Biddle for pointing out that the MIME types should be specified in the format ISO-8859-1, not iso8859-1.

October 26, 2000:

 * Minor modifications to actions required by File Dragging protocol.

February 22, 2000:

 * Added additional notes about why the host name must always be included when dragging files.

June 7, 1999:

 * Version 4 adds XdndProxy window property to support the new protocol for dropping on the root window. Rewrote the protocol for dropping on the root window to conform to the latest implementations. Added note in Technical Details section about how to specify the character set for text. Created Direct Save (XDS) protocol layered on top of XDND.

December 1, 1998:

 * Rewrote the protocol for dropping on the root window to conform to the latest implementations.

September 19, 1998:

 * The File Dragging protocol now uses the well established text/uri-list instead of url/url. Added note to Optimization section about caching the window stack.

September 7, 1998:

 * Version 3 changes the way XdndAware is handled. To reduce the number of !XTranslateCoordinates() calls to the X server and to make life easier for programs that use multiple X windows per widget, XdndAware must now be placed on the top-level X window, not on subwindows. This change is unfortunately incompatible with previous versions. However, since there are still relatively few programs that have been released with XDND support, the specification has simply been adjusted so XDND compliance only requires supporting version 3 and up. (This will never happen again!) In addition, Jeroen van der Zijp has invented an extension that allows dropping onto windows that do not support XDND, and Arnt Gulbrandsen has developed a way to drop on the root window.

August 17, 1998:

* Version 2 adds the following features:
   * The concept of an action. Previously, only copy was supported. Now, the source can specify any action, and the target can either accept it or fall back on copy or private. The predefined actions are XdndActionCopy (the default), XdndActionMove, XdndActionLink, XdndActionAsk, and XdndActionPrivate. Ask tells the target to get a list of acceptable actions from the source's XdndActionList and XdndActionDescription window properties and then ask the user which one to perform.
   * The target is required to send XdndFinished. (Yes, I caved in :) However, if the source blocks, it must be prepared to time out in case the target is malfunctioning. Ideally, the source will not need to block because it will keep a history of past selections. The timestamp in XdndDrop allows the source to safely avoid both blocking and keeping a history by simply rejecting outdated requests.
       * Part of the reason for adding XdndFinished is that this allows XDND to be used with higher level API's (e.g. JavaBeans) that require notification of the end of the operation.
   * With these new features, the File Dragging protocol becomes much simpler. Added page of supporters.

February 25, 1998:

 * Added examples of how XDND fits into the larger picture of cooperating applications.

February 24, 1998:

 * Added trashcan discussion to the File Dragging protocol.

February 2, 1998:

 * Version 0 has a hole. If the user begins a second drag from the same source before the data has been transferred to the first target (over a really slow network, obviously), then the first target may get the wrong data. Thanks to Donal K. Fellows for pointing this out. Version 1 fixes this by adding a time stamp to XdndPosition and XdndDrop which must be used when requesting the data. This way, if the user quickly begins a second drag, the first target will at least get no data instead of the wrong data. Please refer to the Theory section for a more complete discussion and the reasons why this was not fixed by adding a "drop finished" message.

January 28, 1998:

 * Added comparison to Xde.

## Acknowledgements

This protocol was developed by John Lindal at New Planet Software, with help from Glenn Bach and lots of feedback from Arnt Gulbrandsen at TrollTech and Owen Taylor of GTK+ and input from Elliot Lee at Red Hat Software.