From 2b4c51707f4e1d01549c03a05612acb9a5461eb9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 8 May 2026 15:27:36 +0000 Subject: [PATCH] Fix GLFW_DRAG_FINSHED never firing after GLFW_DRAG_DROPPED on macOS Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/5f783d91-e095-4f98-9d13-9d6359889ea2 Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com> --- glfw/cocoa_window.m | 64 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index e92f42cb1..09b1b6f42 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -4141,6 +4141,14 @@ void _glfwCocoaPostEmptyEvent(void) { } // Drag source implementation {{{ + +// Forward declarations for drag-finish helpers used in GLFWDraggingSource methods +static void fire_drag_finished(void); +static void schedule_drag_finish_timer(void); +static GLFWid drag_finish_window_id = 0; +static GLFWDragOperationType drag_finish_action = 0; +static NSTimer *drag_finish_timer = nil; + @implementation GLFWDraggingSource - (NSDragOperation)draggingSession:(NSDraggingSession*)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context @@ -4200,13 +4208,54 @@ - (void)draggingSession:(NSDraggingSession *)session ev.type = GLFW_DRAG_DROPPED; break; } _glfwInputDragSourceRequest(window, &ev); - if (operation == NSDragOperationNone) _glfwFreeDragSourceData(); + if (ev.type == GLFW_DRAG_DROPPED) { + drag_finish_window_id = _glfw.drag.window_id; + drag_finish_action = ev.action; + if (operation == NSDragOperationNone || !file_promise_providers || [file_promise_providers count] == 0) { + fire_drag_finished(); + } else { + schedule_drag_finish_timer(); + } + } else { + if (operation == NSDragOperationNone) _glfwFreeDragSourceData(); + } } } @end static NSMutableArray *file_promise_providers = nil; +static void +fire_drag_finished(void) { + if (drag_finish_timer) { + [drag_finish_timer invalidate]; + drag_finish_timer = nil; + } + if (!drag_finish_window_id) return; + GLFWid wid = drag_finish_window_id; + GLFWDragOperationType action = drag_finish_action; + drag_finish_window_id = 0; + drag_finish_action = 0; + _GLFWwindow *window = _glfwWindowForId(wid); + if (window) { + GLFWDragEvent ev = {.type=GLFW_DRAG_FINSHED, .action=action}; + _glfwInputDragSourceRequest(window, &ev); + } + _glfwFreeDragSourceData(); +} + +static void +schedule_drag_finish_timer(void) { + if (drag_finish_timer) { + [drag_finish_timer invalidate]; + drag_finish_timer = nil; + } + drag_finish_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 repeats:NO block:^(NSTimer *t UNUSED) { + drag_finish_timer = nil; + fire_drag_finished(); + }]; +} + static int set_image_for_dragging_item(NSDraggingItem *draggingItem, const GLFWimage *thumbnail, NSWindow *window) { CGFloat scaleFactor = 1.0; @@ -4386,6 +4435,13 @@ - (void)end_transfer_with_error:(NSError*)err { completion_handler = nil; } [file_promise_providers removeObject:self]; + if (drag_finish_window_id) { + if (!file_promise_providers || [file_promise_providers count] == 0) { + fire_drag_finished(); + } else { + schedule_drag_finish_timer(); + } + } } - (void)end_transfer:(int)errorCode { @@ -4500,6 +4556,12 @@ - (void)filePromiseProvider:(NSFilePromiseProvider*)filePromiseProvider void _glfwPlatformFreeDragSourceData(void) { + if (drag_finish_timer) { + [drag_finish_timer invalidate]; + drag_finish_timer = nil; + } + drag_finish_window_id = 0; + drag_finish_action = 0; if (_glfw.ns.drag_session) [_glfw.ns.drag_session release]; _glfw.ns.drag_session = nil; if (_glfw.ns.drag_view) [_glfw.ns.drag_view release];