From ac5b9bc4ee560e6280044803aee5f651d2e39048 Mon Sep 17 00:00:00 2001
From: DS <[EMAIL REDACTED]>
Date: Wed, 14 Sep 2022 18:28:35 +0200
Subject: [PATCH] Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
- Use c,v,d,f to get and set the clipboard and primary selection.
- Mark text and middle-click also in other applications.
- For wayland under x:
$ mutter --wayland --no-x11 --nested
$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>
include/SDL_clipboard.h | 46 +++
include/SDL_events.h | 2 ±
src/dynapi/SDL2.exports | 3 +
src/dynapi/SDL_dynapi_overrides.h | 3 +
src/dynapi/SDL_dynapi_procs.h | 3 +
src/video/SDL_clipboard.c | 64 ++++
src/video/SDL_sysvideo.h | 8 ±
src/video/wayland/SDL_waylandclipboard.c | 121 ++++±
src/video/wayland/SDL_waylandclipboard.h | 3 +
src/video/wayland/SDL_waylanddatamanager.c | 343 ++++++++++++++±–
src/video/wayland/SDL_waylanddatamanager.h | 63 ++±
src/video/wayland/SDL_waylandevents.c | 154 ++++++±
src/video/wayland/SDL_waylandevents_c.h | 2 +
src/video/wayland/SDL_waylandvideo.c | 13 ±
src/video/wayland/SDL_waylandvideo.h | 1 +
src/video/x11/SDL_x11clipboard.c | 99 ++±-
src/video/x11/SDL_x11clipboard.h | 5 ±
src/video/x11/SDL_x11events.c | 12 ±
src/video/x11/SDL_x11video.c | 3 +
test/testautomation_clipboard.c | 163 +++++++±
…/primary-selection-unstable-v1.xml | 225 ++++++++++++
21 files changed, 1207 insertions(+), 129 deletions(-)
create mode 100644 wayland-protocols/primary-selection-unstable-v1.xml
diff --git a/include/SDL_clipboard.h b/include/SDL_clipboard.h
index 935136305a8d…fbe57719f886 100644
— a/include/SDL_clipboard.h
+++ b/include/SDL_clipboard.h
@@ -82,6 +82,52 @@ extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
*/
extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
+/**
-
- Put UTF-8 text into the primary selection.
-
-
- \param text the text to store in the primary selection
-
- \returns 0 on success or a negative error code on failure; call
-
-
SDL_GetError() for more information.
-
-
-
- \since This function is available since SDL 2.25.0.
-
-
- \sa SDL_GetPrimarySelectionText
-
- \sa SDL_HasPrimarySelectionText
- */
+extern DECLSPEC int SDLCALL SDL_SetPrimarySelectionText(const char *text);
+/**
-
- Get UTF-8 text from the primary selection, which must be freed with SDL_free().
-
-
- This functions returns empty string if there was not enough memory left for
-
- a copy of the primary selection’s content.
-
-
- \returns the primary selection text on success or an empty string on failure;
-
-
call SDL_GetError() for more information. Caller must call SDL_free()
-
-
-
on the returned pointer when done with it (even if there was an
-
-
-
error).
-
-
-
- \since This function is available since SDL 2.25.0.
-
-
- \sa SDL_HasPrimarySelectionText
-
- \sa SDL_SetPrimarySelectionText
- */
+extern DECLSPEC char * SDLCALL SDL_GetPrimarySelectionText(void);
+/**
-
- Query whether the primary selection exists and contains a non-empty text
-
- string.
-
-
- \returns SDL_TRUE if the primary selection has text, or SDL_FALSE if it does
-
-
not.
-
-
-
- \since This function is available since SDL 2.25.0.
-
-
- \sa SDL_GetPrimarySelectionText
-
- \sa SDL_SetPrimarySelectionText
- */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasPrimarySelectionText(void);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
diff --git a/include/SDL_events.h b/include/SDL_events.h
index c0fc9bb1aa34…1836fc06c378 100644
— a/include/SDL_events.h
+++ b/include/SDL_events.h
@@ -143,7 +143,7 @@ typedef enum
SDL_MULTIGESTURE,
/* Clipboard events */
- SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard changed */
-
SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard or primary selection changed */
/* Drag and drop events */
SDL_DROPFILE = 0x1000, /**< The system requests a file open */
diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports
index d25b8f721e5c…d9e3545c3d35 100644
— a/src/dynapi/SDL2.exports
+++ b/src/dynapi/SDL2.exports
@@ -860,3 +860,6 @@
++’_SDL_crc16’.‘SDL2.dll’.‘SDL_crc16’
++’_SDL_GetWindowSizeInPixels’.‘SDL2.dll’.‘SDL_GetWindowSizeInPixels’
++’_SDL_GetJoystickGUIDInfo’.‘SDL2.dll’.‘SDL_GetJoystickGUIDInfo’
+++’_SDL_SetPrimarySelectionText’.‘SDL2.dll’.‘SDL_SetPrimarySelectionText’
+++’_SDL_GetPrimarySelectionText’.‘SDL2.dll’.‘SDL_GetPrimarySelectionText’
+++’_SDL_HasPrimarySelectionText’.‘SDL2.dll’.‘SDL_HasPrimarySelectionText’
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 4b68f1ab496c…2e982b81b123 100644
— a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -886,3 +886,6 @@
#define SDL_crc16 SDL_crc16_REAL
#define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL
#define SDL_GetJoystickGUIDInfo SDL_GetJoystickGUIDInfo_REAL
+#define SDL_SetPrimarySelectionText SDL_SetPrimarySelectionText_REAL
+#define SDL_GetPrimarySelectionText SDL_GetPrimarySelectionText_REAL
+#define SDL_HasPrimarySelectionText SDL_HasPrimarySelectionText_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index b8ecadbcfbf2…b40effffc2f3 100644
— a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -969,3 +969,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return)
SDL_DYNAPI_PROC(Uint16,SDL_crc16,(Uint16 a, const void *b, size_t c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),)
SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_JoystickGUID a, Uint16 *b, Uint16 *c, Uint16 *d, Uint16 *e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(int,SDL_SetPrimarySelectionText,(const char a),(a),return)
+SDL_DYNAPI_PROC(char,SDL_GetPrimarySelectionText,(void),(),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_HasPrimarySelectionText,(void),(),return)
diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c
index c3669af6ec1c…bee570dea8f2 100644
— a/src/video/SDL_clipboard.c
+++ b/src/video/SDL_clipboard.c
@@ -45,6 +45,27 @@ SDL_SetClipboardText(const char *text)
}
}
+int
+SDL_SetPrimarySelectionText(const char *text)
+{
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
-
return SDL_SetError("Video subsystem must be initialized to set primary selection text");
- }
- if (!text) {
-
text = "";
- }
- if (_this->SetPrimarySelectionText) {
-
return _this->SetPrimarySelectionText(_this, text);
- } else {
-
SDL_free(_this->primary_selection_text);
-
_this->primary_selection_text = SDL_strdup(text);
-
return 0;
- }
+}
char *
SDL_GetClipboardText(void)
{
@@ -66,6 +87,27 @@ SDL_GetClipboardText(void)
}
}
+char *
+SDL_GetPrimarySelectionText(void)
+{
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
-
SDL_SetError("Video subsystem must be initialized to get primary selection text");
-
return SDL_strdup("");
- }
- if (_this->GetPrimarySelectionText) {
-
return _this->GetPrimarySelectionText(_this);
- } else {
-
const char *text = _this->primary_selection_text;
-
if (!text) {
-
text = "";
-
}
-
return SDL_strdup(text);
- }
+}
SDL_bool
SDL_HasClipboardText(void)
{
@@ -87,4 +129,26 @@ SDL_HasClipboardText(void)
}
}
+SDL_bool
+SDL_HasPrimarySelectionText(void)
+{
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
-
SDL_SetError("Video subsystem must be initialized to check primary selection text");
-
return SDL_FALSE;
- }
- if (_this->HasPrimarySelectionText) {
-
return _this->HasPrimarySelectionText(_this);
- } else {
-
if (_this->primary_selection_text && _this->primary_selection_text[0] != '\0') {
-
return SDL_TRUE;
-
} else {
-
return SDL_FALSE;
-
}
- }
- return SDL_FALSE;
+}
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index d3f0d83e2a2a…4f602d305a6f 100644
— a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -328,6 +328,9 @@ struct SDL_VideoDevice
int (*SetClipboardText) (_THIS, const char *text);
char * (*GetClipboardText) (_THIS);
SDL_bool (*HasClipboardText) (_THIS);
-
int (*SetPrimarySelectionText) (_THIS, const char *text);
-
char * (*GetPrimarySelectionText) (_THIS);
-
SDL_bool (*HasPrimarySelectionText) (_THIS);
/* MessageBox */
int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid);
@@ -353,6 +356,7 @@ struct SDL_VideoDevice
Uint8 window_magic;
Uint32 next_object_id;
char *clipboard_text; -
char *primary_selection_text;
SDL_bool setting_display_mode;
Uint32 quirk_flags;
@@ -422,11 +426,11 @@ struct SDL_VideoDevice
/* Data private to this driver */
void *driverdata;
struct SDL_GLDriverData *gl_data;
#if SDL_VIDEO_OPENGL_EGL
struct SDL_EGL_VideoData *egl_data;
#endif
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
struct SDL_PrivateGLESData *gles_data;
#endif
diff --git a/src/video/wayland/SDL_waylandclipboard.c b/src/video/wayland/SDL_waylandclipboard.c
index ede016c79bd9…ff19639f7e3e 100644
— a/src/video/wayland/SDL_waylandclipboard.c
+++ b/src/video/wayland/SDL_waylandclipboard.c
@@ -58,6 +58,39 @@ Wayland_SetClipboardText(_THIS, const char *text)
return status;
}
+int
+Wayland_SetPrimarySelectionText(_THIS, const char *text)
+{
- SDL_VideoData *video_data = NULL;
- SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
- int status = 0;
- if (_this == NULL || _this->driverdata == NULL) {
-
status = SDL_SetError("Video driver uninitialized");
- } else {
-
video_data = _this->driverdata;
-
if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) {
-
primary_selection_device = video_data->input->primary_selection_device;
-
if (text[0] != '\0') {
-
SDL_WaylandPrimarySelectionSource* source = Wayland_primary_selection_source_create(_this);
-
Wayland_primary_selection_source_add_data(source, TEXT_MIME, text,
-
SDL_strlen(text));
-
status = Wayland_primary_selection_device_set_selection(primary_selection_device,
-
source);
-
if (status != 0) {
-
Wayland_primary_selection_source_destroy(source);
-
}
-
} else {
-
status = Wayland_primary_selection_device_clear_selection(primary_selection_device);
-
}
-
}
- }
- return status;
+}
char *
Wayland_GetClipboardText(_THIS)
{
@@ -65,8 +98,6 @@ Wayland_GetClipboardText(_THIS)
SDL_WaylandDataDevice *data_device = NULL;
char *text = NULL;
-
void *buffer = NULL;
size_t length = 0;if (_this == NULL || _this->driverdata == NULL) {
@@ -75,19 +106,50 @@ Wayland_GetClipboardText(_THIS)
video_data = _this->driverdata;
if (video_data->input != NULL && video_data->input->data_device != NULL) {
data_device = video_data->input->data_device; -
if (data_device->selection_offer != NULL) {
-
buffer = Wayland_data_offer_receive(data_device->selection_offer,
-
/* Prefer own selection, if not canceled */
-
if (Wayland_data_source_has_mime(
-
data_device->selection_source, TEXT_MIME)) {
-
text = Wayland_data_source_get_data(data_device->selection_source, &length, TEXT_MIME, SDL_TRUE);
-
if (length > 0) {
-
text = (char*) buffer;
-
}
-
} else if (Wayland_data_offer_has_mime(
-
data_device->selection_offer, TEXT_MIME)) {
-
text = Wayland_data_offer_receive(data_device->selection_offer,
-
&length, TEXT_MIME, SDL_TRUE); }
-
if (length == 0 && data_device->selection_source != NULL) {
-
buffer = Wayland_data_source_get_data(data_device->selection_source,
-
&length, TEXT_MIME, SDL_TRUE);
-
if (length > 0) {
-
text = (char*) buffer;
-
}
-
}
- }
- if (text == NULL) {
-
text = SDL_strdup("");
- }
- return text;
+}
+char *
+Wayland_GetPrimarySelectionText(_THIS)
+{
- SDL_VideoData *video_data = NULL;
- SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
- char *text = NULL;
- size_t length = 0;
- if (_this == NULL || _this->driverdata == NULL) {
-
SDL_SetError("Video driver uninitialized");
- } else {
-
video_data = _this->driverdata;
-
if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) {
-
primary_selection_device = video_data->input->primary_selection_device;
-
/* Prefer own selection, if not canceled */
-
if (Wayland_primary_selection_source_has_mime(
-
primary_selection_device->selection_source, TEXT_MIME)) {
-
text = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source,
-
&length, TEXT_MIME, SDL_TRUE);
-
} else if (Wayland_primary_selection_offer_has_mime(
-
primary_selection_device->selection_offer, TEXT_MIME)) {
-
text = Wayland_primary_selection_offer_receive(primary_selection_device->selection_offer,
-
}&length, TEXT_MIME, SDL_TRUE); } }
@@ -112,13 +174,32 @@ Wayland_HasClipboardText(_THIS)
video_data = _this->driverdata;
if (video_data->input != NULL && video_data->input->data_device != NULL) {
data_device = video_data->input->data_device;
-
if (Wayland_data_offer_has_mime(
-
data_device->selection_offer, TEXT_MIME)) {
-
result = SDL_TRUE;
-
} else if (Wayland_data_source_has_mime(
-
data_device->selection_source, TEXT_MIME)) {
-
result = SDL_TRUE;
-
}
-
result = result ||
-
Wayland_data_source_has_mime(data_device->selection_source, TEXT_MIME) ||
-
Wayland_data_offer_has_mime(data_device->selection_offer, TEXT_MIME);
-
}
- }
- return result;
+}
+SDL_bool
+Wayland_HasPrimarySelectionText(_THIS)
+{
- SDL_VideoData *video_data = NULL;
- SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
- SDL_bool result = SDL_FALSE;
- if (_this == NULL || _this->driverdata == NULL) {
-
SDL_SetError("Video driver uninitialized");
- } else {
-
video_data = _this->driverdata;
-
if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) {
-
primary_selection_device = video_data->input->primary_selection_device;
-
result = result ||
-
Wayland_primary_selection_source_has_mime(
-
primary_selection_device->selection_source, TEXT_MIME) ||
-
Wayland_primary_selection_offer_has_mime(
-
}primary_selection_device->selection_offer, TEXT_MIME); }
return result;
diff --git a/src/video/wayland/SDL_waylandclipboard.h b/src/video/wayland/SDL_waylandclipboard.h
index b30e1605b9da…b0e443d955f4 100644
— a/src/video/wayland/SDL_waylandclipboard.h
+++ b/src/video/wayland/SDL_waylandclipboard.h
@@ -26,6 +26,9 @@
extern int Wayland_SetClipboardText(_THIS, const char *text);
extern char *Wayland_GetClipboardText(_THIS);
extern SDL_bool Wayland_HasClipboardText(_THIS);
+extern int Wayland_SetPrimarySelectionText(_THIS, const char *text);
+extern char *Wayland_GetPrimarySelectionText(_THIS);
+extern SDL_bool Wayland_HasPrimarySelectionText(_THIS);
#endif /* SDL_waylandclipboard_h_ */
diff --git a/src/video/wayland/SDL_waylanddatamanager.c b/src/video/wayland/SDL_waylanddatamanager.c
index e61ba457fd19…63e9d489ce17 100644
— a/src/video/wayland/SDL_waylanddatamanager.c
+++ b/src/video/wayland/SDL_waylanddatamanager.c
@@ -33,11 +33,12 @@
#include “SDL_waylandvideo.h”
#include “SDL_waylanddatamanager.h”
+#include “primary-selection-unstable-v1-client-protocol.h”
/* FIXME: This is arbitrary, but we want this to be less than a frame because
- any longer can potentially spin an infinite loop of PumpEvents (!)
*/
-#define PIPE_MS_TIMEOUT 10
+#define PIPE_MS_TIMEOUT 14
static ssize_t
write_pipe(int fd, const void* buffer, size_t total_length, size_t pos)
@@ -53,7 +54,7 @@ write_pipe(int fd, const void buffer, size_t total_length, size_t *pos)
ready = SDL_IOReady(fd, SDL_IOR_WRITE, PIPE_MS_TIMEOUT);
sigemptyset(&sig_set);
- sigaddset(&sig_set, SIGPIPE);
- sigaddset(&sig_set, SIGPIPE);
#if SDL_THREADS_DISABLED
sigprocmask(SIG_BLOCK, &sig_set, &old_sig_set);
@@ -97,7 +98,7 @@ read_pipe(int fd, void** buffer, size_t* total_length, SDL_bool null_terminate)
size_t pos = 0;
ready = SDL_IOReady(fd, SDL_IOR_READ, PIPE_MS_TIMEOUT);
- if (ready == 0) {
bytes_read = SDL_SetError(“Pipe timeout”);
} else if (ready < 0) {
@@ -120,8 +121,8 @@ read_pipe(int fd, void** buffer, size_t* total_length, SDL_bool null_terminate)
output_buffer = SDL_malloc(new_buffer_length);
} else {
output_buffer = SDL_realloc(*buffer, new_buffer_length);
-
}
-
}
-
if (output_buffer == NULL) { bytes_read = SDL_OutOfMemory(); } else {
@@ -130,7 +131,7 @@ read_pipe(int fd, void** buffer, size_t* total_length, SDL_bool null_terminate)
if (null_terminate == SDL_TRUE) {
SDL_memset((Uint8*)output_buffer + (new_buffer_length - 1), 0, 1);
}
-
}*buffer = output_buffer; }
@@ -160,28 +161,28 @@ Wayland_convert_mime_type(const char *mime_type)
break;
}
}
- return found;
}
static SDL_MimeDataList*
-mime_data_list_find(struct wl_list* list,
+mime_data_list_find(struct wl_list* list,
const char* mime_type)
{
SDL_MimeDataList *found = NULL;
SDL_MimeDataList *mime_list = NULL;
- wl_list_for_each(mime_list, list, link) {
- wl_list_for_each(mime_list, list, link) {
if (SDL_strcmp(mime_list->mime_type, mime_type) == 0) {
found = mime_list;
break;
}
- }
- }
return found;
}
static int
-mime_data_list_add(struct wl_list* list,
+mime_data_list_add(struct wl_list* list,
const char* mime_type,
const void* buffer, size_t length)
{
@@ -216,7 +217,7 @@ mime_data_list_add(struct wl_list* list,
}
}
}
- if (mime_data != NULL && buffer != NULL && length > 0) {
if (mime_data->data != NULL) {
SDL_free(mime_data->data);
@@ -233,31 +234,25 @@ mime_data_list_add(struct wl_list* list,
static void
mime_data_list_free(struct wl_list *list)
{
- SDL_MimeDataList *mime_data = NULL;
-
SDL_MimeDataList *mime_data = NULL;
SDL_MimeDataList *next = NULL;wl_list_for_each_safe(mime_data, next, list, link) {
if (mime_data->data != NULL) {
SDL_free(mime_data->data);
-
}
-
} if (mime_data->mime_type != NULL) { SDL_free(mime_data->mime_type); }
-
SDL_free(mime_data);
- }
-
SDL_free(mime_data);
- }
}
-ssize_t
-Wayland_data_source_send(SDL_WaylandDataSource *source,
-
const char *mime_type, int fd)
+static ssize_t
+Wayland_source_send(SDL_MimeDataList *mime_data, const char *mime_type, int fd)
{
size_t written_bytes = 0;
ssize_t status = 0;
-
SDL_MimeDataList *mime_data = NULL;
-
mime_type = Wayland_convert_mime_type(mime_type);
-
mime_data = mime_data_list_find(&source->mimes,
-
mime_type);
if (mime_data == NULL || mime_data->data == NULL) {
status = SDL_SetError(“Invalid mime type”);
@@ -271,15 +266,49 @@ Wayland_data_source_send(SDL_WaylandDataSource *source,
return status;
}
+ssize_t
+Wayland_data_source_send(SDL_WaylandDataSource *source,
-
const char *mime_type, int fd)
+{
- SDL_MimeDataList *mime_data = NULL;
- mime_type = Wayland_convert_mime_type(mime_type);
- mime_data = mime_data_list_find(&source->mimes,
-
mime_type);
- return Wayland_source_send(mime_data, mime_type, fd);
+}
+ssize_t
+Wayland_primary_selection_source_send(SDL_WaylandPrimarySelectionSource *source,
-
const char *mime_type, int fd)
+{
- SDL_MimeDataList *mime_data = NULL;
- mime_type = Wayland_convert_mime_type(mime_type);
- mime_data = mime_data_list_find(&source->mimes,
-
mime_type);
- return Wayland_source_send(mime_data, mime_type, fd);
+}
int Wayland_data_source_add_data(SDL_WaylandDataSource *source,
const char *mime_type,
const void *buffer,
-
size_t length)
-
size_t length)
+{
- return mime_data_list_add(&source->mimes, mime_type, buffer, length);
+}
+int Wayland_primary_selection_source_add_data(SDL_WaylandPrimarySelectionSource *source,
-
const char *mime_type,
-
const void *buffer,
-
size_t length)
{
return mime_data_list_add(&source->mimes, mime_type, buffer, length);
}
-SDL_bool
+SDL_bool
Wayland_data_source_has_mime(SDL_WaylandDataSource *source,
const char *mime_type)
{
@@ -291,7 +320,47 @@ Wayland_data_source_has_mime(SDL_WaylandDataSource *source,
return found;
}
-void*
+SDL_bool
+Wayland_primary_selection_source_has_mime(SDL_WaylandPrimarySelectionSource *source,
-
const char *mime_type)
+{
- SDL_bool found = SDL_FALSE;
- if (source != NULL) {
-
found = mime_data_list_find(&source->mimes, mime_type) != NULL;
- }
- return found;
+}
+static void*
+Wayland_source_get_data(SDL_MimeDataList *mime_data,
-
size_t *length,
-
SDL_bool null_terminate)
+{
- void *buffer = NULL;
- if (mime_data != NULL && mime_data->length > 0) {
-
size_t buffer_length = mime_data->length;
-
if (null_terminate == SDL_TRUE) {
-
++buffer_length;
-
}
-
buffer = SDL_malloc(buffer_length);
-
if (buffer == NULL) {
-
*length = SDL_OutOfMemory();
-
} else {
-
*length = mime_data->length;
-
SDL_memcpy(buffer, mime_data->data, mime_data->length);
-
if (null_terminate) {
-
*((Uint8 *)buffer + mime_data->length) = 0;
-
}
-
}
- }
- return buffer;
+}
+void*
Wayland_data_source_get_data(SDL_WaylandDataSource *source,
size_t length, const char mime_type,
SDL_bool null_terminate)
@@ -304,23 +373,26 @@ Wayland_data_source_get_data(SDL_WaylandDataSource *source,
SDL_SetError(“Invalid data source”);
} else {
mime_data = mime_data_list_find(&source->mimes, mime_type);
-
if (mime_data != NULL && mime_data->length > 0) {
-
size_t buffer_length = mime_data->length;
-
buffer = Wayland_source_get_data(mime_data, length, null_terminate);
- }
-
if (null_terminate == SDL_TRUE) {
-
++buffer_length;
-
}
-
buffer = SDL_malloc(buffer_length);
-
if (buffer == NULL) {
-
*length = SDL_OutOfMemory();
-
} else {
-
*length = mime_data->length;
-
SDL_memcpy(buffer, mime_data->data, mime_data->length);
-
if (null_terminate) {
-
*((Uint8 *)buffer + mime_data->length) = 0;
-
}
-
}
-
}
- return buffer;
+}
+void*
+Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSource *source,
-
size_t *length, const char* mime_type,
-
SDL_bool null_terminate)
+{
-
SDL_MimeDataList *mime_data = NULL;
-
void *buffer = NULL;
-
*length = 0;
-
if (source == NULL) {
-
SDL_SetError("Invalid primary selection source");
-
} else {
-
mime_data = mime_data_list_find(&source->mimes, mime_type);
-
buffer = Wayland_source_get_data(mime_data, length, null_terminate);
}
return buffer;
@@ -340,13 +412,27 @@ Wayland_data_source_destroy(SDL_WaylandDataSource *source)
}
}
-void*
+void
+Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource *source)
+{
- if (source != NULL) {
-
SDL_WaylandPrimarySelectionDevice *primary_selection_device = (SDL_WaylandPrimarySelectionDevice *) source->primary_selection_device;
-
if (primary_selection_device && (primary_selection_device->selection_source == source)) {
-
primary_selection_device->selection_source = NULL;
-
}
-
zwp_primary_selection_source_v1_destroy(source->source);
-
mime_data_list_free(&source->mimes);
-
SDL_free(source);
- }
+}
+void*
Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
size_t length, const char mime_type,
SDL_bool null_terminate)
{
SDL_WaylandDataDevice *data_device = NULL;
-
int pipefd[2];
void *buffer = NULL;
*length = 0;
@@ -364,22 +450,59 @@ Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
WAYLAND_wl_display_flush(data_device->video_data->display);close(pipefd[1]);
-
}while (read_pipe(pipefd[0], &buffer, length, null_terminate) > 0); close(pipefd[0]);
return buffer;
}
-int
+void*
+Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *offer,
-
size_t *length, const char* mime_type,
-
SDL_bool null_terminate)
+{
- SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
- int pipefd[2];
- void *buffer = NULL;
- *length = 0;
- if (offer == NULL) {
-
SDL_SetError("Invalid data offer");
- } else if ((primary_selection_device = offer->primary_selection_device) == NULL) {
-
SDL_SetError("Primary selection device not initialized");
- } else if (pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) {
-
SDL_SetError("Could not read pipe");
- } else {
-
zwp_primary_selection_offer_v1_receive(offer->offer, mime_type, pipefd[1]);
-
/* TODO: Needs pump and flush? */
-
WAYLAND_wl_display_flush(primary_selection_device->video_data->display);
-
close(pipefd[1]);
-
while (read_pipe(pipefd[0], &buffer, length, null_terminate) > 0);
-
close(pipefd[0]);
- }
- return buffer;
+}
+int
Wayland_data_offer_add_mime(SDL_WaylandDataOffer offer,
const char mime_type)
{
return mime_data_list_add(&offer->mimes, mime_type, NULL, 0);
}
+int
+Wayland_primary_selection_offer_add_mime(SDL_WaylandPrimarySelectionOffer *offer,
-
const char* mime_type)
+{
- return mime_data_list_add(&offer->mimes, mime_type, NULL, 0);
+}
-SDL_bool
+SDL_bool
Wayland_data_of
(Patch may be truncated, please check the link at the top of this post.)