|
@@ -29,6 +29,7 @@
|
|
|
#include <signal.h>
|
|
|
|
|
|
#include "../../core/unix/SDL_poll.h"
|
|
|
+#include "../../events/SDL_events_c.h"
|
|
|
|
|
|
#include "SDL_waylandvideo.h"
|
|
|
#include "SDL_waylanddatamanager.h"
|
|
@@ -136,31 +137,6 @@ static ssize_t read_pipe(int fd, void **buffer, size_t *total_length, SDL_bool n
|
|
|
return bytes_read;
|
|
|
}
|
|
|
|
|
|
-#define MIME_LIST_SIZE 4
|
|
|
-
|
|
|
-static const char *mime_conversion_list[MIME_LIST_SIZE][2] = {
|
|
|
- { "text/plain", TEXT_MIME },
|
|
|
- { "TEXT", TEXT_MIME },
|
|
|
- { "UTF8_STRING", TEXT_MIME },
|
|
|
- { "STRING", TEXT_MIME }
|
|
|
-};
|
|
|
-
|
|
|
-const char *Wayland_convert_mime_type(const char *mime_type)
|
|
|
-{
|
|
|
- const char *found = mime_type;
|
|
|
-
|
|
|
- size_t index = 0;
|
|
|
-
|
|
|
- for (index = 0; index < MIME_LIST_SIZE; ++index) {
|
|
|
- if (SDL_strcmp(mime_conversion_list[index][0], mime_type) == 0) {
|
|
|
- found = mime_conversion_list[index][1];
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return found;
|
|
|
-}
|
|
|
-
|
|
|
static SDL_MimeDataList *mime_data_list_find(struct wl_list *list,
|
|
|
const char *mime_type)
|
|
|
{
|
|
@@ -242,131 +218,112 @@ static void mime_data_list_free(struct wl_list *list)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static ssize_t
|
|
|
-Wayland_source_send(SDL_MimeDataList *mime_data, const char *mime_type, int fd)
|
|
|
+static size_t
|
|
|
+Wayland_send_data(void *data, size_t length, int fd)
|
|
|
{
|
|
|
- size_t written_bytes = 0;
|
|
|
- ssize_t status = 0;
|
|
|
+ size_t result = 0;
|
|
|
|
|
|
- if (mime_data == NULL || mime_data->data == NULL) {
|
|
|
- status = SDL_SetError("Invalid mime type");
|
|
|
- close(fd);
|
|
|
- } else {
|
|
|
- while (write_pipe(fd,
|
|
|
- mime_data->data,
|
|
|
- mime_data->length,
|
|
|
- &written_bytes) > 0) {
|
|
|
+ if (length > 0 && data != NULL) {
|
|
|
+ while (write_pipe(fd, data, length, &result) > 0) {
|
|
|
+ /* Just keep spinning */
|
|
|
}
|
|
|
- close(fd);
|
|
|
- status = written_bytes;
|
|
|
}
|
|
|
- return status;
|
|
|
+ close(fd);
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
ssize_t
|
|
|
Wayland_data_source_send(SDL_WaylandDataSource *source,
|
|
|
const char *mime_type, int fd)
|
|
|
{
|
|
|
- SDL_MimeDataList *mime_data = NULL;
|
|
|
+ void *data = NULL;
|
|
|
+ size_t length = 0;
|
|
|
|
|
|
- mime_type = Wayland_convert_mime_type(mime_type);
|
|
|
- mime_data = mime_data_list_find(&source->mimes,
|
|
|
- mime_type);
|
|
|
+ if (source->callback) {
|
|
|
+ data = source->callback(&length, mime_type, source->userdata.data);
|
|
|
+ }
|
|
|
|
|
|
- return Wayland_source_send(mime_data, mime_type, fd);
|
|
|
+ return Wayland_send_data(data, length, 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);
|
|
|
+ void *data = NULL;
|
|
|
+ size_t length = 0;
|
|
|
|
|
|
- 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)
|
|
|
-{
|
|
|
- return mime_data_list_add(&source->mimes, mime_type, buffer, length);
|
|
|
-}
|
|
|
+ if (source->callback) {
|
|
|
+ data = source->callback(&length, mime_type, source->userdata.data);
|
|
|
+ }
|
|
|
|
|
|
-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);
|
|
|
+ return Wayland_send_data(data, length, fd);
|
|
|
}
|
|
|
|
|
|
-SDL_bool Wayland_data_source_has_mime(SDL_WaylandDataSource *source,
|
|
|
- const char *mime_type)
|
|
|
+void Wayland_data_source_set_callback(SDL_WaylandDataSource *source,
|
|
|
+ SDL_ClipboardDataCallback callback,
|
|
|
+ void *userdata,
|
|
|
+ SDL_bool internal)
|
|
|
{
|
|
|
- SDL_bool found = SDL_FALSE;
|
|
|
-
|
|
|
if (source != NULL) {
|
|
|
- found = mime_data_list_find(&source->mimes, mime_type) != NULL;
|
|
|
+ source->callback = callback;
|
|
|
+ source->userdata.internal = internal;
|
|
|
+ source->userdata.data = userdata;
|
|
|
}
|
|
|
- return found;
|
|
|
}
|
|
|
|
|
|
-SDL_bool Wayland_primary_selection_source_has_mime(SDL_WaylandPrimarySelectionSource *source,
|
|
|
- const char *mime_type)
|
|
|
+int Wayland_primary_selection_source_set_callback(SDL_WaylandPrimarySelectionSource *source,
|
|
|
+ SDL_ClipboardDataCallback callback,
|
|
|
+ void *userdata)
|
|
|
{
|
|
|
- SDL_bool found = SDL_FALSE;
|
|
|
-
|
|
|
- if (source != NULL) {
|
|
|
- found = mime_data_list_find(&source->mimes, mime_type) != NULL;
|
|
|
+ if (source == NULL) {
|
|
|
+ return SDL_InvalidParamError("source");
|
|
|
}
|
|
|
- return found;
|
|
|
+ source->callback = callback;
|
|
|
+ source->userdata.internal = SDL_TRUE;
|
|
|
+ source->userdata.data = userdata;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static void *Wayland_source_get_data(SDL_MimeDataList *mime_data,
|
|
|
- size_t *length,
|
|
|
- SDL_bool null_terminate)
|
|
|
+static void *Wayland_clone_data_buffer(void *buffer, size_t *len, SDL_bool null_terminate)
|
|
|
{
|
|
|
- void *buffer = NULL;
|
|
|
-
|
|
|
- if (mime_data != NULL && mime_data->length > 0) {
|
|
|
- size_t buffer_length = mime_data->length;
|
|
|
-
|
|
|
+ void *clone = NULL;
|
|
|
+ if (*len > 0 && buffer != NULL) {
|
|
|
if (null_terminate == SDL_TRUE) {
|
|
|
- ++buffer_length;
|
|
|
- }
|
|
|
- buffer = SDL_malloc(buffer_length);
|
|
|
- if (buffer == NULL) {
|
|
|
- *length = SDL_OutOfMemory();
|
|
|
+ clone = SDL_malloc((*len)+1);
|
|
|
+ if (clone == NULL) {
|
|
|
+ SDL_OutOfMemory();
|
|
|
+ } else {
|
|
|
+ SDL_memcpy(clone, buffer, *len);
|
|
|
+ ((char *) clone)[*len] = '\0';
|
|
|
+ *len += 1;
|
|
|
+ }
|
|
|
} else {
|
|
|
- *length = mime_data->length;
|
|
|
- SDL_memcpy(buffer, mime_data->data, mime_data->length);
|
|
|
- if (null_terminate) {
|
|
|
- *((Uint8 *)buffer + mime_data->length) = 0;
|
|
|
+ clone = SDL_malloc(*len);
|
|
|
+ if (clone == NULL) {
|
|
|
+ SDL_OutOfMemory();
|
|
|
+ } else {
|
|
|
+ SDL_memcpy(clone, buffer, *len);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return buffer;
|
|
|
+ return clone;
|
|
|
}
|
|
|
|
|
|
void *Wayland_data_source_get_data(SDL_WaylandDataSource *source,
|
|
|
size_t *length, const char *mime_type,
|
|
|
SDL_bool null_terminate)
|
|
|
{
|
|
|
- SDL_MimeDataList *mime_data = NULL;
|
|
|
void *buffer = NULL;
|
|
|
+ void *internal_buffer;
|
|
|
*length = 0;
|
|
|
|
|
|
if (source == NULL) {
|
|
|
SDL_SetError("Invalid data source");
|
|
|
- } else {
|
|
|
- mime_data = mime_data_list_find(&source->mimes, mime_type);
|
|
|
- buffer = Wayland_source_get_data(mime_data, length, null_terminate);
|
|
|
+ } else if (source->callback != NULL) {
|
|
|
+ internal_buffer = source->callback(length, mime_type, source->userdata.data);
|
|
|
+ buffer = Wayland_clone_data_buffer(internal_buffer, length, null_terminate);
|
|
|
}
|
|
|
|
|
|
return buffer;
|
|
@@ -376,15 +333,15 @@ void *Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSourc
|
|
|
size_t *length, const char *mime_type,
|
|
|
SDL_bool null_terminate)
|
|
|
{
|
|
|
- SDL_MimeDataList *mime_data = NULL;
|
|
|
void *buffer = NULL;
|
|
|
+ void *internal_buffer;
|
|
|
*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);
|
|
|
+ } else if (source->callback) {
|
|
|
+ internal_buffer = source->callback(length, mime_type, source->userdata.data);
|
|
|
+ buffer = Wayland_clone_data_buffer(internal_buffer, length, null_terminate);
|
|
|
}
|
|
|
|
|
|
return buffer;
|
|
@@ -398,7 +355,11 @@ void Wayland_data_source_destroy(SDL_WaylandDataSource *source)
|
|
|
data_device->selection_source = NULL;
|
|
|
}
|
|
|
wl_data_source_destroy(source->source);
|
|
|
- mime_data_list_free(&source->mimes);
|
|
|
+ if (source->userdata.internal == SDL_TRUE) {
|
|
|
+ SDL_free(source->userdata.data);
|
|
|
+ } else {
|
|
|
+ SDL_SendClipboardCancelled(source->userdata.data);
|
|
|
+ }
|
|
|
SDL_free(source);
|
|
|
}
|
|
|
}
|
|
@@ -411,7 +372,9 @@ void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource
|
|
|
primary_selection_device->selection_source = NULL;
|
|
|
}
|
|
|
zwp_primary_selection_source_v1_destroy(source->source);
|
|
|
- mime_data_list_free(&source->mimes);
|
|
|
+ if (source->userdata.internal == SDL_TRUE) {
|
|
|
+ SDL_free(source->userdata.data);
|
|
|
+ }
|
|
|
SDL_free(source);
|
|
|
}
|
|
|
}
|
|
@@ -566,36 +529,27 @@ int Wayland_primary_selection_device_clear_selection(SDL_WaylandPrimarySelection
|
|
|
}
|
|
|
|
|
|
int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device,
|
|
|
- SDL_WaylandDataSource *source)
|
|
|
+ SDL_WaylandDataSource *source,
|
|
|
+ size_t mime_count,
|
|
|
+ const char **mime_types)
|
|
|
{
|
|
|
int status = 0;
|
|
|
- size_t num_offers = 0;
|
|
|
- size_t index = 0;
|
|
|
|
|
|
if (data_device == NULL) {
|
|
|
status = SDL_SetError("Invalid Data Device");
|
|
|
} else if (source == NULL) {
|
|
|
status = SDL_SetError("Invalid source");
|
|
|
} else {
|
|
|
- SDL_MimeDataList *mime_data = NULL;
|
|
|
+ size_t index = 0;
|
|
|
+ const char *mime_type;
|
|
|
|
|
|
- wl_list_for_each (mime_data, &(source->mimes), link) {
|
|
|
+ for (index = 0; index < mime_count; ++index) {
|
|
|
+ mime_type = mime_types[index];
|
|
|
wl_data_source_offer(source->source,
|
|
|
- mime_data->mime_type);
|
|
|
-
|
|
|
- /* TODO - Improve system for multiple mime types to same data */
|
|
|
- for (index = 0; index < MIME_LIST_SIZE; ++index) {
|
|
|
- if (SDL_strcmp(mime_conversion_list[index][1], mime_data->mime_type) == 0) {
|
|
|
- wl_data_source_offer(source->source,
|
|
|
- mime_conversion_list[index][0]);
|
|
|
- }
|
|
|
- }
|
|
|
- /* */
|
|
|
-
|
|
|
- ++num_offers;
|
|
|
+ mime_type);
|
|
|
}
|
|
|
|
|
|
- if (num_offers == 0) {
|
|
|
+ if (index == 0) {
|
|
|
Wayland_data_device_clear_selection(data_device);
|
|
|
status = SDL_SetError("No mime data");
|
|
|
} else {
|
|
@@ -617,36 +571,26 @@ int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device,
|
|
|
}
|
|
|
|
|
|
int Wayland_primary_selection_device_set_selection(SDL_WaylandPrimarySelectionDevice *primary_selection_device,
|
|
|
- SDL_WaylandPrimarySelectionSource *source)
|
|
|
+ SDL_WaylandPrimarySelectionSource *source,
|
|
|
+ size_t mime_count,
|
|
|
+ const char **mime_types)
|
|
|
{
|
|
|
int status = 0;
|
|
|
- size_t num_offers = 0;
|
|
|
- size_t index = 0;
|
|
|
|
|
|
if (primary_selection_device == NULL) {
|
|
|
status = SDL_SetError("Invalid Primary Selection Device");
|
|
|
} else if (source == NULL) {
|
|
|
status = SDL_SetError("Invalid source");
|
|
|
} else {
|
|
|
- SDL_MimeDataList *mime_data = NULL;
|
|
|
-
|
|
|
- wl_list_for_each (mime_data, &(source->mimes), link) {
|
|
|
- zwp_primary_selection_source_v1_offer(source->source,
|
|
|
- mime_data->mime_type);
|
|
|
-
|
|
|
- /* TODO - Improve system for multiple mime types to same data */
|
|
|
- for (index = 0; index < MIME_LIST_SIZE; ++index) {
|
|
|
- if (SDL_strcmp(mime_conversion_list[index][1], mime_data->mime_type) == 0) {
|
|
|
- zwp_primary_selection_source_v1_offer(source->source,
|
|
|
- mime_conversion_list[index][0]);
|
|
|
- }
|
|
|
- }
|
|
|
- /* */
|
|
|
+ size_t index = 0;
|
|
|
+ const char *mime_type = mime_types[index];
|
|
|
|
|
|
- ++num_offers;
|
|
|
+ for (index = 0; index < mime_count; ++index) {
|
|
|
+ mime_type = mime_types[index];
|
|
|
+ zwp_primary_selection_source_v1_offer(source->source, mime_type);
|
|
|
}
|
|
|
|
|
|
- if (num_offers == 0) {
|
|
|
+ if (index == 0) {
|
|
|
Wayland_primary_selection_device_clear_selection(primary_selection_device);
|
|
|
status = SDL_SetError("No mime data");
|
|
|
} else {
|