From e19562a07cec9437ec5fe54d065f34d33b0d41af Mon Sep 17 00:00:00 2001 From: Window Maker Date: Tue, 2 Jun 2026 14:22:24 +0200 Subject: [PATCH] decompose wl_backend.c: extract wl_dnd.c --- src/Makefile.am | 3 +- src/backend/wayland/wl_backend.c | 137 +--------------------------- src/backend/wayland/wl_dnd.c | 147 +++++++++++++++++++++++++++++++ src/backend/wayland/wl_types.h | 6 ++ 4 files changed, 156 insertions(+), 137 deletions(-) create mode 100644 src/backend/wayland/wl_dnd.c diff --git a/src/Makefile.am b/src/Makefile.am index f50433e..6617b13 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -180,7 +180,8 @@ wmaker_SOURCES += \ backend/wayland/wl_wings.c \ backend/wayland/wl_xdisplay.c \ backend/wayland/wl_stubs.c \ - backend/wayland/wl_clipboard.c + backend/wayland/wl_clipboard.c \ + backend/wayland/wl_dnd.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 9840072..b9aa5fc 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -305,7 +305,7 @@ static void handle_seat_request_cursor(struct wl_listener *listener, void *data) /* Phase 25: client clipboard selection request handler. */ static void handle_seat_request_set_selection(struct wl_listener *listener, void *data); /* Phase 25b: drag-and-drop request handler. */ -static void handle_seat_request_start_drag(struct wl_listener *listener, void *data); +void handle_seat_request_start_drag(struct wl_listener *listener, void *data); /* Phase 26: primary selection request handler. */ static void handle_seat_request_primary_selection(struct wl_listener *listener, void *data); /* Compositor-internal clipboard hooks for WINGs. */ @@ -3948,141 +3948,6 @@ handle_seat_request_set_selection(struct wl_listener *listener, void *data) wlr_seat_set_selection(wl_state.seat, ev->source, ev->serial); } -/* ------------------------------------------------------------------ */ -/* Phase 25b: DND request_start_drag — external client starts a drag */ -/* ------------------------------------------------------------------ */ - -/* Currently active external wlr_drag (NULL if none). */ -static struct wlr_drag *wl_current_drag = NULL; - -static void handle_drag_motion(struct wl_listener *listener, void *data); -static void handle_drag_drop(struct wl_listener *listener, void *data); -static void handle_drag_destroy(struct wl_listener *listener, void *data); - -static struct wl_listener wl_drag_motion_listener = {.notify = handle_drag_motion}; -static struct wl_listener wl_drag_drop_listener = {.notify = handle_drag_drop}; -static struct wl_listener wl_drag_destroy_listener = {.notify = handle_drag_destroy}; - -static void -handle_seat_request_start_drag(struct wl_listener *listener, void *data) -{ - (void)listener; - struct wlr_seat_request_start_drag_event *ev = data; - if (!wl_state.seat) - return; - wwarning("wl_backend: external client started DND"); - wlr_seat_start_pointer_drag(wl_state.seat, ev->drag, ev->serial); - wl_current_drag = ev->drag; - wl_signal_add(&ev->drag->events.motion, &wl_drag_motion_listener); - wl_signal_add(&ev->drag->events.drop, &wl_drag_drop_listener); - wl_signal_add(&ev->drag->events.destroy, &wl_drag_destroy_listener); -} - -static void -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 -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) - 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; -} - -static void -handle_drag_destroy(struct wl_listener *listener, void *data) -{ - (void)listener; - (void)data; - wwarning("wl_backend: external DND finished"); - wl_current_drag = NULL; -} /* * Phase 26: seat request_set_primary_selection — client writes to the diff --git a/src/backend/wayland/wl_dnd.c b/src/backend/wayland/wl_dnd.c new file mode 100644 index 0000000..b581b03 --- /dev/null +++ b/src/backend/wayland/wl_dnd.c @@ -0,0 +1,147 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "wl_types.h" +#include + +/* ------------------------------------------------------------------ */ +/* Phase 25b: DND request_start_drag — external client starts a drag */ +/* ------------------------------------------------------------------ */ + +/* Currently active external wlr_drag (NULL if none). */ +struct wlr_drag *wl_current_drag = NULL; + +void handle_drag_motion(struct wl_listener *listener, void *data); +void handle_drag_drop(struct wl_listener *listener, void *data); +void handle_drag_destroy(struct wl_listener *listener, void *data); + +struct wl_listener wl_drag_motion_listener = {.notify = handle_drag_motion}; +struct wl_listener wl_drag_drop_listener = {.notify = handle_drag_drop}; +struct wl_listener wl_drag_destroy_listener = {.notify = handle_drag_destroy}; + +void +handle_seat_request_start_drag(struct wl_listener *listener, void *data) +{ + (void)listener; + struct wlr_seat_request_start_drag_event *ev = data; + if (!wl_state.seat) + return; + wwarning("wl_backend: external client started DND"); + wlr_seat_start_pointer_drag(wl_state.seat, ev->drag, ev->serial); + wl_current_drag = ev->drag; + wl_signal_add(&ev->drag->events.motion, &wl_drag_motion_listener); + wl_signal_add(&ev->drag->events.drop, &wl_drag_drop_listener); + wl_signal_add(&ev->drag->events.destroy, &wl_drag_destroy_listener); +} + +void +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) */ + } + } +} + +void +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) + 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; +} + +void +handle_drag_destroy(struct wl_listener *listener, void *data) +{ + (void)listener; + (void)data; + wwarning("wl_backend: external DND finished"); + wl_current_drag = NULL; +} diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index 9323d0f..2f80786 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -602,3 +602,9 @@ void wl_pointer_warp_to(int x, int y); int wl_pointer_grab(WNativeWindow grab_win, WNativeWindow confine_to, unsigned int event_mask, int cursor_id, int owner_events, unsigned long timestamp); void wl_clipboard_store_to_seat(const char *text, int len); char *wl_clipboard_fetch_from_seat(int *len_out); + +/* DND module (extracted to wl_dnd.c) */ +void handle_seat_request_start_drag(struct wl_listener *listener, void *data); +void handle_drag_motion(struct wl_listener *listener, void *data); +void handle_drag_drop(struct wl_listener *listener, void *data); +void handle_drag_destroy(struct wl_listener *listener, void *data);