From 3acf2f6b2bb6ba0fa350a2d7616d14489f792b37 Mon Sep 17 00:00:00 2001 From: Ollie Date: Sat, 23 May 2026 16:37:58 +0200 Subject: [PATCH] WINGs: implement Wayland selection fetch (middle-click paste) Add selection_fetch vtable slot for synchronous selection retrieval. On Wayland, WMRequestSelection uses this to fetch clipboard/primary selection data directly (via W_ClipboardFetchFn -> seat pipe read) and calls the callback immediately. On X11, the async path (selection_request -> SelectionNotify event) is unchanged. This makes middle-click paste work in WINGs text widgets on Wayland. --- WINGs/WINGs/WINGsP.h.in | 1 + WINGs/selection.c | 14 ++++++++++++++ WINGs/wview_wl.c | 12 ++++++++++++ WINGs/wview_x11.c | 1 + 4 files changed, 28 insertions(+) diff --git a/WINGs/WINGs/WINGsP.h.in b/WINGs/WINGs/WINGsP.h.in index f883da6..361851b 100644 --- a/WINGs/WINGs/WINGsP.h.in +++ b/WINGs/WINGs/WINGsP.h.in @@ -621,6 +621,7 @@ typedef struct W_ViewBackend { Bool (*selection_acquire)(void *vctx, struct W_View *view, Atom selection, Time timestamp); void (*selection_release)(void *vctx, struct W_View *view, Atom selection); Bool (*selection_request)(void *vctx, struct W_View *view, Atom selection, Atom target, Time timestamp); + char *(*selection_fetch)(void *vctx, Atom selection, int *len_out); /* Platform-specific post-init (e.g. X11 atoms, IM setup) */ void (*platform_init)(struct W_Screen *scr); diff --git a/WINGs/selection.c b/WINGs/selection.c index c8f3fbc..5aa3366 100644 --- a/WINGs/selection.c +++ b/WINGs/selection.c @@ -362,6 +362,20 @@ WMRequestSelection(WMView * view, Atom selection, Atom target, Time timestamp, SelectionCallback *handler; const W_ViewBackend *vb = view->screen->viewBackend; + + /* Synchronous path (Wayland): fetch data directly and call callback */ + if (vb->selection_fetch) { + int len = 0; + char *text = vb->selection_fetch(view->screen->viewBackendCtx, selection, &len); + if (!text) + return False; + WMData *data = WMCreateDataWithBytesNoCopy(text, len, wfree); + (*callback)(view, selection, target, timestamp, cdata, data); + WMReleaseData(data); + return True; + } + + /* Async path (X11): initiate conversion, callback fires on SelectionNotify */ if (!vb->selection_request || !vb->selection_request(view->screen->viewBackendCtx, view, selection, target, timestamp)) return False; diff --git a/WINGs/wview_wl.c b/WINGs/wview_wl.c index 2492c38..6cadf8b 100644 --- a/WINGs/wview_wl.c +++ b/WINGs/wview_wl.c @@ -483,6 +483,17 @@ static void wl_selection_release(void *vctx, W_View *view, Atom selection) (void)vctx; (void)view; (void)selection; } +static char *wl_selection_fetch(void *vctx, Atom selection, int *len_out) +{ + (void)vctx; (void)selection; + /* Use the clipboard fetch path (reads from seat selection via pipe) */ + if (W_ClipboardFetchFn) + return W_ClipboardFetchFn(len_out); + if (len_out) + *len_out = 0; + return NULL; +} + static char *wl_clipboard_buf = NULL; static int wl_clipboard_len = 0; @@ -605,6 +616,7 @@ const W_ViewBackend W_ViewBackendWL = { .selection_acquire = wl_selection_acquire, .selection_release = wl_selection_release, .selection_request = NULL, + .selection_fetch = wl_selection_fetch, .platform_init = NULL, .flush = wl_flush, .clipboard_store = wl_clipboard_store, diff --git a/WINGs/wview_x11.c b/WINGs/wview_x11.c index bf9187a..19760a7 100644 --- a/WINGs/wview_x11.c +++ b/WINGs/wview_x11.c @@ -564,6 +564,7 @@ const W_ViewBackend W_ViewBackendX11 = { .selection_acquire = x11_selection_acquire, .selection_release = x11_selection_release, .selection_request = x11_selection_request, + .selection_fetch = NULL, .platform_init = W_X11PlatformInit, .flush = x11_flush, .clipboard_store = x11_clipboard_store,