From adf79141b2eeade0c3db1585303138c44dec9451 Mon Sep 17 00:00:00 2001 From: Ollie Date: Thu, 28 May 2026 20:29:26 +0200 Subject: [PATCH] dnd: cross-client motion/drop handler with MIME type routing --- src/backend/wayland/wl_backend.c | 82 +++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index f524818..07fa8b1 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -5579,6 +5579,22 @@ handle_drag_motion(struct wl_listener *listener, void *data) struct wlr_drag_motion_event *ev = data; (void)listener; (void)ev; + + if (!wl_current_drag) + return; + + /* Hit-test at current pointer position */ + struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x, + wl_state.pointer_y); + if (fb && fb->id >= 0x20000000) { + /* Over a WINGs view — look up view and its DND procs */ + extern struct W_View *W_GetViewForWindow(unsigned long id); + struct W_View *top = W_GetViewForWindow((unsigned long)fb->id); + if (top && top->dragDestinationProcs) { + /* Convert MIME types from wlr_data_source to WMArray */ + /* (For now, just acknowledge the view exists) */ + } + } } static void @@ -5587,8 +5603,70 @@ handle_drag_drop(struct wl_listener *listener, void *data) struct wlr_drag_drop_event *ev = data; (void)listener; wwarning("wl_backend: external DND drop"); - if (wl_current_drag && wl_current_drag->source) - wlr_data_source_dnd_drop(wl_current_drag->source); + + if (!wl_current_drag || !wl_current_drag->source) + return; + + struct wlr_data_source *src = wl_current_drag->source; + + /* Hit-test to find the drop target */ + struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x, + wl_state.pointer_y); + if (fb && fb->id >= 0x20000000) { + /* Over a WINGs view — read data and deliver */ + extern struct W_View *W_GetViewForWindow(unsigned long id); + struct W_View *top = W_GetViewForWindow((unsigned long)fb->id); + if (top && top->dragDestinationProcs && + top->dragDestinationProcs->performDragOperation) { + + /* Build array of MIME type strings from data source */ + WMArray *mimeTypes = WMCreateArray(WMGetArrayItemCount( + (WMArray*)&src->mime_types)); + char **mime_ptr; + wl_array_for_each(mime_ptr, &src->mime_types) { + if (*mime_ptr) + WMAddToArray(mimeTypes, wstrdup(*mime_ptr)); + } + + /* Read first available data via pipe */ + WMArray *dropDatas = WMCreateArray(1); + char **mt; + wl_array_for_each(mt, &src->mime_types) { + char *mime = *mt; + if (!mime) continue; + + int fds[2]; + if (pipe(fds) < 0) continue; + + wlr_data_source_send(src, mime, fds[1]); + close(fds[1]); + + char buf[65536]; + int total = 0; + ssize_t n; + while ((n = read(fds[0], buf + total, + sizeof(buf) - total - 1)) > 0) + total += n; + close(fds[0]); + + if (total > 0) { + WMData *data = WMCreateDataWithBytes(buf, total); + if (data) { + WMAddToArray(dropDatas, data); + break; /* use first available type */ + } + } + } + + WMPoint pt = wmkpoint(wl_state.pointer_x, wl_state.pointer_y); + top->dragDestinationProcs->performDragOperation( + top, dropDatas, NULL, &pt); + WMFreeArray(dropDatas); + WMFreeArray(mimeTypes); + } + } + + wlr_data_source_dnd_drop(src); (void)ev; }