Implement finishing of drops

This commit is contained in:
Kovid Goyal
2026-03-07 15:13:00 +05:30
parent 5ad55ec936
commit 17e941a180
5 changed files with 40 additions and 14 deletions

View File

@@ -113,7 +113,18 @@ getting the data, the terminal must send an escape code of the form::
OSC _dnd_code ; 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.
``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 revious 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 _dnd_code ; 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.
Metadata reference
---------------------------

View File

@@ -228,15 +228,16 @@ drop_set_status(Window *w, int operation, const char *payload, size_t payload_sz
if (!w->drop.accept_in_progress) {
drop_free_accepted_mimes(w); w->drop.accept_in_progress = true; w->drop.accepted_operation = 0;
switch(operation) {
case 1: w->drop.accepted_operation = GLFW_DRAG_OPERATION_COPY; break;
case 2: w->drop.accepted_operation = GLFW_DRAG_OPERATION_MOVE; break;
default: w->drop.accepted_operation = GLFW_DRAG_OPERATION_NONE; break;
case 1: case 2: w->drop.accepted_operation = operation; break;
default: w->drop.accepted_operation = 0; break;
}
}
w->drop.accepted_mimes = realloc(w->drop.accepted_mimes, w->drop.accepted_mimes_sz + payload_sz + 2);
if (w->drop.accepted_mimes) {
memcpy(w->drop.accepted_mimes + w->drop.accepted_mimes_sz, payload, payload_sz);
w->drop.accepted_mimes_sz += payload_sz;
if (payload_sz) {
w->drop.accepted_mimes = realloc(w->drop.accepted_mimes, w->drop.accepted_mimes_sz + payload_sz + 2);
if (w->drop.accepted_mimes) {
memcpy(w->drop.accepted_mimes + w->drop.accepted_mimes_sz, payload, payload_sz);
w->drop.accepted_mimes_sz += payload_sz;
}
}
if (!more) {
w->drop.accept_in_progress = false;
@@ -250,11 +251,21 @@ drop_set_status(Window *w, int operation, const char *payload, size_t payload_sz
}
}
void
drop_finish(Window *w) {
OSWindow *osw = os_window_for_kitty_window(w->id);
if (osw && osw->handle) {
int op = GLFW_DRAG_OPERATION_GENERIC;
if (w->drop.accepted_operation == 1) op = GLFW_DRAG_OPERATION_COPY;
else if (w->drop.accepted_operation == 2) op = GLFW_DRAG_OPERATION_MOVE;
glfwEndDrop(osw->handle, op);
}
}
size_t
drop_update_mimes(Window *w, const char **allowed_mimes, size_t allowed_mimes_count) {
if (w->drop.accept_in_progress) return allowed_mimes_count;
if (w->drop.accepted_operation == GLFW_DRAG_OPERATION_NONE) return 0;
if (!w->drop.accepted_operation) return 0;
typedef struct mime_sorter { const char *m; ssize_t key; } mime_sorter;
if (!w->drop.accepted_mimes) return allowed_mimes_count;
RAII_ALLOC(mime_sorter, ms, malloc(sizeof(mime_sorter) * allowed_mimes_count));

View File

@@ -16,3 +16,4 @@ void drop_request_data(Window *w, const char *mime);
void drop_set_status(Window *w, int operation, const char *payload, size_t payload_sz, bool more);
size_t drop_update_mimes(Window *w, const char **allowed_mimes, size_t allowed_mimes_count);
void drop_dispatch_data(Window *w, const char *data, ssize_t sz);
void drop_finish(Window *w);

View File

@@ -847,10 +847,12 @@ on_drop(GLFWwindow *window, GLFWDropEvent *ev) {
case GLFW_DROP_DATA_AVAILABLE:
if (global_state.drop_dest.client_window_data_request) {
if ((w = window_for_window_id(global_state.drop_dest.client_window_data_request))) {
char buf[3072];
ssize_t ret = ev->read_data(window, ev, buf, sizeof(buf));
drop_dispatch_data(w, buf, ret);
if (ret <= 0) ev->finish_drop(window, GLFW_DRAG_OPERATION_GENERIC);
if (w->drop.getting_data_for_mime && strcmp(w->drop.getting_data_for_mime, ev->mimes[0]) == 0) {
char buf[3072];
ssize_t ret = ev->read_data(window, ev, buf, sizeof(buf));
drop_dispatch_data(w, buf, ret);
if (ret <= 0) ev->finish_drop(window, GLFW_DRAG_OPERATION_GENERIC);
}
}
} else {
if (!global_state.drop_dest.data) ev->finish_drop(window, GLFW_DRAG_OPERATION_GENERIC);

View File

@@ -1519,7 +1519,8 @@ screen_handle_dnd_command(Screen *self, const DnDCommand *cmd, const uint8_t *pa
case 'm': drop_set_status(w, cmd->operation, (const char*)payload, cmd->payload_sz, cmd->more); break;
case 'r': {
char buf[256];
if (w && cmd->payload_sz + 1 < sizeof(buf)) {
if (!cmd->payload_sz) drop_finish(w);
else if (cmd->payload_sz + 1 < sizeof(buf)) {
memcpy(buf, payload, cmd->payload_sz); buf[cmd->payload_sz] = 0;
drop_request_data(w, buf);
}