Wayland: Simplify clipboard string allocation

(cherry picked from commit 4651165272)
This commit is contained in:
Camilla Löwy 2022-03-24 18:02:48 +01:00
parent a31c648127
commit 857fae4920
3 changed files with 25 additions and 45 deletions

View File

@ -1241,15 +1241,6 @@ int _glfwPlatformInit(void)
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
_glfw.wl.seat); _glfw.wl.seat);
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL); wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
_glfw.wl.clipboardSize = 4096;
_glfw.wl.clipboardString = calloc(_glfw.wl.clipboardSize, 1);
if (!_glfw.wl.clipboardString)
{
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Failed to allocate clipboard memory");
return GLFW_FALSE;
}
} }
return GLFW_TRUE; return GLFW_TRUE;
@ -1346,7 +1337,6 @@ void _glfwPlatformTerminate(void)
close(_glfw.wl.cursorTimerfd); close(_glfw.wl.cursorTimerfd);
free(_glfw.wl.clipboardString); free(_glfw.wl.clipboardString);
free(_glfw.wl.clipboardSendString);
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)

View File

@ -267,7 +267,6 @@ typedef struct _GLFWlibraryWayland
int keyboardLastScancode; int keyboardLastScancode;
char* clipboardString; char* clipboardString;
size_t clipboardSize; size_t clipboardSize;
char* clipboardSendString;
int timerfd; int timerfd;
short int keycodes[256]; short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];

View File

@ -1725,7 +1725,7 @@ static void dataSourceHandleSend(void* userData,
const char* mimeType, const char* mimeType,
int fd) int fd)
{ {
char* string = _glfw.wl.clipboardSendString; char* string = _glfw.wl.clipboardString;
size_t len = strlen(string); size_t len = strlen(string);
int ret; int ret;
@ -1801,16 +1801,23 @@ void _glfwPlatformSetClipboardString(const char* string)
_glfw.wl.selectionSource = NULL; _glfw.wl.selectionSource = NULL;
} }
char* copy = _glfw_strdup(string); const size_t requiredSize = strlen(string) + 1;
if (!copy) if (requiredSize > _glfw.wl.clipboardSize)
{ {
_glfwInputError(GLFW_OUT_OF_MEMORY, free(_glfw.wl.clipboardString);
"Wayland: Failed to allocate clipboard string"); _glfw.wl.clipboardString = calloc(requiredSize, 1);
return; if (!_glfw.wl.clipboardString)
{
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Failed to allocate clipboard string");
return;
}
_glfw.wl.clipboardSize = requiredSize;
} }
free(_glfw.wl.clipboardSendString); // The argument may be a substring of the clipboard string
_glfw.wl.clipboardSendString = copy; memmove(_glfw.wl.clipboardString, string, requiredSize);
_glfw.wl.selectionSource = _glfw.wl.selectionSource =
wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager); wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
@ -1818,8 +1825,6 @@ void _glfwPlatformSetClipboardString(const char* string)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create clipboard data source"); "Wayland: Failed to create clipboard data source");
free(_glfw.wl.clipboardSendString);
_glfw.wl.clipboardSendString = NULL;
return; return;
} }
wl_data_source_add_listener(_glfw.wl.selectionSource, wl_data_source_add_listener(_glfw.wl.selectionSource,
@ -1831,22 +1836,6 @@ void _glfwPlatformSetClipboardString(const char* string)
_glfw.wl.serial); _glfw.wl.serial);
} }
static GLFWbool growClipboardString(void)
{
char* clipboard = _glfw.wl.clipboardString;
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
if (!clipboard)
{
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Failed to grow clipboard string");
return GLFW_FALSE;
}
_glfw.wl.clipboardString = clipboard;
_glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
return GLFW_TRUE;
}
const char* _glfwPlatformGetClipboardString(void) const char* _glfwPlatformGetClipboardString(void)
{ {
int fds[2]; int fds[2];
@ -1861,7 +1850,7 @@ const char* _glfwPlatformGetClipboardString(void)
} }
if (_glfw.wl.selectionSource) if (_glfw.wl.selectionSource)
return _glfw.wl.clipboardSendString; return _glfw.wl.clipboardString;
ret = pipe2(fds, O_CLOEXEC); ret = pipe2(fds, O_CLOEXEC);
if (ret < 0) if (ret < 0)
@ -1881,13 +1870,20 @@ const char* _glfwPlatformGetClipboardString(void)
{ {
// Grow the clipboard if we need to paste something bigger, there is no // Grow the clipboard if we need to paste something bigger, there is no
// shrink operation yet. // shrink operation yet.
if (len + 4096 > _glfw.wl.clipboardSize) const size_t requiredSize = len + 4096 + 1;
if (requiredSize > _glfw.wl.clipboardSize)
{ {
if (!growClipboardString()) char* string = realloc(_glfw.wl.clipboardString, requiredSize);
if (!string)
{ {
_glfwInputError(GLFW_OUT_OF_MEMORY,
"Wayland: Failed to grow clipboard string");
close(fds[0]); close(fds[0]);
return NULL; return NULL;
} }
_glfw.wl.clipboardString = string;
_glfw.wl.clipboardSize = requiredSize;
} }
// Then read from the fd to the clipboard, handling all known errors. // Then read from the fd to the clipboard, handling all known errors.
@ -1907,11 +1903,6 @@ const char* _glfwPlatformGetClipboardString(void)
len += ret; len += ret;
} }
close(fds[0]); close(fds[0]);
if (len + 1 > _glfw.wl.clipboardSize)
{
if (!growClipboardString())
return NULL;
}
_glfw.wl.clipboardString[len] = '\0'; _glfw.wl.clipboardString[len] = '\0';
return _glfw.wl.clipboardString; return _glfw.wl.clipboardString;
} }