From a438713b9276cc1fae310f2f135632d7e2fe25c3 Mon Sep 17 00:00:00 2001 From: Ollie Date: Sat, 23 May 2026 19:07:54 +0200 Subject: [PATCH] WINGs/wview_wl: implement internal DnD for Wayland Implement wl_drag_begin as a simple internal drag-and-drop state machine for WINGs-to-WINGs drag operations (color wells, text widgets). On button press, waits for motion to confirm drag intent, then enters a drag loop tracking the cursor. On release, finds the view under the cursor and if it has drag destination procs + matching types, fetches data from the source and calls performDragOperation on the destination. This handles same-process DnD without needing wl_data_device protocol. --- WINGs/wview_wl.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index 6cadf8b..ec6cd13 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -555,7 +555,69 @@ static void wl_balloon_draw(void *vctx, W_View *view, int x, int y, static void wl_drag_begin(void *vctx, W_View *view, WMEvent *event) { - (void)vctx; (void)view; (void)event; + W_Screen *scr = (W_Screen *)vctx; + if (!view->dragSourceProcs || event->type != WME_BUTTON_PRESS) + return; + + /* Wait for motion to confirm drag */ + WMEvent ev; + WMMaskEvent(scr, ButtonMotionMask | ButtonReleaseMask, &ev); + if (ev.type != WME_MOTION) + return; + + if (view->dragSourceProcs->beganDrag) { + WMPoint pt = wmkpoint(ev.u.motion.x_root, ev.u.motion.y_root); + view->dragSourceProcs->beganDrag(view, &pt); + } + + /* Drag loop */ + W_View *destView = NULL; + Bool deposited = False; + int done = 0; + + while (!done) { + WMMaskEvent(scr, ButtonMotionMask | ButtonReleaseMask, &ev); + switch (ev.type) { + case WME_MOTION: + /* Find view under cursor */ + { + W_View *top = scr->rootView; + int mx = ev.u.motion.x_root; + int my = ev.u.motion.y_root; + destView = W_FindViewAtPoint(top, mx, my); + } + break; + + case WME_BUTTON_RELEASE: + if (destView && destView->dragDestinationProcs && + destView->droppableTypes && view->dragSourceProcs->dropDataTypes) { + WMArray *types = view->dragSourceProcs->dropDataTypes(view); + WMArray *dropData = WMCreateArray(WMGetArrayItemCount(types)); + int i; + for (i = 0; i < WMGetArrayItemCount(types); i++) { + char *type = WMGetFromArray(types, i); + WMData *data = view->dragSourceProcs->fetchDragData(view, type); + if (data) + WMAddToArray(dropData, data); + } + if (WMGetArrayItemCount(dropData) > 0 && + destView->dragDestinationProcs->performDragOperation) { + WMPoint pt = wmkpoint(ev.u.button.x_root, ev.u.button.y_root); + destView->dragDestinationProcs->performDragOperation( + destView, dropData, NULL, &pt); + deposited = True; + } + WMFreeArray(dropData); + } + done = 1; + break; + } + } + + if (view->dragSourceProcs->endedDrag) { + WMPoint pt = wmkpoint(ev.u.button.x_root, ev.u.button.y_root); + view->dragSourceProcs->endedDrag(view, &pt, deposited); + } } static void wl_flush(void *vctx)