|
|
|
@ -812,6 +812,70 @@ static void handleEvents(double* timeout) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Reads the specified data offer as the specified MIME type
|
|
|
|
|
//
|
|
|
|
|
static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mimeType) |
|
|
|
|
{ |
|
|
|
|
int fds[2]; |
|
|
|
|
|
|
|
|
|
if (pipe2(fds, O_CLOEXEC) == -1) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Wayland: Failed to create pipe for data offer: %s", |
|
|
|
|
strerror(errno)); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wl_data_offer_receive(offer, mimeType, fds[1]); |
|
|
|
|
flushDisplay(); |
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
|
|
char* string = NULL; |
|
|
|
|
size_t size = 0; |
|
|
|
|
size_t length = 0; |
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
const size_t readSize = 4096; |
|
|
|
|
const size_t requiredSize = length + readSize + 1; |
|
|
|
|
if (requiredSize > size) |
|
|
|
|
{ |
|
|
|
|
char* longer = _glfw_realloc(string, requiredSize); |
|
|
|
|
if (!longer) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL); |
|
|
|
|
close(fds[0]); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string = longer; |
|
|
|
|
size = requiredSize; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const ssize_t result = read(fds[0], string + length, readSize); |
|
|
|
|
if (result == 0) |
|
|
|
|
break; |
|
|
|
|
else if (result == -1) |
|
|
|
|
{ |
|
|
|
|
if (errno == EINTR) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Wayland: Failed to read from data offer pipe: %s", |
|
|
|
|
strerror(errno)); |
|
|
|
|
close(fds[0]); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
length += result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
close(fds[0]); |
|
|
|
|
|
|
|
|
|
string[length] = '\0'; |
|
|
|
|
return string; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, |
|
|
|
|
int* which) |
|
|
|
|
{ |
|
|
|
@ -2418,23 +2482,15 @@ void _glfwSetClipboardStringWayland(const char* string) |
|
|
|
|
_glfw.wl.selectionSource = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const size_t requiredSize = strlen(string) + 1; |
|
|
|
|
if (requiredSize > _glfw.wl.clipboardSize) |
|
|
|
|
char* copy = _glfw_strdup(string); |
|
|
|
|
if (!copy) |
|
|
|
|
{ |
|
|
|
|
_glfw_free(_glfw.wl.clipboardString); |
|
|
|
|
_glfw.wl.clipboardString = _glfw_calloc(requiredSize, 1); |
|
|
|
|
if (!_glfw.wl.clipboardString) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY, |
|
|
|
|
"Wayland: Failed to allocate clipboard string"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_glfw.wl.clipboardSize = requiredSize; |
|
|
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The argument may be a substring of the clipboard string
|
|
|
|
|
memmove(_glfw.wl.clipboardString, string, requiredSize); |
|
|
|
|
_glfw_free(_glfw.wl.clipboardString); |
|
|
|
|
_glfw.wl.clipboardString = copy; |
|
|
|
|
|
|
|
|
|
_glfw.wl.selectionSource = |
|
|
|
|
wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager); |
|
|
|
@ -2465,66 +2521,9 @@ const char* _glfwGetClipboardStringWayland(void) |
|
|
|
|
if (_glfw.wl.selectionSource) |
|
|
|
|
return _glfw.wl.clipboardString; |
|
|
|
|
|
|
|
|
|
int fds[2]; |
|
|
|
|
|
|
|
|
|
if (pipe2(fds, O_CLOEXEC) == -1) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Wayland: Failed to create clipboard pipe: %s", |
|
|
|
|
strerror(errno)); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wl_data_offer_receive(_glfw.wl.selectionOffer, "text/plain;charset=utf-8", fds[1]); |
|
|
|
|
|
|
|
|
|
flushDisplay(); |
|
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
|
|
size_t length = 0; |
|
|
|
|
|
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
// Grow the clipboard if we need to paste something bigger, there is no
|
|
|
|
|
// shrink operation yet.
|
|
|
|
|
const size_t readSize = 4096; |
|
|
|
|
const size_t requiredSize = length + readSize + 1; |
|
|
|
|
if (requiredSize > _glfw.wl.clipboardSize) |
|
|
|
|
{ |
|
|
|
|
char* string = _glfw_realloc(_glfw.wl.clipboardString, requiredSize); |
|
|
|
|
if (!string) |
|
|
|
|
{ |
|
|
|
|
_glfwInputError(GLFW_OUT_OF_MEMORY, |
|
|
|
|
"Wayland: Failed to grow clipboard string"); |
|
|
|
|
close(fds[0]); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_glfw.wl.clipboardString = string; |
|
|
|
|
_glfw.wl.clipboardSize = requiredSize; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Then read from the fd to the clipboard, handling all known errors.
|
|
|
|
|
const ssize_t result = read(fds[0], _glfw.wl.clipboardString + length, readSize); |
|
|
|
|
if (result == 0) |
|
|
|
|
break; |
|
|
|
|
else if (result == -1) |
|
|
|
|
{ |
|
|
|
|
if (errno == EINTR) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
_glfwInputError(GLFW_PLATFORM_ERROR, |
|
|
|
|
"Wayland: Failed to read from clipboard pipe: %s", |
|
|
|
|
strerror(errno)); |
|
|
|
|
close(fds[0]); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
length += result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
close(fds[0]); |
|
|
|
|
|
|
|
|
|
_glfw.wl.clipboardString[length] = '\0'; |
|
|
|
|
_glfw_free(_glfw.wl.clipboardString); |
|
|
|
|
_glfw.wl.clipboardString = |
|
|
|
|
readDataOfferAsString(_glfw.wl.selectionOffer, "text/plain;charset=utf-8"); |
|
|
|
|
return _glfw.wl.clipboardString; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|