Start and stop accepting drops
This commit is contained in:
parent
2898324047
commit
5a8132d241
6 changed files with 82 additions and 7 deletions
54
docs/dnd-protocol.rst
Normal file
54
docs/dnd-protocol.rst
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
The Drag and Drop protocol
|
||||
==============================================
|
||||
|
||||
.. versionadded:: 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 _dnd_code ; metadata ; base64 encoded payload ST
|
||||
|
||||
Here, ``OSC`` is the bytes ``ESC ] (0x1b 0x5b)``. The ``metadata`` is a colon
|
||||
separated list of ``key=value`` pairs. The final part of the escape code is the
|
||||
:rfc:`base64 <4648>` encoded payload data, whose meaning depends on the
|
||||
metadata. The payload must be no more than 4096 bytes *before base64 encoding*.
|
||||
|
||||
Accepting drops
|
||||
-----------------
|
||||
|
||||
In order to inform the terminal emulator that the program accepts drops, it
|
||||
must, send the following escape code::
|
||||
|
||||
OSC _dnd_code ; 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 _dnd_code ; t=A ST
|
||||
|
||||
to inform the terminal that it no longer wants drops.
|
||||
|
||||
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`` The overall action this graphics command is performing.
|
||||
``(a, A, ``t`` - transmit data, ``T`` - transmit data and display image,
|
||||
)`` ``q`` - query terminal, ``p`` - put (display) previous transmitted image,
|
||||
``d`` - delete image, ``f`` - transmit data for animation frames,
|
||||
``a`` - control animation, ``c`` - compose animation frames
|
||||
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ def parsers() -> None:
|
|||
write_header(text, 'kitty/parse-multicell-command.h')
|
||||
|
||||
keymap = {
|
||||
't': ('type', flag('ae')),
|
||||
't': ('type', flag('aA')),
|
||||
'm': ('more', 'uint'),
|
||||
}
|
||||
text = generate(
|
||||
|
|
|
|||
23
kitty/glfw.c
23
kitty/glfw.c
|
|
@ -765,6 +765,29 @@ read_drop_data(GLFWwindow *window, GLFWDropEvent *ev) {
|
|||
#undef finish
|
||||
}
|
||||
|
||||
void
|
||||
register_drop_window(id_type window_id, const uint8_t *payload, size_t payload_sz, bool on) {
|
||||
Window *w = window_for_window_id(window_id);
|
||||
OSWindow *osw = os_window_for_kitty_window(window_id);
|
||||
if (w && osw && osw->handle) {
|
||||
w->accepts_drops = on;
|
||||
if (on && payload && payload_sz) {
|
||||
#ifdef __APPLE__
|
||||
RAII_ALLOC(char, copy, malloc(payload_sz + 1)); if (!copy) return;
|
||||
RAII_ALLOC(const char*, mimes, calloc(payload_sz, sizeof(char*))); if (!mimes) return;
|
||||
memcpy(copy, payload, payload_sz); copy[payload_sz] = 0;
|
||||
size_t num = 0;
|
||||
char* token = strtok(copy, " ");
|
||||
while (token != NULL) {
|
||||
mimes[num++] = token;
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
glfwCocoaRegisterMIMETypes(osw->handle, mimes, num);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_drop(GLFWwindow *window, GLFWDropEvent *ev) {
|
||||
if (!set_callback_window(window)) return;
|
||||
|
|
|
|||
|
|
@ -1511,11 +1511,8 @@ void
|
|||
screen_handle_dnd_command(Screen *self, const DnDCommand *cmd, const uint8_t *payload) {
|
||||
if (!self->window_id) return;
|
||||
switch(cmd->type) {
|
||||
case 'a':
|
||||
(void)payload;
|
||||
break;
|
||||
case 'e':
|
||||
break;
|
||||
case 'a': register_drop_window(self->window_id, payload, cmd->payload_sz, true); break;
|
||||
case 'A': register_drop_window(self->window_id, NULL, 0, false); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ bool screen_pause_rendering(Screen *self, bool pause, int for_in_ms);
|
|||
void screen_check_pause_rendering(Screen *self, monotonic_t now);
|
||||
void screen_designate_charset(Screen *self, uint32_t which, uint32_t as);
|
||||
void screen_multi_cursor(Screen *self, int queried_shape, int *params, unsigned num_params);
|
||||
void register_drop_window(id_type window_id, const uint8_t *payload, size_t payload_sz, bool on);
|
||||
#define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen);
|
||||
DECLARE_CH_SCREEN_HANDLER(bell)
|
||||
DECLARE_CH_SCREEN_HANDLER(backspace)
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ typedef struct WindowBarData {
|
|||
|
||||
typedef struct Window {
|
||||
id_type id;
|
||||
bool visible;
|
||||
bool visible, accepts_drops;
|
||||
PyObject *title;
|
||||
WindowRenderData render_data;
|
||||
WindowRenderData window_title_render_data;
|
||||
|
|
|
|||
Loading…
Reference in a new issue