dnd: cross-client motion/drop handler with MIME type routing

This commit is contained in:
Ollie 2026-05-28 20:29:26 +02:00
parent b278d6491d
commit adf79141b2
1 changed files with 80 additions and 2 deletions

View File

@ -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;
}