From 077f402bee2043640da43888661092bd2fd30379 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 05:46:21 +0000 Subject: [PATCH] Implement source_actions for X11 and cocoa DnD backends Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/91dbd1d2-ae9d-4816-b710-7d6f3147cda6 Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com> --- glfw/cocoa_window.m | 10 ++++++++++ glfw/x11_init.c | 2 ++ glfw/x11_platform.h | 2 ++ glfw/x11_window.c | 19 +++++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 0d9be8de5..10da335ce 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -1581,6 +1581,11 @@ reset_drop_copy_mimes(_GLFWDropData *d) { window->ns.drop_data.mimes = mime_array; window->ns.drop_data.mimes_count = mime_count; bool from_self = ([sender draggingSource] != nil); + NSDragOperation src_ops = [sender draggingSourceOperationMask]; + window->drop_operation.source_actions = GLFW_DRAG_OPERATION_NONE; + if (src_ops & NSDragOperationCopy) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_COPY; + if (src_ops & NSDragOperationMove) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_MOVE; + if (src_ops & NSDragOperationGeneric) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_GENERIC; _GLFWDropData *d = &window->ns.drop_data; if (reset_drop_copy_mimes(d)) { size_t accepted_count = _glfwInputDropEvent(window, GLFW_DROP_ENTER, xpos, ypos, d->copy_mimes, d->copy_mimes_count, from_self); @@ -1598,6 +1603,11 @@ reset_drop_copy_mimes(_GLFWDropData *d) { double ypos = contentRect.size.height - pos.y; bool from_self = ([sender draggingSource] != nil); + NSDragOperation src_ops = [sender draggingSourceOperationMask]; + window->drop_operation.source_actions = GLFW_DRAG_OPERATION_NONE; + if (src_ops & NSDragOperationCopy) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_COPY; + if (src_ops & NSDragOperationMove) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_MOVE; + if (src_ops & NSDragOperationGeneric) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_GENERIC; _GLFWDropData *d = &window->ns.drop_data; if (reset_drop_copy_mimes(d)) { size_t accepted_count = _glfwInputDropEvent(window, GLFW_DROP_MOVE, xpos, ypos, d->copy_mimes, d->copy_mimes_count, from_self); diff --git a/glfw/x11_init.c b/glfw/x11_init.c index 44385df0e..0ff634e97 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -520,6 +520,8 @@ static bool initExtensions(void) _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False); + _glfw.x11.XdndActionList = XInternAtom(_glfw.x11.display, "XdndActionList", False); + _glfw.x11.XdndActionAsk = XInternAtom(_glfw.x11.display, "XdndActionAsk", False); _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False); _glfw.x11.XdndProxy = XInternAtom(_glfw.x11.display, "XdndProxy", False); diff --git a/glfw/x11_platform.h b/glfw/x11_platform.h index d44a44f4e..ad2099a8c 100644 --- a/glfw/x11_platform.h +++ b/glfw/x11_platform.h @@ -327,6 +327,8 @@ typedef struct _GLFWlibraryX11 Atom XdndFinished; Atom XdndSelection; Atom XdndTypeList; + Atom XdndActionList; + Atom XdndActionAsk; Atom XdndLeave; Atom XdndProxy; diff --git a/glfw/x11_window.c b/glfw/x11_window.c index ecc94ae2e..d307466eb 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -1691,6 +1691,24 @@ _glfwPlatformEndDrop(GLFWwindow *w, GLFWDragOperationType op) { } +static void +update_drop_source_actions(_GLFWwindow *window) { + window->drop_operation.source_actions = GLFW_DRAG_OPERATION_NONE; + Atom *actions = NULL; + unsigned long count = _glfwGetWindowPropertyX11(dnd.source, _glfw.x11.XdndActionList, XA_ATOM, (unsigned char**)&actions); + if (actions) { + for (unsigned long i = 0; i < count; i++) { + if (actions[i] == _glfw.x11.XdndActionCopy) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_COPY; + else if (actions[i] == _glfw.x11.XdndActionMove) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_MOVE; + else if (actions[i] == _glfw.x11.XdndActionAsk) window->drop_operation.source_actions |= GLFW_DRAG_OPERATION_GENERIC; + } + XFree(actions); + } else { + // XdndActionList not present; default to copy only + window->drop_operation.source_actions = GLFW_DRAG_OPERATION_COPY; + } +} + static void drop_start(_GLFWwindow *window, XEvent *event) { // A drag operation has entered the window @@ -1703,6 +1721,7 @@ drop_start(_GLFWwindow *window, XEvent *event) { dnd.format_priority = 0; update_dnd_mimes(event); dnd.from_self = _glfw.x11.drag.source_window != None && dnd.source == _glfw.x11.drag.source_window; + update_drop_source_actions(window); // Position is not known yet at enter time, will be updated with XdndPosition if (reset_dnd_copy_mimes()) { size_t accepted_count = _glfwInputDropEvent(