From f6cf67cb39760a72a347835f3d44b6dcb59155cf Mon Sep 17 00:00:00 2001 From: Window Maker Date: Tue, 2 Jun 2026 14:15:10 +0200 Subject: [PATCH] decompose wl_backend.c: extract wl_clipboard.c --- src/Makefile.am | 3 +- src/backend/wayland/wl_backend.c | 114 +-------------------------- src/backend/wayland/wl_clipboard.c | 121 +++++++++++++++++++++++++++++ src/backend/wayland/wl_types.h | 2 + 4 files changed, 127 insertions(+), 113 deletions(-) create mode 100644 src/backend/wayland/wl_clipboard.c diff --git a/src/Makefile.am b/src/Makefile.am index a453bc4..f50433e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -179,7 +179,8 @@ wmaker_SOURCES += \ backend/wayland/wl_shm.c \ backend/wayland/wl_wings.c \ backend/wayland/wl_xdisplay.c \ - backend/wayland/wl_stubs.c + backend/wayland/wl_stubs.c \ + backend/wayland/wl_clipboard.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 40ca379..9840072 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -309,8 +309,8 @@ static void handle_seat_request_start_drag(struct wl_listener *listener, void *d /* 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. */ -static void wl_clipboard_store_to_seat(const char *text, int len); -static char *wl_clipboard_fetch_from_seat(int *len_out); +void wl_clipboard_store_to_seat(const char *text, int len); +char *wl_clipboard_fetch_from_seat(int *len_out); /* Drag icon overlay for WINGs compositor-internal DND. */ static void wl_drag_icon_show(struct W_View *view, int x, int y); @@ -3821,116 +3821,6 @@ handle_seat_request_cursor(struct wl_listener *listener, void *data) ev->hotspot_x, ev->hotspot_y); } -/* ------------------------------------------------------------------ */ -/* Compositor-internal clipboard (WINGs ↔ Wayland clients) */ -/* ------------------------------------------------------------------ */ - -static char *wl_seat_clipboard_text = NULL; -static int wl_seat_clipboard_len = 0; -static struct wlr_data_source wl_seat_clipboard_source; - -static void wl_clipboard_source_send(struct wlr_data_source *source, - const char *mime_type, int32_t fd) -{ - (void)source; (void)mime_type; - if (wl_seat_clipboard_text && wl_seat_clipboard_len > 0) - write(fd, wl_seat_clipboard_text, wl_seat_clipboard_len); - close(fd); -} - -static void wl_clipboard_source_destroy(struct wlr_data_source *source) -{ - (void)source; - /* Don't free — static lifetime, text freed separately */ -} - -static const struct wlr_data_source_impl wl_clipboard_source_impl = { - .send = wl_clipboard_source_send, - .destroy = wl_clipboard_source_destroy, -}; - -static void wl_clipboard_store_to_seat(const char *text, int len) -{ - if (!wl_state.seat || !text || len <= 0) - return; - - /* If we already own the seat selection, just update the buffer - * instead of re-initializing the source (which can corrupt - * wlroots' internal state for subsequent paste requests). */ - if (wl_state.seat->selection_source == &wl_seat_clipboard_source) { - if (wl_seat_clipboard_text) - free(wl_seat_clipboard_text); - wl_seat_clipboard_text = malloc(len + 1); - memcpy(wl_seat_clipboard_text, text, len); - wl_seat_clipboard_text[len] = '\0'; - wl_seat_clipboard_len = len; - return; - } - - if (wl_seat_clipboard_text) - free(wl_seat_clipboard_text); - wl_seat_clipboard_text = malloc(len + 1); - memcpy(wl_seat_clipboard_text, text, len); - wl_seat_clipboard_text[len] = '\0'; - wl_seat_clipboard_len = len; - - wlr_data_source_init(&wl_seat_clipboard_source, &wl_clipboard_source_impl); - wl_array_release(&wl_seat_clipboard_source.mime_types); - wl_array_init(&wl_seat_clipboard_source.mime_types); - char **mime = wl_array_add(&wl_seat_clipboard_source.mime_types, sizeof(char *)); - *mime = strdup("text/plain;charset=utf-8"); - mime = wl_array_add(&wl_seat_clipboard_source.mime_types, sizeof(char *)); - *mime = strdup("text/plain"); - - wlr_seat_set_selection(wl_state.seat, &wl_seat_clipboard_source, - wl_display_next_serial(wl_state.display)); -} - -static char *wl_clipboard_fetch_from_seat(int *len_out) -{ - if (!wl_state.seat || !wl_state.seat->selection_source) - return NULL; - - /* If we own the selection, return our buffer directly */ - if (wl_state.seat->selection_source == &wl_seat_clipboard_source) { - if (wl_seat_clipboard_text && wl_seat_clipboard_len > 0) { - char *copy = malloc(wl_seat_clipboard_len + 1); - memcpy(copy, wl_seat_clipboard_text, wl_seat_clipboard_len); - copy[wl_seat_clipboard_len] = '\0'; - if (len_out) - *len_out = wl_seat_clipboard_len; - return copy; - } - return NULL; - } - - /* Foreign source — read via pipe */ - int fds[2]; - if (pipe(fds) < 0) - return NULL; - - wlr_data_source_send(wl_state.seat->selection_source, - "text/plain;charset=utf-8", fds[1]); - close(fds[1]); - - char buf[4096]; - 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) - return NULL; - - buf[total] = '\0'; - char *result = malloc(total + 1); - memcpy(result, buf, total + 1); - if (len_out) - *len_out = total; - return result; -} - /* ------------------------------------------------------------------ */ /* Drag icon overlay for WINGs compositor-internal DND */ /* ------------------------------------------------------------------ */ diff --git a/src/backend/wayland/wl_clipboard.c b/src/backend/wayland/wl_clipboard.c new file mode 100644 index 0000000..49f398d --- /dev/null +++ b/src/backend/wayland/wl_clipboard.c @@ -0,0 +1,121 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "wl_types.h" + +/* ------------------------------------------------------------------ */ +/* Compositor-internal clipboard (WINGs ↔ Wayland clients) */ +/* ------------------------------------------------------------------ */ + +char *wl_seat_clipboard_text = NULL; +int wl_seat_clipboard_len = 0; +struct wlr_data_source wl_seat_clipboard_source; + +void wl_clipboard_source_send(struct wlr_data_source *source, + const char *mime_type, int32_t fd) +{ + (void)source; (void)mime_type; + if (wl_seat_clipboard_text && wl_seat_clipboard_len > 0) + write(fd, wl_seat_clipboard_text, wl_seat_clipboard_len); + close(fd); +} + +void wl_clipboard_source_destroy(struct wlr_data_source *source) +{ + (void)source; + /* Don't free — static lifetime, text freed separately */ +} + +const struct wlr_data_source_impl wl_clipboard_source_impl = { + .send = wl_clipboard_source_send, + .destroy = wl_clipboard_source_destroy, +}; + +void wl_clipboard_store_to_seat(const char *text, int len) +{ + if (!wl_state.seat || !text || len <= 0) + return; + + /* If we already own the seat selection, just update the buffer + * instead of re-initializing the source (which can corrupt + * wlroots' internal state for subsequent paste requests). */ + if (wl_state.seat->selection_source == &wl_seat_clipboard_source) { + if (wl_seat_clipboard_text) + free(wl_seat_clipboard_text); + wl_seat_clipboard_text = malloc(len + 1); + memcpy(wl_seat_clipboard_text, text, len); + wl_seat_clipboard_text[len] = '\0'; + wl_seat_clipboard_len = len; + return; + } + + if (wl_seat_clipboard_text) + free(wl_seat_clipboard_text); + wl_seat_clipboard_text = malloc(len + 1); + memcpy(wl_seat_clipboard_text, text, len); + wl_seat_clipboard_text[len] = '\0'; + wl_seat_clipboard_len = len; + + wlr_data_source_init(&wl_seat_clipboard_source, &wl_clipboard_source_impl); + wl_array_release(&wl_seat_clipboard_source.mime_types); + wl_array_init(&wl_seat_clipboard_source.mime_types); + char **mime = wl_array_add(&wl_seat_clipboard_source.mime_types, sizeof(char *)); + *mime = strdup("text/plain;charset=utf-8"); + mime = wl_array_add(&wl_seat_clipboard_source.mime_types, sizeof(char *)); + *mime = strdup("text/plain"); + + wlr_seat_set_selection(wl_state.seat, &wl_seat_clipboard_source, + wl_display_next_serial(wl_state.display)); +} + +char *wl_clipboard_fetch_from_seat(int *len_out) +{ + if (!wl_state.seat || !wl_state.seat->selection_source) + return NULL; + + /* If we own the selection, return our buffer directly */ + if (wl_state.seat->selection_source == &wl_seat_clipboard_source) { + if (wl_seat_clipboard_text && wl_seat_clipboard_len > 0) { + char *copy = malloc(wl_seat_clipboard_len + 1); + memcpy(copy, wl_seat_clipboard_text, wl_seat_clipboard_len); + copy[wl_seat_clipboard_len] = '\0'; + if (len_out) + *len_out = wl_seat_clipboard_len; + return copy; + } + return NULL; + } + + /* Foreign source — read via pipe */ + int fds[2]; + if (pipe(fds) < 0) + return NULL; + + wlr_data_source_send(wl_state.seat->selection_source, + "text/plain;charset=utf-8", fds[1]); + close(fds[1]); + + char buf[4096]; + 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) + return NULL; + + buf[total] = '\0'; + char *result = malloc(total + 1); + memcpy(result, buf, total + 1); + if (len_out) + *len_out = total; + return result; +} + diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index d25ec32..9323d0f 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -600,3 +600,5 @@ WScreen *wl_noop_screen_for_window(WNativeWindow window); unsigned long wl_noop_window_get_event_mask(WNativeWindow window); 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);