mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-13 15:23:34 +00:00
wayland: Increase the read timeout when reading from SDL_GetClipboardData()
The default timeout value of 14ms is ideal when querying clipboard data while polling events, to prevent excessive lag if the source takes a long time to respond, however, when reading from SDL_GetClipboardData(), the timeout can be too short if a large amount of data must be processed or transferred. SDL_GetClipboardData() is not called while polling events, so using a longer read timeout to greatly increase the chance of success is acceptable.
Use a 5 second timeout when reading from SDL_GetClipboardData() and GetPrimarySelectionText() to greatly increase the chances of a successful read, even if the requested format requires heavy processing.
(cherry picked from commit 2a0d04613c)
This commit is contained in:
@@ -72,7 +72,7 @@ void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, si
|
||||
if (data_device->selection_source) {
|
||||
buffer = SDL_GetInternalClipboardData(_this, mime_type, length);
|
||||
} else if (Wayland_data_offer_has_mime(data_device->selection_offer, mime_type)) {
|
||||
buffer = Wayland_data_offer_receive(data_device->selection_offer, mime_type, length);
|
||||
buffer = Wayland_data_offer_receive(data_device->selection_offer, mime_type, length, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,14 @@
|
||||
#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 (!)
|
||||
/* 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.
|
||||
* 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;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
const Sint64 timeout = extended_timeout ? EXTENDED_PIPE_TIMEOUT_NS : DEFAULT_PIPE_TIMEOUT_NS;
|
||||
|
||||
int pipefd[2];
|
||||
void *buffer = NULL;
|
||||
@@ -523,7 +527,7 @@ void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
||||
|
||||
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]);
|
||||
}
|
||||
@@ -557,7 +561,7 @@ void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -140,7 +140,8 @@ extern void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelection
|
||||
// Wayland Data / Primary Selection Offer - (Receiving)
|
||||
extern void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
||||
const char *mime_type,
|
||||
size_t *length);
|
||||
size_t *length,
|
||||
bool extended_timeout);
|
||||
extern void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *offer,
|
||||
const char *mime_type,
|
||||
size_t *length);
|
||||
|
||||
@@ -2900,8 +2900,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
|
||||
bool drop_handled = false;
|
||||
#ifdef SDL_USE_LIBDBUS
|
||||
if (Wayland_data_offer_has_mime(data_device->drag_offer, FILE_PORTAL_MIME)) {
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
|
||||
FILE_PORTAL_MIME, &length);
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer, FILE_PORTAL_MIME, &length, false);
|
||||
if (buffer) {
|
||||
SDL_DBusContext *dbus = SDL_DBus_GetContext();
|
||||
if (dbus) {
|
||||
@@ -2927,7 +2926,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
|
||||
* non paths that are not visible to the application
|
||||
*/
|
||||
if (!drop_handled) {
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer, data_device->mime_type, &length);
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer, data_device->mime_type, &length, false);
|
||||
if (data_device->has_mime_file) {
|
||||
if (buffer) {
|
||||
char *saveptr = NULL;
|
||||
|
||||
Reference in New Issue
Block a user