decompose wl_backend.c: extract wl_dnd.c
This commit is contained in:
parent
f6cf67cb39
commit
e19562a07c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue