From 4bdbfffb78522aafc29cb39ab2066da8b7f0c82e Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 14 Sep 2026 16:45:58 -0700 Subject: [PATCH] xdnd code that i can't really test but i think it might work? --- include/Mw/LowLevel/X11.h | 2 +- src/backend/x11.c | 90 ++++++++++++++++++++++++++++++--------- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/include/Mw/LowLevel/X11.h b/include/Mw/LowLevel/X11.h index 96f49833..9663097c 100644 --- a/include/Mw/LowLevel/X11.h +++ b/include/Mw/LowLevel/X11.h @@ -53,7 +53,7 @@ struct _MwLLX11 { Atom xdnd_aware; int xdnd_source; unsigned char xdnd_version; - int format; + int xdnd_format; XIM xim; XIC xic; diff --git a/src/backend/x11.c b/src/backend/x11.c index 295c5145..c6db2b84 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -451,8 +451,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->x11.xdnd_text_plain = XInternAtom(r->x11.display, "text/plain", False); r->x11.xdnd_aware = XInternAtom(r->x11.display, "XdndAware", False); r->x11.xdnd_version = 5; - r->x11.format = None; - XChangeProperty(r->x11.display, r->x11.window, r->x11.xdnd_aware, 4, 32, PropModeReplace, &r->x11.xdnd_version, 1); + r->x11.xdnd_format = None; r->x11.clipboard_pending = 0; @@ -797,20 +796,17 @@ static void MwLLNextEventImpl(MwLL handle) { if( ev.xclient.message_type == handle->x11.xdnd_enter || - ev.xclient.message_type == handle->x11.xdnd_selection || + ev.xclient.message_type == handle->x11.xdnd_position || ev.xclient.message_type == handle->x11.xdnd_drop) { char* name = XGetAtomName(handle->x11.display, ev.xclient.message_type); - printf("%s\n", name); - if(ev.xclient.message_type == handle->x11.xdnd_enter) { - Bool list = ev.xclient.data.l[1] & 1; - int version = ev.xclient.data.l[1] >> 24; - unsigned long count = 0; - unsigned char* formats = NULL; + Bool list = ev.xclient.data.l[1] & 1; + int version = ev.xclient.data.l[1] >> 24; + unsigned long count = 0; + unsigned char* formats = NULL; + unsigned long i; handle->x11.xdnd_source = ev.xclient.data.l[0]; - - unsigned long i; if(list) { Atom actualType; int32_t actualFormat; @@ -841,7 +837,8 @@ static void MwLLNextEventImpl(MwLL handle) { for(i = 0; i < count; i++) { if(formats[i] == handle->x11.xdnd_text_uri_list || formats[i] == handle->x11.xdnd_text_plain) { - handle->x11.format = formats[i]; + handle->x11.xdnd_format = formats[i]; + printf("format %d\n", handle->x11.xdnd_format); break; } } @@ -850,20 +847,30 @@ static void MwLLNextEventImpl(MwLL handle) { XFree(formats); } } - if(ev.xclient.message_type == handle->x11.xdnd_selection && handle->x11.xdnd_version >= 5) { + if(ev.xclient.message_type == handle->x11.xdnd_position && handle->x11.xdnd_version >= 5) { XEvent reply; reply.xclient.message_type = handle->x11.xdnd_status; - if(handle->x11.format) { + if(handle->x11.xdnd_format) { reply.xclient.data.l[1] = 1; - if(handle->x11.xdnd_version >= 2) - reply.xclient.data.l[4] = handle->x11.xdnd_action_copy; + if(handle->x11.xdnd_version >= 2) reply.xclient.data.l[4] = handle->x11.xdnd_action_copy; } XSendEvent(handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply); XFlush(handle->x11.display); } if(ev.xclient.message_type == handle->x11.xdnd_drop && handle->x11.xdnd_version >= 5) { - printf("whar\n"); + Time time = CurrentTime; + if(handle->x11.xdnd_version >= 1) + time = ev.xclient.data.l[2]; + + if(handle->x11.xdnd_format) { + XConvertSelection((Display*)handle->x11.display, + handle->x11.xdnd_selection, + handle->x11.xdnd_format, + handle->x11.xdnd_selection, + (Window)handle->x11.window, + time); + } } XFree(name); @@ -973,7 +980,51 @@ static void MwLLNextEventImpl(MwLL handle) { { handle->x11.clipboard_pending = 0; - if(ev.xselection.property != None) { + if(ev.xselection.property == handle->x11.xdnd_selection) { + XEvent reply; + char* data; + unsigned long result; + Atom actualType; + int32_t actualFormat; + unsigned long bytesAfter; + + XGetWindowProperty(handle->x11.display, + ev.xselection.requestor, ev.xselection.property, + 0, LONG_MAX, False, ev.xselection.target, + &actualType, &actualFormat, &result, &bytesAfter, + (unsigned char**)&data); + + if(result == 0) + break; + + /* !! untested lmao !! */ + printf("File(s) dropped: %s\n", data); + if(strstr(data, "\n")) { + char* data_ptr = data; + while(data_ptr) { + if(strstr(data_ptr, "file://")) { + MwLLDispatch(handle, drag_and_drop, data_ptr + sizeof("file://") - 1); + } else { + MwLLDispatch(handle, drag_and_drop, data_ptr); + } + data_ptr = strstr(data, "\n"); + } + } else { + MwLLDispatch(handle, drag_and_drop, data); + } + + if(data) + XFree(data); + + if(handle->x11.xdnd_version >= 2) { + reply.xclient.message_type = handle->x11.xdnd_finished; + reply.xclient.data.l[1] = result; + reply.xclient.data.l[2] = handle->x11.xdnd_action_copy; + + XSendEvent((Display*)handle->x11.display, handle->x11.xdnd_source, False, NoEventMask, &reply); + XFlush((Display*)handle->x11.display); + } + } else if(ev.xselection.property != None) { Atom type; int format; unsigned long nitems, after, size; @@ -1010,7 +1061,6 @@ static void MwLLNextEventImpl(MwLL handle) { free(buf); } } - XDeleteProperty(handle->x11.display, handle->x11.window, handle->x11.selection); } } break; @@ -1492,7 +1542,7 @@ static void MwLLGetScreenSizeImpl(MwLL handle, MwRect* rect) { } static void MwLLSetupDragAndDropImpl(MwLL handle) { - (void)handle; + XChangeProperty(handle->x11.display, handle->x11.window, handle->x11.xdnd_aware, 4, 32, PropModeReplace, &handle->x11.xdnd_version, 1); } static void MwLLBeginStateChangeImpl(MwLL handle) {