From 0619c7e435b53477f5f9ace0b4b4621cb8435f04 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 3 Apr 2026 19:58:59 +0530 Subject: [PATCH] More work on DnD protocol --- kitty/dnd.c | 20 +++++++++++++++++++- kitty/dnd.h | 1 + kitty/screen.c | 3 +++ kitty/state.h | 3 ++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/kitty/dnd.c b/kitty/dnd.c index 2fea78b06..7f68dd8f1 100644 --- a/kitty/dnd.c +++ b/kitty/dnd.c @@ -867,6 +867,7 @@ drag_free_offer(Window *w) { free(ds.items); } ds.num_mimes = 0; + ds.pre_sent_total_sz = 0; } void @@ -901,8 +902,25 @@ drag_add_mimes(Window *w, int allowed_operations, const char *data, size_t sz, b p += strlen(p) + 1; } else p++; } + ds.pre_sent_total_sz = 0; } -#undef abrt } +void +drag_add_pre_sent_data(Window *w, unsigned idx, const uint8_t *payload, size_t sz) { + if (!ds.offer_being_built || idx >= ds.num_mimes) abrt(EINVAL); + if (sz + ds.pre_sent_total_sz > 64 * 1024 * 1024) abrt(EFBIG); + ds.pre_sent_total_sz += sz; + DragSourceItem *item = ds.items + idx; + if (item->data_capacity < sz + item->data_size) { + size_t newcap = MAX(item->data_size * 2, sz + item->data_size); + item->optional_data = realloc(item->optional_data, newcap); + if (!item->optional_data) abrt(ENOMEM); + item->data_capacity = newcap; + } + memcpy(item->optional_data + item->data_size, payload, sz); + item->data_size += sz; +} + +#undef abrt #undef ds diff --git a/kitty/dnd.h b/kitty/dnd.h index 0dadb71dd..646d78006 100644 --- a/kitty/dnd.h +++ b/kitty/dnd.h @@ -25,3 +25,4 @@ void dnd_set_test_write_func(PyObject *func); void drag_free_offer(Window *w); void drag_add_mimes(Window *w, int allowed_operations, const char *data, size_t sz, bool has_more); +void drag_add_pre_sent_data(Window *w, unsigned idx, const uint8_t *payload, size_t sz); diff --git a/kitty/screen.c b/kitty/screen.c index b8572f8b7..101497f93 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1548,6 +1548,9 @@ screen_handle_dnd_command(Screen *self, const DnDCommand *cmd, const uint8_t *pa cancel_current_drag_source(); } } break; + case 'p': { + if (cmd->cell_x >= 0) drag_add_pre_sent_data(w, cmd->cell_x, payload, cmd->payload_sz); + } break; } } diff --git a/kitty/state.h b/kitty/state.h index 7bda02504..7524d0eb8 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -236,7 +236,7 @@ typedef struct DirHandle { typedef struct DragSourceItem { const char *mime_type; char *optional_data; - size_t data_size; + size_t data_size, data_capacity; } DragSourceItem; typedef struct Window { @@ -296,6 +296,7 @@ typedef struct Window { struct { double x, y; monotonic_t at; } initial_left_press; char *mimes_buf; size_t num_mimes, bufsz; DragSourceItem *items; + size_t pre_sent_total_sz; int allowed_operations; bool offer_being_built; } drag_source;