decompose wl_backend.c: extract wl_dnd.c

This commit is contained in:
Window Maker 2026-06-02 14:22:24 +02:00
parent f6cf67cb39
commit e19562a07c
4 changed files with 156 additions and 137 deletions

View File

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

View File

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

View File

@ -0,0 +1,147 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_data_device.h>
#include "wl_types.h"
#include <WINGs/WINGsP.h>
/* ------------------------------------------------------------------ */
/* 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;
}

View File

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