The Drag and Drop protocol

Added in version 0.47.0.

This protocol enables drag and drop functionality for terminal programs that is as good as the drag and drop functionality available for GUI programs.

There is one central escape code used for this protocol, which is of the form:

OSC 72 ; metadata ; base64 encoded payload ST

Here, OSC is the bytes ESC ] (0x1b 0x5b) and ST is ESC \\ (0x1b 0x5c). The metadata is a colon separated list of key=value pairs. The final part of the escape code is the payload data, whose meaning depends on the metadata.

The payload must be no more than 4096 bytes. When the payload is larger than 4096 bytes, it is chunked up using the m key. An escape code that has a too long payload is transmitted in chunks. All but the last chunk must have m=1 in their metadata. Each chunk must have a payload of no more than 4096 bytes. Only the first chunk is guaranteed to have metadata other than the m key. Subsequent chunks may optionally omit all metadata except the m and i keys. While a chunked transfer is in progress it is a protocol error to for the sending side to send any protocol related escape codes other than chunked ones.

All integer values used in this escape code must be 32-bit signed or unsigned integers encoded in decimal representation.

When transferring binary data the payload is base64 encoded. The 4096 bytes limit applies to encoded bytes, that is, it is applied after encoding. base64 padding bytes are optional and may or may not be present at the end of the last chunk.

Accepting drops

In order to inform the terminal emulator that the program accepts drops, it must send the following escape code:

OSC 72 ; t=a ; payload ST

The payload here is a space separated list of MIME types the program accepts. The list of MIME types is optional, it is needed if the program wants to accept exotic or private use MIME types on platforms such as macOS, where the system does not deliver drop events unless the MIME type is registered.

When the program is done accepting drops, or at exit, it should send the escape code:

OSC 72 ; t=A ST

to inform the terminal that it no longer wants drops.

Whenever the user drags something over the window, the terminal will send an escape code of the form:

OSC 72 ; t=m:x=x:y=y:X=X:Y=Y ; optional MIME list ST

Here, x, y identify the cell over which the drag is currently present. The (0, 0) cell is at top left of the screen. X and Y are the pixel offsets from the top-left. The optional list of MIMES is a space separated list of MIME types that are available for dropping. To avoid overhead, the terminal should only send this list for the first move event and subsequently only if the list changes.

When the drag leaves the window, the terminal will send the same event but with x, y = -1, -1 to indicate that the drag has left the window. For such events the list of MIME types must be empty. Note that the terminal must never send negative cell co-ordinates for any other reason. No more movement escape codes t=m will be sent until this drop or another re-enters the window.

The client program must inform the terminal whether it will accept the potential drop and which MIME types of the set of offered MIME types it accepts. Until the client does so the terminal will indicate to the OS that the drop is not accepted. To do so, the client sends an escape code of the form:

OSC 72 ; t=m:o=O ; MIME list ST

Here the o key is the operation the client intends to perform if a drop occurs which can be either 1 for copy or 2 for move or 0 for not accepted. The MIME list is the ordered list of MIME types from the offered list that the client wants. If no MIME type list is present, it is equivalent to no change in the offered list of MIME types. The list should be ordered in order of decreasing preference. Some platforms may show the user some indication of the first MIME type in the list.

When the user triggers a drop on the window, the terminal will send an escape code of the form:

OSC 72 ; t=M: ... ; MIME list ST

This is the same as the movement escape codes above, except that t=M (upper case M instead of lower case m), indicating this is a drop. Once this escape code is received, no more movement escape codes t=m will be sent until a new drop enters the window. The MIME list here is mandatory, terminals must send the full list of MIME types available in the drop. The client program can now request data for the MIME types it is interested in.

Requesting data is done by sending an escape code of the form:

OSC 72 ; t=r ; MIME type ST

This will request data for the specified MIME type. The terminal must respond with a series of escape codes of the form:

OSC 72 ; t=r ; base64 encoded data ST

End of data is indicated by an empty payload. If some error occurs while getting the data, the terminal must send an escape code of the form:

OSC 72 ; t=R ; POSIX error name ST

Here POSIX error name is a POSIX symbolic error name such as ENOENT or EIO or the value EUNKNOWN for an unknown error. Note that if a client sends a request for another MIME type before the data for the previous MIME type is completed, the terminal must switch over to sending data for the new MIME type.

Once the client program finishes reading all the dropped data it needs, it must send an escape code of the form:

OSC 72 ; t=r ST

That is, it must send a request for data with no MIME type specified. The terminal emulator must then inform the OS that the drop is completed.

In order to support dropping of files from remote machines or to remote machines, clients can first request the text/uri-list MIME type to get a list of dropped URIs. For every file:// URI they can send the terminal emulator a data request of the form:

OSC 72 ; t=s ; text/uri-list:idx ST

Here idx is the zero based index into the array of MIME types in the text/uri-list entry. The terminal will then read the file and transmit the data as for a normal MIME data request.

Terminals must reply with t=R ; ENOENT if the index is out of bounds. If the client does not first request the text/uri-list MIME type or that MIME type is not present in the drop, the terminal must reply with t=R ; EINVAL. Similarly if the client requests an entry that is not a file:// URI the terminal must reply with EUNKNOWN.

Terminals must ONLY send data for regular files. Symbolic links must be resolved and the corresponding file read. If the terminal does not have permission to read the file it must reply with t=R ; EPERM. Terminals must respond with t=R ; EINVAL if the file is not a regular file after resolving symlinks and t=R ; ENOENT if the file does not exist.

Dropping directories

If the file is actually a directory the terminal must respond with t=d:x=idx ; payload. Here payload is a null byte separated list of entries in the directory that are either regular files, directories or symlinks. The payload must be base64 encoded and might be chunked if the directory has a lot of entries. The first entry in the list must be a unique identifier for the directory, to prevent symlink loops. Terminals may use whatever identifier is most suitable for their platforms, clients should not re-request the contents of a directory whose identifier they have seen before.

idx is an arbitrary 32 bit integer that acts as a handle to this directory. The client can now read the files in this directory using requests of the form t=d:x=idx:y=num, here num is the index into the list of directory entries previously transmitted to the client. Here, 1 will correspond to the first entry in the directory. Once the client is done reading a directory it should transmit t=d:x=idx to the terminal. The terminal can then free any resources associated with that directory. The directory handle is now invalid and terminals must return EINVAL if the client sends a request using and invalid directory handle. It is recommended that clients traverse directories breadth first to minimise resource usage in the terminal. Terminals may deny directory traversal requests if too many resources are used, in order to prevent denial or service attacks. In such cases the terminal must respond with ENOMEM.

Metadata reference

The table below shows all the metadata keys as well as what values they can take, and the default value they take when missing. All integers are 32-bit.

Key

Value

Default

Description

t

Single character. (a, A, )

a

The type of drag and drop event. a - start accepting drops A - stop accepting drops m - a drop move event M - a drop dropped event r - request dropped data R - report an error while retrieving data d - send directory contents

m

Chunking indicator

0

0 or i

i

Postive integer

0

This id is for use by multiplexers. When it is set, all responses from the terminal in that session will have it set to the same value.

o

Positive integer

0

What drop operation to perform. 0 means rejected, 1 means copy and 2 means move.

Keys for location

x

Integer

0

Cell x-coordinate origin is 0, 0 at top left of screen

y

Integer

0

Cell y-coordinate origin is 0, 0 at top left of screen

X

Integer

0

Pixel x-coordinate origin is 0, 0 at top left of screen

Y

Integer

0

Pixel y-coordinate origin is 0, 0 at top left of screen