diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index b527d7f95..74387cda8 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -3960,7 +3960,7 @@ void _glfwCocoaPostEmptyEvent(void) { case NSDragOperationDelete: ev.type = GLFW_DRAG_CANCELLED; break; case NSDragOperationNone: { NSEvent *currentEvent = [NSApp currentEvent]; - if (currentEvent.type == NSEventTypeKeyDown && currentEvent.keyCode == 53) { + if (currentEvent && currentEvent.type == NSEventTypeKeyDown && currentEvent.keyCode == 53) { ev.type = GLFW_DRAG_CANCELLED; } else ev.type = GLFW_DRAG_DROPPED; } break; diff --git a/glfw/glfw3.h b/glfw/glfw3.h index e8dcc30b2..e152d468a 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1391,6 +1391,7 @@ typedef enum { GLFW_DROP_ENTER, GLFW_DROP_MOVE, GLFW_DROP_LEAVE, GLFW_DROP_DROP, * @ingroup input */ typedef enum { + GLFW_DRAG_OPERATION_NONE = 0, // no operation, drop was not accepted /*! Move the dragged data to the destination. */ GLFW_DRAG_OPERATION_MOVE = 1, /*! Copy the dragged data to the destination. */ diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 78193eaa8..b3bb6c566 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -95,7 +95,7 @@ x11_cancel_momentum_scroll_timer(void) { static unsigned _glfwDispatchX11Events(void); // Forward declarations for drag source helper functions -static void send_drag_data(const char *mime_type, const char *data, size_t data_sz, +static void send_drag_data(const char *mime_type, const char *data, size_t data_sz, Window requestor, Atom property, Atom target); static bool add_pending_request(const char *mime_type, Window requestor, Atom property, Atom target); static void handle_drag_motion(int root_x, int root_y, Time timestamp); @@ -1159,15 +1159,15 @@ handleSelectionRequest(XEvent* event) { break; } } - + if (data && data_sz > 0) { // We have preset data, send it immediately - send_drag_data(mime_type, data, data_sz, request->requestor, + send_drag_data(mime_type, data, data_sz, request->requestor, request->property, request->target); reply.xselection.property = request->property; } else { // Add to pending requests for on-demand data - if (add_pending_request(mime_type, request->requestor, + if (add_pending_request(mime_type, request->requestor, request->property, request->target)) { // Request data from application _GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id); @@ -1180,11 +1180,11 @@ handleSelectionRequest(XEvent* event) { .err_num = 0 }; _glfwInputDragSourceRequest(window, &ev); - + if (ev.data && ev.data_sz > 0) { // Data provided synchronously send_drag_data(mime_type, ev.data, ev.data_sz, - request->requestor, request->property, + request->requestor, request->property, request->target); reply.xselection.property = request->property; } else { @@ -1510,6 +1510,7 @@ end_drop(_GLFWwindow *window, GLFWDragOperationType op) { case GLFW_DRAG_OPERATION_COPY: reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; break; case GLFW_DRAG_OPERATION_MOVE: reply.xclient.data.l[2] = _glfw.x11.XdndActionMove; break; case GLFW_DRAG_OPERATION_GENERIC: reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; break; + case GLFW_DRAG_OPERATION_NONE: reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; break; } } XSendEvent(_glfw.x11.display, dnd.source, False, NoEventMask, &reply); @@ -2156,13 +2157,13 @@ static void processEvent(XEvent *event) if (_glfw.x11.drag.active) { int root_x, root_y; Window child; - XTranslateCoordinates(_glfw.x11.display, + XTranslateCoordinates(_glfw.x11.display, event->xmotion.window, _glfw.x11.root, event->xmotion.x, event->xmotion.y, &root_x, &root_y, &child); handle_drag_motion(root_x, root_y, event->xmotion.time); } - + x11_cancel_momentum_scroll_timer(); glfw_cancel_momentum_scroll(); handle_mouse_move_event(window, event->xmotion.x, event->xmotion.y); @@ -3896,7 +3897,7 @@ window_supports_xdnd(Window win, int *version_out) { unsigned long count, bytes_after; unsigned char *data = NULL; bool supported = false; - + if (XGetWindowProperty(_glfw.x11.display, win, _glfw.x11.XdndAware, 0, 1, False, XA_ATOM, &actual_type, &actual_format, @@ -3921,7 +3922,7 @@ find_xdnd_aware_target(Window root, int root_x, int root_y, int *version_out) { Window parent = root; Window *children = NULL; unsigned int nchildren = 0; - + // Walk down the window tree to find the deepest window at these coordinates while (child != None) { target = child; @@ -3932,7 +3933,7 @@ find_xdnd_aware_target(Window root, int root_x, int root_y, int *version_out) { } if (child == None) break; } - + // Walk up the tree to find an XdndAware window while (target != None && target != root) { if (window_supports_xdnd(target, version_out)) { @@ -3941,7 +3942,7 @@ find_xdnd_aware_target(Window root, int root_x, int root_y, int *version_out) { int actual_format; unsigned long count, bytes_after; unsigned char *data = NULL; - + if (XGetWindowProperty(_glfw.x11.display, target, _glfw.x11.XdndProxy, 0, 1, False, XA_WINDOW, &actual_type, &actual_format, @@ -3959,7 +3960,7 @@ find_xdnd_aware_target(Window root, int root_x, int root_y, int *version_out) { } return target; } - + // Move to parent Window new_parent; if (XQueryTree(_glfw.x11.display, target, &parent, &new_parent, &children, &nchildren)) { @@ -3969,7 +3970,7 @@ find_xdnd_aware_target(Window root, int root_x, int root_y, int *version_out) { break; } } - + return None; } @@ -3978,14 +3979,14 @@ static void send_xdnd_enter(Window target, int version) { XEvent event; memset(&event, 0, sizeof(event)); - + event.xclient.type = ClientMessage; event.xclient.window = target; event.xclient.message_type = _glfw.x11.XdndEnter; event.xclient.format = 32; event.xclient.data.l[0] = _glfw.x11.drag.source_window; event.xclient.data.l[1] = (version << 24); - + // If we have more than 3 types, set the type list flag if (_glfw.x11.drag.type_count > 3) { event.xclient.data.l[1] |= 1; // More than 3 types, use property @@ -4001,7 +4002,7 @@ send_xdnd_enter(Window target, int version) { event.xclient.data.l[2 + i] = _glfw.x11.drag.type_atoms[i]; } } - + XSendEvent(_glfw.x11.display, target, False, NoEventMask, &event); XFlush(_glfw.x11.display); } @@ -4011,7 +4012,7 @@ static void send_xdnd_position(Window target, int root_x, int root_y, Time timestamp) { XEvent event; memset(&event, 0, sizeof(event)); - + event.xclient.type = ClientMessage; event.xclient.window = target; event.xclient.message_type = _glfw.x11.XdndPosition; @@ -4021,7 +4022,7 @@ send_xdnd_position(Window target, int root_x, int root_y, Time timestamp) { event.xclient.data.l[2] = (root_x << 16) | root_y; event.xclient.data.l[3] = timestamp; event.xclient.data.l[4] = _glfw.x11.drag.action_atom; - + XSendEvent(_glfw.x11.display, target, False, NoEventMask, &event); XFlush(_glfw.x11.display); _glfw.x11.drag.waiting_for_status = true; @@ -4032,13 +4033,13 @@ static void send_xdnd_leave(Window target) { XEvent event; memset(&event, 0, sizeof(event)); - + event.xclient.type = ClientMessage; event.xclient.window = target; event.xclient.message_type = _glfw.x11.XdndLeave; event.xclient.format = 32; event.xclient.data.l[0] = _glfw.x11.drag.source_window; - + XSendEvent(_glfw.x11.display, target, False, NoEventMask, &event); XFlush(_glfw.x11.display); } @@ -4048,7 +4049,7 @@ static void send_xdnd_drop(Window target, Time timestamp) { XEvent event; memset(&event, 0, sizeof(event)); - + event.xclient.type = ClientMessage; event.xclient.window = target; event.xclient.message_type = _glfw.x11.XdndDrop; @@ -4056,7 +4057,7 @@ send_xdnd_drop(Window target, Time timestamp) { event.xclient.data.l[0] = _glfw.x11.drag.source_window; event.xclient.data.l[1] = 0; // Reserved event.xclient.data.l[2] = timestamp; - + XSendEvent(_glfw.x11.display, target, False, NoEventMask, &event); XFlush(_glfw.x11.display); } @@ -4072,7 +4073,7 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { XSetWindowAttributes attrs; attrs.override_redirect = True; attrs.background_pixel = 0; - + _glfw.x11.drag.thumbnail_window = XCreateWindow( _glfw.x11.display, _glfw.x11.root, @@ -4085,7 +4086,7 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { CWOverrideRedirect | CWBackPixel, &attrs ); - + if (!_glfw.x11.drag.thumbnail_window) { return false; } @@ -4098,7 +4099,7 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { thumbnail->height, DefaultDepth(_glfw.x11.display, _glfw.x11.screen) ); - + if (!_glfw.x11.drag.thumbnail_pixmap) { XDestroyWindow(_glfw.x11.display, _glfw.x11.drag.thumbnail_window); _glfw.x11.drag.thumbnail_window = None; @@ -4129,7 +4130,7 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { 32, // bitmap_pad 0 // bytes_per_line (auto-calculate) ); - + if (!ximage) { XFreeGC(_glfw.x11.display, _glfw.x11.drag.thumbnail_gc); XFreePixmap(_glfw.x11.display, _glfw.x11.drag.thumbnail_pixmap); @@ -4153,7 +4154,7 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { _glfw.x11.drag.thumbnail_gc = None; return false; } - + ximage->data = (char*)ximage_data; // Convert RGBA to the format expected by XImage @@ -4164,38 +4165,38 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { unsigned char g = src[i * 4 + 1]; unsigned char b = src[i * 4 + 2]; unsigned char a = src[i * 4 + 3]; - + // Premultiply alpha if (a < 255) { r = (r * a) / 255; g = (g * a) / 255; b = (b * a) / 255; } - + // Convert to X11 pixel format (typically BGRA on little-endian) if (ximage->byte_order == LSBFirst) { pixel = (a << 24) | (r << 16) | (g << 8) | b; } else { pixel = (b << 24) | (g << 16) | (r << 8) | a; } - + XPutPixel(ximage, i % thumbnail->width, i / thumbnail->width, pixel); } // Draw the image to the pixmap XPutImage(_glfw.x11.display, _glfw.x11.drag.thumbnail_pixmap, _glfw.x11.drag.thumbnail_gc, ximage, 0, 0, 0, 0, thumbnail->width, thumbnail->height); - + // Clean up XImage (including its data) XDestroyImage(ximage); // This also frees ximage_data // Set the pixmap as the window's background XSetWindowBackgroundPixmap(_glfw.x11.display, _glfw.x11.drag.thumbnail_window, _glfw.x11.drag.thumbnail_pixmap); - + // Map the window to make it visible XMapRaised(_glfw.x11.display, _glfw.x11.drag.thumbnail_window); XFlush(_glfw.x11.display); - + return true; } @@ -4203,32 +4204,32 @@ create_drag_thumbnail(const GLFWimage* thumbnail, int x, int y) { static void handle_drag_motion(int root_x, int root_y, Time timestamp) { if (!_glfw.x11.drag.active) return; - + // Move thumbnail window to follow cursor if (_glfw.x11.drag.thumbnail_window != None) { XMoveWindow(_glfw.x11.display, _glfw.x11.drag.thumbnail_window, root_x + 10, root_y + 10); } - + int version = _GLFW_XDND_VERSION; Window new_target = find_xdnd_aware_target(_glfw.x11.root, root_x, root_y, &version); - + if (new_target != _glfw.x11.drag.current_target) { // Send leave to old target if (_glfw.x11.drag.current_target != None) { send_xdnd_leave(_glfw.x11.drag.current_target); } - + _glfw.x11.drag.current_target = new_target; _glfw.x11.drag.waiting_for_status = false; _glfw.x11.drag.accepted = false; - + // Send enter to new target if (new_target != None) { _glfw.x11.drag.xdnd_version = version; send_xdnd_enter(new_target, version); } } - + // Send position to current target if (_glfw.x11.drag.current_target != None && !_glfw.x11.drag.waiting_for_status) { send_xdnd_position(_glfw.x11.drag.current_target, root_x, root_y, timestamp); @@ -4239,7 +4240,7 @@ handle_drag_motion(int root_x, int root_y, Time timestamp) { static void handle_drag_button_release(Time timestamp) { if (!_glfw.x11.drag.active) return; - + if (_glfw.x11.drag.current_target != None && _glfw.x11.drag.accepted) { send_xdnd_drop(_glfw.x11.drag.current_target, timestamp); } else { @@ -4258,10 +4259,10 @@ static void handle_xdnd_status(const XClientMessageEvent *event) { if (!_glfw.x11.drag.active) return; if (event->data.l[0] != (long)_glfw.x11.drag.current_target) return; - + _glfw.x11.drag.waiting_for_status = false; _glfw.x11.drag.accepted = (event->data.l[1] & 1) != 0; - + if (_glfw.x11.drag.accepted && event->data.l[4] != None) { _glfw.x11.drag.accepted_action = event->data.l[4]; } @@ -4272,12 +4273,12 @@ static void handle_xdnd_finished(const XClientMessageEvent *event) { if (!_glfw.x11.drag.active) return; if (event->data.l[0] != (long)_glfw.x11.drag.current_target) return; - + _GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id); if (window) { bool accepted = (event->data.l[1] & 1) != 0; GLFWDragOperationType action = 0; - + if (accepted && event->data.l[2] != None) { Atom action_atom = event->data.l[2]; if (action_atom == _glfw.x11.XdndActionCopy) { @@ -4288,11 +4289,11 @@ handle_xdnd_finished(const XClientMessageEvent *event) { action = GLFW_DRAG_OPERATION_GENERIC; } } - + GLFWDragEvent ev = {.type = GLFW_DRAG_FINSHED, .action = action}; _glfwInputDragSourceRequest(window, &ev); } - + _glfwFreeDragSourceData(); } @@ -4301,26 +4302,26 @@ static bool add_pending_request(const char *mime_type, Window requestor, Atom property, Atom target) { if (_glfw.x11.drag.pending_count >= _glfw.x11.drag.pending_capacity) { size_t new_capacity = _glfw.x11.drag.pending_capacity == 0 ? 8 : _glfw.x11.drag.pending_capacity * 2; - void *new_ptr = realloc(_glfw.x11.drag.pending_requests, + void *new_ptr = realloc(_glfw.x11.drag.pending_requests, new_capacity * sizeof(_glfw.x11.drag.pending_requests[0])); if (!new_ptr) return false; _glfw.x11.drag.pending_requests = new_ptr; _glfw.x11.drag.pending_capacity = new_capacity; } - + size_t idx = _glfw.x11.drag.pending_count++; _glfw.x11.drag.pending_requests[idx].mime_type = _glfw_strdup(mime_type); _glfw.x11.drag.pending_requests[idx].requestor = requestor; _glfw.x11.drag.pending_requests[idx].property = property; _glfw.x11.drag.pending_requests[idx].target = target; _glfw.x11.drag.pending_requests[idx].inflight = true; - + return _glfw.x11.drag.pending_requests[idx].mime_type != NULL; } // Send drag data via XChangeProperty static void -send_drag_data(const char *mime_type, const char *data, size_t data_sz, +send_drag_data(const char *mime_type, const char *data, size_t data_sz, Window requestor, Atom property, Atom target) { (void)mime_type; // Parameter kept for consistency with other platforms if (data && data_sz > 0) { @@ -4341,20 +4342,20 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) { if (_glfw.x11.drag.active) { _glfwFreeDragSourceData(); } - + // Convert MIME types to atoms _glfw.x11.drag.type_count = _glfw.drag.item_count; _glfw.x11.drag.type_atoms = calloc(_glfw.drag.item_count, sizeof(Atom)); if (!_glfw.x11.drag.type_atoms) { return ENOMEM; } - + for (size_t i = 0; i < _glfw.drag.item_count; i++) { - _glfw.x11.drag.type_atoms[i] = XInternAtom(_glfw.x11.display, - _glfw.drag.items[i].mime_type, + _glfw.x11.drag.type_atoms[i] = XInternAtom(_glfw.x11.display, + _glfw.drag.items[i].mime_type, False); } - + // Determine action atom based on operations if (_glfw.drag.operations & GLFW_DRAG_OPERATION_COPY) { _glfw.x11.drag.action_atom = _glfw.x11.XdndActionCopy; @@ -4363,18 +4364,18 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) { } else { _glfw.x11.drag.action_atom = _glfw.x11.XdndActionCopy; } - + _glfw.x11.drag.source_window = window->x11.handle; _glfw.x11.drag.active = true; _glfw.x11.drag.current_target = None; _glfw.x11.drag.waiting_for_status = false; _glfw.x11.drag.accepted = false; - + // Initialize thumbnail fields _glfw.x11.drag.thumbnail_window = None; _glfw.x11.drag.thumbnail_pixmap = None; _glfw.x11.drag.thumbnail_gc = None; - + // Get current cursor position for thumbnail placement Window root_return, child_return; int root_x, root_y, win_x, win_y; @@ -4382,7 +4383,7 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) { XQueryPointer(_glfw.x11.display, _glfw.x11.root, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return); - + // Create thumbnail window if thumbnail is provided if (!create_drag_thumbnail(thumbnail, root_x + 10, root_y + 10)) { // Thumbnail creation failed, but continue with drag operation @@ -4390,13 +4391,13 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) { _glfw.x11.drag.thumbnail_pixmap = None; _glfw.x11.drag.thumbnail_gc = None; } - + // Grab the pointer to track drag motion int result = XGrabPointer(_glfw.x11.display, window->x11.handle, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - + if (result != GrabSuccess) { free(_glfw.x11.drag.type_atoms); _glfw.x11.drag.type_atoms = NULL; @@ -4417,11 +4418,11 @@ _glfwPlatformStartDrag(_GLFWwindow* window, const GLFWimage* thumbnail) { } return EIO; } - + // Set ourselves as the XdndSelection owner - XSetSelectionOwner(_glfw.x11.display, _glfw.x11.XdndSelection, + XSetSelectionOwner(_glfw.x11.display, _glfw.x11.XdndSelection, window->x11.handle, CurrentTime); - + return 0; } @@ -4432,14 +4433,14 @@ _glfwPlatformFreeDragSourceData(void) { if (_glfw.x11.drag.current_target != None) { send_xdnd_leave(_glfw.x11.drag.current_target); } - + // Ungrab the pointer XUngrabPointer(_glfw.x11.display, CurrentTime); - + _glfw.x11.drag.active = false; _glfw.x11.drag.current_target = None; } - + // Clean up thumbnail resources if (_glfw.x11.drag.thumbnail_gc != None) { XFreeGC(_glfw.x11.display, _glfw.x11.drag.thumbnail_gc); @@ -4453,14 +4454,14 @@ _glfwPlatformFreeDragSourceData(void) { XDestroyWindow(_glfw.x11.display, _glfw.x11.drag.thumbnail_window); _glfw.x11.drag.thumbnail_window = None; } - + // Free type atoms if (_glfw.x11.drag.type_atoms) { free(_glfw.x11.drag.type_atoms); _glfw.x11.drag.type_atoms = NULL; } _glfw.x11.drag.type_count = 0; - + // Free pending requests if (_glfw.x11.drag.pending_requests) { for (size_t i = 0; i < _glfw.x11.drag.pending_count; i++) { @@ -4479,11 +4480,11 @@ _glfwPlatformDragDataReady(const char *mime_type) { for (size_t i = 0; i < _glfw.x11.drag.pending_count; i++) { if (_glfw.x11.drag.pending_requests[i].inflight && strcmp(_glfw.x11.drag.pending_requests[i].mime_type, mime_type) == 0) { - + // Get the drag event with data from the application _GLFWwindow *window = _glfwWindowForId(_glfw.drag.window_id); if (!window) return ENODEV; - + GLFWDragEvent ev = { .type = GLFW_DRAG_DATA_REQUEST, .mime_type = mime_type, @@ -4491,15 +4492,15 @@ _glfwPlatformDragDataReady(const char *mime_type) { .data_sz = 0, .err_num = 0 }; - + _glfwInputDragSourceRequest(window, &ev); - + // Send the data send_drag_data(mime_type, ev.data, ev.data_sz, _glfw.x11.drag.pending_requests[i].requestor, _glfw.x11.drag.pending_requests[i].property, _glfw.x11.drag.pending_requests[i].target); - + // Send SelectionNotify XEvent reply; memset(&reply, 0, sizeof(reply)); @@ -4510,16 +4511,16 @@ _glfwPlatformDragDataReady(const char *mime_type) { reply.xselection.target = _glfw.x11.drag.pending_requests[i].target; reply.xselection.property = _glfw.x11.drag.pending_requests[i].property; reply.xselection.time = CurrentTime; - - XSendEvent(_glfw.x11.display, + + XSendEvent(_glfw.x11.display, _glfw.x11.drag.pending_requests[i].requestor, False, 0, &reply); - + _glfw.x11.drag.pending_requests[i].inflight = false; break; } } - + return 0; } // }}} diff --git a/kitty/boss.py b/kitty/boss.py index cff420ccb..8dd799af2 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1940,7 +1940,7 @@ class Boss: set_tab_being_dragged() for tm in self.all_tab_managers: tm.on_tab_drop_move() - if not was_dropped: # detach tab into new OS Window + if was_dropped: # detach tab into new OS Window tab_id = int(tidb.decode()) if (tab := self.tab_for_id(tab_id)): self._move_tab_to(tab) diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index c4b260578..cacfe442c 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1119,6 +1119,7 @@ typedef enum { GLFW_DROP_ENTER, GLFW_DROP_MOVE, GLFW_DROP_LEAVE, GLFW_DROP_DROP, * @ingroup input */ typedef enum { + GLFW_DRAG_OPERATION_NONE = 0, // no operation, drop was not accepted /*! Move the dragged data to the destination. */ GLFW_DRAG_OPERATION_MOVE = 1, /*! Copy the dragged data to the destination. */ diff --git a/kitty/glfw.c b/kitty/glfw.c index 74c4b38c8..d615adba6 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -792,6 +792,13 @@ free_drag_source(void) { static void drag_source_callback(GLFWwindow *window UNUSED, GLFWDragEvent *ev) { +#define finish \ + call_boss(on_drag_source_finished, "OOsiO", \ + ds.was_dropped ? Py_True : Py_False, ds.was_canceled ? Py_True: Py_False, \ + ds.accepted_mime_type ? ds.accepted_mime_type : "", \ + ds.action, ds.drag_data ? ds.drag_data : Py_None); \ + free_drag_source(); + switch (ev->type) { case GLFW_DRAG_DATA_REQUEST: // we currently pre-provide all data so this should never happen if (ev->data_sz) { @@ -804,21 +811,20 @@ drag_source_callback(GLFWwindow *window UNUSED, GLFWDragEvent *ev) { free(ds.accepted_mime_type); ds.accepted_mime_type = ev->mime_type ? strdup(ev->mime_type) : NULL; break; - case GLFW_DRAG_ACTION_CHANGED: ds.action = ev->action; break; + case GLFW_DRAG_ACTION_CHANGED: + ds.action = ev->action; break; case GLFW_DRAG_DROPPED: ds.was_dropped = true; + if (ev->action == GLFW_DRAG_OPERATION_NONE) { finish } break; case GLFW_DRAG_CANCELLED: ds.was_canceled = true; /* fallthrough */ case GLFW_DRAG_FINSHED: - call_boss(on_drag_source_finished, "OOsiO", - ds.was_dropped ? Py_True : Py_False, ds.was_canceled ? Py_True: Py_False, - ds.accepted_mime_type ? ds.accepted_mime_type : "", - ds.action, ds.drag_data ? ds.drag_data : Py_None); - free_drag_source(); + finish break; } +#undef finish } #undef ds