decompose wl_backend.c: extract wl_clipboard.c

This commit is contained in:
Window Maker 2026-06-02 14:15:10 +02:00
parent 5fd0eda8d2
commit f6cf67cb39
4 changed files with 127 additions and 113 deletions

View File

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

View File

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

View File

@ -0,0 +1,121 @@
#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"
/* ------------------------------------------------------------------ */
/* 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;
}

View File

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