|
@@ -37,10 +37,14 @@
|
|
|
#include "SDL_waylanddatamanager.h"
|
|
#include "SDL_waylanddatamanager.h"
|
|
|
#include "primary-selection-unstable-v1-client-protocol.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 (!)
|
|
|
|
|
|
|
+/* This is arbitrary, but reading while polling should block for less than a frame, to
|
|
|
|
|
+ * prevent hanging while pumping events.
|
|
|
|
|
+ *
|
|
|
|
|
+ * When querying the clipboard data directly, a larger value is needed to avoid timing
|
|
|
|
|
+ * out if the source needs to process or transfer a large amount of data.
|
|
|
*/
|
|
*/
|
|
|
-#define PIPE_TIMEOUT_NS SDL_MS_TO_NS(14)
|
|
|
|
|
|
|
+#define DEFAULT_PIPE_TIMEOUT_NS SDL_MS_TO_NS(14)
|
|
|
|
|
+#define EXTENDED_PIPE_TIMEOUT_NS SDL_MS_TO_NS(5000)
|
|
|
|
|
|
|
|
/* sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it.
|
|
/* sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it.
|
|
|
* Based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation
|
|
* Based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation
|
|
@@ -94,7 +98,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_
|
|
|
sigset_t old_sig_set;
|
|
sigset_t old_sig_set;
|
|
|
struct timespec zerotime = { 0 };
|
|
struct timespec zerotime = { 0 };
|
|
|
|
|
|
|
|
- ready = SDL_IOReady(fd, SDL_IOR_WRITE, PIPE_TIMEOUT_NS);
|
|
|
|
|
|
|
+ ready = SDL_IOReady(fd, SDL_IOR_WRITE, DEFAULT_PIPE_TIMEOUT_NS);
|
|
|
|
|
|
|
|
sigemptyset(&sig_set);
|
|
sigemptyset(&sig_set);
|
|
|
sigaddset(&sig_set, SIGPIPE);
|
|
sigaddset(&sig_set, SIGPIPE);
|
|
@@ -130,7 +134,7 @@ static ssize_t write_pipe(int fd, const void *buffer, size_t total_length, size_
|
|
|
return bytes_written;
|
|
return bytes_written;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static ssize_t read_pipe(int fd, void **buffer, size_t *total_length)
|
|
|
|
|
|
|
+static ssize_t read_pipe(int fd, void **buffer, size_t *total_length, Sint64 timeout_ns)
|
|
|
{
|
|
{
|
|
|
int ready = 0;
|
|
int ready = 0;
|
|
|
void *output_buffer = NULL;
|
|
void *output_buffer = NULL;
|
|
@@ -139,7 +143,7 @@ static ssize_t read_pipe(int fd, void **buffer, size_t *total_length)
|
|
|
ssize_t bytes_read = 0;
|
|
ssize_t bytes_read = 0;
|
|
|
size_t pos = 0;
|
|
size_t pos = 0;
|
|
|
|
|
|
|
|
- ready = SDL_IOReady(fd, SDL_IOR_READ, PIPE_TIMEOUT_NS);
|
|
|
|
|
|
|
+ ready = SDL_IOReady(fd, SDL_IOR_READ, timeout_ns);
|
|
|
|
|
|
|
|
if (ready == 0) {
|
|
if (ready == 0) {
|
|
|
bytes_read = SDL_SetError("Pipe timeout");
|
|
bytes_read = SDL_SetError("Pipe timeout");
|
|
@@ -404,7 +408,7 @@ static void offer_source_done_handler(void *data, struct wl_callback *callback,
|
|
|
wl_callback_destroy(offer->callback);
|
|
wl_callback_destroy(offer->callback);
|
|
|
offer->callback = NULL;
|
|
offer->callback = NULL;
|
|
|
|
|
|
|
|
- while (read_pipe(offer->read_fd, (void **)&id, &length) > 0) {
|
|
|
|
|
|
|
+ while (read_pipe(offer->read_fd, (void **)&id, &length, DEFAULT_PIPE_TIMEOUT_NS) > 0) {
|
|
|
}
|
|
}
|
|
|
close(offer->read_fd);
|
|
close(offer->read_fd);
|
|
|
offer->read_fd = -1;
|
|
offer->read_fd = -1;
|
|
@@ -499,10 +503,10 @@ void Wayland_data_offer_notify_from_mimes(SDL_WaylandDataOffer *offer, bool chec
|
|
|
SDL_SendClipboardUpdate(false, new_mime_types, nformats);
|
|
SDL_SendClipboardUpdate(false, new_mime_types, nformats);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
|
|
|
|
- const char *mime_type, size_t *length)
|
|
|
|
|
|
|
+void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer, const char *mime_type, size_t *length, bool extended_timeout)
|
|
|
{
|
|
{
|
|
|
SDL_WaylandDataDevice *data_device = NULL;
|
|
SDL_WaylandDataDevice *data_device = NULL;
|
|
|
|
|
+ const Sint64 timeout = extended_timeout ? EXTENDED_PIPE_TIMEOUT_NS : DEFAULT_PIPE_TIMEOUT_NS;
|
|
|
|
|
|
|
|
int pipefd[2];
|
|
int pipefd[2];
|
|
|
void *buffer = NULL;
|
|
void *buffer = NULL;
|
|
@@ -523,7 +527,7 @@ void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
|
|
|
|
|
|
|
WAYLAND_wl_display_flush(data_device->seat->display->display);
|
|
WAYLAND_wl_display_flush(data_device->seat->display->display);
|
|
|
|
|
|
|
|
- while (read_pipe(pipefd[0], &buffer, length) > 0) {
|
|
|
|
|
|
|
+ while (read_pipe(pipefd[0], &buffer, length, timeout) > 0) {
|
|
|
}
|
|
}
|
|
|
close(pipefd[0]);
|
|
close(pipefd[0]);
|
|
|
}
|
|
}
|
|
@@ -557,7 +561,7 @@ void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *
|
|
|
|
|
|
|
|
WAYLAND_wl_display_flush(primary_selection_device->seat->display->display);
|
|
WAYLAND_wl_display_flush(primary_selection_device->seat->display->display);
|
|
|
|
|
|
|
|
- while (read_pipe(pipefd[0], &buffer, length) > 0) {
|
|
|
|
|
|
|
+ while (read_pipe(pipefd[0], &buffer, length, EXTENDED_PIPE_TIMEOUT_NS) > 0) {
|
|
|
}
|
|
}
|
|
|
close(pipefd[0]);
|
|
close(pipefd[0]);
|
|
|
}
|
|
}
|